gonum.org/v1/gonum@v0.14.0/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 // 127 // (∂/∂θ) log(p(x;θ)) 128 // 129 // If deriv is non-nil, len(deriv) must equal the number of parameters otherwise 130 // Score will panic, and the derivative is stored in-place into deriv. If deriv 131 // is nil a new slice will be allocated and returned. 132 // 133 // The order is [∂LogProb / ∂Mu, ∂LogProb / ∂Sigma]. 134 // 135 // For more information, see https://en.wikipedia.org/wiki/Score_%28statistics%29. 136 func (u Uniform) Score(deriv []float64, x float64) []float64 { 137 if deriv == nil { 138 deriv = make([]float64, u.NumParameters()) 139 } 140 if len(deriv) != u.NumParameters() { 141 panic(badLength) 142 } 143 if (x < u.Min) || (x > u.Max) { 144 deriv[0] = math.NaN() 145 deriv[1] = math.NaN() 146 } else { 147 deriv[0] = 1 / (u.Max - u.Min) 148 deriv[1] = -deriv[0] 149 if x == u.Min { 150 deriv[0] = math.NaN() 151 } 152 if x == u.Max { 153 deriv[1] = math.NaN() 154 } 155 } 156 return deriv 157 } 158 159 // ScoreInput returns the score function with respect to the input of the 160 // distribution at the input location specified by x. The score function is the 161 // derivative of the log-likelihood 162 // 163 // (d/dx) log(p(x)) . 164 func (u Uniform) ScoreInput(x float64) float64 { 165 if (x <= u.Min) || (x >= u.Max) { 166 return math.NaN() 167 } 168 return 0 169 } 170 171 // Skewness returns the skewness of the distribution. 172 func (Uniform) Skewness() float64 { 173 return 0 174 } 175 176 // StdDev returns the standard deviation of the probability distribution. 177 func (u Uniform) StdDev() float64 { 178 return math.Sqrt(u.Variance()) 179 } 180 181 // Survival returns the survival function (complementary CDF) at x. 182 func (u Uniform) Survival(x float64) float64 { 183 if x < u.Min { 184 return 1 185 } 186 if x > u.Max { 187 return 0 188 } 189 return (u.Max - x) / (u.Max - u.Min) 190 } 191 192 // setParameters modifies the parameters of the distribution. 193 func (u *Uniform) setParameters(p []Parameter) { 194 if len(p) != u.NumParameters() { 195 panic("uniform: incorrect number of parameters to set") 196 } 197 if p[0].Name != "Min" { 198 panic("uniform: " + panicNameMismatch) 199 } 200 if p[1].Name != "Max" { 201 panic("uniform: " + panicNameMismatch) 202 } 203 204 u.Min = p[0].Value 205 u.Max = p[1].Value 206 } 207 208 // Variance returns the variance of the probability distribution. 209 func (u Uniform) Variance() float64 { 210 return 1.0 / 12.0 * (u.Max - u.Min) * (u.Max - u.Min) 211 }