gonum.org/v1/gonum@v0.14.0/stat/distuv/exponential_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 TestExponentialProb(t *testing.T) { 16 t.Parallel() 17 pts := []univariateProbPoint{ 18 { 19 loc: 0, 20 prob: 1, 21 cumProb: 0, 22 logProb: 0, 23 }, 24 { 25 loc: -1, 26 prob: 0, 27 cumProb: 0, 28 logProb: math.Inf(-1), 29 }, 30 { 31 loc: 1, 32 prob: 1 / (math.E), 33 cumProb: 0.6321205588285576784044762298385391325541888689682321654921631983025385042551001966428527256540803563, 34 logProb: -1, 35 }, 36 { 37 loc: 20, 38 prob: math.Exp(-20), 39 cumProb: 0.999999997938846377561442172034059619844179023624192724400896307027755338370835976215440646720089072, 40 logProb: -20, 41 }, 42 } 43 testDistributionProbs(t, Exponential{Rate: 1}, "Exponential", pts) 44 } 45 46 func TestExponentialFitPrior(t *testing.T) { 47 t.Parallel() 48 testConjugateUpdate(t, func() ConjugateUpdater { return &Exponential{Rate: 13.7, Src: rand.NewSource(1)} }) 49 } 50 51 func TestExponential(t *testing.T) { 52 t.Parallel() 53 src := rand.New(rand.NewSource(1)) 54 for i, dist := range []Exponential{ 55 {Rate: 3, Src: src}, 56 {Rate: 1.5, Src: src}, 57 {Rate: 0.9, Src: src}, 58 } { 59 testExponential(t, dist, i) 60 } 61 } 62 63 func testExponential(t *testing.T, dist Exponential, i int) { 64 const ( 65 tol = 1e-2 66 n = 3e6 67 bins = 50 68 ) 69 x := make([]float64, n) 70 generateSamples(x, dist) 71 sort.Float64s(x) 72 73 checkMean(t, i, x, dist, tol) 74 checkVarAndStd(t, i, x, dist, tol) 75 checkEntropy(t, i, x, dist, tol) 76 checkExKurtosis(t, i, x, dist, tol) 77 checkSkewness(t, i, x, dist, tol) 78 checkMedian(t, i, x, dist, tol) 79 checkQuantileCDFSurvival(t, i, x, dist, tol) 80 checkProbContinuous(t, i, x, 0, math.Inf(1), dist, 1e-10) 81 checkProbQuantContinuous(t, i, x, dist, tol) 82 83 if dist.Mode() != 0 { 84 t.Errorf("Mode is not 0. Got %v", dist.Mode()) 85 } 86 87 if dist.NumParameters() != 1 { 88 t.Errorf("NumParameters is not 1. Got %v", dist.NumParameters()) 89 } 90 91 if dist.NumSuffStat() != 1 { 92 t.Errorf("NumSuffStat is not 1. Got %v", dist.NumSuffStat()) 93 } 94 95 scoreInput := dist.ScoreInput(-0.0001) 96 if scoreInput != 0 { 97 t.Errorf("ScoreInput is not 0 for a negative argument. Got %v", scoreInput) 98 } 99 scoreInput = dist.ScoreInput(0) 100 if !math.IsNaN(scoreInput) { 101 t.Errorf("ScoreInput is not NaN at 0. Got %v", scoreInput) 102 } 103 scoreInput = dist.ScoreInput(1) 104 if scoreInput != -dist.Rate { 105 t.Errorf("ScoreInput mismatch for a positive argument. Got %v, want %g", scoreInput, dist.Rate) 106 } 107 108 deriv := make([]float64, 1) 109 dist.Score(deriv, -0.0001) 110 if deriv[0] != 0 { 111 t.Errorf("Score is not 0 for a negative argument. Got %v", deriv[0]) 112 } 113 dist.Score(deriv, 0) 114 if !math.IsNaN(deriv[0]) { 115 t.Errorf("Score is not NaN at 0. Got %v", deriv[0]) 116 } 117 118 if !panics(func() { dist.Quantile(-0.0001) }) { 119 t.Errorf("Expected panic with negative argument to Quantile") 120 } 121 if !panics(func() { dist.Quantile(1.0001) }) { 122 t.Errorf("Expected panic with argument to Quantile above 1") 123 } 124 } 125 126 func TestExponentialScore(t *testing.T) { 127 t.Parallel() 128 for _, test := range []*Exponential{ 129 { 130 Rate: 1, 131 }, 132 { 133 Rate: 0.35, 134 }, 135 { 136 Rate: 4.6, 137 }, 138 } { 139 testDerivParam(t, test) 140 } 141 } 142 143 func TestExponentialFitPanic(t *testing.T) { 144 t.Parallel() 145 e := Exponential{Rate: 2} 146 defer func() { 147 r := recover() 148 if r != nil { 149 t.Errorf("unexpected panic for Fit call: %v", r) 150 } 151 }() 152 e.Fit(make([]float64, 10), nil) 153 } 154 155 func TestExponentialCDFSmallArgument(t *testing.T) { 156 t.Parallel() 157 e := Exponential{Rate: 1} 158 x := 1e-17 159 p := e.CDF(x) 160 if math.Abs(p-x) > 1e-20 { 161 t.Errorf("Wrong CDF value for small argument. Got: %v, want: %g", p, x) 162 } 163 }