mirror of
https://github.com/apache/commons-math.git
synced 2025-02-06 10:09:26 +00:00
Merged BinomialDistribution and BinomialDistributionImpl (MATH-711).
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1205963 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
936b937517
commit
a0817f428e
@ -16,31 +16,175 @@
|
||||
*/
|
||||
package org.apache.commons.math.distribution;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.commons.math.exception.OutOfRangeException;
|
||||
import org.apache.commons.math.exception.NotPositiveException;
|
||||
import org.apache.commons.math.exception.util.LocalizedFormats;
|
||||
import org.apache.commons.math.special.Beta;
|
||||
import org.apache.commons.math.util.FastMath;
|
||||
|
||||
/**
|
||||
* The Binomial Distribution.
|
||||
*
|
||||
* <p>
|
||||
* References:
|
||||
* <ul>
|
||||
* <li><a href="http://mathworld.wolfram.com/BinomialDistribution.html">
|
||||
* Binomial Distribution</a></li>
|
||||
* </ul>
|
||||
* </p>
|
||||
* Implementation of the binomial distribution.
|
||||
*
|
||||
* @see <a href="http://en.wikipedia.org/wiki/Binomial_distribution">Binomial distribution (Wikipedia)</a>
|
||||
* @see <a href="http://mathworld.wolfram.com/BinomialDistribution.html">Binomial Distribution (MathWorld)</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface BinomialDistribution extends IntegerDistribution {
|
||||
public class BinomialDistribution extends AbstractIntegerDistribution
|
||||
implements Serializable {
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = 6751309484392813623L;
|
||||
/** The number of trials. */
|
||||
private final int numberOfTrials;
|
||||
/** The probability of success. */
|
||||
private final double probabilityOfSuccess;
|
||||
|
||||
/**
|
||||
* Create a binomial distribution with the given number of trials and
|
||||
* probability of success.
|
||||
*
|
||||
* @param trials Number of trials.
|
||||
* @param p Probability of success.
|
||||
* @throws NotPositiveException if {@code trials < 0}.
|
||||
* @throws OutOfRangeException if {@code p < 0} or {@code p > 1}.
|
||||
*/
|
||||
public BinomialDistribution(int trials, double p) {
|
||||
if (trials < 0) {
|
||||
throw new NotPositiveException(LocalizedFormats.NUMBER_OF_TRIALS,
|
||||
trials);
|
||||
}
|
||||
if (p < 0 || p > 1) {
|
||||
throw new OutOfRangeException(p, 0, 1);
|
||||
}
|
||||
|
||||
probabilityOfSuccess = p;
|
||||
numberOfTrials = trials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the number of trials for this distribution.
|
||||
*
|
||||
* @return the number of trials.
|
||||
*/
|
||||
int getNumberOfTrials();
|
||||
public int getNumberOfTrials() {
|
||||
return numberOfTrials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the probability of success for this distribution.
|
||||
*
|
||||
* @return the probability of success.
|
||||
*/
|
||||
double getProbabilityOfSuccess();
|
||||
public double getProbabilityOfSuccess() {
|
||||
return probabilityOfSuccess;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
protected int getDomainLowerBound(double p) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
protected int getDomainUpperBound(double p) {
|
||||
return numberOfTrials;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public double cumulativeProbability(int x) {
|
||||
double ret;
|
||||
if (x < 0) {
|
||||
ret = 0.0;
|
||||
} else if (x >= numberOfTrials) {
|
||||
ret = 1.0;
|
||||
} else {
|
||||
ret = 1.0 - Beta.regularizedBeta(getProbabilityOfSuccess(),
|
||||
x + 1.0, numberOfTrials - x);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public double probability(int x) {
|
||||
double ret;
|
||||
if (x < 0 || x > numberOfTrials) {
|
||||
ret = 0.0;
|
||||
} else {
|
||||
ret = FastMath.exp(SaddlePointExpansion.logBinomialProbability(x,
|
||||
numberOfTrials, probabilityOfSuccess,
|
||||
1.0 - probabilityOfSuccess));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* This implementation return -1 when {@code p == 0} and
|
||||
* {@code Integer.MAX_VALUE} when {@code p == 1}.
|
||||
*/
|
||||
@Override
|
||||
public int inverseCumulativeProbability(final double p) {
|
||||
// handle extreme values explicitly
|
||||
if (p == 0) {
|
||||
return -1;
|
||||
}
|
||||
if (p == 1) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
// use default bisection impl
|
||||
return super.inverseCumulativeProbability(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* The lower bound of the support is always 0 no matter the number of trials
|
||||
* and probability parameter.
|
||||
*
|
||||
* @return lower bound of the support (always 0)
|
||||
*/
|
||||
@Override
|
||||
public int getSupportLowerBound() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* The upper bound of the support is the number of trials.
|
||||
*
|
||||
* @return upper bound of the support (equal to number of trials)
|
||||
*/
|
||||
@Override
|
||||
public int getSupportUpperBound() {
|
||||
return getNumberOfTrials();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* For {@code n} trials and probability parameter {@code p}, the mean is
|
||||
* {@code n * p}.
|
||||
*/
|
||||
@Override
|
||||
protected double calculateNumericalMean() {
|
||||
return getNumberOfTrials() * getProbabilityOfSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* For {@code n} trials and probability parameter {@code p}, the variance is
|
||||
* {@code n * p * (1 - p)}.
|
||||
*/
|
||||
@Override
|
||||
protected double calculateNumericalVariance() {
|
||||
final double p = getProbabilityOfSuccess();
|
||||
return getNumberOfTrials() * p * (1 - p);
|
||||
}
|
||||
}
|
||||
|
@ -1,216 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.math.distribution;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.apache.commons.math.exception.OutOfRangeException;
|
||||
import org.apache.commons.math.exception.NotPositiveException;
|
||||
import org.apache.commons.math.exception.util.LocalizedFormats;
|
||||
import org.apache.commons.math.special.Beta;
|
||||
import org.apache.commons.math.util.FastMath;
|
||||
|
||||
/**
|
||||
* The default implementation of {@link BinomialDistribution}.
|
||||
*
|
||||
* @version $Id$
|
||||
*/
|
||||
public class BinomialDistributionImpl extends AbstractIntegerDistribution
|
||||
implements BinomialDistribution, Serializable {
|
||||
/** Serializable version identifier. */
|
||||
private static final long serialVersionUID = 6751309484392813623L;
|
||||
/** The number of trials. */
|
||||
private final int numberOfTrials;
|
||||
/** The probability of success. */
|
||||
private final double probabilityOfSuccess;
|
||||
|
||||
/**
|
||||
* Create a binomial distribution with the given number of trials and
|
||||
* probability of success.
|
||||
*
|
||||
* @param trials Number of trials.
|
||||
* @param p Probability of success.
|
||||
* @throws NotPositiveException if {@code trials < 0}.
|
||||
* @throws OutOfRangeException if {@code p < 0} or {@code p > 1}.
|
||||
*/
|
||||
public BinomialDistributionImpl(int trials, double p) {
|
||||
if (trials < 0) {
|
||||
throw new NotPositiveException(LocalizedFormats.NUMBER_OF_TRIALS,
|
||||
trials);
|
||||
}
|
||||
if (p < 0 || p > 1) {
|
||||
throw new OutOfRangeException(p, 0, 1);
|
||||
}
|
||||
|
||||
probabilityOfSuccess = p;
|
||||
numberOfTrials = trials;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int getNumberOfTrials() {
|
||||
return numberOfTrials;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public double getProbabilityOfSuccess() {
|
||||
return probabilityOfSuccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the domain value lower bound, based on {@code p}, used to
|
||||
* bracket a PDF root.
|
||||
*
|
||||
* @param p Desired probability for the critical value.
|
||||
* @return the domain value lower bound, i.e. {@code P(X < 'lower bound') < p}.
|
||||
*/
|
||||
@Override
|
||||
protected int getDomainLowerBound(double p) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the domain value upper bound, based on {@code p}, used to
|
||||
* bracket a PDF root.
|
||||
*
|
||||
* @param p Desired probability for the critical value
|
||||
* @return the domain value upper bound, i.e. {@code P(X < 'upper bound') > p}.
|
||||
*/
|
||||
@Override
|
||||
protected int getDomainUpperBound(double p) {
|
||||
return numberOfTrials;
|
||||
}
|
||||
|
||||
/**
|
||||
* For this distribution, {@code X}, this method returns {@code P(X <= x)}.
|
||||
*
|
||||
* @param x Value at which the PDF is evaluated.
|
||||
* @return PDF for this distribution.
|
||||
* due to convergence or other numerical errors.
|
||||
*/
|
||||
@Override
|
||||
public double cumulativeProbability(int x) {
|
||||
double ret;
|
||||
if (x < 0) {
|
||||
ret = 0.0;
|
||||
} else if (x >= numberOfTrials) {
|
||||
ret = 1.0;
|
||||
} else {
|
||||
ret = 1.0 - Beta.regularizedBeta(getProbabilityOfSuccess(),
|
||||
x + 1.0, numberOfTrials - x);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* For this distribution, {@code X}, this method returns {@code P(X = x)}.
|
||||
*
|
||||
* @param x Value at which the PMF is evaluated.
|
||||
* @return PMF for this distribution.
|
||||
*/
|
||||
public double probability(int x) {
|
||||
double ret;
|
||||
if (x < 0 || x > numberOfTrials) {
|
||||
ret = 0.0;
|
||||
} else {
|
||||
ret = FastMath.exp(SaddlePointExpansion.logBinomialProbability(x,
|
||||
numberOfTrials, probabilityOfSuccess,
|
||||
1.0 - probabilityOfSuccess));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* For this distribution, {@code X}, this method returns the largest
|
||||
* {@code x}, such that {@code P(X < x) p}.
|
||||
* It will return -1 when p = 0 and {@code Integer.MAX_VALUE} when p = 1.
|
||||
*
|
||||
* @param p Desired probability.
|
||||
* @return the largest {@code x} such that {@code P(X < x) <= p}.
|
||||
* @throws OutOfRangeException if {@code p < 0} or {@code p > 1}.
|
||||
*/
|
||||
@Override
|
||||
public int inverseCumulativeProbability(final double p) {
|
||||
// handle extreme values explicitly
|
||||
if (p == 0) {
|
||||
return -1;
|
||||
}
|
||||
if (p == 1) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
// use default bisection impl
|
||||
return super.inverseCumulativeProbability(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* The lower bound of the support is always 0 no matter the number of trials
|
||||
* and probability parameter.
|
||||
*
|
||||
* @return lower bound of the support (always 0)
|
||||
*/
|
||||
@Override
|
||||
public int getSupportLowerBound() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* The upper bound of the support is the number of trials.
|
||||
*
|
||||
* @return upper bound of the support (equal to number of trials)
|
||||
*/
|
||||
@Override
|
||||
public int getSupportUpperBound() {
|
||||
return getNumberOfTrials();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* For <code>n</code> number of trials and
|
||||
* probability parameter <code>p</code>, the mean is
|
||||
* <code>n * p</code>
|
||||
*
|
||||
* @return {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected double calculateNumericalMean() {
|
||||
return (double)getNumberOfTrials() * getProbabilityOfSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* For <code>n</code> number of trials and
|
||||
* probability parameter <code>p</code>, the variance is
|
||||
* <code>n * p * (1 - p)</code>
|
||||
*
|
||||
* @return {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected double calculateNumericalVariance() {
|
||||
final double p = getProbabilityOfSuccess();
|
||||
return (double)getNumberOfTrials() * p * (1 - p);
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ import java.security.SecureRandom;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.commons.math.distribution.BetaDistribution;
|
||||
import org.apache.commons.math.distribution.BinomialDistributionImpl;
|
||||
import org.apache.commons.math.distribution.BinomialDistribution;
|
||||
import org.apache.commons.math.distribution.CauchyDistributionImpl;
|
||||
import org.apache.commons.math.distribution.ChiSquaredDistributionImpl;
|
||||
import org.apache.commons.math.distribution.ContinuousDistribution;
|
||||
@ -613,7 +613,7 @@ public class RandomDataImpl implements RandomData, Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random value from the {@link BinomialDistributionImpl Binomial Distribution}.
|
||||
* Generates a random value from the {@link BinomialDistribution Binomial Distribution}.
|
||||
* This implementation uses {@link #nextInversionDeviate(ContinuousDistribution) inversion}
|
||||
* to generate random values.
|
||||
*
|
||||
@ -623,7 +623,7 @@ public class RandomDataImpl implements RandomData, Serializable {
|
||||
* @since 2.2
|
||||
*/
|
||||
public int nextBinomial(int numberOfTrials, double probabilityOfSuccess) {
|
||||
return nextInversionDeviate(new BinomialDistributionImpl(numberOfTrials, probabilityOfSuccess));
|
||||
return nextInversionDeviate(new BinomialDistribution(numberOfTrials, probabilityOfSuccess));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,7 +31,7 @@ public class BinomialDistributionTest extends IntegerDistributionAbstractTest {
|
||||
/** Creates the default discrete distribution instance to use in tests. */
|
||||
@Override
|
||||
public IntegerDistribution makeDistribution() {
|
||||
return new BinomialDistributionImpl(10, 0.70);
|
||||
return new BinomialDistribution(10, 0.70);
|
||||
}
|
||||
|
||||
/** Creates the default probability density test input values */
|
||||
@ -82,7 +82,7 @@ public class BinomialDistributionTest extends IntegerDistributionAbstractTest {
|
||||
/** Test degenerate case p = 0 */
|
||||
@Test
|
||||
public void testDegenerate0() throws Exception {
|
||||
setDistribution(new BinomialDistributionImpl(5, 0.0d));
|
||||
setDistribution(new BinomialDistribution(5, 0.0d));
|
||||
setCumulativeTestPoints(new int[] { -1, 0, 1, 5, 10 });
|
||||
setCumulativeTestValues(new double[] { 0d, 1d, 1d, 1d, 1d });
|
||||
setDensityTestPoints(new int[] { -1, 0, 1, 10, 11 });
|
||||
@ -97,7 +97,7 @@ public class BinomialDistributionTest extends IntegerDistributionAbstractTest {
|
||||
/** Test degenerate case p = 1 */
|
||||
@Test
|
||||
public void testDegenerate1() throws Exception {
|
||||
setDistribution(new BinomialDistributionImpl(5, 1.0d));
|
||||
setDistribution(new BinomialDistribution(5, 1.0d));
|
||||
setCumulativeTestPoints(new int[] { -1, 0, 1, 2, 5, 10 });
|
||||
setCumulativeTestValues(new double[] { 0d, 0d, 0d, 0d, 1d, 1d });
|
||||
setDensityTestPoints(new int[] { -1, 0, 1, 2, 5, 10 });
|
||||
@ -113,12 +113,12 @@ public class BinomialDistributionTest extends IntegerDistributionAbstractTest {
|
||||
public void testMoments() {
|
||||
final double tol = 1e-9;
|
||||
BinomialDistribution dist;
|
||||
|
||||
dist = new BinomialDistributionImpl(10, 0.5);
|
||||
|
||||
dist = new BinomialDistribution(10, 0.5);
|
||||
Assert.assertEquals(dist.getNumericalMean(), 10d * 0.5d, tol);
|
||||
Assert.assertEquals(dist.getNumericalVariance(), 10d * 0.5d * 0.5d, tol);
|
||||
|
||||
dist = new BinomialDistributionImpl(30, 0.3);
|
||||
Assert.assertEquals(dist.getNumericalVariance(), 10d * 0.5d * 0.5d, tol);
|
||||
|
||||
dist = new BinomialDistribution(30, 0.3);
|
||||
Assert.assertEquals(dist.getNumericalMean(), 30d * 0.3d, tol);
|
||||
Assert.assertEquals(dist.getNumericalVariance(), 30d * 0.3d * (1d - 0.3d), tol);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ import org.apache.commons.math.Retry;
|
||||
import org.apache.commons.math.RetryRunner;
|
||||
import org.apache.commons.math.TestUtils;
|
||||
import org.apache.commons.math.distribution.BetaDistribution;
|
||||
import org.apache.commons.math.distribution.BinomialDistributionImpl;
|
||||
import org.apache.commons.math.distribution.BinomialDistribution;
|
||||
import org.apache.commons.math.distribution.BinomialDistributionTest;
|
||||
import org.apache.commons.math.distribution.CauchyDistributionImpl;
|
||||
import org.apache.commons.math.distribution.ChiSquaredDistributionImpl;
|
||||
@ -963,7 +963,7 @@ public class RandomDataTest {
|
||||
double[] densityValues = testInstance.makeDensityTestValues();
|
||||
int sampleSize = 1000;
|
||||
int length = TestUtils.eliminateZeroMassPoints(densityPoints, densityValues);
|
||||
BinomialDistributionImpl distribution = (BinomialDistributionImpl) testInstance.makeDistribution();
|
||||
BinomialDistribution distribution = (BinomialDistribution) testInstance.makeDistribution();
|
||||
double[] expectedCounts = new double[length];
|
||||
long[] observedCounts = new long[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user