github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/stat/distuv/uniform.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 10 "golang.org/x/exp/rand" 11 ) 12 13 // UnitUniform is an instantiation of the uniform distribution with Min = 0 14 // and Max = 1. 15 var UnitUniform = Uniform{Min: 0, Max: 1} 16 17 // Uniform represents a continuous uniform distribution (https://en.wikipedia.org/wiki/Uniform_distribution_%28continuous%29). 18 type Uniform struct { 19 Min float64 20 Max float64 21 Src rand.Source 22 } 23 24 // CDF computes the value of the cumulative density function at x. 25 func (u Uniform) CDF(x float64) float64 { 26 if x < u.Min { 27 return 0 28 } 29 if x > u.Max { 30 return 1 31 } 32 return (x - u.Min) / (u.Max - u.Min) 33 } 34 35 // Uniform doesn't have any of the DLogProbD? because the derivative is 0 everywhere 36 // except where it's undefined 37 38 // Entropy returns the entropy of the distribution. 39 func (u Uniform) Entropy() float64 { 40 return math.Log(u.Max - u.Min) 41 } 42 43 // ExKurtosis returns the excess kurtosis of the distribution. 44 func (Uniform) ExKurtosis() float64 { 45 return -6.0 / 5.0 46 } 47 48 // Uniform doesn't have Fit because it's a bad idea to fit a uniform from data. 49 50 // LogProb computes the natural logarithm of the value of the probability density function at x. 51 func (u Uniform) LogProb(x float64) float64 { 52 if x < u.Min { 53 return math.Inf(-1) 54 } 55 if x > u.Max { 56 return math.Inf(-1) 57 } 58 return -math.Log(u.Max - u.Min) 59 } 60 61 // parameters returns the parameters of the distribution. 62 func (u Uniform) parameters(p []Parameter) []Parameter { 63 nParam := u.NumParameters() 64 if p == nil { 65 p = make([]Parameter, nParam) 66 } else if len(p) != nParam { 67 panic("uniform: improper parameter length") 68 } 69 p[0].Name = "Min" 70 p[0].Value = u.Min 71 p[1].Name = "Max" 72 p[1].Value = u.Max 73 return p 74 } 75 76 // Mean returns the mean of the probability distribution. 77 func (u Uniform) Mean() float64 { 78 return (u.Max + u.Min) / 2 79 } 80 81 // Median returns the median of the probability distribution. 82 func (u Uniform) Median() float64 { 83 return (u.Max + u.Min) / 2 84 } 85 86 // Uniform doesn't have a mode because it's any value in the distribution 87 88 // NumParameters returns the number of parameters in the distribution. 89 func (Uniform) NumParameters() int { 90 return 2 91 } 92 93 // Prob computes the value of the probability density function at x. 94 func (u Uniform) Prob(x float64) float64 { 95 if x < u.Min { 96 return 0 97 } 98 if x > u.Max { 99 return 0 100 } 101 return 1 / (u.Max - u.Min) 102 } 103 104 // Quantile returns the inverse of the cumulative probability distribution. 105 func (u Uniform) Quantile(p float64) float64 { 106 if p < 0 || p > 1 { 107 panic(badPercentile) 108 } 109 return p*(u.Max-u.Min) + u.Min 110 } 111 112 // Rand returns a random sample drawn from the distribution. 113 func (u Uniform) Rand() float64 { 114 var rnd float64 115 if u.Src == nil { 116 rnd = rand.Float64() 117 } else { 118 rnd = rand.New(u.Src).Float64() 119 } 120 return rnd*(u.Max-u.Min) + u.Min 121 } 122 123 // Score returns the score function with respect to the parameters of the 124 // distribution at the input location x. The score function is the derivative 125 // of the log-likelihood at x with respect to the parameters 126 // (∂/∂θ) log(p(x;θ)) 127 // If deriv is non-nil, len(deriv) must equal the number of parameters otherwise 128 // Score will panic, and the derivative is stored in-place into deriv. If deriv 129 // is nil a new slice will be allocated and returned. 130 // 131 // The order is [∂LogProb / ∂Mu, ∂LogProb / ∂Sigma]. 132 // 133 // For more information, see https://en.wikipedia.org/wiki/Score_%28statistics%29. 134 func (u Uniform) Score(deriv []float64, x float64) []float64 { 135 if deriv == nil { 136 deriv = make([]float64, u.NumParameters()) 137 } 138 if len(deriv) != u.NumParameters() { 139 panic(badLength) 140 } 141 if (x < u.Min) || (x > u.Max) { 142 deriv[0] = math.NaN() 143 deriv[1] = math.NaN() 144 } else { 145 deriv[0] = 1 / (u.Max - u.Min) 146 deriv[1] = -deriv[0] 147 if x == u.Min { 148 deriv[0] = math.NaN() 149 } 150 if x == u.Max { 151 deriv[1] = math.NaN() 152 } 153 } 154 return deriv 155 } 156 157 // ScoreInput returns the score function with respect to the input of the 158 // distribution at the input location specified by x. The score function is the 159 // derivative of the log-likelihood 160 // (d/dx) log(p(x)) . 161 func (u Uniform) ScoreInput(x float64) float64 { 162 if (x <= u.Min) || (x >= u.Max) { 163 return math.NaN() 164 } 165 return 0 166 } 167 168 // Skewness returns the skewness of the distribution. 169 func (Uniform) Skewness() float64 { 170 return 0 171 } 172 173 // StdDev returns the standard deviation of the probability distribution. 174 func (u Uniform) StdDev() float64 { 175 return math.Sqrt(u.Variance()) 176 } 177 178 // Survival returns the survival function (complementary CDF) at x. 179 func (u Uniform) Survival(x float64) float64 { 180 if x < u.Min { 181 return 1 182 } 183 if x > u.Max { 184 return 0 185 } 186 return (u.Max - x) / (u.Max - u.Min) 187 } 188 189 // setParameters modifies the parameters of the distribution. 190 func (u *Uniform) setParameters(p []Parameter) { 191 if len(p) != u.NumParameters() { 192 panic("uniform: incorrect number of parameters to set") 193 } 194 if p[0].Name != "Min" { 195 panic("uniform: " + panicNameMismatch) 196 } 197 if p[1].Name != "Max" { 198 panic("uniform: " + panicNameMismatch) 199 } 200 201 u.Min = p[0].Value 202 u.Max = p[1].Value 203 } 204 205 // Variance returns the variance of the probability distribution. 206 func (u Uniform) Variance() float64 { 207 return 1.0 / 12.0 * (u.Max - u.Min) * (u.Max - u.Min) 208 }