View Javadoc

    1   /*
    2    * Copyright 2004 The Apache Software Foundation.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *      http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  package org.apache.commons.math.distribution;
    17
    18  import java.io.Serializable;
    19
    20  import org.apache.commons.math.MathException;
    21  import org.apache.commons.math.special.Gamma;
    22  import org.apache.commons.math.util.MathUtils;
    23
    24  /***
    25   * Implementation for the {@link PoissonDistribution}.
    26   *
    27   * @version $Revision: 355770 $ $Date: 2005-12-10 12:48:57 -0700 (Sat, 10 Dec 2005) $
    28   */
    29  public class PoissonDistributionImpl extends AbstractIntegerDistribution
    30          implements PoissonDistribution, Serializable {
    31
    32      /*** Serializable version identifier */
    33      private static final long serialVersionUID = -3349935121172596109L;
    34
    35      /***
    36       * Holds the Poisson mean for the distribution.
    37       */
    38      private double mean;
    39
    40      /***
    41       * Create a new Poisson distribution with the given the mean.
    42       * The mean value must be positive; otherwise an
    43       * <code>IllegalArgument</code> is thrown.
    44       *
    45       * @param p the Poisson mean
    46       * @throws IllegalArgumentException if p &le; 0
    47       */
    48      public PoissonDistributionImpl(double p) {
    49          super();
    50          setMean(p);
    51      }
    52
    53      /***
    54       * Get the Poisson mean for the distribution.
    55       *
    56       * @return the Poisson mean for the distribution.
    57       */
    58      public double getMean() {
    59          return this.mean;
    60      }
    61
    62      /***
    63       * Set the Poisson mean for the distribution.
    64       * The mean value must be positive; otherwise an
    65       * <code>IllegalArgument</code> is thrown.
    66       *
    67       * @param p the Poisson mean value
    68       * @throws IllegalArgumentException if p &le; 0
    69       */
    70      public void setMean(double p) {
    71          if (p <= 0) {
    72              throw new IllegalArgumentException(
    73                      "The Poisson mean must be positive");
    74          }
    75          this.mean = p;
    76      }
    77
    78      /***
    79       * The probability mass function P(X = x) for a Poisson distribution.
    80       *
    81       * @param x the value at which the probability density function is evaluated.
    82       * @return the value of the probability mass function at x
    83       */
    84      public double probability(int x) {
    85          if (x < 0 || x == Integer.MAX_VALUE) {
    86              return 0;
    87          }
    88          return Math.pow(getMean(), x) /
    89              MathUtils.factorialDouble(x) * Math.exp(-mean);
    90      }
    91
    92      /***
    93       * The probability distribution function P(X <= x) for a Poisson distribution.
    94       *
    95       * @param x the value at which the PDF is evaluated.
    96       * @return Poisson distribution function evaluated at x
    97       * @throws MathException if the cumulative probability can not be
    98       *            computed due to convergence or other numerical errors.
    99       */
    100     public double cumulativeProbability(int x) throws MathException {
    101         if (x < 0) {
    102             return 0;
    103         }
    104         if (x == Integer.MAX_VALUE) {
    105             return 1;
    106         }
    107         return Gamma.regularizedGammaQ((double)x + 1, mean,
    108                 1E-12, Integer.MAX_VALUE);
    109     }
    110
    111     /***
    112      * Calculates the Poisson distribution function using a normal
    113      * approximation.  The <code>N(mean, sqrt(mean))</code>
    114      * distribution is used to approximate the Poisson distribution.
    115      * <p>
    116      * The computation uses "half-correction" -- evaluating the normal
    117      * distribution function at <code>x + 0.5</code>
    118      *
    119      * @param x the upper bound, inclusive
    120      * @return the distribution function value calculated using a normal approximation
    121      * @throws MathException if an error occurs computing the normal approximation
    122      */
    123     public double normalApproximateProbability(int x) throws MathException {
    124         NormalDistribution normal = DistributionFactory.newInstance()
    125                 .createNormalDistribution(getMean(),
    126                         Math.sqrt(getMean()));
    127
    128         // calculate the probability using half-correction
    129         return normal.cumulativeProbability(x + 0.5);
    130     }
    131
    132     /***
    133      * Access the domain value lower bound, based on <code>p</code>, used to
    134      * bracket a CDF root.  This method is used by
    135      * {@link #inverseCumulativeProbability(double)} to find critical values.
    136      *
    137      * @param p the desired probability for the critical value
    138      * @return domain lower bound
    139      */
    140     protected int getDomainLowerBound(double p) {
    141         return 0;
    142     }
    143
    144     /***
    145      * Access the domain value upper bound, based on <code>p</code>, used to
    146      * bracket a CDF root.  This method is used by
    147      * {@link #inverseCumulativeProbability(double)} to find critical values.
    148      *
    149      * @param p the desired probability for the critical value
    150      * @return domain upper bound
    151      */
    152     protected int getDomainUpperBound(double p) {
    153         return Integer.MAX_VALUE;
    154     }
    155
    156 }