MATH-1401: Cover all possible inputs.

Thanks to Michele De Stefano.
This commit is contained in:
Gilles Sadowski 2019-04-18 14:43:27 +02:00
parent 53d9c7fbfb
commit 0df313bef6
3 changed files with 76 additions and 14 deletions

View File

@ -54,8 +54,8 @@ If the output is not quite correct, check for invisible trailing spaces!
</release>
<release version="4.0" date="XXXX-XX-XX" description="">
<action dev="erans" type="fix" issue="MATH-1401">
"ClopperPearsonInterval": Fixed case where number of trials equals number of successes.
<action dev="erans" type="fix" issue="MATH-1401" due-to="Michele De Stefano">
"ClopperPearsonInterval": Missing cases.
</action>
<action dev="erans" type="add" issue="MATH-1477" due-to="Chee Sing Lee">
"MillerUpdatingRegression": Fixed "ArrayIndexOutOfBounds" exception.

View File

@ -35,26 +35,24 @@ public class ClopperPearsonInterval implements BinomialConfidenceInterval {
double confidenceLevel) {
IntervalUtils.checkParameters(numberOfTrials, numberOfSuccesses, confidenceLevel);
double lowerBound = 0;
double upperBound = 0;
double upperBound = 1;
if (numberOfSuccesses > 0) {
final double alpha = 0.5 * (1 - confidenceLevel);
if (numberOfSuccesses > 0) {
final FDistribution distributionLowerBound = new FDistribution(2 * (numberOfTrials - numberOfSuccesses + 1),
2 * numberOfSuccesses);
final double fValueLowerBound = distributionLowerBound.inverseCumulativeProbability(1 - alpha);
lowerBound = numberOfSuccesses /
(numberOfSuccesses + (numberOfTrials - numberOfSuccesses + 1) * fValueLowerBound);
}
if (numberOfSuccesses != numberOfTrials) {
if (numberOfSuccesses < numberOfTrials) {
final FDistribution distributionUpperBound = new FDistribution(2 * (numberOfSuccesses + 1),
2 * (numberOfTrials - numberOfSuccesses));
final double fValueUpperBound = distributionUpperBound.inverseCumulativeProbability(1 - alpha);
upperBound = (numberOfSuccesses + 1) * fValueUpperBound /
(numberOfTrials - numberOfSuccesses + (numberOfSuccesses + 1) * fValueUpperBound);
} else {
upperBound = 1;
}
}
return new ConfidenceInterval(lowerBound, upperBound, confidenceLevel);

View File

@ -46,4 +46,68 @@ public class ClopperPearsonIntervalTest extends BinomialConfidenceIntervalAbstra
Assert.assertEquals(0.025, interval.getLowerBound(), 1e-16);
Assert.assertEquals(1, interval.getUpperBound(), 0d);
}
// number of successes = 0, number of trials = N
@Test
public void testCase1() {
// Check correctness against values obtained with the Python statsmodels.stats.proportion.proportion_confint
final int successes = 0;
final int trials = 10;
final double confidenceLevel = 0.95;
// proportion_confint(0,10,method='beta') = (0, 0.3084971078187608)
final ConfidenceInterval expected = new ConfidenceInterval(0,
0.3084971078187608,
confidenceLevel);
check(expected, createBinomialConfidenceInterval().createInterval(trials, successes, confidenceLevel));
}
// number of successes = number of trials = N
@Test
public void testCase2() {
// Check correctness against values obtained with the Python statsmodels.stats.proportion.proportion_confint
final int successes = 10;
final int trials = 10;
final double confidenceLevel = 0.95;
// prop.proportion_confint(10,10,method='beta') = (0.6915028921812392, 1)
final ConfidenceInterval expected = new ConfidenceInterval(0.6915028921812392,
1,
confidenceLevel);
check(expected, createBinomialConfidenceInterval().createInterval(trials, successes, confidenceLevel));
}
// number of successes = k, number of trials = N, 0 < k < N
@Test
public void testCase3() {
// Check correctness against values obtained with the Python statsmodels.stats.proportion.proportion_confint
final int successes = 3;
final int trials = 10;
final double confidenceLevel = 0.95;
// prop.proportion_confint(3,10,method='beta') = (0.06673951117773447, 0.6524528500599972)
final ConfidenceInterval expected = new ConfidenceInterval(0.06673951117773447,
0.6524528500599972,
confidenceLevel);
check(expected, createBinomialConfidenceInterval().createInterval(trials, successes, confidenceLevel));
}
private void check(ConfidenceInterval expected,
ConfidenceInterval actual) {
final double relTol = 1.0e-6; // Reasonable relative tolerance for floating point comparison
// Compare bounds using a relative tolerance
Assert.assertEquals(expected.getLowerBound(),
actual.getLowerBound(),
relTol * (1.0 + Math.abs(expected.getLowerBound())));
Assert.assertEquals(expected.getUpperBound(),
actual.getUpperBound(),
relTol * (1.0 + Math.abs(expected.getUpperBound())));
// The confidence level must be exact
Assert.assertEquals(expected.getConfidenceLevel(),
actual.getConfidenceLevel(),
0.0);
}
}