You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2022/11/21 19:23:14 UTC
[commons-statistics] 01/12: Convert to parameterized tests
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-statistics.git
commit a7153c2343a70665ca8b45dbbc45f66be0bac7be
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Mon Nov 21 16:57:12 2022 +0000
Convert to parameterized tests
---
.../distribution/GammaDistributionTest.java | 264 +++++++++------------
1 file changed, 116 insertions(+), 148 deletions(-)
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GammaDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GammaDistributionTest.java
index 7c5ae4b..3d9c73c 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GammaDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GammaDistributionTest.java
@@ -25,9 +25,9 @@ import java.util.stream.Stream;
import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
import org.apache.commons.numbers.gamma.LanczosApproximation;
import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.MethodSource;
/**
@@ -80,114 +80,111 @@ class GammaDistributionTest extends BaseContinuousDistributionTest {
);
}
- @Test
- void testAdditionalCumulativeProbability() {
- checkCumulativeProbability(-1.000, 4.0, 2.0, 0.0);
- checkCumulativeProbability(15.501, 4.0, 2.0, 0.94989465156755404);
- checkCumulativeProbability(0.504, 4.0, 1.0, 0.0018026739713985257);
- checkCumulativeProbability(10.011, 1.0, 2.0, 0.99329900998454213);
- checkCumulativeProbability(5.000, 2.0, 2.0, 0.71270250481635422);
- }
-
- private void checkCumulativeProbability(double x, double a, double b, double expected) {
- final GammaDistribution distribution = GammaDistribution.of(a, b);
- final double actual = distribution.cumulativeProbability(x);
+ @ParameterizedTest
+ @CsvSource({
+ "4.0, 2.0, -1.0, 0.0",
+ "4.0, 2.0, 15.501, 0.94989465156755404",
+ "4.0, 1.0, 0.504, 0.0018026739713985257",
+ "1.0, 2.0, 10.011, 0.99329900998454213",
+ "2.0, 2.0, 5.000, 0.71270250481635422",
+ })
+ void testAdditionalCumulativeProbability(double a, double b, double x, double expected) {
+ final GammaDistribution dist = GammaDistribution.of(a, b);
+ final double actual = dist.cumulativeProbability(x);
Assertions.assertEquals(expected, actual, expected * 1e-15, () -> "probability for " + x);
}
- @Test
- void testAdditionalInverseCumulativeProbability() {
- checkInverseCumulativeProbability(15.501, 4.0, 2.0, 0.94989465156755404);
- checkInverseCumulativeProbability(0.504, 4.0, 1.0, 0.0018026739713985257);
- checkInverseCumulativeProbability(10.011, 1.0, 2.0, 0.99329900998454213);
- checkInverseCumulativeProbability(5.000, 2.0, 2.0, 0.71270250481635422);
- }
-
- private void checkInverseCumulativeProbability(double expected, double a, double b, double p) {
- final GammaDistribution distribution = GammaDistribution.of(a, b);
- final double actual = distribution.inverseCumulativeProbability(p);
- Assertions.assertEquals(expected, actual, expected * 1e-10, () -> "critical value for " + p);
+ @ParameterizedTest
+ @CsvSource({
+ "4.0, 2.0, 0.94989465156755404, 15.501",
+ "4.0, 1.0, 0.0018026739713985257, 0.504",
+ "1.0, 2.0, 0.99329900998454213, 10.011",
+ "2.0, 2.0, 0.71270250481635422, 5.0",
+ })
+ void testAdditionalInverseCumulativeProbability(double a, double b, double p, double expected) {
+ final GammaDistribution dist = GammaDistribution.of(a, b);
+ final double actual = dist.inverseCumulativeProbability(p);
+ Assertions.assertEquals(expected, actual, expected * 5e-15, () -> "critical value for " + p);
}
- @Test
- void testAdditionalDensity() {
- final double[] x = new double[]{-0.1, 1e-6, 0.5, 1, 2, 5};
- // R2.5: print(dgamma(x, shape=1, rate=1), digits=10)
- checkDensity(1, 1, x, new double[]{0.000000000000, 0.999999000001, 0.606530659713, 0.367879441171, 0.135335283237, 0.006737946999});
- // R2.5: print(dgamma(x, shape=2, rate=1), digits=10)
- checkDensity(2, 1, x, new double[]{0.000000000000, 0.000000999999, 0.303265329856, 0.367879441171, 0.270670566473, 0.033689734995});
- // R2.5: print(dgamma(x, shape=4, rate=1), digits=10)
- checkDensity(4, 1, x, new double[]{0.000000000e+00, 1.666665000e-19, 1.263605541e-02, 6.131324020e-02, 1.804470443e-01, 1.403738958e-01});
- // R2.5: print(dgamma(x, shape=4, rate=10), digits=10)
- checkDensity(4, 10, x, new double[]{0.000000000e+00, 1.666650000e-15, 1.403738958e+00, 7.566654960e-02, 2.748204830e-05, 4.018228850e-17});
- // R2.5: print(dgamma(x, shape=.1, rate=10), digits=10)
- checkDensity(0.1, 10, x, new double[]{0.000000000e+00, 3.323953832e+04, 1.663849010e-03, 6.007786726e-06, 1.461647647e-10, 5.996008322e-24});
- // R2.5: print(dgamma(x, shape=.1, rate=20), digits=10)
- checkDensity(0.1, 20, x, new double[]{0.000000000e+00, 3.562489883e+04, 1.201557345e-05, 2.923295295e-10, 3.228910843e-19, 1.239484589e-45});
- // R2.5: print(dgamma(x, shape=.1, rate=4), digits=10)
- checkDensity(0.1, 4, x, new double[]{0.000000000e+00, 3.032938388e+04, 3.049322494e-02, 2.211502311e-03, 2.170613371e-05, 5.846590589e-11});
- // R2.5: print(dgamma(x, shape=.1, rate=1), digits=10)
- checkDensity(0.1, 1, x, new double[]{0.000000000e+00, 2.640334143e+04, 1.189704437e-01, 3.866916944e-02, 7.623306235e-03, 1.663849010e-04});
- // To force overflow condition
- // R2.5: print(dgamma(x, shape=1000, rate=100), digits=10)
- checkDensity(1000, 100, x, new double[]{0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 3.304830256e-84});
+ @ParameterizedTest
+ @MethodSource
+ void testAdditionalDensity(double alpha, double rate, double[] x, double[] expected) {
+ final GammaDistribution dist = GammaDistribution.of(alpha, 1 / rate);
+ testDensity(dist, x, expected, DoubleTolerances.relative(1e-9));
}
- /**
- * Test a shape far below 1. Support for very small shape parameters
- * was fixed in STATISTICS-39.
- */
- @Test
- void testShapeBelow1() {
- // R2.5: print(dgamma(x, shape=0.05, rate=1), digits=20)
- final double[] x = new double[]{1e-100, 1e-10, 1e-5, 0.1};
- checkDensity(0.05, 1, x, new double[] {
- 5.1360843263583843333e+93, 1.6241724724359893799e+08,
- 2.8882035841935007738e+03, 4.1419294512123655538e-01
- });
+ static Stream<Arguments> testAdditionalDensity() {
+ final double[] x = {-0.1, 1e-6, 0.5, 1, 2, 5};
+ final double[] x1 = new double[]{1e-100, 1e-10, 1e-5, 0.1};
+ return Stream.of(
+ // R2.5: print(dgamma((x, shape=1, rate=1), digits=10)
+ Arguments.of(1, 1, x, new double[]{0.000000000000, 0.999999000001, 0.606530659713, 0.367879441171, 0.135335283237, 0.006737946999}),
+ // R2.5: print(dgamma((x, shape=2, rate=1), digits=10)
+ Arguments.of(2, 1, x, new double[]{0.000000000000, 0.000000999999, 0.303265329856, 0.367879441171, 0.270670566473, 0.033689734995}),
+ // R2.5: print(dgamma((x, shape=4, rate=1), digits=10)
+ Arguments.of(4, 1, x, new double[]{0.000000000e+00, 1.666665000e-19, 1.263605541e-02, 6.131324020e-02, 1.804470443e-01, 1.403738958e-01}),
+ // R2.5: print(dgamma((x, shape=4, rate=10), digits=10)
+ Arguments.of(4, 10, x, new double[]{0.000000000e+00, 1.666650000e-15, 1.403738958e+00, 7.566654960e-02, 2.748204830e-05, 4.018228850e-17}),
+ // R2.5: print(dgamma((x, shape=.1, rate=10), digits=10)
+ Arguments.of(0.1, 10, x, new double[]{0.000000000e+00, 3.323953832e+04, 1.663849010e-03, 6.007786726e-06, 1.461647647e-10, 5.996008322e-24}),
+ // R2.5: print(dgamma((x, shape=.1, rate=20), digits=10)
+ Arguments.of(0.1, 20, x, new double[]{0.000000000e+00, 3.562489883e+04, 1.201557345e-05, 2.923295295e-10, 3.228910843e-19, 1.239484589e-45}),
+ // R2.5: print(dgamma((x, shape=.1, rate=4), digits=10)
+ Arguments.of(0.1, 4, x, new double[]{0.000000000e+00, 3.032938388e+04, 3.049322494e-02, 2.211502311e-03, 2.170613371e-05, 5.846590589e-11}),
+ // R2.5: print(dgamma((x, shape=.1, rate=1), digits=10)
+ Arguments.of(0.1, 1, x, new double[]{0.000000000e+00, 2.640334143e+04, 1.189704437e-01, 3.866916944e-02, 7.623306235e-03, 1.663849010e-04}),
+ // To force overflow condition
+ // R2.5: print(dgamma((x, shape=1000, rate=100), digits=10)
+ Arguments.of(1000, 100, x, new double[]{0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 3.304830256e-84}),
+
+ // Test a shape far below 1.
+ // Support for very small shape parameters was fixed in STATISTICS-39.
+ // R2.5: print(dgamma((x1, shape=0.05, rate=1), digits=20)
+ Arguments.of(0.05, 1, x1,
+ new double[] {
+ 5.1360843263583843333e+93, 1.6241724724359893799e+08,
+ 2.8882035841935007738e+03, 4.1419294512123655538e-01
+ })
+ );
}
- private void checkDensity(double alpha, double rate, double[] x, double[] expected) {
+ @ParameterizedTest
+ @MethodSource
+ void testAdditionalLogDensity(double alpha, double rate, double[] x, double[] expected) {
final GammaDistribution dist = GammaDistribution.of(alpha, 1 / rate);
- for (int i = 0; i < x.length; i++) {
- Assertions.assertEquals(expected[i], dist.density(x[i]), Math.abs(expected[i]) * 1e-9);
- }
+ testLogDensity(dist, x, expected, DoubleTolerances.relative(1e-9));
}
- @Test
- void testAdditionalLogDensity() {
- final double[] x = new double[]{-0.1, 1e-6, 0.5, 1, 2, 5};
- final double inf = Double.POSITIVE_INFINITY;
- // R2.5: print(dgamma(x, shape=1, rate=1, log=TRUE), digits=10)
- checkLogDensity(1, 1, x, new double[]{-inf, -1e-06, -5e-01, -1e+00, -2e+00, -5e+00});
- // R2.5: print(dgamma(x, shape=2, rate=1, log=TRUE), digits=10)
- checkLogDensity(2, 1, x, new double[]{-inf, -13.815511558, -1.193147181, -1.000000000, -1.306852819, -3.390562088});
- // R2.5: print(dgamma(x, shape=4, rate=1, log=TRUE), digits=10)
- checkLogDensity(4, 1, x, new double[]{-inf, -43.238292143, -4.371201011, -2.791759469, -1.712317928, -1.963445732});
- // R2.5: print(dgamma(x, shape=4, rate=10, log=TRUE), digits=10)
- checkLogDensity(4, 10, x, new double[]{-inf, -34.0279607711, 0.3391393611, -2.5814190973, -10.5019775556, -37.7531053599});
- // R2.5: print(dgamma(x, shape=.1, rate=10, log=TRUE), digits=10)
- checkLogDensity(0.1, 10, x, new double[]{-inf, 10.41149536, -6.39862168, -12.02245414, -22.64628660, -53.47094826});
- // R2.5: print(dgamma(x, shape=.1, rate=20, log=TRUE), digits=10)
- checkLogDensity(0.1, 20, x, new double[]{-inf, 10.48080008, -11.32930696, -21.95313942, -42.57697189, -103.40163355});
- // R2.5: print(dgamma(x, shape=.1, rate=4, log=TRUE), digits=10)
- checkLogDensity(0.1, 4, x, new double[]{-inf, 10.319872287, -3.490250753, -6.114083216, -10.737915678, -23.562577337});
- // R2.5: print(dgamma(x, shape=.1, rate=1, log=TRUE), digits=10)
- checkLogDensity(0.1, 1, x, new double[]{-inf, 10.181245850, -2.128880189, -3.252712652, -4.876545114, -8.701206773});
- // To force overflow condition to pdf=zero
- // R2.5: print(dgamma(x, shape=1000, rate=100, log=TRUE), digits=10)
- checkLogDensity(1000, 100, x, new double[]{-inf, -15101.7453846, -2042.5042706, -1400.0502372, -807.5962038, -192.2217627});
- // To force overflow condition to pdf=infinity
+ static Stream<Arguments> testAdditionalLogDensity() {
+ final double[] x = {-0.1, 1e-6, 0.5, 1, 2, 5};
final double[] x1 = {1e-315, 1e-320, 1e-323};
- // scipy.stats gamma(1e-2).logpdf(x1)
- checkLogDensity(0.01, 1, x1, new double[]{713.46168137365419, 724.85948860402209, 731.70997561537104});
- }
-
- private void checkLogDensity(double alpha, double rate, double[] x, double[] expected) {
- final GammaDistribution dist = GammaDistribution.of(alpha, 1 / rate);
- for (int i = 0; i < x.length; i++) {
- Assertions.assertEquals(expected[i], dist.logDensity(x[i]), Math.abs(expected[i]) * 1e-9);
- }
+ final double inf = Double.POSITIVE_INFINITY;
+ return Stream.of(
+ // R2.5: print(dgamma((x, shape=1, rate=1, log=TRUE), digits=10)
+ Arguments.of(1, 1, x, new double[]{-inf, -1e-06, -5e-01, -1e+00, -2e+00, -5e+00}),
+ // R2.5: print(dgamma((x, shape=2, rate=1, log=TRUE), digits=10)
+ Arguments.of(2, 1, x, new double[]{-inf, -13.815511558, -1.193147181, -1.000000000, -1.306852819, -3.390562088}),
+ // R2.5: print(dgamma((x, shape=4, rate=1, log=TRUE), digits=10)
+ Arguments.of(4, 1, x, new double[]{-inf, -43.238292143, -4.371201011, -2.791759469, -1.712317928, -1.963445732}),
+ // R2.5: print(dgamma((x, shape=4, rate=10, log=TRUE), digits=10)
+ Arguments.of(4, 10, x, new double[]{-inf, -34.0279607711, 0.3391393611, -2.5814190973, -10.5019775556, -37.7531053599}),
+ // R2.5: print(dgamma((x, shape=.1, rate=10, log=TRUE), digits=10)
+ Arguments.of(0.1, 10, x, new double[]{-inf, 10.41149536, -6.39862168, -12.02245414, -22.64628660, -53.47094826}),
+ // R2.5: print(dgamma((x, shape=.1, rate=20, log=TRUE), digits=10)
+ Arguments.of(0.1, 20, x, new double[]{-inf, 10.48080008, -11.32930696, -21.95313942, -42.57697189, -103.40163355}),
+ // R2.5: print(dgamma((x, shape=.1, rate=4, log=TRUE), digits=10)
+ Arguments.of(0.1, 4, x, new double[]{-inf, 10.319872287, -3.490250753, -6.114083216, -10.737915678, -23.562577337}),
+ // R2.5: print(dgamma((x, shape=.1, rate=1, log=TRUE), digits=10)
+ Arguments.of(0.1, 1, x, new double[]{-inf, 10.181245850, -2.128880189, -3.252712652, -4.876545114, -8.701206773}),
+ // To force overflow condition to pdf=zero
+ // R2.5: print(dgamma((x, shape=1000, rate=100, log=TRUE), digits=10)
+ Arguments.of(1000, 100, x, new double[]{-inf, -15101.7453846, -2042.5042706, -1400.0502372, -807.5962038, -192.2217627}),
+ // To force overflow condition to pdf=infinity
+ // scipy.stats gamma(1e-2).logpdf(x1)
+ Arguments.of(0.01, 1, x1,
+ new double[]{713.46168137365419, 724.85948860402209, 731.70997561537104})
+ );
}
private static double logGamma(double x) {
@@ -205,9 +202,9 @@ class GammaDistributionTest extends BaseContinuousDistributionTest {
HALF_LOG_2_PI + Math.log(sum / x);
}
- private static double density(final double x,
- final double shape,
- final double scale) {
+ private static double density(double x,
+ double shape,
+ double scale) {
/*
* This is a copy of
* double GammaDistribution.density(double)
@@ -234,11 +231,13 @@ class GammaDistributionTest extends BaseContinuousDistributionTest {
* @param resourceName Resource name containing a pair of comma separated values for the
* random variable x and the expected value of the gamma distribution: x, gamma(x; shape, scale=1)
*/
- private void doTestMath753(final double shape,
- final double meanNoOF, final double sdNoOF,
- final double meanOF, final double sdOF,
- final String resourceName) {
- final GammaDistribution distribution = GammaDistribution.of(shape, 1.0);
+ @ParameterizedTest
+ @MethodSource
+ void testMath753(double shape,
+ double meanNoOF, double sdNoOF,
+ double meanOF, double sdOF,
+ String resourceName) {
+ final GammaDistribution dist = GammaDistribution.of(shape, 1.0);
final SummaryStatistics statOld = new SummaryStatistics();
// statNewNoOF = No overflow of old function
// statNewOF = Overflow of old function
@@ -261,7 +260,7 @@ class GammaDistributionTest extends BaseContinuousDistributionTest {
final double expected = Double.parseDouble(tokens[1]);
final double ulp = Math.ulp(expected);
final double actualOld = density(x, shape, 1.0);
- final double actualNew = distribution.density(x);
+ final double actualNew = dist.density(x);
final double errOld = Math.abs((actualOld - expected) / ulp);
final double errNew = Math.abs((actualNew - expected) / ulp);
@@ -333,48 +332,17 @@ class GammaDistributionTest extends BaseContinuousDistributionTest {
}
}
- @Test
- void testMath753Shape025() {
- doTestMath753(0.25, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-0.25.csv");
- }
-
- @Test
- void testMath753Shape05() {
- doTestMath753(0.5, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-0.5.csv");
- }
-
- @Test
- void testMath753Shape075() {
- doTestMath753(0.75, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-0.75.csv");
- }
-
- @Test
- void testMath753Shape1() {
- doTestMath753(1.0, 1.0, 0.5, 0.0, 0.0, "gamma-distribution-shape-1.csv");
- }
-
- @Test
- void testMath753Shape8() {
- doTestMath753(8.0, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-8.csv");
- }
-
- @Test
- void testMath753Shape10() {
- doTestMath753(10.0, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-10.csv");
- }
-
- @Test
- void testMath753Shape100() {
- doTestMath753(100.0, 2.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-100.csv");
- }
-
- @Test
- void testMath753Shape142() {
- doTestMath753(142.0, 1.5, 1.0, 40.0, 40.0, "gamma-distribution-shape-142.csv");
- }
-
- @Test
- void testMath753Shape1000() {
- doTestMath753(1000.0, 1.0, 1.0, 160.0, 200.0, "gamma-distribution-shape-1000.csv");
+ static Stream<Arguments> testMath753() {
+ return Stream.of(
+ Arguments.of(0.25, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-0.25.csv"),
+ Arguments.of(0.5, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-0.5.csv"),
+ Arguments.of(0.75, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-0.75.csv"),
+ Arguments.of(1.0, 1.0, 0.5, 0.0, 0.0, "gamma-distribution-shape-1.csv"),
+ Arguments.of(8.0, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-8.csv"),
+ Arguments.of(10.0, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-10.csv"),
+ Arguments.of(100.0, 2.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-100.csv"),
+ Arguments.of(142.0, 1.5, 1.0, 40.0, 40.0, "gamma-distribution-shape-142.csv"),
+ Arguments.of(1000.0, 1.0, 1.0, 160.0, 200.0, "gamma-distribution-shape-1000.csv")
+ );
}
}