View Javadoc
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    *      https://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  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.distribution.discrete;
23  
24  import org.hipparchus.distribution.IntegerDistribution;
25  import org.hipparchus.exception.MathIllegalArgumentException;
26  import org.hipparchus.util.FastMath;
27  import org.junit.Assert;
28  import org.junit.Test;
29  
30  /**
31   * <code>PoissonDistributionTest</code>
32   */
33  public class PoissonDistributionTest extends IntegerDistributionAbstractTest {
34  
35      /**
36       * Poisson parameter value for the test distribution.
37       */
38      private static final double DEFAULT_TEST_POISSON_PARAMETER = 4.0;
39  
40      /**
41       * Constructor.
42       */
43      public PoissonDistributionTest() {
44          setTolerance(1e-12);
45      }
46  
47      /**
48       * Creates the default discrete distribution instance to use in tests.
49       */
50      @Override
51      public IntegerDistribution makeDistribution() {
52          return new PoissonDistribution(DEFAULT_TEST_POISSON_PARAMETER);
53      }
54  
55      /**
56       * Creates the default probability density test input values.
57       */
58      @Override
59      public int[] makeDensityTestPoints() {
60          return new int[] { -1, 0, 1, 2, 3, 4, 5, 10, 20};
61      }
62  
63      /**
64       * Creates the default probability density test expected values.
65       * These and all other test values are generated by R, version 1.8.1
66       */
67      @Override
68      public double[] makeDensityTestValues() {
69          return new double[] { 0d, 0.0183156388887d,  0.073262555555d,
70                  0.14652511111d, 0.195366814813d, 0.195366814813,
71                  0.156293451851d, 0.00529247667642d, 8.27746364655e-09};
72      }
73  
74      /**
75       * Creates the default logarithmic probability density test expected values.
76       * Reference values are from R, version 2.14.1.
77       */
78      @Override
79      public double[] makeLogDensityTestValues() {
80          return new double[] { Double.NEGATIVE_INFINITY, -4.000000000000d,
81                  -2.613705638880d, -1.920558458320d, -1.632876385868d,
82                  -1.632876385868d, -1.856019937183d, -5.241468961877d,
83                  -18.609729238356d};
84      }
85  
86      /**
87       * Creates the default cumulative probability density test input values.
88       */
89      @Override
90      public int[] makeCumulativeTestPoints() {
91          return new int[] { -1, 0, 1, 2, 3, 4, 5, 10, 20 };
92      }
93  
94      /**
95       * Creates the default cumulative probability density test expected values.
96       */
97      @Override
98      public double[] makeCumulativeTestValues() {
99          return new double[] { 0d,  0.0183156388887d, 0.0915781944437d,
100                 0.238103305554d, 0.433470120367d, 0.62883693518,
101                 0.78513038703d,  0.99716023388d, 0.999999998077 };
102     }
103 
104     /**
105      * Creates the default inverse cumulative probability test input values.
106      */
107     @Override
108     public double[] makeInverseCumulativeTestPoints() {
109         IntegerDistribution dist = getDistribution();
110         return new double[] { 0d, 0.018315638886d, 0.018315638890d,
111                 0.091578194441d, 0.091578194445d, 0.238103305552d,
112                 0.238103305556d, dist.cumulativeProbability(3),
113                 dist.cumulativeProbability(4), dist.cumulativeProbability(5),
114                 dist.cumulativeProbability(10), dist.cumulativeProbability(20)};
115     }
116 
117     /**
118      * Creates the default inverse cumulative probability density test expected values.
119      */
120     @Override
121     public int[] makeInverseCumulativeTestValues() {
122         return new int[] { 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 10, 20};
123     }
124 
125     /**
126      * Test the normal approximation of the Poisson distribution by
127      * calculating P(90 &le; X &le; 110) for X = Po(100) and
128      * P(9900 &le; X &le; 10200) for X  = Po(10000)
129      */
130     @Test
131     public void testNormalApproximateProbability() {
132         PoissonDistribution dist = new PoissonDistribution(100);
133         double result = dist.normalApproximateProbability(110)
134                 - dist.normalApproximateProbability(89);
135         Assert.assertEquals(0.706281887248, result, 1E-10);
136 
137         dist = new PoissonDistribution(10000);
138         result = dist.normalApproximateProbability(10200)
139         - dist.normalApproximateProbability(9899);
140         Assert.assertEquals(0.820070051552, result, 1E-10);
141     }
142 
143     /**
144      * Test the degenerate cases of a 0.0 and 1.0 inverse cumulative probability.
145      */
146     @Test
147     public void testDegenerateInverseCumulativeProbability() {
148         PoissonDistribution dist = new PoissonDistribution(DEFAULT_TEST_POISSON_PARAMETER);
149         Assert.assertEquals(Integer.MAX_VALUE, dist.inverseCumulativeProbability(1.0d));
150         Assert.assertEquals(0, dist.inverseCumulativeProbability(0d));
151     }
152 
153     @Test(expected=MathIllegalArgumentException.class)
154     public void testNegativeMean() {
155         new PoissonDistribution(-1);
156     }
157 
158     @Test
159     public void testMean() {
160         PoissonDistribution dist = new PoissonDistribution(10.0);
161         Assert.assertEquals(10.0, dist.getMean(), 0.0);
162     }
163 
164     @Test
165     public void testLargeMeanCumulativeProbability() {
166         double mean = 1.0;
167         while (mean <= 10000000.0) {
168             PoissonDistribution dist = new PoissonDistribution(mean);
169 
170             double x = mean * 2.0;
171             double dx = x / 10.0;
172             double p = Double.NaN;
173             double sigma = FastMath.sqrt(mean);
174             while (x >= 0) {
175                 try {
176                     p = dist.cumulativeProbability((int) x);
177                     Assert.assertFalse("NaN cumulative probability returned for mean = " +
178                             mean + " x = " + x,Double.isNaN(p));
179                     if (x > mean - 2 * sigma) {
180                         Assert.assertTrue("Zero cum probaility returned for mean = " +
181                                 mean + " x = " + x, p > 0);
182                     }
183                 } catch (Exception ex) {
184                     Assert.fail("mean of " + mean + " and x of " + x + " caused " + ex.getMessage());
185                 }
186                 x -= dx;
187             }
188 
189             mean *= 10.0;
190         }
191     }
192 
193     /**
194      * JIRA: MATH-282
195      */
196     @Test
197     public void testCumulativeProbabilitySpecial() {
198         PoissonDistribution dist;
199         dist = new PoissonDistribution(9120);
200         checkProbability(dist, 9075);
201         checkProbability(dist, 9102);
202         dist = new PoissonDistribution(5058);
203         checkProbability(dist, 5044);
204         dist = new PoissonDistribution(6986);
205         checkProbability(dist, 6950);
206     }
207 
208     private void checkProbability(PoissonDistribution dist, int x) {
209         double p = dist.cumulativeProbability(x);
210         Assert.assertFalse("NaN cumulative probability returned for mean = " +
211                 dist.getMean() + " x = " + x, Double.isNaN(p));
212         Assert.assertTrue("Zero cum probability returned for mean = " +
213                 dist.getMean() + " x = " + x, p > 0);
214     }
215 
216     @Test
217     public void testLargeMeanInverseCumulativeProbability() {
218         double mean = 1.0;
219         while (mean <= 100000.0) { // Extended test value: 1E7.  Reduced to limit run time.
220             PoissonDistribution dist = new PoissonDistribution(mean);
221             double p = 0.1;
222             double dp = p;
223             while (p < .99) {
224                 try {
225                     int ret = dist.inverseCumulativeProbability(p);
226                     // Verify that returned value satisties definition
227                     Assert.assertTrue(p <= dist.cumulativeProbability(ret));
228                     Assert.assertTrue(p > dist.cumulativeProbability(ret - 1));
229                 } catch (Exception ex) {
230                     Assert.fail("mean of " + mean + " and p of " + p + " caused " + ex.getMessage());
231                 }
232                 p += dp;
233             }
234             mean *= 10.0;
235         }
236     }
237 
238     @Test
239     public void testMoments() {
240         final double tol = 1e-9;
241         PoissonDistribution dist;
242 
243         dist = new PoissonDistribution(1);
244         Assert.assertEquals(dist.getNumericalMean(), 1, tol);
245         Assert.assertEquals(dist.getNumericalVariance(), 1, tol);
246 
247         dist = new PoissonDistribution(11.23);
248         Assert.assertEquals(dist.getNumericalMean(), 11.23, tol);
249         Assert.assertEquals(dist.getNumericalVariance(), 11.23, tol);
250     }
251 }