[MATH-1065] Fix EnumeratedRealDistribution.inverseCumulativeProbability. Thanks to matteodg and Phil.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1566274 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Thomas Neidhart 2014-02-09 11:21:28 +00:00
parent 3f59a81a15
commit 996c0c164a
3 changed files with 78 additions and 0 deletions

View File

@ -51,6 +51,11 @@ If the output is not quite correct, check for invisible trailing spaces!
</properties> </properties>
<body> <body>
<release version="3.3" date="TBD" description="TBD"> <release version="3.3" date="TBD" description="TBD">
<action dev="tn" type="fix" issue="MATH-1065" due-to="matteodg">
Calculating the inverse cumulative probability of an "EnumeratedRealDistribution"
will now return the correct result according to the selected enumerated probability
mass function.
</action>
<action dev="erans" type="update" issue="MATH-1050"> <action dev="erans" type="update" issue="MATH-1050">
Deprecated "ArithmeticUtils#pow(int, long)" and "ArithmeticUtils#pow(long, long)" Deprecated "ArithmeticUtils#pow(int, long)" and "ArithmeticUtils#pow(long, long)"
in favor of corresponding methods "ArithmeticUtils#pow(..., int)". in favor of corresponding methods "ArithmeticUtils#pow(..., int)".

View File

@ -18,11 +18,13 @@ package org.apache.commons.math3.distribution;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.commons.math3.exception.DimensionMismatchException; import org.apache.commons.math3.exception.DimensionMismatchException;
import org.apache.commons.math3.exception.MathArithmeticException; import org.apache.commons.math3.exception.MathArithmeticException;
import org.apache.commons.math3.exception.NotANumberException; import org.apache.commons.math3.exception.NotANumberException;
import org.apache.commons.math3.exception.NotFiniteNumberException; import org.apache.commons.math3.exception.NotFiniteNumberException;
import org.apache.commons.math3.exception.NotPositiveException; import org.apache.commons.math3.exception.NotPositiveException;
import org.apache.commons.math3.exception.OutOfRangeException;
import org.apache.commons.math3.random.RandomGenerator; import org.apache.commons.math3.random.RandomGenerator;
import org.apache.commons.math3.random.Well19937c; import org.apache.commons.math3.random.Well19937c;
import org.apache.commons.math3.util.Pair; import org.apache.commons.math3.util.Pair;
@ -136,6 +138,33 @@ public class EnumeratedRealDistribution extends AbstractRealDistribution {
return probability; return probability;
} }
/**
* {@inheritDoc}
*/
@Override
public double inverseCumulativeProbability(final double p) throws OutOfRangeException {
if (p < 0.0 || p > 1.0) {
throw new OutOfRangeException(p, 0, 1);
}
double probability = 0;
double x = getSupportLowerBound();
for (final Pair<Double, Double> sample : innerDistribution.getPmf()) {
if (sample.getValue() == 0.0) {
continue;
}
probability += sample.getValue();
x = sample.getKey();
if (probability >= p) {
break;
}
}
return x;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
* *

View File

@ -16,6 +16,8 @@
*/ */
package org.apache.commons.math3.distribution; package org.apache.commons.math3.distribution;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -213,4 +215,46 @@ public class EnumeratedRealDistributionTest {
Assert.assertEquals(1, new EnumeratedDistribution<Object>(list).sample(1).length); Assert.assertEquals(1, new EnumeratedDistribution<Object>(list).sample(1).length);
} }
@Test
public void testIssue1065() {
// Test Distribution for inverseCumulativeProbability
//
// ^
// |
// 1.000 +--------------------------------o===============
// | 3|
// | |
// | 1o=
// 0.750 +-------------------------> o== .
// | 3| . .
// | 0 | . .
// 0.5625 +---------------> o==o====== . .
// | | . . . .
// | | . . . .
// | 5| . . . .
// | | . . . .
// | o=== . . . .
// | | . . . . .
// | 4| . . . . .
// | | . . . . .
// 0.000 +=============----+--+------+--+-+--------------->
// 14 18 21 28 31 33
//
// sum = 4+5+0+3+1+3 = 16
EnumeratedRealDistribution distribution = new EnumeratedRealDistribution(
new double[] { 14.0, 18.0, 21.0, 28.0, 31.0, 33.0 },
new double[] { 4.0 / 16.0, 5.0 / 16.0, 0.0 / 16.0, 3.0 / 16.0, 1.0 / 16.0, 3.0 / 16.0 });
assertEquals(14.0, distribution.inverseCumulativeProbability(0.0000), 0.0);
assertEquals(14.0, distribution.inverseCumulativeProbability(0.2500), 0.0);
assertEquals(33.0, distribution.inverseCumulativeProbability(1.0000), 0.0);
assertEquals(18.0, distribution.inverseCumulativeProbability(0.5000), 0.0);
assertEquals(18.0, distribution.inverseCumulativeProbability(0.5624), 0.0);
assertEquals(28.0, distribution.inverseCumulativeProbability(0.5626), 0.0);
assertEquals(31.0, distribution.inverseCumulativeProbability(0.7600), 0.0);
assertEquals(18.0, distribution.inverseCumulativeProbability(0.5625), 0.0);
assertEquals(28.0, distribution.inverseCumulativeProbability(0.7500), 0.0);
}
} }