1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.statistics.distribution;
19
20 import java.util.stream.Stream;
21 import org.apache.commons.math3.util.MathArrays;
22 import org.apache.commons.rng.simple.RandomSource;
23 import org.junit.jupiter.api.Assertions;
24 import org.junit.jupiter.api.Test;
25 import org.junit.jupiter.params.ParameterizedTest;
26 import org.junit.jupiter.params.provider.Arguments;
27 import org.junit.jupiter.params.provider.MethodSource;
28
29
30
31
32
33 class ZipfDistributionTest extends BaseDiscreteDistributionTest {
34 @Override
35 DiscreteDistribution makeDistribution(Object... parameters) {
36 final int n = (Integer) parameters[0];
37 final double e = (Double) parameters[1];
38 return ZipfDistribution.of(n, e);
39 }
40
41
42 @Override
43 Object[][] makeInvalidParameters() {
44 return new Object[][] {
45 {0, 1.0},
46 {-1, 1.0},
47 {1, -0.1},
48 };
49 }
50
51 @Override
52 String[] getParameterNames() {
53 return new String[] {"NumberOfElements", "Exponent"};
54 }
55
56 @Override
57 protected double getRelativeTolerance() {
58 return 1e-14;
59 }
60
61
62
63 @ParameterizedTest
64 @MethodSource
65 void testAdditionlSurvivalProbabilityHighPrecision(int n, double e, int[] x, double[] expected, DoubleTolerance tol) {
66 testSurvivalProbabilityHighPrecision(ZipfDistribution.of(n, e), x, expected, tol);
67 }
68
69 static Stream<Arguments> testAdditionlSurvivalProbabilityHighPrecision() {
70
71 return Stream.of(
72 Arguments.of(60, 10,
73 new int[] {57, 59},
74 new double[] {2.3189337454689757e-18, 1.6521739576668957e-18},
75 DoubleTolerances.absolute(1e-25)),
76 Arguments.of(60, 50.5,
77 new int[] {57, 59},
78 new double[] {8.8488396450491320e-90, 1.5972093932264611e-90},
79 DoubleTolerances.absolute(1e-95)),
80 Arguments.of(60, 100.5,
81 new int[] {57, 59},
82 new double[] {5.9632998443758656e-178, 1.9760564023408183e-179},
83 DoubleTolerances.absolute(1e-185))
84 );
85 }
86
87
88
89
90
91
92 @Test
93 void testAdditionalSurvivalAndCumulativeProbabilityComplement() {
94
95 final int n = 60;
96 final double a = 200.5;
97 Assertions.assertEquals(Double.POSITIVE_INFINITY, Math.pow(n, a));
98 ZipfDistribution dist = ZipfDistribution.of(n, a);
99 final int[] points = MathArrays.natural(n);
100 testSurvivalAndCumulativeProbabilityComplement(dist, points, createTolerance());
101 }
102
103
104
105
106 @Test
107 void testSamplingExtended() {
108 final int sampleSize = 1000;
109
110 final int[] numPointsValues = {
111 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 35, 40, 45, 50, 60, 70, 80, 90, 100
112 };
113 final double[] exponentValues = {
114 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 2e-1, 5e-1,
115 1. - 1e-9, 1.0, 1. + 1e-9, 1.1, 1.2, 1.3, 1.5, 1.6, 1.7, 1.8, 2.0,
116 2.5, 3.0, 4., 5., 6., 7., 8., 9., 10., 20., 30., 100., 150.
117 };
118
119 for (final int numPoints : numPointsValues) {
120 for (final double exponent : exponentValues) {
121 double weightSum = 0.;
122 final double[] weights = new double[numPoints];
123 for (int i = numPoints; i >= 1; i -= 1) {
124 weights[i - 1] = Math.pow(i, -exponent);
125 weightSum += weights[i - 1];
126 }
127
128
129
130
131 final DiscreteDistribution.Sampler distribution =
132 ZipfDistribution.of(numPoints, exponent).createSampler(
133 RandomSource.XO_SHI_RO_256_PP.create(1));
134
135 final double[] expectedCounts = new double[numPoints];
136 final long[] observedCounts = new long[numPoints];
137 for (int i = 0; i < numPoints; i++) {
138 expectedCounts[i] = sampleSize * (weights[i] / weightSum);
139 }
140 final int[] sample = TestUtils.sample(sampleSize, distribution);
141 for (final int s : sample) {
142 observedCounts[s - 1]++;
143 }
144 TestUtils.assertChiSquareAccept(expectedCounts, observedCounts, 0.001);
145 }
146 }
147 }
148 }