001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     * 
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.math.distribution;
018    
019    import org.apache.commons.math.MathException;
020    
021    /**
022     * <code>PoissonDistributionTest</code>
023     * 
024     * @version $Revision: 762087 $ $Date: 2009-04-05 10:20:18 -0400 (Sun, 05 Apr 2009) $
025     */
026    public class PoissonDistributionTest extends IntegerDistributionAbstractTest {
027    
028        /**
029         * Poisson parameter value for the test distribution.
030         */
031        private static final double DEFAULT_TEST_POISSON_PARAMETER = 4.0;
032    
033        /**
034         * Constructor.
035         * @param name
036         */
037        public PoissonDistributionTest(String name) {
038            super(name);
039            setTolerance(1e-12);
040        }
041    
042        /** 
043         * Creates the default discrete distribution instance to use in tests. 
044         */
045        @Override
046        public IntegerDistribution makeDistribution() {
047            return new PoissonDistributionImpl(DEFAULT_TEST_POISSON_PARAMETER);  
048        }
049    
050        /** 
051         * Creates the default probability density test input values.
052         */
053        @Override
054        public int[] makeDensityTestPoints() {
055            return new int[] { -1, 0, 1, 2, 3, 4, 5, 10, 20};
056        }
057    
058        /**
059         * Creates the default probability density test expected values.
060         * These and all other test values are generated by R, version 1.8.1
061         */
062        @Override
063        public double[] makeDensityTestValues() {
064            return new double[] { 0d, 0.0183156388887d,  0.073262555555d,
065                    0.14652511111d, 0.195366814813d, 0.195366814813, 
066                    0.156293451851d, 0.00529247667642d, 8.27746364655e-09};
067        }
068    
069        /**
070         * Creates the default cumulative probability density test input values.
071         */
072        @Override
073        public int[] makeCumulativeTestPoints() {
074            return new int[] { -1, 0, 1, 2, 3, 4, 5, 10, 20 };
075        }
076    
077        /**
078         * Creates the default cumulative probability density test expected values.
079         */
080        @Override
081        public double[] makeCumulativeTestValues() {
082            return new double[] { 0d,  0.0183156388887d, 0.0915781944437d, 
083                    0.238103305554d, 0.433470120367d, 0.62883693518,
084                    0.78513038703d,  0.99716023388d, 0.999999998077 };
085        }
086    
087        /** 
088         * Creates the default inverse cumulative probability test input values.
089         * Increased 3rd and 7th values slightly as computed cumulative
090         * probabilities for corresponding values exceeds the target value (still 
091         * within tolerance).
092         */
093        @Override
094        public double[] makeInverseCumulativeTestPoints() {
095            return new double[] { 0d,  0.018315638889d, 0.0915781944437d, 
096                    0.238103305554d, 0.433470120367d, 0.62883693518,
097                    0.78513038704d,  0.99716023388d, 0.999999998077 };
098        }
099    
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    }