gonum.org/v1/gonum@v0.14.0/stat/distuv/poisson_test.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 "fmt" 9 "math" 10 "sort" 11 "testing" 12 13 "golang.org/x/exp/rand" 14 15 "gonum.org/v1/gonum/floats/scalar" 16 ) 17 18 func TestPoissonProb(t *testing.T) { 19 t.Parallel() 20 const tol = 1e-10 21 for i, tt := range []struct { 22 k float64 23 lambda float64 24 want float64 25 }{ 26 {0, 1, 3.678794411714423e-01}, 27 {1, 1, 3.678794411714423e-01}, 28 {2, 1, 1.839397205857211e-01}, 29 {3, 1, 6.131324019524039e-02}, 30 {4, 1, 1.532831004881010e-02}, 31 {5, 1, 3.065662009762020e-03}, 32 {6, 1, 5.109436682936698e-04}, 33 {7, 1, 7.299195261338139e-05}, 34 {8, 1, 9.123994076672672e-06}, 35 {9, 1, 1.013777119630298e-06}, 36 37 {0, 2.5, 8.208499862389880e-02}, 38 {1, 2.5, 2.052124965597470e-01}, 39 {2, 2.5, 2.565156206996838e-01}, 40 {3, 2.5, 2.137630172497365e-01}, 41 {4, 2.5, 1.336018857810853e-01}, 42 {5, 2.5, 6.680094289054267e-02}, 43 {6, 2.5, 2.783372620439277e-02}, 44 {7, 2.5, 9.940616501568845e-03}, 45 {8, 2.5, 3.106442656740263e-03}, 46 {9, 2.5, 8.629007379834082e-04}, 47 48 {0.5, 2.5, 0}, 49 {1.5, 2.5, 0}, 50 {2.5, 2.5, 0}, 51 {3.5, 2.5, 0}, 52 {4.5, 2.5, 0}, 53 {5.5, 2.5, 0}, 54 {6.5, 2.5, 0}, 55 {7.5, 2.5, 0}, 56 {8.5, 2.5, 0}, 57 {9.5, 2.5, 0}, 58 } { 59 p := Poisson{Lambda: tt.lambda} 60 got := p.Prob(tt.k) 61 if !scalar.EqualWithinAbs(got, tt.want, tol) { 62 t.Errorf("test-%d: got=%e. want=%e\n", i, got, tt.want) 63 } 64 } 65 } 66 67 func TestPoissonCDF(t *testing.T) { 68 t.Parallel() 69 const tol = 1e-10 70 for i, tt := range []struct { 71 k float64 72 lambda float64 73 want float64 74 }{ 75 {0, 1, 0.367879441171442}, 76 {1, 1, 0.735758882342885}, 77 {2, 1, 0.919698602928606}, 78 {3, 1, 0.981011843123846}, 79 {4, 1, 0.996340153172656}, 80 {5, 1, 0.999405815182418}, 81 {6, 1, 0.999916758850712}, 82 {7, 1, 0.999989750803325}, 83 {8, 1, 0.999998874797402}, 84 {9, 1, 0.999999888574522}, 85 86 {0, 2.5, 0.082084998623899}, 87 {1, 2.5, 0.287297495183646}, 88 {2, 2.5, 0.543813115883329}, 89 {3, 2.5, 0.757576133133066}, 90 {4, 2.5, 0.891178018914151}, 91 {5, 2.5, 0.957978961804694}, 92 {6, 2.5, 0.985812688009087}, 93 {7, 2.5, 0.995753304510655}, 94 {8, 2.5, 0.998859747167396}, 95 {9, 2.5, 0.999722647905379}, 96 } { 97 p := Poisson{Lambda: tt.lambda} 98 got := p.CDF(tt.k) 99 if !scalar.EqualWithinAbs(got, tt.want, tol) { 100 t.Errorf("test-%d: got=%e. want=%e\n", i, got, tt.want) 101 } 102 } 103 } 104 105 func TestPoisson(t *testing.T) { 106 t.Parallel() 107 src := rand.New(rand.NewSource(1)) 108 for i, b := range []Poisson{ 109 {100, src}, 110 {15, src}, 111 {10, src}, 112 {9.9, src}, 113 {3, src}, 114 {1.5, src}, 115 {0.9, src}, 116 } { 117 testPoisson(t, b, i) 118 } 119 } 120 121 func testPoisson(t *testing.T, p Poisson, i int) { 122 const ( 123 tol = 1e-2 124 n = 2e6 125 ) 126 x := make([]float64, n) 127 generateSamples(x, p) 128 sort.Float64s(x) 129 130 checkProbDiscrete(t, i, x, p, 2e-3) 131 checkMean(t, i, x, p, tol) 132 checkVarAndStd(t, i, x, p, tol) 133 checkExKurtosis(t, i, x, p, 7e-2) 134 checkSkewness(t, i, x, p, tol) 135 136 if p.NumParameters() != 1 { 137 t.Errorf("Mismatch in NumParameters: got %v, want 1", p.NumParameters()) 138 } 139 cdf := p.CDF(-0.0001) 140 if cdf != 0 { 141 t.Errorf("Mismatch in CDF for x < 0: got %v, want 0", cdf) 142 } 143 surv := p.Survival(-0.0001) 144 if surv != 1 { 145 t.Errorf("Mismatch in Survival for x < 0: got %v, want 1", surv) 146 } 147 logProb := p.LogProb(-0.0001) 148 if !math.IsInf(logProb, -1) { 149 t.Errorf("Mismatch in LogProb for x < 0: got %v, want -Inf", logProb) 150 } 151 logProb = p.LogProb(1.5) 152 if !math.IsInf(logProb, -1) { 153 t.Errorf("Mismatch in LogProb for non-integer x: got %v, want -Inf", logProb) 154 } 155 for _, xx := range x { 156 cdf = p.CDF(xx) 157 surv = p.Survival(xx) 158 if math.Abs(cdf+surv-1) > 1e-10 { 159 t.Errorf("Mismatch between CDF and Survival at %g", xx) 160 } 161 } 162 } 163 164 func BenchmarkPoissonRand(b *testing.B) { 165 src := rand.New(rand.NewSource(1)) 166 for i, p := range []Poisson{ 167 {100, src}, 168 {15, src}, 169 {10, src}, 170 {9.9, src}, 171 {3, src}, 172 {1.5, src}, 173 {0.9, src}, 174 } { 175 b.Run(fmt.Sprintf("case %d", i), func(b *testing.B) { 176 for i := 0; i < b.N; i++ { 177 p.Rand() 178 } 179 }) 180 } 181 }