001: /*
002: * Copyright 2003-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.math.distribution;
017:
018: import java.io.Serializable;
019:
020: import org.apache.commons.math.MathException;
021: import org.apache.commons.math.special.Beta;
022: import org.apache.commons.math.util.MathUtils;
023:
024: /**
025: * The default implementation of {@link BinomialDistribution}.
026: *
027: * @version $Revision: 348519 $ $Date: 2005-11-23 12:12:18 -0700 (Wed, 23 Nov 2005) $
028: */
029: public class BinomialDistributionImpl extends
030: AbstractIntegerDistribution implements BinomialDistribution,
031: Serializable {
032:
033: /** Serializable version identifier */
034: private static final long serialVersionUID = 6751309484392813623L;
035:
036: /** The number of trials. */
037: private int numberOfTrials;
038:
039: /** The probability of success. */
040: private double probabilityOfSuccess;
041:
042: /**
043: * Create a binomial distribution with the given number of trials and
044: * probability of success.
045: * @param trials the number of trials.
046: * @param p the probability of success.
047: */
048: public BinomialDistributionImpl(int trials, double p) {
049: super ();
050: setNumberOfTrials(trials);
051: setProbabilityOfSuccess(p);
052: }
053:
054: /**
055: * Access the number of trials for this distribution.
056: * @return the number of trials.
057: */
058: public int getNumberOfTrials() {
059: return numberOfTrials;
060: }
061:
062: /**
063: * Access the probability of success for this distribution.
064: * @return the probability of success.
065: */
066: public double getProbabilityOfSuccess() {
067: return probabilityOfSuccess;
068: }
069:
070: /**
071: * Change the number of trials for this distribution.
072: * @param trials the new number of trials.
073: * @throws IllegalArgumentException if <code>trials</code> is not a valid
074: * number of trials.
075: */
076: public void setNumberOfTrials(int trials) {
077: if (trials < 0) {
078: throw new IllegalArgumentException(
079: "number of trials must be non-negative.");
080: }
081: numberOfTrials = trials;
082: }
083:
084: /**
085: * Change the probability of success for this distribution.
086: * @param p the new probability of success.
087: * @throws IllegalArgumentException if <code>p</code> is not a valid
088: * probability.
089: */
090: public void setProbabilityOfSuccess(double p) {
091: if (p < 0.0 || p > 1.0) {
092: throw new IllegalArgumentException(
093: "probability of success must be between 0.0 and 1.0, inclusive.");
094: }
095: probabilityOfSuccess = p;
096: }
097:
098: /**
099: * Access the domain value lower bound, based on <code>p</code>, used to
100: * bracket a PDF root.
101: *
102: * @param p the desired probability for the critical value
103: * @return domain value lower bound, i.e.
104: * P(X < <i>lower bound</i>) < <code>p</code>
105: */
106: protected int getDomainLowerBound(double p) {
107: return -1;
108: }
109:
110: /**
111: * Access the domain value upper bound, based on <code>p</code>, used to
112: * bracket a PDF root.
113: *
114: * @param p the desired probability for the critical value
115: * @return domain value upper bound, i.e.
116: * P(X < <i>upper bound</i>) > <code>p</code>
117: */
118: protected int getDomainUpperBound(double p) {
119: return getNumberOfTrials();
120: }
121:
122: /**
123: * For this distribution, X, this method returns P(X ≤ x).
124: * @param x the value at which the PDF is evaluated.
125: * @return PDF for this distribution.
126: * @throws MathException if the cumulative probability can not be
127: * computed due to convergence or other numerical errors.
128: */
129: public double cumulativeProbability(int x) throws MathException {
130: double ret;
131: if (x < 0) {
132: ret = 0.0;
133: } else if (x >= getNumberOfTrials()) {
134: ret = 1.0;
135: } else {
136: ret = 1.0 - Beta.regularizedBeta(getProbabilityOfSuccess(),
137: x + 1.0, getNumberOfTrials() - x);
138: }
139: return ret;
140: }
141:
142: /**
143: * For this disbution, X, this method returns P(X = x).
144: *
145: * @param x the value at which the PMF is evaluated.
146: * @return PMF for this distribution.
147: */
148: public double probability(int x) {
149: double ret;
150: if (x < 0 || x > getNumberOfTrials()) {
151: ret = 0.0;
152: } else {
153: ret = MathUtils.binomialCoefficientDouble(
154: getNumberOfTrials(), x)
155: * Math.pow(getProbabilityOfSuccess(), x)
156: * Math.pow(1.0 - getProbabilityOfSuccess(),
157: getNumberOfTrials() - x);
158: }
159: return ret;
160: }
161:
162: /**
163: * For this distribution, X, this method returns the largest x, such
164: * that P(X ≤ x) ≤ <code>p</code>.
165: * <p>
166: * Returns <code>-1</code> for p=0 and <code>Integer.MAX_VALUE</code> for
167: * p=1.
168: *
169: * @param p the desired probability
170: * @return the largest x such that P(X ≤ x) <= p
171: * @throws MathException if the inverse cumulative probability can not be
172: * computed due to convergence or other numerical errors.
173: * @throws IllegalArgumentException if p < 0 or p > 1
174: */
175: public int inverseCumulativeProbability(final double p)
176: 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: }
|