001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.math3.distribution; 018 019import org.apache.commons.math3.exception.OutOfRangeException; 020import org.apache.commons.math3.exception.util.LocalizedFormats; 021import org.apache.commons.math3.random.RandomGenerator; 022import org.apache.commons.math3.random.Well19937c; 023import org.apache.commons.math3.util.FastMath; 024 025/** 026 * Implementation of the geometric distribution. 027 * 028 * @see <a href="http://en.wikipedia.org/wiki/Geometric_distribution">Geometric distribution (Wikipedia)</a> 029 * @see <a href="http://mathworld.wolfram.com/GeometricDistribution.html">Geometric Distribution (MathWorld)</a> 030 * @since 3.3 031 */ 032public class GeometricDistribution extends AbstractIntegerDistribution { 033 034 /** Serializable version identifier. */ 035 private static final long serialVersionUID = 20130507L; 036 /** The probability of success. */ 037 private final double probabilityOfSuccess; 038 039 /** 040 * Create a geometric distribution with the given probability of success. 041 * <p> 042 * <b>Note:</b> this constructor will implicitly create an instance of 043 * {@link Well19937c} as random generator to be used for sampling only (see 044 * {@link #sample()} and {@link #sample(int)}). In case no sampling is 045 * needed for the created distribution, it is advised to pass {@code null} 046 * as random generator via the appropriate constructors to avoid the 047 * additional initialisation overhead. 048 * 049 * @param p probability of success. 050 * @throws OutOfRangeException if {@code p <= 0} or {@code p > 1}. 051 */ 052 public GeometricDistribution(double p) { 053 this(new Well19937c(), p); 054 } 055 056 /** 057 * Creates a geometric distribution. 058 * 059 * @param rng Random number generator. 060 * @param p Probability of success. 061 * @throws OutOfRangeException if {@code p <= 0} or {@code p > 1}. 062 */ 063 public GeometricDistribution(RandomGenerator rng, double p) { 064 super(rng); 065 066 if (p <= 0 || p > 1) { 067 throw new OutOfRangeException(LocalizedFormats.OUT_OF_RANGE_LEFT, p, 0, 1); 068 } 069 070 probabilityOfSuccess = p; 071 } 072 073 /** 074 * Access the probability of success for this distribution. 075 * 076 * @return the probability of success. 077 */ 078 public double getProbabilityOfSuccess() { 079 return probabilityOfSuccess; 080 } 081 082 /** {@inheritDoc} */ 083 public double probability(int x) { 084 double ret; 085 if (x < 0) { 086 ret = 0.0; 087 } else { 088 final double p = probabilityOfSuccess; 089 ret = FastMath.pow(1 - p, x) * p; 090 } 091 return ret; 092 } 093 094 /** {@inheritDoc} */ 095 @Override 096 public double logProbability(int x) { 097 double ret; 098 if (x < 0) { 099 ret = Double.NEGATIVE_INFINITY; 100 } else { 101 final double p = probabilityOfSuccess; 102 ret = x * FastMath.log1p(-p) + FastMath.log(p); 103 } 104 return ret; 105 } 106 107 /** {@inheritDoc} */ 108 public double cumulativeProbability(int x) { 109 double ret; 110 if (x < 0) { 111 ret = 0.0; 112 } else { 113 final double p = probabilityOfSuccess; 114 ret = 1.0 - FastMath.pow(1 - p, x + 1); 115 } 116 return ret; 117 } 118 119 /** 120 * {@inheritDoc} 121 * 122 * For probability parameter {@code p}, the mean is {@code (1 - p) / p}. 123 */ 124 public double getNumericalMean() { 125 final double p = probabilityOfSuccess; 126 return (1 - p) / p; 127 } 128 129 /** 130 * {@inheritDoc} 131 * 132 * For probability parameter {@code p}, the variance is 133 * {@code (1 - p) / (p * p)}. 134 */ 135 public double getNumericalVariance() { 136 final double p = probabilityOfSuccess; 137 return (1 - p) / (p * p); 138 } 139 140 /** 141 * {@inheritDoc} 142 * 143 * The lower bound of the support is always 0. 144 * 145 * @return lower bound of the support (always 0) 146 */ 147 public int getSupportLowerBound() { 148 return 0; 149 } 150 151 /** 152 * {@inheritDoc} 153 * 154 * The upper bound of the support is infinite (which we approximate as 155 * {@code Integer.MAX_VALUE}). 156 * 157 * @return upper bound of the support (always Integer.MAX_VALUE) 158 */ 159 public int getSupportUpperBound() { 160 return Integer.MAX_VALUE; 161 } 162 163 /** 164 * {@inheritDoc} 165 * 166 * The support of this distribution is connected. 167 * 168 * @return {@code true} 169 */ 170 public boolean isSupportConnected() { 171 return true; 172 } 173}