Class: ERV::MixtureDistribution

Inherits:
Object
  • Object
show all
Defined in:
lib/erv/mixture_distribution.rb

Instance Method Summary collapse

Constructor Details

#initialize(confs, opts = {}) ⇒ MixtureDistribution

Returns a new instance of MixtureDistribution.

Raises:

  • (ArgumentError)


13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/erv/mixture_distribution.rb', line 13

def initialize(confs, opts={})
  raise ArgumentError, "Please, provide at least 2 distributions!" if confs.count < 2

  @mixture = []
  weight_sum = 0.0
  confs.each do |x|
    dist_conf = x.dup
    # get weight ...
    weight = dist_conf.delete(:weight).to_f

    # ... and keep track of it
    weight_sum += weight

    # get distribution name
    dist_name = dist_conf.delete(:distribution).to_s

    # get class name that corresponds to the requested distribution
    klass_name = dist_name.split('_').push('distribution').map(&:capitalize).join

    # create distribution object
    distribution = ERV.const_get(klass_name).new(dist_conf[:args])

    # add distribution to mixture
    @mixture << { weight: weight, distribution: distribution }
  end

  # normalize weights
  @mixture.each do |dist|
    dist[:weight] /= weight_sum
  end

  seed = opts[:seed]
  @mixture_sampler = (seed ? Random.new(seed) : Random.new)
end

Instance Method Details

#meanObject



62
63
64
# File 'lib/erv/mixture_distribution.rb', line 62

def mean
  @mean ||= calculate_mean
end

#sampleObject



48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/erv/mixture_distribution.rb', line 48

def sample
  x = @mixture_sampler.rand

  # find index of distribution we are supposed to sample from
  i = 0
  while x > @mixture[i][:weight]
    x -= @mixture[i][:weight]
    i += 1
  end

  # return sample
  @mixture[i][:distribution].sample
end

#varianceObject



66
67
68
# File 'lib/erv/mixture_distribution.rb', line 66

def variance
  @variance ||= calculate_variance
end