View Javadoc
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  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.distribution.discrete;
23  
24  import org.hipparchus.exception.LocalizedCoreFormats;
25  import org.hipparchus.exception.MathIllegalArgumentException;
26  import org.hipparchus.special.Beta;
27  import org.hipparchus.util.FastMath;
28  import org.hipparchus.util.MathUtils;
29  
30  /**
31   * Implementation of the binomial distribution.
32   *
33   * @see <a href="http://en.wikipedia.org/wiki/Binomial_distribution">Binomial distribution (Wikipedia)</a>
34   * @see <a href="http://mathworld.wolfram.com/BinomialDistribution.html">Binomial Distribution (MathWorld)</a>
35   */
36  public class BinomialDistribution extends AbstractIntegerDistribution {
37      /** Serializable version identifier. */
38      private static final long serialVersionUID = 20160320L;
39      /** The number of trials. */
40      private final int numberOfTrials;
41      /** The probability of success. */
42      private final double probabilityOfSuccess;
43  
44      /**
45       * Create a binomial distribution with the given number of trials and
46       * probability of success.
47       *
48       * @param trials Number of trials.
49       * @param p Probability of success.
50       * @throws MathIllegalArgumentException if {@code trials < 0}.
51       * @throws MathIllegalArgumentException if {@code p < 0} or {@code p > 1}.
52       */
53      public BinomialDistribution(int trials, double p)
54          throws MathIllegalArgumentException {
55          if (trials < 0) {
56              throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_OF_TRIALS,
57                                             trials);
58          }
59  
60          MathUtils.checkRangeInclusive(p, 0, 1);
61  
62          probabilityOfSuccess = p;
63          numberOfTrials = trials;
64      }
65  
66      /**
67       * Access the number of trials for this distribution.
68       *
69       * @return the number of trials.
70       */
71      public int getNumberOfTrials() {
72          return numberOfTrials;
73      }
74  
75      /**
76       * Access the probability of success for this distribution.
77       *
78       * @return the probability of success.
79       */
80      public double getProbabilityOfSuccess() {
81          return probabilityOfSuccess;
82      }
83  
84      /** {@inheritDoc} */
85      @Override
86      public double probability(int x) {
87          final double logProbability = logProbability(x);
88          return logProbability == Double.NEGATIVE_INFINITY ? 0 : FastMath.exp(logProbability);
89      }
90  
91      /** {@inheritDoc} **/
92      @Override
93      public double logProbability(int x) {
94          if (numberOfTrials == 0) {
95              return (x == 0) ? 0. : Double.NEGATIVE_INFINITY;
96          }
97          double ret;
98          if (x < 0 || x > numberOfTrials) {
99              ret = Double.NEGATIVE_INFINITY;
100         } else {
101             ret = SaddlePointExpansion.logBinomialProbability(x,
102                     numberOfTrials, probabilityOfSuccess,
103                     1.0 - probabilityOfSuccess);
104         }
105         return ret;
106     }
107 
108     /** {@inheritDoc} */
109     @Override
110     public double cumulativeProbability(int x) {
111         double ret;
112         if (x < 0) {
113             ret = 0.0;
114         } else if (x >= numberOfTrials) {
115             ret = 1.0;
116         } else {
117             ret = 1.0 - Beta.regularizedBeta(probabilityOfSuccess,
118                     x + 1.0, numberOfTrials - x);
119         }
120         return ret;
121     }
122 
123     /**
124      * {@inheritDoc}
125      *
126      * For {@code n} trials and probability parameter {@code p}, the mean is
127      * {@code n * p}.
128      */
129     @Override
130     public double getNumericalMean() {
131         return numberOfTrials * probabilityOfSuccess;
132     }
133 
134     /**
135      * {@inheritDoc}
136      *
137      * For {@code n} trials and probability parameter {@code p}, the variance is
138      * {@code n * p * (1 - p)}.
139      */
140     @Override
141     public double getNumericalVariance() {
142         final double p = probabilityOfSuccess;
143         return numberOfTrials * p * (1 - p);
144     }
145 
146     /**
147      * {@inheritDoc}
148      *
149      * The lower bound of the support is always 0 except for the probability
150      * parameter {@code p = 1}.
151      *
152      * @return lower bound of the support (0 or the number of trials)
153      */
154     @Override
155     public int getSupportLowerBound() {
156         return probabilityOfSuccess < 1.0 ? 0 : numberOfTrials;
157     }
158 
159     /**
160      * {@inheritDoc}
161      *
162      * The upper bound of the support is the number of trials except for the
163      * probability parameter {@code p = 0}.
164      *
165      * @return upper bound of the support (number of trials or 0)
166      */
167     @Override
168     public int getSupportUpperBound() {
169         return probabilityOfSuccess > 0.0 ? numberOfTrials : 0;
170     }
171 
172     /**
173      * {@inheritDoc}
174      *
175      * The support of this distribution is connected.
176      *
177      * @return {@code true}
178      */
179     @Override
180     public boolean isSupportConnected() {
181         return true;
182     }
183 }