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.MathRuntimeException;
23  import org.apache.commons.math.special.Beta;
24  import org.apache.commons.math.util.MathUtils;
25  
26  /**
27   * The default implementation of {@link PascalDistribution}.
28   * @version $Revision: 772119 $ $Date: 2009-05-06 05:43:28 -0400 (Wed, 06 May 2009) $
29   * @since 1.2
30   */
31  public class PascalDistributionImpl extends AbstractIntegerDistribution
32      implements PascalDistribution, Serializable {
33  
34      /** Serializable version identifier */
35      private static final long serialVersionUID = 6751309484392813623L;
36  
37      /** The number of successes */
38      private int numberOfSuccesses;
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 r the number of successes
47       * @param p the probability of success
48       */
49      public PascalDistributionImpl(int r, double p) {
50          super();
51          setNumberOfSuccesses(r);
52          setProbabilityOfSuccess(p);
53      }
54  
55      /**
56       * Access the number of successes for this distribution.
57       * @return the number of successes
58       */
59      public int getNumberOfSuccesses() {
60          return numberOfSuccesses;
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 successes for this distribution.
73       * @param successes the new number of successes
74       * @throws IllegalArgumentException if <code>successes</code> is not
75       *         positive.
76       */
77      public void setNumberOfSuccesses(int successes) {
78          if (successes < 0) {
79              throw MathRuntimeException.createIllegalArgumentException(
80                    "number of successes must be non-negative ({0})",
81                    successes);
82          }
83          numberOfSuccesses = successes;
84      }
85  
86      /**
87       * Change the probability of success for this distribution.
88       * @param p the new probability of success
89       * @throws IllegalArgumentException if <code>p</code> is not a valid
90       *         probability.
91       */
92      public void setProbabilityOfSuccess(double p) {
93          if (p < 0.0 || p > 1.0) {
94              throw MathRuntimeException.createIllegalArgumentException(
95                    "{0} out of [{1}, {2}] range", p, 0.0, 1.0);
96          }
97          probabilityOfSuccess = p;
98      }
99  
100     /**
101      * Access the domain value lower bound, based on <code>p</code>, used to
102      * bracket a PDF root.
103      * @param p the desired probability for the critical value
104      * @return domain value lower bound, i.e. P(X &lt; <i>lower bound</i>) &lt;
105      *         <code>p</code>
106      */
107     @Override
108     protected int getDomainLowerBound(double p) {
109         return -1;
110     }
111 
112     /**
113      * Access the domain value upper bound, based on <code>p</code>, used to
114      * bracket a PDF root.
115      * @param p the desired probability for the critical value
116      * @return domain value upper bound, i.e. P(X &lt; <i>upper bound</i>) &gt;
117      *         <code>p</code>
118      */
119     @Override
120     protected int getDomainUpperBound(double p) {
121         // use MAX - 1 because MAX causes loop
122         return Integer.MAX_VALUE - 1;
123     }
124 
125     /**
126      * For this distribution, X, this method returns P(X &le; x).
127      * @param x the value at which the PDF is evaluated
128      * @return PDF for this distribution
129      * @throws MathException if the cumulative probability can not be computed
130      *         due to convergence or other numerical errors
131      */
132     @Override
133     public double cumulativeProbability(int x) throws MathException {
134         double ret;
135         if (x < 0) {
136             ret = 0.0;
137         } else {
138             ret = Beta.regularizedBeta(getProbabilityOfSuccess(),
139                 getNumberOfSuccesses(), x + 1);
140         }
141         return ret;
142     }
143 
144     /**
145      * For this distribution, X, this method returns P(X = x).
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) {
152             ret = 0.0;
153         } else {
154             ret = MathUtils.binomialCoefficientDouble(x +
155                   getNumberOfSuccesses() - 1, getNumberOfSuccesses() - 1) *
156                   Math.pow(getProbabilityOfSuccess(), getNumberOfSuccesses()) *
157                   Math.pow(1.0 - getProbabilityOfSuccess(), x);
158         }
159         return ret;
160     }
161 
162     /**
163      * For this distribution, X, this method returns the largest x, such that
164      * P(X &le; x) &le; <code>p</code>.
165      * <p>
166      * Returns <code>-1</code> for p=0 and <code>Integer.MAX_VALUE</code>
167      * for p=1.</p>
168      * @param p the desired probability
169      * @return the largest x such that P(X &le; x) <= p
170      * @throws MathException if the inverse cumulative probability can not be
171      *         computed due to convergence or other numerical errors.
172      * @throws IllegalArgumentException if p < 0 or p > 1
173      */
174     @Override
175     public int inverseCumulativeProbability(final double p)
176         throws MathException {
177         int ret;
178 
179         // handle extreme values explicitly
180         if (p == 0) {
181             ret = -1;
182         } else if (p == 1) {
183             ret = Integer.MAX_VALUE;
184         } else {
185             ret = super.inverseCumulativeProbability(p);
186         }
187 
188         return ret;
189     }
190 }