From 55b2cc8c039d659da8f4d8af332814043d084a3b Mon Sep 17 00:00:00 2001 From: Brent Worden Date: Thu, 5 Apr 2007 14:48:48 +0000 Subject: [PATCH] MATH-120: finished review of pascal distribution. git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/math/trunk@525837 13f79535-47bb-0310-9956-ffa450edef68 --- .../distribution/DistributionFactory.java | 7 +- .../distribution/DistributionFactoryImpl.java | 13 --- .../math/distribution/PascalDistribution.java | 13 ++- .../distribution/PascalDistributionImpl.java | 98 +++++++++---------- 4 files changed, 61 insertions(+), 70 deletions(-) diff --git a/src/java/org/apache/commons/math/distribution/DistributionFactory.java b/src/java/org/apache/commons/math/distribution/DistributionFactory.java index 58d75dabe..bb6c713f9 100644 --- a/src/java/org/apache/commons/math/distribution/DistributionFactory.java +++ b/src/java/org/apache/commons/math/distribution/DistributionFactory.java @@ -89,9 +89,12 @@ public abstract class DistributionFactory { * @param numberOfSuccesses the number of successes. * @param probabilityOfSuccess the probability of success * @return a new Pascal distribution + * @since 1.2 */ - public abstract PascalDistribution createPascalDistribution( - int numberOfSuccesses, double probabilityOfSuccess); + public PascalDistribution createPascalDistribution( + int numberOfSuccesses, double probabilityOfSuccess) { + return new PascalDistributionImpl(numberOfSuccesses, probabilityOfSuccess); + } /** * Create a new cauchy distribution with the given median and scale. diff --git a/src/java/org/apache/commons/math/distribution/DistributionFactoryImpl.java b/src/java/org/apache/commons/math/distribution/DistributionFactoryImpl.java index 8978f59df..71de892af 100644 --- a/src/java/org/apache/commons/math/distribution/DistributionFactoryImpl.java +++ b/src/java/org/apache/commons/math/distribution/DistributionFactoryImpl.java @@ -154,17 +154,4 @@ public class DistributionFactoryImpl extends DistributionFactory { public PoissonDistribution createPoissonDistribution(double lambda) { return new PoissonDistributionImpl(lambda); } - - /** - * Create a Pascal distribution with the given number of successes and - * probability of success. - * - * @param numberOfSuccesses the number of successes. - * @param probabilityOfSuccess the probability of success - * @return a new Pascal distribution - */ - public PascalDistribution createPascalDistribution(int numberOfSuccesses, double probabilityOfSuccess) { - return new PascalDistributionImpl(numberOfSuccesses, probabilityOfSuccess); - } - } diff --git a/src/java/org/apache/commons/math/distribution/PascalDistribution.java b/src/java/org/apache/commons/math/distribution/PascalDistribution.java index 035f9eb06..2753dfc4f 100644 --- a/src/java/org/apache/commons/math/distribution/PascalDistribution.java +++ b/src/java/org/apache/commons/math/distribution/PascalDistribution.java @@ -17,20 +17,29 @@ package org.apache.commons.math.distribution; /** - * The Pascal Distribution. + * The Pascal distribution. The Pascal distribution is a special case of the + * Negative Binomial distribution where the number of successes parameter is an + * integer. + * + * There are various ways to express the probability mass and distribution + * functions for the Pascal distribution. The convention employed by the + * library is to express these functions in terms of the number of failures in + * a Bernoulli experiment [2]. * * Instances of PascalDistribution objects should be created using * {@link DistributionFactory#createPascalDistribution(int, double)}. * *

* References: - *

*

* * @version $Revision:$ + * @since 1.2 */ public interface PascalDistribution extends IntegerDistribution { /** diff --git a/src/java/org/apache/commons/math/distribution/PascalDistributionImpl.java b/src/java/org/apache/commons/math/distribution/PascalDistributionImpl.java index 1ec6eb6cc..39bfbc17a 100644 --- a/src/java/org/apache/commons/math/distribution/PascalDistributionImpl.java +++ b/src/java/org/apache/commons/math/distribution/PascalDistributionImpl.java @@ -24,17 +24,16 @@ import org.apache.commons.math.util.MathUtils; /** * The default implementation of {@link PascalDistribution}. - * * @version $Revision:$ + * @since 1.2 */ -public class PascalDistributionImpl - extends AbstractIntegerDistribution +public class PascalDistributionImpl extends AbstractIntegerDistribution implements PascalDistribution, Serializable { /** Serializable version identifier */ private static final long serialVersionUID = 6751309484392813623L; - /** The number of trials */ + /** The number of successes */ private int numberOfSuccesses; /** The probability of success */ @@ -43,7 +42,6 @@ public class PascalDistributionImpl /** * Create a binomial distribution with the given number of trials and * probability of success. - * * @param r the number of successes * @param p the probability of success */ @@ -54,9 +52,8 @@ public class PascalDistributionImpl } /** - * Access the number of trials for this distribution. - * - * @return the number of trials + * Access the number of successes for this distribution. + * @return the number of successes */ public int getNumberOfSuccesses() { return numberOfSuccesses; @@ -64,7 +61,6 @@ public class PascalDistributionImpl /** * Access the probability of success for this distribution. - * * @return the probability of success */ public double getProbabilityOfSuccess() { @@ -72,28 +68,29 @@ public class PascalDistributionImpl } /** - * Change the number of trials for this distribution. - * - * @param successes the new number of trials - * @throws IllegalArgumentException if trials is not positive. + * Change the number of successes for this distribution. + * @param successes the new number of successes + * @throws IllegalArgumentException if successes is not + * positive. */ public void setNumberOfSuccesses(int successes) { if (successes < 0) { - throw new IllegalArgumentException("number of trials must be non-negative."); + throw new IllegalArgumentException( + "number of successes must be non-negative."); } numberOfSuccesses = successes; } /** * Change the probability of success for this distribution. - * * @param p the new probability of success * @throws IllegalArgumentException if p is not a valid * probability. */ public void setProbabilityOfSuccess(double p) { if (p < 0.0 || p > 1.0) { - throw new IllegalArgumentException("probability of success must be between 0.0 and 1.0, inclusive."); + throw new IllegalArgumentException( + "probability of success must be between 0.0 and 1.0, inclusive."); } probabilityOfSuccess = p; } @@ -101,10 +98,9 @@ public class PascalDistributionImpl /** * Access the domain value lower bound, based on p, used to * bracket a PDF root. - * * @param p the desired probability for the critical value - * @return domain value lower bound, i.e. - * P(X < lower bound) < p + * @return domain value lower bound, i.e. P(X < lower bound) < + * p */ protected int getDomainLowerBound(double p) { return -1; @@ -113,80 +109,76 @@ public class PascalDistributionImpl /** * Access the domain value upper bound, based on p, used to * bracket a PDF root. - * * @param p the desired probability for the critical value - * @return domain value upper bound, i.e. - * P(X < upper bound) > p + * @return domain value upper bound, i.e. P(X < upper bound) > + * p */ protected int getDomainUpperBound(double p) { - // use MAX - 1 because MAX causes loop - return Integer.MAX_VALUE - 1; + // use MAX - 1 because MAX causes loop + return Integer.MAX_VALUE - 1; } /** * For this distribution, X, this method returns P(X ≤ x). - * * @param x the value at which the PDF is evaluated * @return PDF for this distribution - * @throws MathException if the cumulative probability can not be - * computed due to convergence or other numerical errors + * @throws MathException if the cumulative probability can not be computed + * due to convergence or other numerical errors */ public double cumulativeProbability(int x) throws MathException { double ret; if (x < 0) { ret = 0.0; } else { - ret = Beta.regularizedBeta( - getProbabilityOfSuccess(), - getNumberOfSuccesses(), - x + 1); + ret = Beta.regularizedBeta(getProbabilityOfSuccess(), + getNumberOfSuccesses(), x + 1); } return ret; } /** * For this distribution, X, this method returns P(X = x). - * * @param x the value at which the PMF is evaluated - * @return PMF for this distribution + * @return PMF for this distribution */ public double probability(int x) { double ret; if (x < 0) { ret = 0.0; } else { - ret = MathUtils.binomialCoefficientDouble(x + getNumberOfSuccesses() - 1, - getNumberOfSuccesses() - 1) * - Math.pow(getProbabilityOfSuccess(), getNumberOfSuccesses()) * - Math.pow(1.0 - getProbabilityOfSuccess(), - x); + ret = MathUtils.binomialCoefficientDouble(x + + getNumberOfSuccesses() - 1, getNumberOfSuccesses() - 1) + * Math.pow(getProbabilityOfSuccess(), getNumberOfSuccesses()) + * Math.pow(1.0 - getProbabilityOfSuccess(), x); } return ret; } - + /** - * For this distribution, X, this method returns the largest x, such - * that P(X ≤ x) ≤ p. + * For this distribution, X, this method returns the largest x, such that + * P(X ≤ x) ≤ p. *

- * Returns -1 for p=0 and Integer.MAX_VALUE for - * p=1. - * + * Returns -1 for p=0 and Integer.MAX_VALUE + * for p=1. * @param p the desired probability * @return the largest x such that P(X ≤ x) <= p * @throws MathException if the inverse cumulative probability can not be - * computed due to convergence or other numerical errors. + * computed due to convergence or other numerical errors. * @throws IllegalArgumentException if p < 0 or p > 1 */ - public int inverseCumulativeProbability(final double p) throws MathException { + public int inverseCumulativeProbability(final double p) + throws MathException { + int ret; + // handle extreme values explicitly if (p == 0) { - return -1; - } - if (p == 1) { - return Integer.MAX_VALUE; + ret = -1; + } else if (p == 1) { + ret = Integer.MAX_VALUE; + } else { + ret = super.inverseCumulativeProbability(p); } - - // use default bisection impl - return super.inverseCumulativeProbability(p); + + return ret; } }