All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.commons.statistics.distribution.BinomialDistribution Maven / Gradle / Ivy

/*
 * 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.statistics.distribution;

import org.apache.commons.numbers.gamma.RegularizedBeta;

/**
 * Implementation of the binomial distribution.
 *
 * 

The probability mass function of \( X \) is: * *

\[ f(k; n, p) = \binom{n}{k} p^k (1-p)^{n-k} \] * *

for \( n \in \{0, 1, 2, \dots\} \) the number of trials, * \( p \in [0, 1] \) the probability of success, * \( k \in \{0, 1, \dots, n\} \) the number of successes, and * *

\[ \binom{n}{k} = \frac{n!}{k! \, (n-k)!} \] * *

is the binomial coefficient. * * @see Binomial distribution (Wikipedia) * @see Binomial distribution (MathWorld) */ public final class BinomialDistribution extends AbstractDiscreteDistribution { /** 1/2. */ private static final float HALF = 0.5f; /** The number of trials. */ private final int numberOfTrials; /** The probability of success. */ private final double probabilityOfSuccess; /** Cached value for pmf(x=0). */ private final double pmf0; /** Cached value for pmf(x=n). */ private final double pmfn; /** * @param trials Number of trials. * @param p Probability of success. */ private BinomialDistribution(int trials, double p) { probabilityOfSuccess = p; numberOfTrials = trials; // Special pmf cases where the power function is more accurate: // (n choose k) == 1 for k=0, k=n // pmf = p^k (1-p)^(n-k) // Note: This handles the edge case of n=0: pmf(k=0) = 1, else 0 if (probabilityOfSuccess >= HALF) { pmf0 = Math.pow(1 - probabilityOfSuccess, numberOfTrials); } else { pmf0 = Math.exp(numberOfTrials * Math.log1p(-probabilityOfSuccess)); } pmfn = Math.pow(probabilityOfSuccess, numberOfTrials); } /** * Creates a binomial distribution. * * @param trials Number of trials. * @param p Probability of success. * @return the distribution * @throws IllegalArgumentException if {@code trials < 0}, or if {@code p < 0} * or {@code p > 1}. */ public static BinomialDistribution of(int trials, double p) { if (trials < 0) { throw new DistributionException(DistributionException.NEGATIVE, trials); } ArgumentUtils.checkProbability(p); // Avoid p = -0.0 to avoid returning -0.0 for some probability computations. return new BinomialDistribution(trials, Math.abs(p)); } /** * Gets the number of trials parameter of this distribution. * * @return the number of trials. */ public int getNumberOfTrials() { return numberOfTrials; } /** * Gets the probability of success parameter of this distribution. * * @return the probability of success. */ public double getProbabilityOfSuccess() { return probabilityOfSuccess; } /** {@inheritDoc} */ @Override public double probability(int x) { if (x < 0 || x > numberOfTrials) { return 0; } else if (x == 0) { return pmf0; } else if (x == numberOfTrials) { return pmfn; } return Math.exp(SaddlePointExpansionUtils.logBinomialProbability(x, numberOfTrials, probabilityOfSuccess, 1.0 - probabilityOfSuccess)); } /** {@inheritDoc} **/ @Override public double logProbability(int x) { if (numberOfTrials == 0) { return (x == 0) ? 0.0 : Double.NEGATIVE_INFINITY; } else if (x < 0 || x > numberOfTrials) { return Double.NEGATIVE_INFINITY; } // Special cases for x=0, x=n // are handled in the saddle point expansion return SaddlePointExpansionUtils.logBinomialProbability(x, numberOfTrials, probabilityOfSuccess, 1.0 - probabilityOfSuccess); } /** {@inheritDoc} */ @Override public double cumulativeProbability(int x) { if (x < 0) { return 0.0; } else if (x >= numberOfTrials) { return 1.0; } else if (x == 0) { return pmf0; } return RegularizedBeta.complement(probabilityOfSuccess, x + 1.0, (double) numberOfTrials - x); } /** {@inheritDoc} */ @Override public double survivalProbability(int x) { if (x < 0) { return 1.0; } else if (x >= numberOfTrials) { return 0.0; } else if (x == numberOfTrials - 1) { return pmfn; } return RegularizedBeta.value(probabilityOfSuccess, x + 1.0, (double) numberOfTrials - x); } /** * {@inheritDoc} * *

For number of trials \( n \) and probability of success \( p \), the mean is \( np \). */ @Override public double getMean() { return numberOfTrials * probabilityOfSuccess; } /** * {@inheritDoc} * *

For number of trials \( n \) and probability of success \( p \), the variance is \( np (1 - p) \). */ @Override public double getVariance() { final double p = probabilityOfSuccess; return numberOfTrials * p * (1 - p); } /** * {@inheritDoc} * *

The lower bound of the support is always 0 except for the probability * parameter {@code p = 1}. * * @return 0 or the number of trials. */ @Override public int getSupportLowerBound() { return probabilityOfSuccess < 1.0 ? 0 : numberOfTrials; } /** * {@inheritDoc} * *

The upper bound of the support is the number of trials except for the * probability parameter {@code p = 0}. * * @return number of trials or 0. */ @Override public int getSupportUpperBound() { return probabilityOfSuccess > 0.0 ? numberOfTrials : 0; } /** {@inheritDoc} */ @Override int getMedian() { // Overridden for the probability(int, int) method. // This is intentionally not a public method. // Can be floor or ceiling of np. For the probability in a range use the floor // as this only used for values >= median+1. return (int) (numberOfTrials * probabilityOfSuccess); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy