erv 0.3.2 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/lib/erv/constant_distribution.rb +1 -1
- data/lib/erv/discrete_uniform_distribution.rb +1 -1
- data/lib/erv/distribution.rb +1 -1
- data/lib/erv/exponential_distribution.rb +1 -1
- data/lib/erv/gamma_distribution.rb +1 -1
- data/lib/erv/gaussian_distribution.rb +1 -1
- data/lib/erv/{general_pareto_distribution.rb → generalized_pareto_distribution.rb} +2 -2
- data/lib/erv/geometric_distribution.rb +1 -1
- data/lib/erv/mixture_distribution.rb +12 -23
- data/lib/erv/random_variable.rb +14 -8
- data/lib/erv/uniform_distribution.rb +1 -1
- data/lib/erv/version.rb +1 -1
- data/test/erv/discrete_uniform_distribution_test.rb +7 -7
- data/test/erv/exponential_distribution_test.rb +44 -0
- data/test/erv/gamma_distribution_test.rb +4 -4
- data/test/erv/gaussian_distribution_test.rb +44 -0
- data/test/erv/{general_pareto_distribution_test.rb → generalized_pareto_distribution_test.rb} +8 -8
- data/test/erv/geometric_distribution_test.rb +4 -4
- data/test/erv/mixture_distribution_test.rb +74 -39
- metadata +10 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c01ff8ee7e228352bd7e91cf37398ac1c9a4599
|
4
|
+
data.tar.gz: 1df36e92cac62835249f6b3be46e6b15ee23609c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61281fab1ea61ce27f999075719b1ad7a4cd955ab2cc5d48ec8d790eee445024a880329e3fea1f2d65e0d3eb014dc1d41e289533e2caec05a815b0b554c18916
|
7
|
+
data.tar.gz: b6db99c3a1a4babc7fdbb56028b16e9b865eadb95159269a5e63e8c6618a99a5950932c75e02fae7046c22523a40a33393bad5d02e8fb378567e597c0c3c11cc
|
data/LICENSE
CHANGED
data/lib/erv/distribution.rb
CHANGED
@@ -8,7 +8,7 @@ module ERV
|
|
8
8
|
class GpdDistribution < Distribution
|
9
9
|
attr_accessor :mean, :variance
|
10
10
|
|
11
|
-
def initialize(opts)
|
11
|
+
def initialize(opts={})
|
12
12
|
super(opts)
|
13
13
|
|
14
14
|
raise ArgumentError unless opts[:scale] and opts[:shape]
|
@@ -23,7 +23,7 @@ module ERV
|
|
23
23
|
end
|
24
24
|
|
25
25
|
@variance = if @shape < 0.5
|
26
|
-
(@scale ** 2.0) / (
|
26
|
+
(@scale ** 2.0) / (1.0 - @shape) ** 2 / (1.0 - 2 * @shape)
|
27
27
|
else
|
28
28
|
Infinity
|
29
29
|
end
|
@@ -3,7 +3,7 @@ require 'erv/discrete_uniform_distribution'
|
|
3
3
|
require 'erv/exponential_distribution'
|
4
4
|
require 'erv/gamma_distribution'
|
5
5
|
require 'erv/gaussian_distribution'
|
6
|
-
require 'erv/
|
6
|
+
require 'erv/generalized_pareto_distribution'
|
7
7
|
require 'erv/geometric_distribution'
|
8
8
|
require 'erv/uniform_distribution'
|
9
9
|
|
@@ -11,7 +11,7 @@ module ERV
|
|
11
11
|
|
12
12
|
class MixtureDistribution
|
13
13
|
def initialize(confs, opts={})
|
14
|
-
raise ArgumentError, "Please, provide at least 2 distributions!"
|
14
|
+
raise ArgumentError, "Please, provide at least 2 distributions!" if confs.count < 2
|
15
15
|
|
16
16
|
@mixture = []
|
17
17
|
weight_sum = 0.0
|
@@ -22,12 +22,6 @@ module ERV
|
|
22
22
|
# ... and keep track of it
|
23
23
|
weight_sum += weight
|
24
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
|
30
|
-
|
31
25
|
# get distribution name
|
32
26
|
dist_name = dist_conf.delete(:distribution).to_s
|
33
27
|
|
@@ -35,10 +29,10 @@ module ERV
|
|
35
29
|
klass_name = dist_name.split('_').push('distribution').map(&:capitalize).join
|
36
30
|
|
37
31
|
# create distribution object
|
38
|
-
distribution = ERV.const_get(klass_name).new(dist_conf)
|
32
|
+
distribution = ERV.const_get(klass_name).new(dist_conf[:args])
|
39
33
|
|
40
34
|
# add distribution to mixture
|
41
|
-
@mixture << {
|
35
|
+
@mixture << { weight: weight, distribution: distribution }
|
42
36
|
end
|
43
37
|
|
44
38
|
# normalize weights
|
@@ -61,7 +55,7 @@ module ERV
|
|
61
55
|
end
|
62
56
|
|
63
57
|
# return sample
|
64
|
-
@mixture[i][:
|
58
|
+
@mixture[i][:distribution].sample
|
65
59
|
end
|
66
60
|
|
67
61
|
def mean
|
@@ -76,23 +70,18 @@ module ERV
|
|
76
70
|
|
77
71
|
def calculate_mean
|
78
72
|
@mixture.inject(0.0) do |s,x|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
# remember: E[aX] = a E[X]
|
83
|
-
x[:amplitude] * x[:distribution].mean)
|
73
|
+
# the following formula was taken from
|
74
|
+
# https://en.wikipedia.org/wiki/Mixture_Distribution#Moments
|
75
|
+
s += (x[:weight] * x[:distribution].mean)
|
84
76
|
end
|
85
77
|
end
|
86
78
|
|
87
79
|
def calculate_variance
|
88
80
|
@mixture.inject(0.0) do |s,x|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
((x[:amplitude] * x[:distribution].mean - self.mean) ** 2 +
|
94
|
-
# remember: Var(aX) = a**2 Var(X)
|
95
|
-
x[:amplitude] ** 2 * x[:distribution].variance))
|
81
|
+
# the following formula was taken from
|
82
|
+
# https://en.wikipedia.org/wiki/Mixture_Distribution#Moments
|
83
|
+
s += (x[:weight] * ((x[:distribution].mean - self.mean) ** 2 +
|
84
|
+
x[:distribution].variance))
|
96
85
|
end
|
97
86
|
end
|
98
87
|
end
|
data/lib/erv/random_variable.rb
CHANGED
@@ -3,7 +3,7 @@ require 'erv/discrete_uniform_distribution'
|
|
3
3
|
require 'erv/exponential_distribution'
|
4
4
|
require 'erv/gamma_distribution'
|
5
5
|
require 'erv/gaussian_distribution'
|
6
|
-
require 'erv/
|
6
|
+
require 'erv/generalized_pareto_distribution'
|
7
7
|
require 'erv/geometric_distribution'
|
8
8
|
require 'erv/mixture_distribution'
|
9
9
|
require 'erv/uniform_distribution'
|
@@ -13,15 +13,20 @@ require 'erv/support/try'
|
|
13
13
|
module ERV
|
14
14
|
|
15
15
|
class RandomVariable
|
16
|
-
|
16
|
+
|
17
|
+
extend Forwardable
|
18
|
+
|
19
|
+
def_delegators :@dist, :mean, :variance
|
20
|
+
|
21
|
+
def initialize(args={})
|
17
22
|
# get distribution name
|
18
|
-
dist_name =
|
23
|
+
dist_name = args[:distribution].try(:to_s)
|
19
24
|
|
20
25
|
# get class name that corresponds to the requested distribution
|
21
26
|
klass_name = dist_name.split('_').push('distribution').map(&:capitalize).join
|
22
27
|
|
23
28
|
# create distribution object
|
24
|
-
@dist = ERV.const_get(klass_name).new(
|
29
|
+
@dist = ERV.const_get(klass_name).new(args)
|
25
30
|
end
|
26
31
|
|
27
32
|
def next
|
@@ -31,10 +36,11 @@ module ERV
|
|
31
36
|
|
32
37
|
|
33
38
|
class SequentialRandomVariable
|
34
|
-
def initialize(args)
|
35
|
-
first = args
|
36
|
-
|
37
|
-
@
|
39
|
+
def initialize(args={})
|
40
|
+
first = args.delete(:first_value)
|
41
|
+
raise ArgumentError, "First value must be provided!" if first.nil?
|
42
|
+
@most_recent = first.to_f
|
43
|
+
@var = RandomVariable.new(args)
|
38
44
|
end
|
39
45
|
|
40
46
|
def next
|
data/lib/erv/version.rb
CHANGED
@@ -4,7 +4,7 @@ require 'erv/discrete_uniform_distribution'
|
|
4
4
|
|
5
5
|
describe ERV::DiscreteUniformDistribution do
|
6
6
|
|
7
|
-
|
7
|
+
let :num_samples { 10000 }
|
8
8
|
|
9
9
|
it 'should require at least a maximum parameter' do
|
10
10
|
lambda do
|
@@ -29,16 +29,16 @@ describe ERV::DiscreteUniformDistribution do
|
|
29
29
|
|
30
30
|
context 'moments' do
|
31
31
|
let :samples do
|
32
|
-
0.upto(
|
32
|
+
0.upto(num_samples).collect { zero_to_sixty.sample }
|
33
33
|
end
|
34
34
|
|
35
35
|
it 'should have the expected mean' do
|
36
|
-
sample_mean = samples.inject(0.0) {|s,x| s += x } /
|
36
|
+
sample_mean = samples.inject(0.0) {|s,x| s += x } / num_samples.to_f
|
37
37
|
sample_mean.must_be_within_epsilon zero_to_sixty.mean, 0.05
|
38
38
|
end
|
39
39
|
|
40
40
|
it 'should have the expected variance' do
|
41
|
-
sample_variance = samples.inject(0.0) {|s,x| s += (x - zero_to_sixty.mean) ** 2 } /
|
41
|
+
sample_variance = samples.inject(0.0) {|s,x| s += (x - zero_to_sixty.mean) ** 2 } / num_samples.to_f
|
42
42
|
sample_variance.must_be_within_epsilon zero_to_sixty.variance, 0.05
|
43
43
|
end
|
44
44
|
|
@@ -62,16 +62,16 @@ describe ERV::DiscreteUniformDistribution do
|
|
62
62
|
context 'moments' do
|
63
63
|
|
64
64
|
let :samples do
|
65
|
-
0.upto(
|
65
|
+
0.upto(num_samples).collect { ten_to_ninety.sample }
|
66
66
|
end
|
67
67
|
|
68
68
|
it 'should have the expected mean' do
|
69
|
-
sample_mean = samples.inject(0.0) {|s,x| s += x } /
|
69
|
+
sample_mean = samples.inject(0.0) {|s,x| s += x } / num_samples.to_f
|
70
70
|
sample_mean.must_be_within_epsilon ten_to_ninety.mean, 0.05
|
71
71
|
end
|
72
72
|
|
73
73
|
it 'should have the expected variance' do
|
74
|
-
sample_variance = samples.inject(0.0) {|s,x| s += (x - ten_to_ninety.mean) ** 2 } /
|
74
|
+
sample_variance = samples.inject(0.0) {|s,x| s += (x - ten_to_ninety.mean) ** 2 } / num_samples.to_f
|
75
75
|
sample_variance.must_be_within_epsilon ten_to_ninety.variance, 0.05
|
76
76
|
end
|
77
77
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
require 'erv/exponential_distribution'
|
4
|
+
|
5
|
+
describe ERV::ExponentialDistribution do
|
6
|
+
|
7
|
+
let :num_samples { 10000 }
|
8
|
+
|
9
|
+
it 'should require the rate parameter' do
|
10
|
+
lambda do
|
11
|
+
ERV::ExponentialDistribution.new()
|
12
|
+
end.must_raise ArgumentError
|
13
|
+
end
|
14
|
+
|
15
|
+
let :ed do
|
16
|
+
ERV::ExponentialDistribution.new(rate: 20.0)
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'sampling' do
|
20
|
+
|
21
|
+
it 'should allow sampling' do
|
22
|
+
ed.sample
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'moments' do
|
28
|
+
let :samples do
|
29
|
+
0.upto(num_samples).collect { ed.sample }
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should have the expected mean' do
|
33
|
+
sample_mean = samples.inject(0.0) {|s,x| s += x } / num_samples.to_f
|
34
|
+
sample_mean.must_be_within_epsilon ed.mean, 0.05
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should have the expected variance' do
|
38
|
+
sample_variance = samples.inject(0.0) {|s,x| s += (x - ed.mean) ** 2 } / num_samples.to_f
|
39
|
+
sample_variance.must_be_within_epsilon ed.variance, 0.05
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -4,7 +4,7 @@ require 'erv/gamma_distribution'
|
|
4
4
|
|
5
5
|
describe ERV::GammaDistribution do
|
6
6
|
|
7
|
-
|
7
|
+
let :num_samples { 10000 }
|
8
8
|
|
9
9
|
it 'should require the scale and shape parameters' do
|
10
10
|
lambda do
|
@@ -28,16 +28,16 @@ describe ERV::GammaDistribution do
|
|
28
28
|
|
29
29
|
context 'moments' do
|
30
30
|
let :samples do
|
31
|
-
0.upto(
|
31
|
+
0.upto(num_samples).collect { gsgtone.sample }
|
32
32
|
end
|
33
33
|
|
34
34
|
it 'should have the expected mean' do
|
35
|
-
sample_mean = samples.inject(0.0) {|s,x| s += x } /
|
35
|
+
sample_mean = samples.inject(0.0) {|s,x| s += x } / num_samples.to_f
|
36
36
|
sample_mean.must_be_within_epsilon gsgtone.mean, 0.05
|
37
37
|
end
|
38
38
|
|
39
39
|
it 'should have the expected variance' do
|
40
|
-
sample_variance = samples.inject(0.0) {|s,x| s += (x - gsgtone.mean) ** 2 } /
|
40
|
+
sample_variance = samples.inject(0.0) {|s,x| s += (x - gsgtone.mean) ** 2 } / num_samples.to_f
|
41
41
|
sample_variance.must_be_within_epsilon gsgtone.variance, 0.05
|
42
42
|
end
|
43
43
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
require 'erv/gaussian_distribution'
|
4
|
+
|
5
|
+
describe ERV::GaussianDistribution do
|
6
|
+
|
7
|
+
let :num_samples { 10000 }
|
8
|
+
|
9
|
+
it 'should require the scale and shape parameters' do
|
10
|
+
lambda do
|
11
|
+
ERV::GaussianDistribution.new()
|
12
|
+
end.must_raise ArgumentError
|
13
|
+
end
|
14
|
+
|
15
|
+
let :gd do
|
16
|
+
ERV::GaussianDistribution.new(mean: 20.0, sd: 0.5)
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'sampling' do
|
20
|
+
|
21
|
+
it 'should allow sampling' do
|
22
|
+
gd.sample
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'moments' do
|
28
|
+
let :samples do
|
29
|
+
0.upto(num_samples).collect { gd.sample }
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should have the expected mean' do
|
33
|
+
sample_mean = samples.inject(0.0) {|s,x| s += x } / num_samples.to_f
|
34
|
+
sample_mean.must_be_within_epsilon gd.mean, 0.05
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should have the expected variance' do
|
38
|
+
sample_variance = samples.inject(0.0) {|s,x| s += (x - gd.mean) ** 2 } / num_samples.to_f
|
39
|
+
sample_variance.must_be_within_epsilon gd.variance, 0.05
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
data/test/erv/{general_pareto_distribution_test.rb → generalized_pareto_distribution_test.rb}
RENAMED
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
require 'erv/
|
3
|
+
require 'erv/generalized_pareto_distribution'
|
4
4
|
|
5
5
|
describe ERV::GpdDistribution do
|
6
6
|
|
7
|
-
|
7
|
+
let :num_samples { 200000 }
|
8
8
|
|
9
9
|
it 'should require scale and shape parameters' do
|
10
10
|
lambda do
|
@@ -29,16 +29,16 @@ describe ERV::GpdDistribution do
|
|
29
29
|
|
30
30
|
context 'moments' do
|
31
31
|
let :samples do
|
32
|
-
0.upto(
|
32
|
+
0.upto(num_samples).collect { gpd_2params.sample }
|
33
33
|
end
|
34
34
|
|
35
35
|
it 'should have the expected mean' do
|
36
|
-
sample_mean = samples.inject(0.0) {|s,x| s += x } /
|
36
|
+
sample_mean = samples.inject(0.0) {|s,x| s += x } / num_samples.to_f
|
37
37
|
sample_mean.must_be_within_epsilon gpd_2params.mean, 0.1
|
38
38
|
end
|
39
39
|
|
40
40
|
it 'should have the expected variance' do
|
41
|
-
sample_variance = samples.inject(0.0) {|s,x| s += (x - gpd_2params.mean) ** 2 } /
|
41
|
+
sample_variance = samples.inject(0.0) {|s,x| s += (x - gpd_2params.mean) ** 2 } / num_samples.to_f
|
42
42
|
sample_variance.must_be_within_epsilon gpd_2params.variance, 0.1
|
43
43
|
end
|
44
44
|
|
@@ -64,16 +64,16 @@ describe ERV::GpdDistribution do
|
|
64
64
|
|
65
65
|
context 'moments' do
|
66
66
|
let :samples do
|
67
|
-
0.upto(
|
67
|
+
0.upto(num_samples).collect { gpd_3params.sample }
|
68
68
|
end
|
69
69
|
|
70
70
|
it 'should have the expected mean' do
|
71
|
-
sample_mean = samples.inject(0.0) {|s,x| s += x } /
|
71
|
+
sample_mean = samples.inject(0.0) {|s,x| s += x } / num_samples.to_f
|
72
72
|
sample_mean.must_be_within_epsilon gpd_3params.mean, 0.1
|
73
73
|
end
|
74
74
|
|
75
75
|
it 'should have the expected variance' do
|
76
|
-
sample_variance = samples.inject(0.0) {|s,x| s += (x - gpd_3params.mean) ** 2 } /
|
76
|
+
sample_variance = samples.inject(0.0) {|s,x| s += (x - gpd_3params.mean) ** 2 } / num_samples.to_f
|
77
77
|
sample_variance.must_be_within_epsilon gpd_3params.variance, 0.1
|
78
78
|
end
|
79
79
|
|
@@ -4,7 +4,7 @@ require 'erv/geometric_distribution'
|
|
4
4
|
|
5
5
|
describe ERV::GeometricDistribution do
|
6
6
|
|
7
|
-
|
7
|
+
let :num_samples { 10000 }
|
8
8
|
|
9
9
|
it 'should require at least a probability of success parameter' do
|
10
10
|
lambda do
|
@@ -26,16 +26,16 @@ describe ERV::GeometricDistribution do
|
|
26
26
|
|
27
27
|
context 'moments' do
|
28
28
|
let :samples do
|
29
|
-
0.upto(
|
29
|
+
0.upto(num_samples).collect { gd.sample }
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'should have the expected mean' do
|
33
|
-
sample_mean = samples.inject(0.0) {|s,x| s += x } /
|
33
|
+
sample_mean = samples.inject(0.0) {|s,x| s += x } / num_samples.to_f
|
34
34
|
sample_mean.must_be_within_epsilon gd.mean, 0.05
|
35
35
|
end
|
36
36
|
|
37
37
|
it 'should have the expected variance' do
|
38
|
-
sample_variance = samples.inject(0.0) {|s,x| s += (x - gd.mean) ** 2 } /
|
38
|
+
sample_variance = samples.inject(0.0) {|s,x| s += (x - gd.mean) ** 2 } / num_samples.to_f
|
39
39
|
sample_variance.must_be_within_epsilon gd.variance, 0.05
|
40
40
|
end
|
41
41
|
|
@@ -3,20 +3,23 @@ require 'test_helper'
|
|
3
3
|
require 'erv/mixture_distribution'
|
4
4
|
|
5
5
|
describe ERV::MixtureDistribution do
|
6
|
+
|
7
|
+
let :num_samples { 10000 }
|
8
|
+
|
6
9
|
it 'should require at least two distributions' do
|
7
10
|
lambda do
|
8
|
-
ERV::MixtureDistribution.new([ { distribution: :exponential, rate: 1.0, weight: 0.5 } ])
|
11
|
+
ERV::MixtureDistribution.new([ { distribution: :exponential, args: { rate: 1.0 }, weight: 0.5 } ])
|
9
12
|
end.must_raise ArgumentError
|
10
13
|
end
|
11
14
|
|
12
|
-
let :md do
|
13
|
-
ERV::MixtureDistribution.new([ { distribution: :exponential, rate: 1.0, weight: 0.3 },
|
14
|
-
{ distribution: :exponential, rate: 2.0, weight: 0.2 },
|
15
|
-
{ distribution: :exponential, rate: 3.0, weight: 0.5 } ])
|
16
|
-
end
|
17
|
-
|
18
15
|
context 'sampling' do
|
19
16
|
|
17
|
+
let :md do
|
18
|
+
ERV::MixtureDistribution.new([ { distribution: :exponential, args: { rate: 1.0 }, weight: 0.3 },
|
19
|
+
{ distribution: :exponential, args: { rate: 2.0 }, weight: 0.2 },
|
20
|
+
{ distribution: :exponential, args: { rate: 3.0 }, weight: 0.5 } ])
|
21
|
+
end
|
22
|
+
|
20
23
|
it 'should allow sampling from the mixture' do
|
21
24
|
md.sample
|
22
25
|
end
|
@@ -25,43 +28,24 @@ describe ERV::MixtureDistribution do
|
|
25
28
|
|
26
29
|
context 'moments' do
|
27
30
|
|
28
|
-
context 'with
|
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
|
31
|
+
context 'with normalized weights' do
|
38
32
|
|
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
|
46
|
-
end
|
47
|
-
|
48
|
-
context 'with different amplitudes' do
|
49
33
|
let :amd do
|
50
|
-
ERV::MixtureDistribution.new([ { distribution: :gaussian,
|
51
|
-
{ distribution: :gaussian,
|
52
|
-
{ distribution: :gaussian,
|
34
|
+
ERV::MixtureDistribution.new([ { distribution: :gaussian, args: { mean: 1.0, sd: 0.1 }, weight: 0.3 },
|
35
|
+
{ distribution: :gaussian, args: { mean: 2.0, sd: 0.2 }, weight: 0.2 },
|
36
|
+
{ distribution: :gaussian, args: { mean: 3.0, sd: 0.3 }, weight: 0.5 } ])
|
53
37
|
end
|
54
38
|
|
55
39
|
let :amd_expected_mean do
|
56
|
-
0.3 *
|
57
|
-
0.2 *
|
58
|
-
0.5 *
|
40
|
+
0.3 * 1.0 +
|
41
|
+
0.2 * 2.0 +
|
42
|
+
0.5 * 3.0
|
59
43
|
end
|
60
44
|
|
61
45
|
let :amd_expected_variance do
|
62
|
-
0.3 * ((
|
63
|
-
0.2 * ((
|
64
|
-
0.5 * ((
|
46
|
+
0.3 * ((1.0 - amd_expected_mean) ** 2 + 0.1 ** 2) +
|
47
|
+
0.2 * ((2.0 - amd_expected_mean) ** 2 + 0.2 ** 2) +
|
48
|
+
0.5 * ((3.0 - amd_expected_mean) ** 2 + 0.3 ** 2)
|
65
49
|
end
|
66
50
|
|
67
51
|
it 'should correctly calculate the mean of the mixture' do
|
@@ -71,13 +55,29 @@ describe ERV::MixtureDistribution do
|
|
71
55
|
it 'should correctly calculate the variance of the mixture' do
|
72
56
|
amd.variance.must_equal amd_expected_variance
|
73
57
|
end
|
58
|
+
|
59
|
+
let :samples do
|
60
|
+
0.upto(num_samples).collect { amd.sample }
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'mean of a sample set should match the expected mean' do
|
64
|
+
sample_mean = samples.inject(0.0) {|s,x| s += x } / num_samples.to_f
|
65
|
+
sample_mean.must_be_within_epsilon amd.mean, 0.05
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'variance of a sample set should match the expected variance' do
|
69
|
+
sample_variance = samples.inject(0.0) {|s,x| s += (x - amd.mean) ** 2 } / num_samples.to_f
|
70
|
+
sample_variance.must_be_within_epsilon amd.variance, 0.05
|
71
|
+
end
|
72
|
+
|
74
73
|
end
|
75
74
|
|
76
75
|
context 'with unnormalized weights' do
|
76
|
+
|
77
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 } ])
|
78
|
+
ERV::MixtureDistribution.new([ { distribution: :exponential, args: { rate: 1.0 }, weight: 300 },
|
79
|
+
{ distribution: :exponential, args: { rate: 2.0 }, weight: 200 },
|
80
|
+
{ distribution: :exponential, args: { rate: 3.0 }, weight: 500 } ])
|
81
81
|
end
|
82
82
|
|
83
83
|
let :uwmd_expected_mean do
|
@@ -98,6 +98,41 @@ describe ERV::MixtureDistribution do
|
|
98
98
|
uwmd.variance.must_equal uwmd_expected_variance
|
99
99
|
end
|
100
100
|
|
101
|
+
let :samples do
|
102
|
+
0.upto(num_samples).collect { uwmd.sample }
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'mean of a sample set should match the expected mean' do
|
106
|
+
sample_mean = samples.inject(0.0) {|s,x| s += x } / num_samples.to_f
|
107
|
+
sample_mean.must_be_within_epsilon uwmd.mean, 0.05
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'variance of a sample set should match the expected variance' do
|
111
|
+
sample_variance = samples.inject(0.0) {|s,x| s += (x - uwmd.mean) ** 2 } / num_samples.to_f
|
112
|
+
sample_variance.must_be_within_epsilon uwmd.variance, 0.05
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'mixture of mixtures' do
|
120
|
+
let :momd do
|
121
|
+
ERV::MixtureDistribution.new([ { distribution: :mixture,
|
122
|
+
args: [ { distribution: :exponential, args: { rate: 4.0 }, weight: 300 },
|
123
|
+
{ distribution: :exponential, args: { rate: 5.0 }, weight: 200 },
|
124
|
+
{ distribution: :exponential, args: { rate: 6.0 }, weight: 500 } ],
|
125
|
+
weight: 200 },
|
126
|
+
{ distribution: :mixture,
|
127
|
+
args: [ { distribution: :exponential, args: { rate: 7.0 }, weight: 300 },
|
128
|
+
{ distribution: :exponential, args: { rate: 8.0 }, weight: 200 },
|
129
|
+
{ distribution: :exponential, args: { rate: 9.0 }, weight: 500 } ],
|
130
|
+
weight: 300 },
|
131
|
+
], inspect: true)
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should allow sampling from the mixture' do
|
135
|
+
momd.sample
|
101
136
|
end
|
102
137
|
|
103
138
|
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.3.
|
4
|
+
version: 0.3.3
|
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-
|
11
|
+
date: 2017-08-24 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.3.
|
83
|
+
description: erv-0.3.3
|
84
84
|
email:
|
85
85
|
- mauro.tortonesi@unife.it
|
86
86
|
executables: []
|
@@ -100,7 +100,7 @@ files:
|
|
100
100
|
- lib/erv/exponential_distribution.rb
|
101
101
|
- lib/erv/gamma_distribution.rb
|
102
102
|
- lib/erv/gaussian_distribution.rb
|
103
|
-
- lib/erv/
|
103
|
+
- lib/erv/generalized_pareto_distribution.rb
|
104
104
|
- lib/erv/geometric_distribution.rb
|
105
105
|
- lib/erv/mixture_distribution.rb
|
106
106
|
- lib/erv/random_variable.rb
|
@@ -110,8 +110,10 @@ files:
|
|
110
110
|
- test/erv/constant_distribution_test.rb
|
111
111
|
- test/erv/discrete_uniform_distribution_test.rb
|
112
112
|
- test/erv/distribution_test.rb
|
113
|
+
- test/erv/exponential_distribution_test.rb
|
113
114
|
- test/erv/gamma_distribution_test.rb
|
114
|
-
- test/erv/
|
115
|
+
- test/erv/gaussian_distribution_test.rb
|
116
|
+
- test/erv/generalized_pareto_distribution_test.rb
|
115
117
|
- test/erv/geometric_distribution_test.rb
|
116
118
|
- test/erv/mixture_distribution_test.rb
|
117
119
|
- test/erv/random_variable_test.rb
|
@@ -144,8 +146,10 @@ test_files:
|
|
144
146
|
- test/erv/constant_distribution_test.rb
|
145
147
|
- test/erv/discrete_uniform_distribution_test.rb
|
146
148
|
- test/erv/distribution_test.rb
|
149
|
+
- test/erv/exponential_distribution_test.rb
|
147
150
|
- test/erv/gamma_distribution_test.rb
|
148
|
-
- test/erv/
|
151
|
+
- test/erv/gaussian_distribution_test.rb
|
152
|
+
- test/erv/generalized_pareto_distribution_test.rb
|
149
153
|
- test/erv/geometric_distribution_test.rb
|
150
154
|
- test/erv/mixture_distribution_test.rb
|
151
155
|
- test/erv/random_variable_test.rb
|