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: 348519 $ $Date: 2005-11-23 12:12:18 -0700 (Wed, 23 Nov 2005) $
28   */
29  public class BinomialDistributionImpl
30      extends AbstractIntegerDistribution
31      implements BinomialDistribution, Serializable {
32  
33      /** Serializable version identifier */
34      private 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 }