View Javadoc

    1   /*
    2    * Copyright 2003-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.Beta;
    22  import org.apache.commons.math.util.MathUtils;
    23
    24  /***
    25   * The default implementation of {@link BinomialDistribution}.
    26   *
    27   * @version $Revision: 1.19 $ $Date: 2004/11/07 03:32:48 $
    28   */
    29  public class BinomialDistributionImpl
    30      extends AbstractIntegerDistribution
    31      implements BinomialDistribution, Serializable {
    32
    33      /*** Serializable version identifier */
    34      static final long serialVersionUID = 6751309484392813623L;
    35
    36      /*** The number of trials. */
    37      private int numberOfTrials;
    38
    39      /*** The probability of success. */
    40      private double probabilityOfSuccess;
    41
    42      /***
    43       * Create a binomial distribution with the given number of trials and
    44       * probability of success.
    45       * @param trials the number of trials.
    46       * @param p the probability of success.
    47       */
    48      public BinomialDistributionImpl(int trials, double p) {
    49          super();
    50          setNumberOfTrials(trials);
    51          setProbabilityOfSuccess(p);
    52      }
    53
    54      /***
    55       * Access the number of trials for this distribution.
    56       * @return the number of trials.
    57       */
    58      public int getNumberOfTrials() {
    59          return numberOfTrials;
    60      }
    61
    62      /***
    63       * Access the probability of success for this distribution.
    64       * @return the probability of success.
    65       */
    66      public double getProbabilityOfSuccess() {
    67          return probabilityOfSuccess;
    68      }
    69
    70      /***
    71       * Change the number of trials for this distribution.
    72       * @param trials the new number of trials.
    73       * @throws IllegalArgumentException if <code>trials</code> is not a valid
    74       *         number of trials.
    75       */
    76      public void setNumberOfTrials(int trials) {
    77          if (trials < 0) {
    78              throw new IllegalArgumentException("number of trials must be non-negative.");
    79          }
    80          numberOfTrials = trials;
    81      }
    82
    83      /***
    84       * Change the probability of success for this distribution.
    85       * @param p the new probability of success.
    86       * @throws IllegalArgumentException if <code>p</code> is not a valid
    87       *         probability.
    88       */
    89      public void setProbabilityOfSuccess(double p) {
    90          if (p < 0.0 || p > 1.0) {
    91              throw new IllegalArgumentException("probability of success must be between 0.0 and 1.0, inclusive.");
    92          }
    93          probabilityOfSuccess = p;
    94      }
    95
    96      /***
    97       * Access the domain value lower bound, based on <code>p</code>, used to
    98       * bracket a PDF root.
    99       *
    100      * @param p the desired probability for the critical value
    101      * @return domain value lower bound, i.e.
    102      *         P(X &lt; <i>lower bound</i>) &lt; <code>p</code>
    103      */
    104     protected int getDomainLowerBound(double p) {
    105         return -1;
    106     }
    107
    108     /***
    109      * Access the domain value upper bound, based on <code>p</code>, used to
    110      * bracket a PDF root.
    111      *
    112      * @param p the desired probability for the critical value
    113      * @return domain value upper bound, i.e.
    114      *         P(X &lt; <i>upper bound</i>) &gt; <code>p</code>
    115      */
    116     protected int getDomainUpperBound(double p) {
    117         return getNumberOfTrials();
    118     }
    119
    120     /***
    121      * For this distribution, X, this method returns P(X &le; x).
    122      * @param x the value at which the PDF is evaluated.
    123      * @return PDF for this distribution.
    124      * @throws MathException if the cumulative probability can not be
    125      *            computed due to convergence or other numerical errors.
    126      */
    127     public double cumulativeProbability(int x) throws MathException {
    128         double ret;
    129         if (x < 0) {
    130             ret = 0.0;
    131         } else if (x >= getNumberOfTrials()) {
    132             ret = 1.0;
    133         } else {
    134             ret =
    135                 1.0 - Beta.regularizedBeta(
    136                         getProbabilityOfSuccess(),
    137                         x + 1.0,
    138                         getNumberOfTrials() - x);
    139         }
    140         return ret;
    141     }
    142
    143     /***
    144      * For this disbution, X, this method returns P(X = x).
    145      *
    146      * @param x the value at which the PMF is evaluated.
    147      * @return PMF for this distribution.
    148      */
    149     public double probability(int x) {
    150         double ret;
    151         if (x < 0 || x > getNumberOfTrials()) {
    152             ret = 0.0;
    153         } else {
    154             ret = MathUtils.binomialCoefficientDouble(
    155             		getNumberOfTrials(), x) *
    156 				  Math.pow(getProbabilityOfSuccess(), x) *
    157 				  Math.pow(1.0 - getProbabilityOfSuccess(),
    158 				  		getNumberOfTrials() - x);
    159         }
    160         return ret;
    161     }
    162
    163     /***
    164      * For this distribution, X, this method returns the largest x, such
    165      * that P(X &le; x) &le; <code>p</code>.
    166      * <p>
    167      * Returns <code>-1</code> for p=0 and <code>Integer.MAX_VALUE</code> for
    168      * p=1.
    169      *
    170      * @param p the desired probability
    171      * @return the largest x such that P(X &le; x) <= p
    172      * @throws MathException if the inverse cumulative probability can not be
    173      *            computed due to convergence or other numerical errors.
    174      * @throws IllegalArgumentException if p < 0 or p > 1
    175      */
    176     public int inverseCumulativeProbability(final double p) throws MathException {
    177         // handle extreme values explicitly
    178         if (p == 0) {
    179             return -1;
    180         }
    181         if (p == 1) {
    182             return Integer.MAX_VALUE;
    183         }
    184
    185         // use default bisection impl
    186         return super.inverseCumulativeProbability(p);
    187     }
    188 }