erv 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4df7f1fe74e08a93b0011dbce05db2862db6f742
4
- data.tar.gz: bef0cb26a91b1353971c3d2f1de8cc071832b60b
3
+ metadata.gz: 7dd791a7886ff932086acc0bfe0c30eb43dab514
4
+ data.tar.gz: b3b088d570cfb19d579d524f86fe35ddc731d879
5
5
  SHA512:
6
- metadata.gz: 85bc816dcaf649c8410138ddcb3496d449c701e9f847d842139c59c8e17a5f0e97b857ca362845c7365138afe0b524902bbdfd1eb060aa4151b03246582b1298
7
- data.tar.gz: 4308c0e5862acb574b6adb771998e95459f19dc929749716f55118ac068246f319be8bcd3a801ee36d6aaa2a812a6c94ed08f41efcb7568773624c4a0a1c95b5
6
+ metadata.gz: 11b2ad325261926571fe63d51c9f08227fa1785de31c57c7f60769721d9195b892965debd9278a42b1aca129e5c8a53f812a29ef900eab502cde48df16c41a6d
7
+ data.tar.gz: af27054d6de5b9e3d2285505c116957a96faaae155dcc7441d3beaf23ad582eeef9a98b4d2e0dc217c938daf867cf16af3825415fd7a85ed5ade682f8d4b77a4
@@ -14,13 +14,19 @@ module ERV
14
14
  raise ArgumentError, "Please, provide at least 2 distributions!" unless confs.length >= 2
15
15
 
16
16
  @mixture = []
17
- @weight_sum = 0.0
17
+ weight_sum = 0.0
18
18
  while dist_conf = confs.shift
19
19
  # get weight ...
20
20
  weight = dist_conf.delete(:weight).to_f
21
21
 
22
22
  # ... and keep track of it
23
- @weight_sum += weight
23
+ weight_sum += weight
24
+
25
+ # get amplitude
26
+ amplitude = dist_conf.fetch(:amplitude) { 1.0 }
27
+ # unless amplitude.is_a? Float
28
+ # raise ArgumentError, "Please, provide at least 2 distributions!" unless confs.length >= 2
29
+ # end
24
30
 
25
31
  # get distribution name
26
32
  dist_name = dist_conf.delete(:distribution).to_s
@@ -32,7 +38,12 @@ module ERV
32
38
  distribution = ERV.const_get(klass_name).new(dist_conf)
33
39
 
34
40
  # add distribution to mixture
35
- @mixture << { weight: weight, distribution: distribution }
41
+ @mixture << { amplitude: amplitude, weight: weight, distribution: distribution }
42
+ end
43
+
44
+ # normalize weights
45
+ @mixture.each do |dist|
46
+ dist[:weight] /= weight_sum
36
47
  end
37
48
 
38
49
  seed = opts[:seed]
@@ -44,13 +55,13 @@ module ERV
44
55
 
45
56
  # find index of distribution we are supposed to sample from
46
57
  i = 0
47
- while x > (@mixture[i][:weight] / @weight_sum)
48
- x -= (@mixture[i][:weight] / @weight_sum)
58
+ while x > @mixture[i][:weight]
59
+ x -= @mixture[i][:weight]
49
60
  i += 1
50
61
  end
51
62
 
52
63
  # return sample
53
- @mixture[i][:distribution].sample
64
+ @mixture[i][:amplitude] * @mixture[i][:distribution].sample
54
65
  end
55
66
 
56
67
  def mean
@@ -64,16 +75,24 @@ module ERV
64
75
  private
65
76
 
66
77
  def calculate_mean
67
- @mixture.inject(0.0) do |s,x|
68
- s += (x[:weight] / @weight_sum * x[:distribution].mean)
78
+ @mixture.inject(0.0) do |s,x|
79
+ s += (# the following formula was taken from
80
+ # https://en.wikipedia.org/wiki/Mixture_Distribution#Moments
81
+ x[:weight] *
82
+ # remember: E[aX] = a E[X]
83
+ x[:amplitude] * x[:distribution].mean)
69
84
  end
70
85
  end
71
86
 
72
87
  def calculate_variance
73
- @mixture.inject(0.0) do |s,x|
74
- s += (x[:weight] / @weight_sum *
75
- ((x[:distribution].mean - self.mean) ** 2 +
76
- x[:distribution].variance))
88
+ @mixture.inject(0.0) do |s,x|
89
+ s += (# the following formula was taken from
90
+ # https://en.wikipedia.org/wiki/Mixture_Distribution#Moments
91
+ x[:weight] *
92
+ # remember: E[aX] = a E[X]
93
+ ((x[:amplitude] * x[:distribution].mean - self.mean) ** 2 +
94
+ # remember: Var(aX) = a**2 Var(X)
95
+ x[:amplitude] ** 2 * x[:distribution].variance))
77
96
  end
78
97
  end
79
98
  end
data/lib/erv/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module ERV
2
- VERSION = '0.2.0'
2
+ VERSION = '0.3.0'
3
3
  end
@@ -9,14 +9,6 @@ describe ERV::MixtureDistribution do
9
9
  end.must_raise ArgumentError
10
10
  end
11
11
 
12
- it 'should keep track of distribution weights (for normalization)' do
13
- # create a mixture distribution with unnormalized weights
14
- uw_md = ERV::MixtureDistribution.new([ { distribution: :exponential, rate: 1.0, weight: 100.0 },
15
- { distribution: :exponential, rate: 2.0, weight: 200.0 },
16
- { distribution: :exponential, rate: 3.0, weight: 300.0 } ])
17
- uw_md.instance_variable_get("@weight_sum").must_equal 600.0
18
- end
19
-
20
12
  let :md do
