Class: Saulabs::Gauss::Distribution

Inherits:
Object
  • Object
show all
Defined in:
lib/saulabs/gauss/distribution.rb

Overview

Implementation of a gaussian distribution

Direct Known Subclasses

TrueSkill::Rating

Constant Summary collapse

@@sqrt2 =
Math.sqrt(2).freeze
@@inv_sqrt_2pi =
(1 / Math.sqrt(2 * Math::PI)).freeze
@@log_sqrt_2pi =
Math.log(Math.sqrt(2 * Math::PI)).freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(mean = 0.0, deviation = 0.0) ⇒ Distribution

Returns a new instance of Distribution.



16
17
18
19
20
21
22
23
24
# File 'lib/saulabs/gauss/distribution.rb', line 16

def initialize(mean = 0.0, deviation = 0.0)
  mean = 0.0 unless mean.to_f.finite?
  deviation = 0.0 unless deviation.to_f.finite?
  @mean = mean
  @deviation = deviation
  @variance = deviation * deviation
  @precision = deviation == 0.0 ? 0.0 : 1 / @variance.to_f
  @precision_mean = @precision * mean
end

Instance Attribute Details

#deviationObject

gaussian normal distribution values



14
15
16
# File 'lib/saulabs/gauss/distribution.rb', line 14

def deviation
  @deviation
end

#meanObject

gaussian normal distribution values



14
15
16
# File 'lib/saulabs/gauss/distribution.rb', line 14

def mean
  @mean
end

#precisionObject

gaussian normal distribution values



14
15
16
# File 'lib/saulabs/gauss/distribution.rb', line 14

def precision
  @precision
end

#precision_meanObject

gaussian normal distribution values



14
15
16
# File 'lib/saulabs/gauss/distribution.rb', line 14

def precision_mean
  @precision_mean
end

#varianceObject

gaussian normal distribution values



14
15
16
# File 'lib/saulabs/gauss/distribution.rb', line 14

def variance
  @variance
end

Class Method Details

.absolute_difference(x, y) ⇒ Object



44
45
46
# File 'lib/saulabs/gauss/distribution.rb', line 44

def absolute_difference(x, y)
  [(x.precision_mean - y.precision_mean).abs, Math.sqrt((x.precision - y.precision).abs)].max
end

.cumulative_distribution_function(x) ⇒ Object Also known as: cdf

Computes the cummulative Gaussian distribution at a specified point of interest



64
65
66
# File 'lib/saulabs/gauss/distribution.rb', line 64

def cumulative_distribution_function(x)
  0.5 * (1 + Math.erf(x / @@sqrt2))
end

.erf(x) ⇒ Object



96
97
98
# File 'lib/saulabs/gauss/distribution.rb', line 96

def erf(x)
  Math.erfc(x)
end

.inv_erf(p) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/saulabs/gauss/distribution.rb', line 81

def inv_erf(p)
  return -100 if p >= 2.0
  return 100 if p <= 0.0

  pp = p < 1.0 ? p : 2 - p
  t = Math.sqrt(-2*Math.log(pp/2.0)) # Initial guess
  x = -0.70711*((2.30753 + t*0.27061)/(1.0 + t*(0.99229 + t*0.04481)) - t)

  [0,1].each do |j|
    err = erf(x) - pp
    x += err/(1.12837916709551257*Math.exp(-(x*x)) - x*err) # Halley
  end
  p < 1.0 ? x : -x
end

.log_product_normalization(x, y) ⇒ Object



48
49
50
51
52
53
# File 'lib/saulabs/gauss/distribution.rb', line 48

def log_product_normalization(x, y)
  return 0.0 if x.precision == 0.0 || y.precision == 0.0
  variance_sum = x.variance + y.variance
  mean_diff = x.mean - y.mean
  -@@log_sqrt_2pi - (Math.log(variance_sum) / 2.0) - (mean_diff**2 / (2.0 * variance_sum))
end

.log_ratio_normalization(x, y) ⇒ Object



