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