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 org.apache.commons.math.MathException;
20  
21  /**
22   * <code>PoissonDistributionTest</code>
23   * 
24   * @version $Revision: 762087 $ $Date: 2009-04-05 10:20:18 -0400 (Sun, 05 Apr 2009) $
25   */
26  public class PoissonDistributionTest extends IntegerDistributionAbstractTest {
27  
28      /**
29       * Poisson parameter value for the test distribution.
30       */
31      private static final double DEFAULT_TEST_POISSON_PARAMETER = 4.0;
32  
33      /**
34       * Constructor.
35       * @param name
36       */
37      public PoissonDistributionTest(String name) {
38          super(name);
39          setTolerance(1e-12);
40      }
41  
42      /** 
43       * Creates the default discrete distribution instance to use in tests. 
44       */
45      @Override
46      public IntegerDistribution makeDistribution() {
47          return new PoissonDistributionImpl(DEFAULT_TEST_POISSON_PARAMETER);  
48      }
49  
50      /** 
51       * Creates the default probability density test input values.
52       */
53      @Override
54      public int[] makeDensityTestPoints() {
55          return new int[] { -1, 0, 1, 2, 3, 4, 5, 10, 20};
56      }
57  
58      /**
59       * Creates the default probability density test expected values.
60       * These and all other test values are generated by R, version 1.8.1
61       */
62      @Override
63      public double[] makeDensityTestValues() {
64          return new double[] { 0d, 0.0183156388887d,  0.073262555555d,
65                  0.14652511111d, 0.195366814813d, 0.195366814813, 
66                  0.156293451851d, 0.00529247667642d, 8.27746364655e-09};
67      }
68  
69      /**
70       * Creates the default cumulative probability density test input values.
71       */
72      @Override
73      public int[] makeCumulativeTestPoints() {
74          return new int[] { -1, 0, 1, 2, 3, 4, 5, 10, 20 };
75      }
76  
77      /**
78       * Creates the default cumulative probability density test expected values.
79       */
80      @Override
81      public double[] makeCumulativeTestValues() {
82          return new double[] { 0d,  0.0183156388887d, 0.0915781944437d, 
83                  0.238103305554d, 0.433470120367d, 0.62883693518,
84                  0.78513038703d,  0.99716023388d, 0.999999998077 };
85      }
86  
87      /** 
88       * Creates the default inverse cumulative probability test input values.
89       * Increased 3rd and 7th values slightly as computed cumulative
90       * probabilities for corresponding values exceeds the target value (still 
91       * within tolerance).
92       */
93      @Override
94      public double[] makeInverseCumulativeTestPoints() {
95          return new double[] { 0d,  0.018315638889d, 0.0915781944437d, 
96                  0.238103305554d, 0.433470120367d, 0.62883693518,
97                  0.78513038704d,  0.99716023388d, 0.999999998077 };
98      }
99  
100     /**
101      * Creates the default inverse cumulative probability density test expected values.
102      */
103     @Override
104     public int[] makeInverseCumulativeTestValues() {
105         return new int[] { -1, 0, 1, 2, 3, 4, 5, 10, 20};
106     }
107 
108     /**
109      * Test the normal approximation of the Poisson distribution by
110      * calculating P(90 &le; X &le; 110) for X = Po(100) and
111      * P(9900 &le; X &le; 10200) for X  = Po(10000)
112      */
113     public void testNormalApproximateProbability() throws Exception {
114         PoissonDistribution dist = new PoissonDistributionImpl(100);
115         double result = dist.normalApproximateProbability(110)
116                 - dist.normalApproximateProbability(89);
117         assertEquals(0.706281887248, result, 1E-10);
118         dist.setMean(10000);
119         result = dist.normalApproximateProbability(10200)
120         - dist.normalApproximateProbability(9899);
121         assertEquals(0.820070051552, result, 1E-10);
122     }
123 
124     /**
125      * Test the degenerate cases of a 0.0 and 1.0 inverse cumulative probability.
126      * @throws Exception
127      */
128     public void testDegenerateInverseCumulativeProbability() throws Exception {
129         PoissonDistribution dist = new PoissonDistributionImpl(DEFAULT_TEST_POISSON_PARAMETER);
130         assertEquals(Integer.MAX_VALUE, dist.inverseCumulativeProbability(1.0d));
131         assertEquals(-1, dist.inverseCumulativeProbability(0d));
132     }
133     
134     public void testMean() {
135         PoissonDistribution dist = new PoissonDistributionImpl(DEFAULT_TEST_POISSON_PARAMETER);
136         try {
137             dist.setMean(-1);
138             fail("negative mean.  IllegalArgumentException expected");
139         } catch(IllegalArgumentException ex) {
140         }
141         
142         dist.setMean(10.0);
143         assertEquals(10.0, dist.getMean(), 0.0);
144     }
145     
146     public void testLargeMeanCumulativeProbability() {
147         PoissonDistribution dist = new PoissonDistributionImpl(1.0);
148         double mean = 1.0;
149         while (mean <= 10000000.0) {
150             dist.setMean(mean);
151             
152             double x = mean * 2.0;
153             double dx = x / 10.0;
154             while (x >= 0) {
155                 try {
156                     dist.cumulativeProbability(x);
157                 } catch (MathException ex) {
158                     fail("mean of " + mean + " and x of " + x + " caused " + ex.getMessage());
159                 }
160                 x -= dx;
161             }
162             
163             mean *= 10.0;
164         }
165     }
166     
167     public void testLargeMeanInverseCumulativeProbability() {
168         PoissonDistribution dist = new PoissonDistributionImpl(1.0);
169         double mean = 1.0;
170         while (mean <= 10000000.0) {
171             dist.setMean(mean);
172             
173             double p = 0.1;
174             double dp = p;
175             while (p < 1.0) {
176                 try {
177                     dist.inverseCumulativeProbability(p);
178                 } catch (MathException ex) {
179                     fail("mean of " + mean + " and p of " + p + " caused " + ex.getMessage());
180                 }
181                 p += dp;
182             }
183             
184             mean *= 10.0;
185         }
186     }
187 }