GeometricDistribution.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.util.FastMath;
  25. import org.hipparchus.util.MathUtils;

  26. /**
  27.  * Implementation of the geometric distribution.
  28.  *
  29.  * @see <a href="http://en.wikipedia.org/wiki/Geometric_distribution">Geometric distribution (Wikipedia)</a>
  30.  * @see <a href="http://mathworld.wolfram.com/GeometricDistribution.html">Geometric Distribution (MathWorld)</a>
  31.  */
  32. public class GeometricDistribution extends AbstractIntegerDistribution {

  33.     /** Serializable version identifier. */
  34.     private static final long serialVersionUID = 20130507L;
  35.     /** The probability of success. */
  36.     private final double probabilityOfSuccess;
  37.     /** {@code log(p)} where p is the probability of success. */
  38.     private final double logProbabilityOfSuccess;
  39.     /** {@code log(1 - p)} where p is the probability of success. */
  40.     private final double log1mProbabilityOfSuccess;

  41.     /**
  42.      * Create a geometric distribution with the given probability of success.
  43.      *
  44.      * @param p probability of success.
  45.      * @throws MathIllegalArgumentException if {@code p <= 0} or {@code p > 1}.
  46.      */
  47.     public GeometricDistribution(double p)
  48.         throws MathIllegalArgumentException {
  49.         if (p <= 0 || p > 1) {
  50.             throw new MathIllegalArgumentException(LocalizedCoreFormats.OUT_OF_RANGE_LEFT, p, 0, 1);
  51.         }

  52.         probabilityOfSuccess = p;
  53.         logProbabilityOfSuccess = FastMath.log(p);
  54.         log1mProbabilityOfSuccess = FastMath.log1p(-p);
  55.     }

  56.     /**
  57.      * Access the probability of success for this distribution.
  58.      *
  59.      * @return the probability of success.
  60.      */
  61.     public double getProbabilityOfSuccess() {
  62.         return probabilityOfSuccess;
  63.     }

  64.     /** {@inheritDoc} */
  65.     @Override
  66.     public double probability(int x) {
  67.         if (x < 0) {
  68.             return 0.0;
  69.         } else {
  70.             return FastMath.exp(log1mProbabilityOfSuccess * x) * probabilityOfSuccess;
  71.         }
  72.     }

  73.     /** {@inheritDoc} */
  74.     @Override
  75.     public double logProbability(int x) {
  76.         if (x < 0) {
  77.             return Double.NEGATIVE_INFINITY;
  78.         } else {
  79.             return x * log1mProbabilityOfSuccess + logProbabilityOfSuccess;
  80.         }
  81.     }

  82.     /** {@inheritDoc} */
  83.     @Override
  84.     public double cumulativeProbability(int x) {
  85.         if (x < 0) {
  86.             return 0.0;
  87.         } else {
  88.             return -FastMath.expm1(log1mProbabilityOfSuccess * (x + 1));
  89.         }
  90.     }

  91.     /**
  92.      * {@inheritDoc}
  93.      *
  94.      * For probability parameter {@code p}, the mean is {@code (1 - p) / p}.
  95.      */
  96.     @Override
  97.     public double getNumericalMean() {
  98.         return (1 - probabilityOfSuccess) / probabilityOfSuccess;
  99.     }

  100.     /**
  101.      * {@inheritDoc}
  102.      *
  103.      * For probability parameter {@code p}, the variance is
  104.      * {@code (1 - p) / (p * p)}.
  105.      */
  106.     @Override
  107.     public double getNumericalVariance() {
  108.         return (1 - probabilityOfSuccess) / (probabilityOfSuccess * probabilityOfSuccess);
  109.     }

  110.     /**
  111.      * {@inheritDoc}
  112.      *
  113.      * The lower bound of the support is always 0.
  114.      *
  115.      * @return lower bound of the support (always 0)
  116.      */
  117.     @Override
  118.     public int getSupportLowerBound() {
  119.         return 0;
  120.     }

  121.     /**
  122.      * {@inheritDoc}
  123.      *
  124.      * The upper bound of the support is infinite (which we approximate as
  125.      * {@code Integer.MAX_VALUE}).
  126.      *
  127.      * @return upper bound of the support (always Integer.MAX_VALUE)
  128.      */
  129.     @Override
  130.     public int getSupportUpperBound() {
  131.         return Integer.MAX_VALUE;
  132.     }

  133.     /**
  134.      * {@inheritDoc}
  135.      *
  136.      * The support of this distribution is connected.
  137.      *
  138.      * @return {@code true}
  139.      */
  140.     @Override
  141.     public boolean isSupportConnected() {
  142.         return true;
  143.     }

  144.     /**
  145.      * {@inheritDoc}
  146.      */
  147.     @Override
  148.     public int inverseCumulativeProbability(double p) throws MathIllegalArgumentException {
  149.         MathUtils.checkRangeInclusive(p, 0, 1);

  150.         if (p == 1) {
  151.             return Integer.MAX_VALUE;
  152.         }
  153.         if (p == 0) {
  154.             return 0;
  155.         }
  156.         return Math.max(0, (int) Math.ceil(FastMath.log1p(-p)/log1mProbabilityOfSuccess-1));
  157.     }
  158. }