1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.math.distribution;
18  
19  import junit.framework.TestCase;
20  
21  /**
22   * Abstract base class for {@link IntegerDistribution} tests.
23   * <p>
24   * To create a concrete test class for an integer distribution implementation,
25   *  implement makeDistribution() to return a distribution instance to use in 
26   *  tests and each of the test data generation methods below.  In each case, the
27   *  test points and test values arrays returned represent parallel arrays of 
28   *  inputs and expected values for the distribution returned by makeDistribution().
29   *  <p>
30   *  makeDensityTestPoints() -- arguments used to test probability density calculation
31   *  makeDensityTestValues() -- expected probability densities
32   *  makeCumulativeTestPoints() -- arguments used to test cumulative probabilities
33   *  makeCumulativeTestValues() -- expected cumulative probabilites
34   *  makeInverseCumulativeTestPoints() -- arguments used to test inverse cdf evaluation
35   *  makeInverseCumulativeTestValues() -- expected inverse cdf values
36   * <p>
37   *  To implement additional test cases with different distribution instances and test data,
38   *  use the setXxx methods for the instance data in test cases and call the verifyXxx methods
39   *  to verify results. 
40   * 
41   * @version $Revision: 762118 $ $Date: 2009-04-05 12:55:59 -0400 (Sun, 05 Apr 2009) $
42   */
43  public abstract class IntegerDistributionAbstractTest extends TestCase {
44      
45  //-------------------- Private test instance data -------------------------
46      /** Discrete distribution instance used to perform tests */
47      private IntegerDistribution distribution;
48      
49      /** Tolerance used in comparing expected and returned values */
50      private double tolerance = 1E-4;
51      
52      /** Arguments used to test probability density calculations */
53      private int[] densityTestPoints;
54      
55      /** Values used to test probability density calculations */
56      private double[] densityTestValues;
57      
58      /** Arguments used to test cumulative probability density calculations */
59      private int[] cumulativeTestPoints;
60      
61      /** Values used to test cumulative probability density calculations */
62      private double[] cumulativeTestValues;
63      
64      /** Arguments used to test inverse cumulative probability density calculations */
65      private double[] inverseCumulativeTestPoints;
66      
67      /** Values used to test inverse cumulative probability density calculations */
68      private int[] inverseCumulativeTestValues;
69      
70      //-------------------------------------------------------------------------
71      
72      /**
73       * Constructor for IntegerDistributionAbstractTest.
74       * @param name
75       */
76      public IntegerDistributionAbstractTest(String name) {
77          super(name);
78      }
79      
80      //-------------------- Abstract methods -----------------------------------
81      
82      /** Creates the default discrete distribution instance to use in tests. */
83      public abstract IntegerDistribution makeDistribution();
84      
85      /** Creates the default probability density test input values */
86      public abstract int[] makeDensityTestPoints();
87      
88      /** Creates the default probability density test expected values */
89      public abstract double[] makeDensityTestValues();
90      
91      /** Creates the default cumulative probability density test input values */
92      public abstract int[] makeCumulativeTestPoints();
93      
94      /** Creates the default cumulative probability density test expected values */
95      public abstract double[] makeCumulativeTestValues();
96      
97      /** Creates the default inverse cumulative probability test input values */
98      public abstract double[] makeInverseCumulativeTestPoints();
99      
100     /** Creates the default inverse cumulative probability density test expected values */
101     public abstract int[] makeInverseCumulativeTestValues();
102     
103     //-------------------- Setup / tear down ----------------------------------
104      
105     /**
106      * Setup sets all test instance data to default values 
107      */
108     @Override
109     protected void setUp() throws Exception {
110         super.setUp();
111         distribution = makeDistribution();
112         densityTestPoints = makeDensityTestPoints();
113         densityTestValues = makeDensityTestValues();
114         cumulativeTestPoints = makeCumulativeTestPoints();
115         cumulativeTestValues = makeCumulativeTestValues();
116         inverseCumulativeTestPoints = makeInverseCumulativeTestPoints();
117         inverseCumulativeTestValues = makeInverseCumulativeTestValues();   
118     }
119     
120     /**
121      * Cleans up test instance data
122      */
123     @Override
124     protected void tearDown() throws Exception {      
125         super.tearDown();
126         distribution = null;
127         densityTestPoints = null;
128         densityTestValues = null;
129         cumulativeTestPoints = null;
130         cumulativeTestValues = null;
131         inverseCumulativeTestPoints = null;
132         inverseCumulativeTestValues = null;   
133     }
134     
135     //-------------------- Verification methods -------------------------------
136     
137     /**
138      * Verifies that probability density calculations match expected values
139      * using current test instance data
140      */
141     protected void verifyDensities() throws Exception {
142         for (int i = 0; i < densityTestPoints.length; i++) {
143             assertEquals("Incorrect density value returned for " + densityTestPoints[i],
144                     densityTestValues[i], 
145                     distribution.probability(densityTestPoints[i]), tolerance);
146         }     
147     }
148     
149     /**
150      * Verifies that cumulative probability density calculations match expected values
151      * using current test instance data
152      */   
153     protected void verifyCumulativeProbabilities() throws Exception {
154         for (int i = 0; i < cumulativeTestPoints.length; i++) {
155             assertEquals("Incorrect cumulative probability value returned for " + cumulativeTestPoints[i],
156                     cumulativeTestValues[i], 
157                     distribution.cumulativeProbability(cumulativeTestPoints[i]), tolerance);
158         }           
159     }
160     
161     
162     /**
163      * Verifies that inverse cumulative probability density calculations match expected values
164      * using current test instance data
165      */
166     protected void verifyInverseCumulativeProbabilities() throws Exception {
167         for (int i = 0; i < inverseCumulativeTestPoints.length; i++) {
168             assertEquals("Incorrect inverse cumulative probability value returned for " 
169                     + inverseCumulativeTestPoints[i], inverseCumulativeTestValues[i], 
170                     distribution.inverseCumulativeProbability(inverseCumulativeTestPoints[i]));
171         }           
172     }
173     
174     //------------------------ Default test cases -----------------------------
175 
176     /**
177      * Verifies that probability density calculations match expected values
178      * using default test instance data
179      */
180     public void testDensities() throws Exception {
181         verifyDensities();     
182     }
183     
184     /**
185      * Verifies that cumulative probability density calculations match expected values
186      * using default test instance data
187      */
188     public void testCumulativeProbabilities() throws Exception {
189         verifyCumulativeProbabilities();      
190     }
191     
192     /**
193      * Verifies that floating point arguments are correctly handled by
194      * cumulativeProbablility(-,-)
195      * JIRA: MATH-184
196      */
197     public void testFloatingPointArguments() throws Exception {
198         for (int i = 0; i < cumulativeTestPoints.length; i++) {
199             double arg = cumulativeTestPoints[i];
200             assertEquals(
201                     "Incorrect cumulative probability value returned for " +
202                     cumulativeTestPoints[i],
203                     cumulativeTestValues[i], 
204                     distribution.cumulativeProbability(arg), tolerance);
205             if (i < cumulativeTestPoints.length - 1) {
206                 double arg2 = cumulativeTestPoints[i + 1];
207                 assertEquals("Inconsistent probability for discrete range " +
208                         "[ " + arg + "," + arg2 + " ]",
209                    distribution.cumulativeProbability(
210                            cumulativeTestPoints[i],
211                            cumulativeTestPoints[i + 1]),
212                    distribution.cumulativeProbability(arg, arg2), tolerance);
213                 arg = arg - Math.random();
214                 arg2 = arg2 + Math.random();
215                 assertEquals("Inconsistent probability for discrete range " +
216                         "[ " + arg + "," + arg2 + " ]",
217                    distribution.cumulativeProbability(
218                            cumulativeTestPoints[i],
219                            cumulativeTestPoints[i + 1]),
220                    distribution.cumulativeProbability(arg, arg2), tolerance);
221             }
222         } 
223         int one = 1;
224         int ten = 10;
225         int two = 2;
226         double oned = one;
227         double twod = two;
228         double tend = ten;
229         assertEquals(distribution.cumulativeProbability(one, two), 
230                 distribution.cumulativeProbability(oned, twod), tolerance);
231         assertEquals(distribution.cumulativeProbability(one, two), 
232                 distribution.cumulativeProbability(oned - tolerance,
233                         twod + 0.9), tolerance);
234         assertEquals(distribution.cumulativeProbability(two, ten), 
235                 distribution.cumulativeProbability(twod, tend), tolerance);
236         assertEquals(distribution.cumulativeProbability(two, ten), 
237                 distribution.cumulativeProbability(twod - tolerance,
238                         tend + 0.9), tolerance);
239     }
240     
241     /**
242      * Verifies that inverse cumulative probability density calculations match expected values
243      * using default test instance data
244      */
245     public void testInverseCumulativeProbabilities() throws Exception {
246         verifyInverseCumulativeProbabilities();       
247     }
248     
249     /**
250      * Verifies that illegal arguments are correctly handled
251      */
252     public void testIllegalArguments() throws Exception {
253         try {
254             distribution.cumulativeProbability(1, 0);
255             fail("Expecting IllegalArgumentException for bad cumulativeProbability interval");
256         } catch (IllegalArgumentException ex) {
257             // expected
258         }
259         try {
260             distribution.inverseCumulativeProbability(-1);
261             fail("Expecting IllegalArgumentException for p = -1");
262         } catch (IllegalArgumentException ex) {
263             // expected
264         }
265         try {
266             distribution.inverseCumulativeProbability(2);
267             fail("Expecting IllegalArgumentException for p = 2");
268         } catch (IllegalArgumentException ex) {
269             // expected
270         }       
271     }
272     
273     //------------------ Getters / Setters for test instance data -----------
274     /**
275      * @return Returns the cumulativeTestPoints.
276      */
277     protected int[] getCumulativeTestPoints() {
278         return cumulativeTestPoints;
279     }
280 
281     /**
282      * @param cumulativeTestPoints The cumulativeTestPoints to set.
283      */
284     protected void setCumulativeTestPoints(int[] cumulativeTestPoints) {
285         this.cumulativeTestPoints = cumulativeTestPoints;
286     }
287 
288     /**
289      * @return Returns the cumulativeTestValues.
290      */
291     protected double[] getCumulativeTestValues() {
292         return cumulativeTestValues;
293     }
294 
295     /**
296      * @param cumulativeTestValues The cumulativeTestValues to set.
297      */
298     protected void setCumulativeTestValues(double[] cumulativeTestValues) {
299         this.cumulativeTestValues = cumulativeTestValues;
300     }
301 
302     /**
303      * @return Returns the densityTestPoints.
304      */
305     protected int[] getDensityTestPoints() {
306         return densityTestPoints;
307     }
308 
309     /**
310      * @param densityTestPoints The densityTestPoints to set.
311      */
312     protected void setDensityTestPoints(int[] densityTestPoints) {
313         this.densityTestPoints = densityTestPoints;
314     }
315 
316     /**
317      * @return Returns the densityTestValues.
318      */
319     protected double[] getDensityTestValues() {
320         return densityTestValues;
321     }
322 
323     /**
324      * @param densityTestValues The densityTestValues to set.
325      */
326     protected void setDensityTestValues(double[] densityTestValues) {
327         this.densityTestValues = densityTestValues;
328     }
329 
330     /**
331      * @return Returns the distribution.
332      */
333     protected IntegerDistribution getDistribution() {
334         return distribution;
335     }
336 
337     /**
338      * @param distribution The distribution to set.
339      */
340     protected void setDistribution(IntegerDistribution distribution) {
341         this.distribution = distribution;
342     }
343 
344     /**
345      * @return Returns the inverseCumulativeTestPoints.
346      */
347     protected double[] getInverseCumulativeTestPoints() {
348         return inverseCumulativeTestPoints;
349     }
350 
351     /**
352      * @param inverseCumulativeTestPoints The inverseCumulativeTestPoints to set.
353      */
354     protected void setInverseCumulativeTestPoints(double[] inverseCumulativeTestPoints) {
355         this.inverseCumulativeTestPoints = inverseCumulativeTestPoints;
356     }
357 
358     /**
359      * @return Returns the inverseCumulativeTestValues.
360      */
361     protected int[] getInverseCumulativeTestValues() {
362         return inverseCumulativeTestValues;
363     }
364 
365     /**
366      * @param inverseCumulativeTestValues The inverseCumulativeTestValues to set.
367      */
368     protected void setInverseCumulativeTestValues(int[] inverseCumulativeTestValues) {
369         this.inverseCumulativeTestValues = inverseCumulativeTestValues;
370     }
371 
372     /**
373      * @return Returns the tolerance.
374      */
375     protected double getTolerance() {
376         return tolerance;
377     }
378 
379     /**
380      * @param tolerance The tolerance to set.
381      */
382     protected void setTolerance(double tolerance) {
383         this.tolerance = tolerance;
384     }
385 
386 }