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 PascalDistribution}.
27   * @version $Revision: 617953 $ $Date: 2008-02-02 22:54:00 -0700 (Sat, 02 Feb 2008) $
28   * @since 1.2
29   */
30  public class PascalDistributionImpl extends AbstractIntegerDistribution
31      implements PascalDistribution, Serializable {
32  
33      /** Serializable version identifier */
34      private static final long serialVersionUID = 6751309484392813623L;
35  
36      /** The number of successes */
37      private int numberOfSuccesses;
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 r the number of successes
46       * @param p the probability of success
47       */
48      public PascalDistributionImpl(int r, double p) {
49          super();
50          setNumberOfSuccesses(r);
51          setProbabilityOfSuccess(p);
52      }
53  
54      /**
55       * Access the number of successes for this distribution.
56       * @return the number of successes
57       */
58      public int getNumberOfSuccesses() {
59          return numberOfSuccesses;
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 successes for this distribution.
72       * @param successes the new number of successes
73       * @throws IllegalArgumentException if <code>successes</code> is not
74       *         positive.
75       */
76      public void setNumberOfSuccesses(int successes) {
77          if (successes < 0) {
78              throw new IllegalArgumentException(
79                  "number of successes must be non-negative.");
80          }
81          numberOfSuccesses = successes;
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(
93                  "probability of success must be between 0.0 and 1.0, inclusive.");
94          }
95          probabilityOfSuccess = p;
96      }
97  
98      /**
99       * Access the domain value lower bound, based on <code>p</code>, used to
100      * bracket a PDF root.
101      * @param p the desired probability for the critical value
102      * @return domain value lower bound, i.e. P(X &lt; <i>lower bound</i>) &lt;
103      *         <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      * @param p the desired probability for the critical value
113      * @return domain value upper bound, i.e. P(X &lt; <i>upper bound</i>) &gt;
114      *         <code>p</code>
115      */
116     protected int getDomainUpperBound(double p) {
117         // use MAX - 1 because MAX causes loop
118         return Integer.MAX_VALUE - 1;
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 computed
126      *         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 {
133             ret = Beta.regularizedBeta(getProbabilityOfSuccess(),
134                 getNumberOfSuccesses(), x + 1);
135         }
136         return ret;
137     }
138 
139     /**
140      * For this distribution, X, this method returns P(X = x).
141      * @param x the value at which the PMF is evaluated
142      * @return PMF for this distribution
143      */
144     public double probability(int x) {
145         double ret;
146         if (x < 0) {
147             ret = 0.0;
148         } else {
149             ret = MathUtils.binomialCoefficientDouble(x +
150                   getNumberOfSuccesses() - 1, getNumberOfSuccesses() - 1) *
151                   Math.pow(getProbabilityOfSuccess(), getNumberOfSuccesses()) *
152                   Math.pow(1.0 - getProbabilityOfSuccess(), x);
153         }
154         return ret;
155     }
156 
157     /**
158      * For this distribution, X, this method returns the largest x, such that
159      * P(X &le; x) &le; <code>p</code>.
160      * <p>
161      * Returns <code>-1</code> for p=0 and <code>Integer.MAX_VALUE</code>
162      * for p=1.</p>
163      * @param p the desired probability
164      * @return the largest x such that P(X &le; x) <= p
165      * @throws MathException if the inverse cumulative probability can not be
166      *         computed due to convergence or other numerical errors.
167      * @throws IllegalArgumentException if p < 0 or p > 1
168      */
169     public int inverseCumulativeProbability(final double p)
170         throws MathException {
171         int ret;
172 
173         // handle extreme values explicitly
174         if (p == 0) {
175             ret = -1;
176         } else if (p == 1) {
177             ret = Integer.MAX_VALUE;
178         } else {
179             ret = super.inverseCumulativeProbability(p);
180         }
181 
182         return ret;
183     }
184 }