BinomialDistribution.java

  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.  *      https://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. /*
  18.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */
  21. package org.hipparchus.distribution.discrete;

  22. import org.hipparchus.exception.LocalizedCoreFormats;
  23. import org.hipparchus.exception.MathIllegalArgumentException;
  24. import org.hipparchus.special.Beta;
  25. import org.hipparchus.util.FastMath;
  26. import org.hipparchus.util.MathUtils;

  27. /**
  28.  * Implementation of the binomial distribution.
  29.  *
  30.  * @see <a href="http://en.wikipedia.org/wiki/Binomial_distribution">Binomial distribution (Wikipedia)</a>
  31.  * @see <a href="http://mathworld.wolfram.com/BinomialDistribution.html">Binomial Distribution (MathWorld)</a>
  32.  */
  33. public class BinomialDistribution extends AbstractIntegerDistribution {
  34.     /** Serializable version identifier. */
  35.     private static final long serialVersionUID = 20160320L;
  36.     /** The number of trials. */
  37.     private final int numberOfTrials;
  38.     /** The probability of success. */
  39.     private final double probabilityOfSuccess;

  40.     /**
  41.      * Create a binomial distribution with the given number of trials and
  42.      * probability of success.
  43.      *
  44.      * @param trials Number of trials.
  45.      * @param p Probability of success.
  46.      * @throws MathIllegalArgumentException if {@code trials < 0}.
  47.      * @throws MathIllegalArgumentException if {@code p < 0} or {@code p > 1}.
  48.      */
  49.     public BinomialDistribution(int trials, double p)
  50.         throws MathIllegalArgumentException {
  51.         if (trials < 0) {
  52.             throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_OF_TRIALS,
  53.                                            trials);
  54.         }

  55.         MathUtils.checkRangeInclusive(p, 0, 1);

  56.         probabilityOfSuccess = p;
  57.         numberOfTrials = trials;
  58.     }

  59.     /**
  60.      * Access the number of trials for this distribution.
  61.      *
  62.      * @return the number of trials.
  63.      */
  64.     public int getNumberOfTrials() {
  65.         return numberOfTrials;
  66.     }

  67.     /**
  68.      * Access the probability of success for this distribution.
  69.      *
  70.      * @return the probability of success.
  71.      */
  72.     public double getProbabilityOfSuccess() {
  73.         return probabilityOfSuccess;
  74.     }

  75.     /** {@inheritDoc} */
  76.     @Override
  77.     public double probability(int x) {
  78.         final double logProbability = logProbability(x);
  79.         return logProbability == Double.NEGATIVE_INFINITY ? 0 : FastMath.exp(logProbability);
  80.     }

  81.     /** {@inheritDoc} **/
  82.     @Override
  83.     public double logProbability(int x) {
  84.         if (numberOfTrials == 0) {
  85.             return (x == 0) ? 0. : Double.NEGATIVE_INFINITY;
  86.         }
  87.         double ret;
  88.         if (x < 0 || x > numberOfTrials) {
  89.             ret = Double.NEGATIVE_INFINITY;
  90.         } else {
  91.             ret = SaddlePointExpansion.logBinomialProbability(x,
  92.                     numberOfTrials, probabilityOfSuccess,
  93.                     1.0 - probabilityOfSuccess);
  94.         }
  95.         return ret;
  96.     }

  97.     /** {@inheritDoc} */
  98.     @Override
  99.     public double cumulativeProbability(int x) {
  100.         double ret;
  101.         if (x < 0) {
  102.             ret = 0.0;
  103.         } else if (x >= numberOfTrials) {
  104.             ret = 1.0;
  105.         } else {
  106.             ret = 1.0 - Beta.regularizedBeta(probabilityOfSuccess,
  107.                     x + 1.0, numberOfTrials - x);
  108.         }
  109.         return ret;
  110.     }

  111.     /**
  112.      * {@inheritDoc}
  113.      *
  114.      * For {@code n} trials and probability parameter {@code p}, the mean is
  115.      * {@code n * p}.
  116.      */
  117.     @Override
  118.     public double getNumericalMean() {
  119.         return numberOfTrials * probabilityOfSuccess;
  120.     }

  121.     /**
  122.      * {@inheritDoc}
  123.      *
  124.      * For {@code n} trials and probability parameter {@code p}, the variance is
  125.      * {@code n * p * (1 - p)}.
  126.      */
  127.     @Override
  128.     public double getNumericalVariance() {
  129.         final double p = probabilityOfSuccess;
  130.         return numberOfTrials * p * (1 - p);
  131.     }

  132.     /**
  133.      * {@inheritDoc}
  134.      *
  135.      * The lower bound of the support is always 0 except for the probability
  136.      * parameter {@code p = 1}.
  137.      *
  138.      * @return lower bound of the support (0 or the number of trials)
  139.      */
  140.     @Override
  141.     public int getSupportLowerBound() {
  142.         return probabilityOfSuccess < 1.0 ? 0 : numberOfTrials;
  143.     }

  144.     /**
  145.      * {@inheritDoc}
  146.      *
  147.      * The upper bound of the support is the number of trials except for the
  148.      * probability parameter {@code p = 0}.
  149.      *
  150.      * @return upper bound of the support (number of trials or 0)
  151.      */
  152.     @Override
  153.     public int getSupportUpperBound() {
  154.         return probabilityOfSuccess > 0.0 ? numberOfTrials : 0;
  155.     }

  156.     /**
  157.      * {@inheritDoc}
  158.      *
  159.      * The support of this distribution is connected.
  160.      *
  161.      * @return {@code true}
  162.      */
  163.     @Override
  164.     public boolean isSupportConnected() {
  165.         return true;
  166.     }
  167. }