55
56
57
58
59
60
61
# File 'lib/saulabs/gauss/distribution.rb', line 55

def log_ratio_normalization(x, y)
  return 0.0 if x.precision == 0.0 || y.precision == 0.0
  variance_diff = y.variance - x.variance
  return 0.0 if variance_diff == 0.0
  mean_diff = x.mean - y.mean
  Math.log(y.variance) + @@log_sqrt_2pi - (Math.log(variance_diff) / 2.0) + (mean_diff**2 / (2.0 * variance_diff))
end

.probability_density_function(x) ⇒ Object Also known as: pdf

Computes the Gaussian density at a specified point of interest



70
71
72
# File 'lib/saulabs/gauss/distribution.rb', line 70

def probability_density_function(x)
  @@inv_sqrt_2pi * Math.exp(-0.5 * (x**2))
end

.quantile_function(x) ⇒ Object Also known as: inv_cdf

The inverse of the cummulative Gaussian distribution function



76
77
78
# File 'lib/saulabs/gauss/distribution.rb', line 76

def quantile_function(x)
  -@@sqrt2 * inv_erf(2.0 * x)
end

.standardObject



28
29
30
# File 'lib/saulabs/gauss/distribution.rb', line 28

def standard
  Distribution.new(0.0, 1.0)
end

.with_deviation(mean, deviation) ⇒ Object



32
33
34
# File 'lib/saulabs/gauss/distribution.rb', line 32

def with_deviation(mean, deviation)
  Distribution.new(mean, deviation)
end

.with_precision(mean, precision) ⇒ Object



40
41
42
# File 'lib/saulabs/gauss/distribution.rb', line 40

def with_precision(mean, precision)
  Distribution.new(mean / precision, Math.sqrt(1 / precision))
end

.with_variance(mean, variance) ⇒ Object



36
37
38
# File 'lib/saulabs/gauss/distribution.rb', line 36

def with_variance(mean, variance)
  Distribution.new(mean, Math.sqrt(variance))
end

Instance Method Details

#*(other) ⇒ Object



116
117
118
# File 'lib/saulabs/gauss/distribution.rb', line 116

def *(other)
  Distribution.with_precision(self.precision_mean + other.precision_mean, self.precision + other.precision)
end

#+(other) ⇒ Object



129
130
131
# File 'lib/saulabs/gauss/distribution.rb', line 129

def +(other)

end

#-(other) ⇒ Object

absolute difference



125
126
127
# File 'lib/saulabs/gauss/distribution.rb', line 125

def -(other)
  Distribution.absolute_difference(self, other)
end

#/(other) ⇒ Object



120
121
122
# File 'lib/saulabs/gauss/distribution.rb', line 120

def /(other)
  Distribution.with_precision(self.precision_mean - other.precision_mean, self.precision - other.precision)
end

#==(other) ⇒ Object



133
134
135
# File 'lib/saulabs/gauss/distribution.rb', line 133

def ==(other)
  self.mean == other.mean && self.variance == other.variance
end

#equals(other) ⇒ Object



137
138
139
# File 'lib/saulabs/gauss/distribution.rb', line 137

def equals(other)
  self == other
end

#replace(other) ⇒ Object

copy values from other distribution



108
109
110
111
112
113
114
# File 'lib/saulabs/gauss/distribution.rb', line 108

def replace(other)
  @precision = other.precision
  @precision_mean = other.precision_mean
  @mean = other.mean
  @deviation = other.deviation
  @variance = other.variance
end

#to_sObject



141
142
143
# File 'lib/saulabs/gauss/distribution.rb', line 141

def to_s
  "[μ=#{'%.4f' % mean}, σ=#{'%.4f' % deviation}]"
end

#value_at(x) ⇒ Object



102
103
104
105
# File 'lib/saulabs/gauss/distribution.rb', line 102

def value_at(x)
  exp = -(x - @mean)**2.0 / (2.0 * @variance)
  (1.0/@deviation) * @@inv_sqrt_2pi * Math.exp(exp)
end