1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.math4.legacy.distribution;
18
19
20 import java.util.ArrayList;
21 import java.util.Collections;
22
23 import org.apache.commons.statistics.distribution.ContinuousDistribution;
24 import org.apache.commons.math4.legacy.TestUtils;
25 import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
26 import org.apache.commons.math4.legacy.analysis.integration.BaseAbstractUnivariateIntegrator;
27 import org.apache.commons.math4.legacy.analysis.integration.IterativeLegendreGaussIntegrator;
28 import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
29 import org.apache.commons.math4.legacy.exception.NumberIsTooLargeException;
30 import org.apache.commons.rng.simple.RandomSource;
31 import org.apache.commons.math4.core.jdkmath.JdkMath;
32 import org.junit.After;
33 import org.junit.Assert;
34 import org.junit.Before;
35 import org.junit.Test;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 public abstract class RealDistributionAbstractTest {
68
69
70
71 private ContinuousDistribution distribution;
72
73
74 private double tolerance = 1E-4;
75
76
77 private double[] cumulativeTestPoints;
78
79
80 private double[] cumulativeTestValues;
81
82
83 private double[] inverseCumulativeTestPoints;
84
85
86 private double[] inverseCumulativeTestValues;
87
88
89 private double[] densityTestValues;
90
91
92 private double[] logDensityTestValues;
93
94
95
96
97 public abstract ContinuousDistribution makeDistribution();
98
99
100 public abstract double[] makeCumulativeTestPoints();
101
102
103 public abstract double[] makeCumulativeTestValues();
104
105
106 public abstract double[] makeDensityTestValues();
107
108
109
110
111 public double[] makeLogDensityTestValues() {
112 final double[] densityTestValues = makeDensityTestValues();
113 final double[] logDensityTestValues = new double[densityTestValues.length];
114 for (int i = 0; i < densityTestValues.length; i++) {
115 logDensityTestValues[i] = JdkMath.log(densityTestValues[i]);
116 }
117 return logDensityTestValues;
118 }
119
120
121
122
123 public double[] makeInverseCumulativeTestPoints() {
124 return makeCumulativeTestValues();
125 }
126
127
128 public double[] makeInverseCumulativeTestValues() {
129 return makeCumulativeTestPoints();
130 }
131
132
133
134
135
136
137 @Before
138 public void setUp() {
139 distribution = makeDistribution();
140 cumulativeTestPoints = makeCumulativeTestPoints();
141 cumulativeTestValues = makeCumulativeTestValues();
142 inverseCumulativeTestPoints = makeInverseCumulativeTestPoints();
143 inverseCumulativeTestValues = makeInverseCumulativeTestValues();
144 densityTestValues = makeDensityTestValues();
145 logDensityTestValues = makeLogDensityTestValues();
146 }
147
148
149
150
151 @After
152 public void tearDown() {
153 distribution = null;
154 cumulativeTestPoints = null;
155 cumulativeTestValues = null;
156 inverseCumulativeTestPoints = null;
157 inverseCumulativeTestValues = null;
158 densityTestValues = null;
159 logDensityTestValues = null;
160 }
161
162
163
164
165
166
167
168 protected void verifyCumulativeProbabilities() {
169
170 for (int i = 0; i < cumulativeTestPoints.length; i++) {
171 TestUtils.assertEquals("Incorrect cumulative probability value returned for "
172 + cumulativeTestPoints[i], cumulativeTestValues[i],
173 distribution.cumulativeProbability(cumulativeTestPoints[i]),
174 getTolerance());
175 }
176
177 for (int i = 0; i < cumulativeTestPoints.length; i++) {
178 for (int j = 0; j < cumulativeTestPoints.length; j++) {
179 if (cumulativeTestPoints[i] <= cumulativeTestPoints[j]) {
180 TestUtils.assertEquals(cumulativeTestValues[j] - cumulativeTestValues[i],
181 distribution.probability(cumulativeTestPoints[i], cumulativeTestPoints[j]),
182 getTolerance());
183 } else {
184 try {
185 distribution.probability(cumulativeTestPoints[i], cumulativeTestPoints[j]);
186 } catch (NumberIsTooLargeException e) {
187 continue;
188 }
189 Assert.fail("distribution.probability(double, double) should have thrown an exception that second argument is too large");
190 }
191 }
192 }
193 }
194
195
196
197
198
199 protected void verifyInverseCumulativeProbabilities() {
200 for (int i = 0; i < inverseCumulativeTestPoints.length; i++) {
201 TestUtils.assertEquals("Incorrect inverse cumulative probability value returned for "
202 + inverseCumulativeTestPoints[i], inverseCumulativeTestValues[i],
203 distribution.inverseCumulativeProbability(inverseCumulativeTestPoints[i]),
204 getTolerance());
205 }
206 }
207
208
209
210
211 protected void verifyDensities() {
212 for (int i = 0; i < cumulativeTestPoints.length; i++) {
213 TestUtils.assertEquals("Incorrect probability density value returned for "
214 + cumulativeTestPoints[i], densityTestValues[i],
215 distribution.density(cumulativeTestPoints[i]),
216 getTolerance());
217 }
218 }
219
220
221
222
223 protected void verifyLogDensities() {
224 for (int i = 0; i < cumulativeTestPoints.length; i++) {
225 TestUtils.assertEquals("Incorrect probability density value returned for "
226 + cumulativeTestPoints[i], logDensityTestValues[i],
227 distribution.logDensity(cumulativeTestPoints[i]),
228 getTolerance());
229 }
230 }
231
232
233
234
235
236
237
238 @Test
239 public void testCumulativeProbabilities() {
240 verifyCumulativeProbabilities();
241 }
242
243
244
245
246
247 @Test
248 public void testInverseCumulativeProbabilities() {
249 verifyInverseCumulativeProbabilities();
250 }
251
252
253
254
255
256 @Test
257 public void testDensities() {
258 verifyDensities();
259 }
260
261
262
263
264
265 @Test
266 public void testLogDensities() {
267 verifyLogDensities();
268 }
269
270
271
272
273 @Test
274 public void testConsistency() {
275 for (int i=1; i < cumulativeTestPoints.length; i++) {
276
277
278 TestUtils.assertEquals(0d,
279 distribution.probability
280 (cumulativeTestPoints[i], cumulativeTestPoints[i]), tolerance);
281
282
283 double upper = JdkMath.max(cumulativeTestPoints[i], cumulativeTestPoints[i -1]);
284 double lower = JdkMath.min(cumulativeTestPoints[i], cumulativeTestPoints[i -1]);
285 double diff = distribution.cumulativeProbability(upper) -
286 distribution.cumulativeProbability(lower);
287 double direct = distribution.probability(lower, upper);
288 TestUtils.assertEquals("Inconsistent probability for ("
289 + lower + "," + upper + ")", diff, direct, tolerance);
290 }
291 }
292
293
294
295
296 @Test
297 public void testIllegalArguments() {
298 try {
299 distribution.probability(1, 0);
300 Assert.fail("Expecting MathIllegalArgumentException for bad cumulativeProbability interval");
301 } catch (MathIllegalArgumentException ex) {
302
303 }
304 try {
305 distribution.inverseCumulativeProbability(-1);
306 Assert.fail("Expecting MathIllegalArgumentException for p = -1");
307 } catch (MathIllegalArgumentException ex) {
308
309 }
310 try {
311 distribution.inverseCumulativeProbability(2);
312 Assert.fail("Expecting MathIllegalArgumentException for p = 2");
313 } catch (MathIllegalArgumentException ex) {
314
315 }
316 }
317
318
319
320
321 @Test
322 public void testSampler() {
323 final int sampleSize = 1000;
324 final ContinuousDistribution.Sampler sampler =
325 distribution.createSampler(RandomSource.WELL_19937_C.create(123456789L));
326 final double[] sample = AbstractRealDistribution.sample(sampleSize, sampler);
327 final double[] quartiles = TestUtils.getDistributionQuartiles(distribution);
328 final double[] expected = {250, 250, 250, 250};
329 final long[] counts = new long[4];
330
331 for (int i = 0; i < sampleSize; i++) {
332 TestUtils.updateCounts(sample[i], counts, quartiles);
333 }
334 TestUtils.assertChiSquareAccept(expected, counts, 0.001);
335 }
336
337
338
339
340
341
342
343
344
345 @Test
346 public void testDensityIntegrals() {
347 final double tol = 1.0e-9;
348 final BaseAbstractUnivariateIntegrator integrator =
349 new IterativeLegendreGaussIntegrator(5, 1.0e-12, 1.0e-10);
350 final UnivariateFunction d = new UnivariateFunction() {
351 @Override
352 public double value(double x) {
353 return distribution.density(x);
354 }
355 };
356 final ArrayList<Double> integrationTestPoints = new ArrayList<>();
357 for (int i = 0; i < cumulativeTestPoints.length; i++) {
358 if (Double.isNaN(cumulativeTestValues[i]) ||
359 cumulativeTestValues[i] < 1.0e-5 ||
360 cumulativeTestValues[i] > 1 - 1.0e-5) {
361 continue;
362 }
363 integrationTestPoints.add(cumulativeTestPoints[i]);
364 }
365 Collections.sort(integrationTestPoints);
366 for (int i = 1; i < integrationTestPoints.size(); i++) {
367 Assert.assertEquals(
368 distribution.probability(
369 integrationTestPoints.get(0), integrationTestPoints.get(i)),
370 integrator.integrate(
371 1000000,
372 d, integrationTestPoints.get(0),
373 integrationTestPoints.get(i)), tol);
374 }
375 }
376
377
378
379
380
381 protected double[] getCumulativeTestPoints() {
382 return cumulativeTestPoints;
383 }
384
385
386
387
388 protected void setCumulativeTestPoints(double[] cumulativeTestPoints) {
389 this.cumulativeTestPoints = cumulativeTestPoints;
390 }
391
392
393
394
395 protected double[] getCumulativeTestValues() {
396 return cumulativeTestValues;
397 }
398
399
400
401
402 protected void setCumulativeTestValues(double[] cumulativeTestValues) {
403 this.cumulativeTestValues = cumulativeTestValues;
404 }
405
406 protected double[] getDensityTestValues() {
407 return densityTestValues;
408 }
409
410 protected void setDensityTestValues(double[] densityTestValues) {
411 this.densityTestValues = densityTestValues;
412 }
413
414
415
416
417 protected ContinuousDistribution getDistribution() {
418 return distribution;
419 }
420
421
422
423
424 protected void setDistribution(ContinuousDistribution distribution) {
425 this.distribution = distribution;
426 }
427
428
429
430
431 protected double[] getInverseCumulativeTestPoints() {
432 return inverseCumulativeTestPoints;
433 }
434
435
436
437
438 protected void setInverseCumulativeTestPoints(double[] inverseCumulativeTestPoints) {
439 this.inverseCumulativeTestPoints = inverseCumulativeTestPoints;
440 }
441
442
443
444
445 protected double[] getInverseCumulativeTestValues() {
446 return inverseCumulativeTestValues;
447 }
448
449
450
451
452 protected void setInverseCumulativeTestValues(double[] inverseCumulativeTestValues) {
453 this.inverseCumulativeTestValues = inverseCumulativeTestValues;
454 }
455
456
457
458
459 protected double getTolerance() {
460 return tolerance;
461 }
462
463
464
465
466 protected void setTolerance(double tolerance) {
467 this.tolerance = tolerance;
468 }
469 }