gonum.org/v1/gonum@v0.14.0/stat/distuv/weibull_test.go (about) 1 // Copyright ©2014 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 "sort" 10 "testing" 11 12 "golang.org/x/exp/rand" 13 ) 14 15 func TestHalfKStandardWeibullProb(t *testing.T) { 16 t.Parallel() 17 pts := []univariateProbPoint{ 18 { 19 loc: 0, 20 prob: math.Inf(1), 21 cumProb: 0, 22 logProb: math.Inf(1), 23 }, 24 { 25 loc: -1, 26 prob: 0, 27 cumProb: 0, 28 logProb: math.Inf(-1), 29 }, 30 { 31 loc: 1, 32 prob: 0.183939720585721, 33 cumProb: 0.632120558828558, 34 logProb: -1.693147180559950, 35 }, 36 { 37 loc: 20, 38 prob: 0.001277118038048, 39 cumProb: 0.988577109006533, 40 logProb: -6.663149272336520, 41 }, 42 } 43 testDistributionProbs(t, Weibull{K: 0.5, Lambda: 1}, "0.5K Standard Weibull", pts) 44 } 45 46 func TestExponentialStandardWeibullProb(t *testing.T) { 47 t.Parallel() 48 pts := []univariateProbPoint{ 49 { 50 loc: 0, 51 prob: 1, 52 cumProb: 0, 53 logProb: 0, 54 }, 55 { 56 loc: -1, 57 prob: 0, 58 cumProb: 0, 59 logProb: math.Inf(-1), 60 }, 61 { 62 loc: 1, 63 prob: 0.367879441171442, 64 cumProb: 0.632120558828558, 65 logProb: -1.0, 66 }, 67 { 68 loc: 20, 69 prob: 0.000000002061154, 70 cumProb: 0.999999997938846, 71 logProb: -20.0, 72 }, 73 } 74 testDistributionProbs(t, Weibull{K: 1, Lambda: 1}, "1K (Exponential) Standard Weibull", pts) 75 } 76 77 func TestRayleighStandardWeibullProb(t *testing.T) { 78 t.Parallel() 79 pts := []univariateProbPoint{ 80 { 81 loc: 0, 82 prob: 0, 83 cumProb: 0, 84 logProb: math.Inf(-1), 85 }, 86 { 87 loc: -1, 88 prob: 0, 89 cumProb: 0, 90 logProb: math.Inf(-1), 91 }, 92 { 93 loc: 1, 94 prob: 0.735758882342885, 95 cumProb: 0.632120558828558, 96 logProb: -0.306852819440055, 97 }, 98 { 99 loc: 20, 100 prob: 0, 101 cumProb: 1, 102 logProb: -396.31112054588607, 103 }, 104 } 105 testDistributionProbs(t, Weibull{K: 2, Lambda: 1}, "2K (Rayleigh) Standard Weibull", pts) 106 } 107 108 func TestFiveKStandardWeibullProb(t *testing.T) { 109 t.Parallel() 110 pts := []univariateProbPoint{ 111 { 112 loc: 0, 113 prob: 0, 114 cumProb: 0, 115 logProb: math.Inf(-1), 116 }, 117 { 118 loc: -1, 119 prob: 0, 120 cumProb: 0, 121 logProb: math.Inf(-1), 122 }, 123 { 124 loc: 1, 125 prob: 1.839397205857210, 126 cumProb: 0.632120558828558, 127 logProb: 0.609437912434100, 128 }, 129 { 130 loc: 20, 131 prob: 0, 132 cumProb: 1, 133 logProb: -3199986.4076329935, 134 }, 135 } 136 testDistributionProbs(t, Weibull{K: 5, Lambda: 1}, "5K Standard Weibull", pts) 137 } 138 139 func TestScaledUpHalfKStandardWeibullProb(t *testing.T) { 140 t.Parallel() 141 pts := []univariateProbPoint{ 142 { 143 loc: 0, 144 prob: math.Inf(1), 145 cumProb: 0, 146 logProb: math.Inf(1), 147 }, 148 { 149 loc: -1, 150 prob: 0, 151 cumProb: 0, 152 logProb: math.Inf(-1), 153 }, 154 { 155 loc: 1, 156 prob: 0.180436508682207, 157 cumProb: 0.558022622759326, 158 logProb: -1.712376315541750, 159 }, 160 { 161 loc: 20, 162 prob: 0.002369136850928, 163 cumProb: 0.974047406098605, 164 logProb: -6.045229588092130, 165 }, 166 } 167 testDistributionProbs(t, Weibull{K: 0.5, Lambda: 1.5}, "0.5K 1.5λ Weibull", pts) 168 } 169 170 func TestScaledDownHalfKStandardWeibullProb(t *testing.T) { 171 t.Parallel() 172 pts := []univariateProbPoint{ 173 { 174 loc: 0, 175 prob: math.Inf(1), 176 cumProb: 0, 177 logProb: math.Inf(1), 178 }, 179 { 180 loc: -1, 181 prob: 0, 182 cumProb: 0, 183 logProb: math.Inf(-1), 184 }, 185 { 186 loc: 1, 187 prob: 0.171909491538362, 188 cumProb: 0.756883265565786, 189 logProb: -1.760787152653070, 190 }, 191 { 192 loc: 20, 193 prob: 0.000283302579100, 194 cumProb: 0.998208237166091, 195 logProb: -8.168995047393730, 196 }, 197 } 198 testDistributionProbs(t, Weibull{K: 0.5, Lambda: 0.5}, "0.5K 0.5λ Weibull", pts) 199 } 200 201 func TestWeibullScores(t *testing.T) { 202 t.Parallel() 203 for i, test := range []*Weibull{ 204 { 205 K: 1, 206 Lambda: 1, 207 }, 208 { 209 K: 2, 210 Lambda: 3.6, 211 }, 212 { 213 K: 3.4, 214 Lambda: 8, 215 }, 216 } { 217 testDerivParam(t, test) 218 for _, x := range []float64{0, -0.0001} { 219 score := test.Score(nil, 0) 220 if !math.IsNaN(score[0]) || !math.IsNaN(score[1]) { 221 t.Errorf("Score mismatch for case %d and x == %g: got %v, want [NaN, NaN]", i, x, score) 222 } 223 scoreInput := test.ScoreInput(0) 224 if !math.IsNaN(scoreInput) { 225 t.Errorf("ScoreInput mismatch for case %d and x == %g: got %v, want NaN", i, x, score) 226 } 227 } 228 } 229 } 230 231 func TestWeibull(t *testing.T) { 232 t.Parallel() 233 src := rand.New(rand.NewSource(1)) 234 for i, dist := range []Weibull{ 235 {K: 0.75, Lambda: 1, Src: src}, 236 {K: 1, Lambda: 1, Src: src}, 237 {K: 2, Lambda: 3.6, Src: src}, 238 {K: 3.4, Lambda: 8, Src: src}, 239 } { 240 testWeibull(t, dist, i) 241 } 242 } 243 244 func testWeibull(t *testing.T, dist Weibull, i int) { 245 const ( 246 tol = 1e-2 247 n = 3e6 248 bins = 50 249 ) 250 x := make([]float64, n) 251 generateSamples(x, dist) 252 sort.Float64s(x) 253 254 checkMean(t, i, x, dist, tol) 255 checkVarAndStd(t, i, x, dist, tol) 256 checkEntropy(t, i, x, dist, tol) 257 checkExKurtosis(t, i, x, dist, tol) 258 checkSkewness(t, i, x, dist, tol) 259 checkMedian(t, i, x, dist, tol) 260 checkQuantileCDFSurvival(t, i, x, dist, tol) 261 // Weibull distribution PDF has a singularity at 0 for K < 1, 262 // so we need higher tolerance. 263 var probTol float64 264 if dist.K >= 1 { 265 probTol = 1e-10 266 } else { 267 probTol = 1e-8 268 } 269 checkProbContinuous(t, i, x, 0, math.Inf(1), dist, probTol) 270 checkProbQuantContinuous(t, i, x, dist, tol) 271 checkMode(t, i, x, dist, 1e-1, 2e-1) 272 }