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 }