github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/stat/distuv/lognormal.go (about)

     1  // Copyright ©2015 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  // LogNormal represents a random variable whose log is normally distributed.
    14  // The probability density function is given by
    15  //  1/(x σ √2π) exp(-(ln(x)-μ)^2)/(2σ^2))
    16  type LogNormal struct {
    17  	Mu    float64
    18  	Sigma float64
    19  	Src   rand.Source
    20  }
    21  
    22  // CDF computes the value of the cumulative density function at x.
    23  func (l LogNormal) CDF(x float64) float64 {
    24  	return 0.5 * math.Erfc(-(math.Log(x)-l.Mu)/(math.Sqrt2*l.Sigma))
    25  }
    26  
    27  // Entropy returns the differential entropy of the distribution.
    28  func (l LogNormal) Entropy() float64 {
    29  	return 0.5 + 0.5*math.Log(2*math.Pi*l.Sigma*l.Sigma) + l.Mu
    30  }
    31  
    32  // ExKurtosis returns the excess kurtosis of the distribution.
    33  func (l LogNormal) ExKurtosis() float64 {
    34  	s2 := l.Sigma * l.Sigma
    35  	return math.Exp(4*s2) + 2*math.Exp(3*s2) + 3*math.Exp(2*s2) - 6
    36  }
    37  
    38  // LogProb computes the natural logarithm of the value of the probability density function at x.
    39  func (l LogNormal) LogProb(x float64) float64 {
    40  	if x < 0 {
    41  		return math.Inf(-1)
    42  	}
    43  	logx := math.Log(x)
    44  	normdiff := (logx - l.Mu) / l.Sigma
    45  	return -0.5*normdiff*normdiff - logx - math.Log(l.Sigma) - logRoot2Pi
    46  }
    47  
    48  // Mean returns the mean of the probability distribution.
    49  func (l LogNormal) Mean() float64 {
    50  	return math.Exp(l.Mu + 0.5*l.Sigma*l.Sigma)
    51  }
    52  
    53  // Median returns the median of the probability distribution.
    54  func (l LogNormal) Median() float64 {
    55  	return math.Exp(l.Mu)
    56  }
    57  
    58  // Mode returns the mode of the probability distribution.
    59  func (l LogNormal) Mode() float64 {
    60  	return math.Exp(l.Mu - l.Sigma*l.Sigma)
    61  }
    62  
    63  // NumParameters returns the number of parameters in the distribution.
    64  func (LogNormal) NumParameters() int {
    65  	return 2
    66  }
    67  
    68  // Prob computes the value of the probability density function at x.
    69  func (l LogNormal) Prob(x float64) float64 {
    70  	return math.Exp(l.LogProb(x))
    71  }
    72  
    73  // Quantile returns the inverse of the cumulative probability distribution.
    74  func (l LogNormal) Quantile(p float64) float64 {
    75  	if p < 0 || p > 1 {
    76  		panic(badPercentile)
    77  	}
    78  	// Formula from http://www.math.uah.edu/stat/special/LogNormal.html.
    79  	return math.Exp(l.Mu + l.Sigma*UnitNormal.Quantile(p))
    80  }
    81  
    82  // Rand returns a random sample drawn from the distribution.
    83  func (l LogNormal) Rand() float64 {
    84  	var rnd float64
    85  	if l.Src == nil {
    86  		rnd = rand.NormFloat64()
    87  	} else {
    88  		rnd = rand.New(l.Src).NormFloat64()
    89  	}
    90  	return math.Exp(rnd*l.Sigma + l.Mu)
    91  }
    92  
    93  // Skewness returns the skewness of the distribution.
    94  func (l LogNormal) Skewness() float64 {
    95  	s2 := l.Sigma * l.Sigma
    96  	return (math.Exp(s2) + 2) * math.Sqrt(math.Exp(s2)-1)
    97  }
    98  
    99  // StdDev returns the standard deviation of the probability distribution.
   100  func (l LogNormal) StdDev() float64 {
   101  	return math.Sqrt(l.Variance())
   102  }
   103  
   104  // Survival returns the survival function (complementary CDF) at x.
   105  func (l LogNormal) Survival(x float64) float64 {
   106  	return 0.5 * (1 - math.Erf((math.Log(x)-l.Mu)/(math.Sqrt2*l.Sigma)))
   107  }
   108  
   109  // Variance returns the variance of the probability distribution.
   110  func (l LogNormal) Variance() float64 {
   111  	s2 := l.Sigma * l.Sigma
   112  	return (math.Exp(s2) - 1) * math.Exp(2*l.Mu+s2)
   113  }