1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.statistics.distribution;
18
19 import java.util.Arrays;
20 import java.util.stream.Stream;
21 import org.junit.jupiter.api.Assertions;
22 import org.junit.jupiter.api.Test;
23 import org.junit.jupiter.params.ParameterizedTest;
24 import org.junit.jupiter.params.provider.Arguments;
25 import org.junit.jupiter.params.provider.MethodSource;
26 import org.junit.jupiter.params.provider.ValueSource;
27
28
29
30
31
32 class GeometricDistributionTest extends BaseDiscreteDistributionTest {
33 @Override
34 DiscreteDistribution makeDistribution(Object... parameters) {
35 final double p = (Double) parameters[0];
36 return GeometricDistribution.of(p);
37 }
38
39 @Override
40 Object[][] makeInvalidParameters() {
41 return new Object[][] {
42 {-0.1},
43 {0.0},
44 {1.1},
45 };
46 }
47
48 @Override
49 String[] getParameterNames() {
50 return new String[] {"ProbabilityOfSuccess"};
51 }
52
53 @Override
54 protected double getRelativeTolerance() {
55 return 2 * RELATIVE_EPS;
56 }
57
58
59
60 @ParameterizedTest
61 @MethodSource
62 void testAdditionalMoments(double p, double mean, double variance) {
63 final GeometricDistribution dist = GeometricDistribution.of(p);
64 testMoments(dist, mean, variance, DoubleTolerances.ulps(1));
65 }
66
67 static Stream<Arguments> testAdditionalMoments() {
68 return Stream.of(
69 Arguments.of(0.5, (1.0 - 0.5) / 0.5, (1.0 - 0.5) / (0.5 * 0.5)),
70 Arguments.of(0.3, (1.0 - 0.3) / 0.3, (1.0 - 0.3) / (0.3 * 0.3))
71 );
72 }
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 @ParameterizedTest
89 @ValueSource(doubles = {0.5, 0.6658665, 0.75, 0.8125347, 0.9, 0.95, 0.99})
90 void testPMF(double p) {
91 final GeometricDistribution dist = GeometricDistribution.of(p);
92 final int[] x = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40};
93 final double[] values = Arrays.stream(x).mapToDouble(k -> p * Math.pow(1 - p, k)).toArray();
94
95 testProbability(dist, x, values, DoubleTolerances.equals());
96 }
97
98
99
100
101
102
103 @ParameterizedTest
104 @ValueSource(doubles = {
105 0.2,
106 0.8,
107
108 0.07131208016887369,
109 0.14441285445326058,
110 0.272118157703929,
111 0.424656239093432,
112 0.00899452845634574,
113
114 0.3441320118140774,
115 0.5680886873083258,
116 0.8738746761971425,
117 0.17373328785967923,
118 0.09252030895185881,
119 })
120 void testInverseCDF(double p) {
121 final GeometricDistribution dist = GeometricDistribution.of(p);
122 final int[] x = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
123 testCumulativeProbabilityInverseMapping(dist, x);
124 }
125
126
127
128
129
130
131 @ParameterizedTest
132 @ValueSource(doubles = {
133 0.2,
134 0.8,
135
136 0.9625911263689207,
137 0.2858964038911178,
138 0.31872883511135996,
139 0.46149078212832284,
140 0.3701613946505057,
141
142 0.3796493606864414,
143 0.1113177920615187,
144 0.2587259503484439,
145 0.8996839434455458,
146 0.450704136259792,
147 })
148 void testInverseSF(double p) {
149 final GeometricDistribution dist = GeometricDistribution.of(p);
150 final int[] x = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
151 testSurvivalProbabilityInverseMapping(dist, x);
152 }
153
154
155
156
157
158
159 @Test
160 void testExtremeParameters() {
161 final double p = Double.MIN_VALUE;
162 final GeometricDistribution dist = GeometricDistribution.of(p);
163
164 final int x = Integer.MAX_VALUE;
165
166
167 final double cdf = -Math.expm1(Math.log1p(-p) * (x + 1.0));
168 Assertions.assertNotEquals(1.0, cdf);
169 Assertions.assertEquals(cdf, dist.cumulativeProbability(x));
170 for (int i = 0; i < 5; i++) {
171 Assertions.assertEquals(x - i, dist.inverseCumulativeProbability(dist.cumulativeProbability(x - i)));
172 }
173
174
175 Assertions.assertEquals(p, dist.cumulativeProbability(0));
176 Assertions.assertEquals(0, dist.inverseCumulativeProbability(p));
177 Assertions.assertEquals(1, dist.inverseCumulativeProbability(Math.nextUp(p)));
178 for (int i = 1; i < 5; i++) {
179 Assertions.assertEquals(i, dist.inverseCumulativeProbability(dist.cumulativeProbability(i)));
180 }
181
182
183
184 final double sf = Math.exp(Math.log1p(-p) * (x + 1.0));
185 Assertions.assertEquals(1.0 - cdf, sf);
186 Assertions.assertEquals(sf, dist.survivalProbability(x));
187
188 Assertions.assertEquals(1.0, sf);
189 Assertions.assertEquals(x, dist.inverseSurvivalProbability(Math.nextDown(1.0)));
190 }
191
192
193
194
195
196
197
198 @Test
199 void testExtremeParameters2() {
200 final double p = Math.nextDown(1.0);
201 final GeometricDistribution dist = GeometricDistribution.of(p);
202
203 final int x = 0;
204
205
206 Assertions.assertEquals(p, dist.cumulativeProbability(0));
207 Assertions.assertEquals(0, dist.inverseCumulativeProbability(p));
208
209 Assertions.assertEquals(Integer.MAX_VALUE, dist.inverseCumulativeProbability(Math.nextUp(p)));
210
211
212 final double sf = 1 - p;
213 Assertions.assertNotEquals(0.0, sf);
214 Assertions.assertEquals(sf, dist.survivalProbability(x));
215 for (int i = 1; i < 5; i++) {
216 Assertions.assertEquals(i, dist.inverseSurvivalProbability(dist.survivalProbability(i)));
217 }
218 }
219
220
221
222
223
224
225
226 @Test
227 void testExtremeParameters3() {
228 final double p = Math.nextDown(Math.nextDown(1.0));
229 final GeometricDistribution dist = GeometricDistribution.of(p);
230
231 final int x = 0;
232
233
234 Assertions.assertEquals(p, dist.cumulativeProbability(0));
235 Assertions.assertEquals(0, dist.inverseCumulativeProbability(p));
236 Assertions.assertEquals(1, dist.inverseCumulativeProbability(Math.nextUp(p)));
237
238 Assertions.assertEquals(Integer.MAX_VALUE, dist.inverseCumulativeProbability(Math.nextUp(Math.nextUp(p))));
239
240
241 final double sf = 1 - p;
242 Assertions.assertNotEquals(0.0, sf);
243 Assertions.assertEquals(sf, dist.survivalProbability(x));
244 for (int i = 1; i < 5; i++) {
245 Assertions.assertEquals(i, dist.inverseSurvivalProbability(dist.survivalProbability(i)));
246 }
247 }
248 }