github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/stat/distuv/poisson.go (about) 1 // Copyright ©2017 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package distuv 6 7 import ( 8 "math" 9 10 "golang.org/x/exp/rand" 11 12 "github.com/jingcheng-WU/gonum/mathext" 13 ) 14 15 // Poisson implements the Poisson distribution, a discrete probability distribution 16 // that expresses the probability of a given number of events occurring in a fixed 17 // interval. 18 // The poisson distribution has density function: 19 // f(k) = λ^k / k! e^(-λ) 20 // For more information, see https://en.wikipedia.org/wiki/Poisson_distribution. 21 type Poisson struct { 22 // Lambda is the average number of events in an interval. 23 // Lambda must be greater than 0. 24 Lambda float64 25 26 Src rand.Source 27 } 28 29 // CDF computes the value of the cumulative distribution function at x. 30 func (p Poisson) CDF(x float64) float64 { 31 if x < 0 { 32 return 0 33 } 34 return mathext.GammaIncRegComp(math.Floor(x+1), p.Lambda) 35 } 36 37 // ExKurtosis returns the excess kurtosis of the distribution. 38 func (p Poisson) ExKurtosis() float64 { 39 return 1 / p.Lambda 40 } 41 42 // LogProb computes the natural logarithm of the value of the probability 43 // density function at x. 44 func (p Poisson) LogProb(x float64) float64 { 45 if x < 0 || math.Floor(x) != x { 46 return math.Inf(-1) 47 } 48 lg, _ := math.Lgamma(math.Floor(x) + 1) 49 return x*math.Log(p.Lambda) - p.Lambda - lg 50 } 51 52 // Mean returns the mean of the probability distribution. 53 func (p Poisson) Mean() float64 { 54 return p.Lambda 55 } 56 57 // NumParameters returns the number of parameters in the distribution. 58 func (Poisson) NumParameters() int { 59 return 1 60 } 61 62 // Prob computes the value of the probability density function at x. 63 func (p Poisson) Prob(x float64) float64 { 64 return math.Exp(p.LogProb(x)) 65 } 66 67 // Rand returns a random sample drawn from the distribution. 68 func (p Poisson) Rand() float64 { 69 // NUMERICAL RECIPES IN C: THE ART OF SCIENTIFIC COMPUTING (ISBN 0-521-43108-5) 70 // p. 294 71 // <http://www.aip.de/groups/soe/local/numres/bookcpdf/c7-3.pdf> 72 73 rnd := rand.ExpFloat64 74 var rng *rand.Rand 75 if p.Src != nil { 76 rng = rand.New(p.Src) 77 rnd = rng.ExpFloat64 78 } 79 80 if p.Lambda < 10.0 { 81 // Use direct method. 82 var em float64 83 t := 0.0 84 for { 85 t += rnd() 86 if t >= p.Lambda { 87 break 88 } 89 em++ 90 } 91 return em 92 } 93 // Generate using: 94 // W. Hörmann. "The transformed rejection method for generating Poisson 95 // random variables." Insurance: Mathematics and Economics 96 // 12.1 (1993): 39-45. 97 98 // Algorithm PTRS 99 rnd = rand.Float64 100 if rng != nil { 101 rnd = rng.Float64 102 } 103 b := 0.931 + 2.53*math.Sqrt(p.Lambda) 104 a := -0.059 + 0.02483*b 105 invalpha := 1.1239 + 1.1328/(b-3.4) 106 vr := 0.9277 - 3.6224/(b-2) 107 for { 108 U := rnd() - 0.5 109 V := rnd() 110 us := 0.5 - math.Abs(U) 111 k := math.Floor((2*a/us+b)*U + p.Lambda + 0.43) 112 if us >= 0.07 && V <= vr { 113 return k 114 } 115 if k <= 0 || (us < 0.013 && V > us) { 116 continue 117 } 118 lg, _ := math.Lgamma(k + 1) 119 if math.Log(V*invalpha/(a/(us*us)+b)) <= k*math.Log(p.Lambda)-p.Lambda-lg { 120 return k 121 } 122 } 123 } 124 125 // Skewness returns the skewness of the distribution. 126 func (p Poisson) Skewness() float64 { 127 return 1 / math.Sqrt(p.Lambda) 128 } 129 130 // StdDev returns the standard deviation of the probability distribution. 131 func (p Poisson) StdDev() float64 { 132 return math.Sqrt(p.Variance()) 133 } 134 135 // Survival returns the survival function (complementary CDF) at x. 136 func (p Poisson) Survival(x float64) float64 { 137 return 1 - p.CDF(x) 138 } 139 140 // Variance returns the variance of the probability distribution. 141 func (p Poisson) Variance() float64 { 142 return p.Lambda 143 }