21
13
  ERV::MixtureDistribution.new([ { distribution: :exponential, rate: 1.0, weight: 0.3 },
22
14
  { distribution: :exponential, rate: 2.0, weight: 0.2 },
@@ -33,23 +25,81 @@ describe ERV::MixtureDistribution do
33
25
 
34
26
  context 'moments' do
35
27
 
36
- let :expected_mean do
37
- 0.3 * 1/1.0 + 0.2 * 1/2.0 + 0.5 * 1/3.0
38
- end
28
+ context 'with default amplitude' do
29
+ let :md_expected_mean do
30
+ 0.3 * 1/1.0 + 0.2 * 1/2.0 + 0.5 * 1/3.0
31
+ end
32
+
33
+ let :md_expected_variance do
34
+ 0.3 * ((1/1.0 - md_expected_mean) ** 2 + (1/1.0) ** 2) +
35
+ 0.2 * ((1/2.0 - md_expected_mean) ** 2 + (1/2.0) ** 2) +
36
+ 0.5 * ((1/3.0 - md_expected_mean) ** 2 + (1/3.0) ** 2)
37
+ end
39
38
 
40
- let :expected_variance do
41
- 0.3 * (1/1.0 - expected_mean) ** 2 + (1/1.0) ** 2 +
42
- 0.2 * (1/2.0 - expected_mean) ** 2 + (1/2.0) ** 2 +
43
- 0.5 * (1/3.0 - expected_mean) ** 2 + (1/3.0) ** 2
39
+ it 'should correctly calculate the mean of the mixture' do
40
+ md.mean.must_equal md_expected_mean
41
+ end
42
+
43
+ it 'should correctly calculate the variance of the mixture' do
44
+ md.variance.must_equal md_expected_variance
45
+ end
44
46
  end
45
47
 
46
- it 'should correctly calculate the mean of the mixture' do
47
- md.mean.must_equal expected_mean
48
+ context 'with different amplitudes' do
49
+ let :amd do
50
+ ERV::MixtureDistribution.new([ { distribution: :gaussian, amplitude: 3.0, mean: 1.0, sd: 0.1, weight: 0.3 },
51
+ { distribution: :gaussian, amplitude: 5.0, mean: 2.0, sd: 0.2, weight: 0.2 },
52
+ { distribution: :gaussian, amplitude: 7.0, mean: 3.0, sd: 0.3, weight: 0.5 } ])
53
+ end
54
+
55
+ let :amd_expected_mean do
56
+ 0.3 * 3.0 * 1.0 +
57
+ 0.2 * 5.0 * 2.0 +
58
+ 0.5 * 7.0 * 3.0
59
+ end
60
+
61
+ let :amd_expected_variance do
62
+ 0.3 * ((3.0 * 1.0 - amd_expected_mean) ** 2 + (3.0 * 0.1) ** 2) +
63
+ 0.2 * ((5.0 * 2.0 - amd_expected_mean) ** 2 + (5.0 * 0.2) ** 2) +
64
+ 0.5 * ((7.0 * 3.0 - amd_expected_mean) ** 2 + (7.0 * 0.3) ** 2)
65
+ end
66
+
67
+ it 'should correctly calculate the mean of the mixture' do
68
+ amd.mean.must_equal amd_expected_mean
69
+ end
70
+
71
+ it 'should correctly calculate the variance of the mixture' do
72
+ amd.variance.must_equal amd_expected_variance
73
+ end
48
74
  end
49
75
 
50
- it 'should correctly calculate the variance of the mixture' do
51
- md.mean.must_equal expected_mean
76
+ context 'with unnormalized weights' do
77
+ let :uwmd do
78
+ ERV::MixtureDistribution.new([ { distribution: :exponential, rate: 1.0, weight: 300 },
79
+ { distribution: :exponential, rate: 2.0, weight: 200 },
80
+ { distribution: :exponential, rate: 3.0, weight: 500 } ])
81
+ end
82
+
83
+ let :uwmd_expected_mean do
84
+ 0.3 * 1/1.0 + 0.2 * 1/2.0 + 0.5 * 1/3.0
85
+ end
86
+
87
+ let :uwmd_expected_variance do
88
+ 0.3 * ((1/1.0 - uwmd_expected_mean) ** 2 + (1/1.0) ** 2) +
89
+ 0.2 * ((1/2.0 - uwmd_expected_mean) ** 2 + (1/2.0) ** 2) +
90
+ 0.5 * ((1/3.0 - uwmd_expected_mean) ** 2 + (1/3.0) ** 2)
91
+ end
92
+
93
+ it 'should correctly calculate the mean of the mixture' do
94
+ uwmd.mean.must_equal uwmd_expected_mean
95
+ end
96
+
97
+ it 'should correctly calculate the variance of the mixture' do
98
+ uwmd.variance.must_equal uwmd_expected_variance
99
+ end
100
+
52
101
  end
53
102
 
54
103
  end
104
+
55
105
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: erv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mauro Tortonesi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-26 00:00:00.000000000 Z
11
+ date: 2017-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,7 +80,7 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: 0.0.3
83
- description: erv-0.2.0
83
+ description: erv-0.3.0
84
84
  email:
85
85
  - mauro.tortonesi@unife.it
86
86
  executables: []