Class: Wallace::Distributions::GaussianDistribution

Inherits:
Object
  • Object
show all
Defined in:
lib/distributions/gaussian_distribution.rb

Overview

Used to represent and sample values from a given Gaussian distribution.

Uses the popular Box-Muller transformation to generate two values, one of which is returned, the other which is cached (and returned upon the next request).

Since the Box-Muller transform samples two values from the distribution, rather than discarding the extra value, we cache it and return it upon the next request.

*Credit to:* stackoverflow.com/questions/5825680/code-to-generate-gaussian-normally-distributed-random-numbers-in-ruby

Instance Method Summary collapse

Constructor Details

#initialize(mean, std_dev) ⇒ GaussianDistribution

Constructs a new Gaussian distribution.

Parameters:

  • mean, the mean of this distribution.

  • std_dev, the standard deviation of this distribution.



20
21
22
23
24
# File 'lib/distributions/gaussian_distribution.rb', line 20

def initialize(mean, std_dev)
  @mean = mean
  @std_dev = std_dev
  @cached = nil
end

Instance Method Details

#sample(opts = {}) ⇒ Object

Samples a value from this distribution.

Uses the popular Box-Muller transformation to generate two values, one of which is returned, the other which is cached (and returned upon the next request).

Parameters:

  • opts, keyword arguments for this method.

  • -> random, the random number generation to use to seed the selection process.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/distributions/gaussian_distribution.rb', line 35

def sample(opts = {})

  # Create a RNG if one isn't already provided.
  random = opts[:random] || Random.new

  # Return a cached value if there is one.
  # We could collapse these 4 lines into a much nicer:
  # return @values.pop if @values.empty?
  # However .empty? is much more expensive!
  unless @cached.nil?
    value = @cached
    @cached = nil
    return value
  end

  # Otherwise calculate two new values, caching one and
  # returning the other.
  theta = 2 * Math::PI * random.rand
  rho = Math.sqrt(-2 * Math.log(1 - random.rand))
  scale = @std_dev * rho
  @cached = @mean + scale * Math.cos(theta)
  return @mean + scale * Math.sin(theta)
  
end