erv 0.3.5 → 0.4.0
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 +2 -1
- data/README.md +6 -2
- data/config/sus.rb +2 -0
- data/erv.gemspec +2 -5
- data/fixtures/erv/distribution_behaviour.rb +23 -0
- data/lib/erv/beta_distribution.rb +36 -0
- data/lib/erv/discrete_uniform_distribution.rb +5 -7
- data/lib/erv/distribution.rb +3 -1
- data/lib/erv/expnorm_distribution.rb +40 -0
- data/lib/erv/exponential_distribution.rb +1 -2
- data/lib/erv/generalized_pareto_distribution.rb +4 -8
- data/lib/erv/lognorm_distribution.rb +32 -0
- data/lib/erv/mixture_distribution.rb +4 -0
- data/lib/erv/random_variable.rb +12 -14
- data/lib/erv/uniform_distribution.rb +3 -4
- data/lib/erv/version.rb +1 -1
- data/lib/erv/weibull_distribution.rb +23 -0
- data/test/erv/beta_distribution_test.rb +22 -0
- data/test/erv/constant_distribution_test.rb +4 -14
- data/test/erv/discrete_uniform_distribution_test.rb +14 -66
- data/test/erv/distribution_test.rb +2 -10
- data/test/erv/expnorm_distribution_test.rb +27 -0
- data/test/erv/exponential_distribution_test.rb +8 -34
- data/test/erv/gamma_distribution_test.rb +8 -38
- data/test/erv/gaussian_distribution_test.rb +8 -35
- data/test/erv/generalized_pareto_distribution_test.rb +21 -70
- data/test/erv/geometric_distribution_test.rb +8 -35
- data/test/erv/log_normal_distribution_test.rb +17 -0
- data/test/erv/mixture_distribution_test.rb +36 -64
- data/test/erv/random_variable_test.rb +3 -9
- metadata +20 -73
- data/Rakefile +0 -11
- data/TODO +0 -2
- data/lib/erv/support/try.rb +0 -15
- data/test/test_helper.rb +0 -6
|
@@ -1,44 +1,18 @@
|
|
|
1
|
-
require '
|
|
2
|
-
|
|
3
|
-
require 'erv/exponential_distribution'
|
|
1
|
+
require 'erv/distribution_behaviour'
|
|
4
2
|
|
|
5
3
|
describe ERV::ExponentialDistribution do
|
|
6
|
-
|
|
7
|
-
let (:num_samples) { 10000 }
|
|
8
|
-
|
|
9
4
|
it 'should require the rate parameter' do
|
|
10
|
-
|
|
11
|
-
ERV::ExponentialDistribution.new()
|
|
12
|
-
end.must_raise ArgumentError
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
let :ed do
|
|
16
|
-
ERV::ExponentialDistribution.new(rate: 20.0)
|
|
5
|
+
expect{ ERV::ExponentialDistribution.new() }.to raise_exception(ArgumentError)
|
|
17
6
|
end
|
|
18
7
|
|
|
19
|
-
|
|
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
|
|
8
|
+
with 'sampling' do
|
|
9
|
+
let(:distribution) { ERV::ExponentialDistribution.new(rate: 20.0) }
|
|
36
10
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
end
|
|
11
|
+
let(:num_samples) { 200_000 }
|
|
12
|
+
let(:samples) { num_samples.times.map { distribution.sample } }
|
|
13
|
+
let(:epsilon) { 1E-2 }
|
|
41
14
|
|
|
15
|
+
include ERV::DistributionBehavior
|
|
42
16
|
end
|
|
43
17
|
|
|
44
18
|
end
|
|
@@ -1,47 +1,17 @@
|
|
|
1
|
-
require '
|
|
2
|
-
|
|
3
|
-
require 'erv/gamma_distribution'
|
|
1
|
+
require 'erv/distribution_behaviour'
|
|
4
2
|
|
|
5
3
|
describe ERV::GammaDistribution do
|
|
6
|
-
|
|
7
|
-
let (:num_samples) { 10000 }
|
|
8
|
-
|
|
9
4
|
it 'should require the scale and shape parameters' do
|
|
10
|
-
|
|
11
|
-
ERV::GammaDistribution.new()
|
|
12
|
-
end.must_raise ArgumentError
|
|
5
|
+
expect{ ERV::GammaDistribution.new }.to raise_exception(ArgumentError)
|
|
13
6
|
end
|
|
14
7
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
let :gsgtone do
|
|
18
|
-
ERV::GammaDistribution.new(shape: 2.0, scale: 0.5)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
context 'sampling' do
|
|
8
|
+
with 'sampling' do
|
|
9
|
+
let(:distribution) { ERV::GammaDistribution.new(shape: 2.0, scale: 0.5) }
|
|
22
10
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
11
|
+
let(:num_samples) { 200_000 }
|
|
12
|
+
let(:samples) { num_samples.times.map { distribution.sample } }
|
|
13
|
+
let(:epsilon) { 1E-2 }
|
|
26
14
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
context 'moments' do
|
|
30
|
-
let :samples do
|
|
31
|
-
0.upto(num_samples).collect { gsgtone.sample }
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
it 'should have the expected mean' do
|
|
35
|
-
sample_mean = samples.inject(0.0) {|s,x| s += x } / num_samples.to_f
|
|
36
|
-
sample_mean.must_be_within_epsilon gsgtone.mean, 0.05
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
it 'should have the expected variance' do
|
|
40
|
-
sample_variance = samples.inject(0.0) {|s,x| s += (x - gsgtone.mean) ** 2 } / num_samples.to_f
|
|
41
|
-
sample_variance.must_be_within_epsilon gsgtone.variance, 0.05
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
end
|
|
15
|
+
include ERV::DistributionBehavior
|
|
45
16
|
end
|
|
46
|
-
|
|
47
17
|
end
|
|
@@ -1,44 +1,17 @@
|
|
|
1
|
-
require '
|
|
2
|
-
|
|
3
|
-
require 'erv/gaussian_distribution'
|
|
1
|
+
require 'erv/distribution_behaviour'
|
|
4
2
|
|
|
5
3
|
describe ERV::GaussianDistribution do
|
|
6
|
-
|
|
7
|
-
let (:num_samples) { 10000 }
|
|
8
|
-
|
|
9
4
|
it 'should require the scale and shape parameters' do
|
|
10
|
-
|
|
11
|
-
ERV::GaussianDistribution.new()
|
|
12
|
-
end.must_raise ArgumentError
|
|
5
|
+
expect{ ERV::GaussianDistribution.new }.to raise_exception(ArgumentError)
|
|
13
6
|
end
|
|
14
7
|
|
|
15
|
-
|
|
16
|
-
ERV::GaussianDistribution.new(mean: 20.0, sd: 0.5)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
context 'sampling' do
|
|
8
|
+
with 'sampling' do
|
|
9
|
+
let(:distribution) { ERV::GaussianDistribution.new(mean: 20.0, sd: 0.5) }
|
|
20
10
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
11
|
+
let(:num_samples) { 200_000 }
|
|
12
|
+
let(:samples) { num_samples.times.map { distribution.sample } }
|
|
13
|
+
let(:epsilon) { 5E-3 }
|
|
24
14
|
|
|
15
|
+
include ERV::DistributionBehavior
|
|
25
16
|
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
17
|
end
|
|
@@ -1,82 +1,33 @@
|
|
|
1
|
-
require '
|
|
2
|
-
|
|
3
|
-
require 'erv/generalized_pareto_distribution'
|
|
1
|
+
require 'erv/distribution_behaviour'
|
|
4
2
|
|
|
5
3
|
describe ERV::GpdDistribution do
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
it 'should require scale and shape parameters' do
|
|
10
|
-
lambda do
|
|
11
|
-
ERV::GpdDistribution.new()
|
|
12
|
-
end.must_raise ArgumentError
|
|
4
|
+
it 'should require the scale and shape parameters' do
|
|
5
|
+
expect{ ERV::GpdDistribution.new }.to raise_exception(ArgumentError)
|
|
13
6
|
end
|
|
14
7
|
|
|
8
|
+
with 'a (default) 2-parameter distribution' do
|
|
9
|
+
# Caveat:
|
|
10
|
+
# 1) if shape >= 0.5, variance is infinite
|
|
11
|
+
# 2) if shape >= 0.25, the 4th moment is infinite - so the variance of the
|
|
12
|
+
# variance is infinite
|
|
13
|
+
let(:distribution) { ERV::GpdDistribution.new(scale: 1.0, shape: 0.1) }
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
let
|
|
19
|
-
ERV::GpdDistribution.new(scale: 1.0, shape: 0.3)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
context 'sampling' do
|
|
23
|
-
|
|
24
|
-
it 'should allow sampling' do
|
|
25
|
-
gpd_2params.sample
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
context 'moments' do
|
|
31
|
-
let :samples do
|
|
32
|
-
0.upto(num_samples).collect { gpd_2params.sample }
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
it 'should have the expected mean' do
|
|
36
|
-
sample_mean = samples.inject(0.0) {|s,x| s += x } / num_samples.to_f
|
|
37
|
-
sample_mean.must_be_within_epsilon gpd_2params.mean, 0.1
|
|
38
|
-
end
|
|
15
|
+
let(:num_samples) { 200_000 }
|
|
16
|
+
let(:samples) { num_samples.times.map { distribution.sample } }
|
|
17
|
+
let(:epsilon) { 1E-2 }
|
|
39
18
|
|
|
40
|
-
|
|
41
|
-
sample_variance = samples.inject(0.0) {|s,x| s += (x - gpd_2params.mean) ** 2 } / num_samples.to_f
|
|
42
|
-
sample_variance.must_be_within_epsilon gpd_2params.variance, 0.1
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
end
|
|
19
|
+
include ERV::DistributionBehavior
|
|
46
20
|
end
|
|
47
21
|
|
|
22
|
+
with 'a 3-parameter distribution' do
|
|
23
|
+
let(:distribution) { ERV::GpdDistribution.new(scale: 1.0,
|
|
24
|
+
shape: 0.1,
|
|
25
|
+
location: 1.0) }
|
|
48
26
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
let
|
|
52
|
-
ERV::GpdDistribution.new(scale: 1.0,
|
|
53
|
-
shape: 0.3,
|
|
54
|
-
location: 1.0)
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
context 'sampling' do
|
|
58
|
-
|
|
59
|
-
it 'should allow sampling' do
|
|
60
|
-
gpd_3params.sample
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
context 'moments' do
|
|
66
|
-
let :samples do
|
|
67
|
-
0.upto(num_samples).collect { gpd_3params.sample }
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
it 'should have the expected mean' do
|
|
71
|
-
sample_mean = samples.inject(0.0) {|s,x| s += x } / num_samples.to_f
|
|
72
|
-
sample_mean.must_be_within_epsilon gpd_3params.mean, 0.1
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
it 'should have the expected variance' do
|
|
76
|
-
sample_variance = samples.inject(0.0) {|s,x| s += (x - gpd_3params.mean) ** 2 } / num_samples.to_f
|
|
77
|
-
sample_variance.must_be_within_epsilon gpd_3params.variance, 0.1
|
|
78
|
-
end
|
|
27
|
+
let(:num_samples) { 200_000 }
|
|
28
|
+
let(:samples) { num_samples.times.map { distribution.sample } }
|
|
29
|
+
let(:epsilon) { 1E-2 }
|
|
79
30
|
|
|
80
|
-
|
|
31
|
+
include ERV::DistributionBehavior
|
|
81
32
|
end
|
|
82
33
|
end
|
|
@@ -1,44 +1,17 @@
|
|
|
1
|
-
require '
|
|
2
|
-
|
|
3
|
-
require 'erv/geometric_distribution'
|
|
1
|
+
require 'erv/distribution_behaviour'
|
|
4
2
|
|
|
5
3
|
describe ERV::GeometricDistribution do
|
|
6
|
-
|
|
7
|
-
let (:num_samples) { 10000 }
|
|
8
|
-
|
|
9
4
|
it 'should require at least a probability of success parameter' do
|
|
10
|
-
|
|
11
|
-
ERV::GeometricDistribution.new()
|
|
12
|
-
end.must_raise ArgumentError
|
|
5
|
+
expect{ ERV::GeometricDistribution.new }.to raise_exception(ArgumentError)
|
|
13
6
|
end
|
|
14
7
|
|
|
15
|
-
|
|
16
|
-
ERV::GeometricDistribution.new(probability_of_success: 0.5)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
context 'sampling' do
|
|
8
|
+
with 'sampling' do
|
|
9
|
+
let(:distribution) { ERV::GeometricDistribution.new(probability_of_success: 0.5) }
|
|
20
10
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
11
|
+
let(:num_samples) { 200_000 }
|
|
12
|
+
let(:samples) { num_samples.times.map { distribution.sample } }
|
|
13
|
+
let(:epsilon) { 5E-3 }
|
|
24
14
|
|
|
15
|
+
include ERV::DistributionBehavior
|
|
25
16
|
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
17
|
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'erv/distribution_behaviour'
|
|
2
|
+
|
|
3
|
+
describe ERV::LogNormDistribution do
|
|
4
|
+
it 'should require the mu and sigma parameters' do
|
|
5
|
+
expect{ ERV::LogNormDistribution.new }.to raise_exception(ArgumentError)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
with 'sampling' do
|
|
9
|
+
let(:distribution) { ERV::LogNormDistribution.new(mu: 0.0, sigma: 0.25) }
|
|
10
|
+
|
|
11
|
+
let(:num_samples) { 200_000 }
|
|
12
|
+
let(:samples) { num_samples.times.map { distribution.sample } }
|
|
13
|
+
let(:epsilon) { 1E-2 }
|
|
14
|
+
|
|
15
|
+
include ERV::DistributionBehavior
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -1,123 +1,97 @@
|
|
|
1
|
-
require '
|
|
2
|
-
|
|
3
|
-
require 'erv/mixture_distribution'
|
|
1
|
+
require 'erv/distribution_behaviour'
|
|
4
2
|
|
|
5
3
|
describe ERV::MixtureDistribution do
|
|
6
4
|
|
|
7
5
|
let (:num_samples) { 10000 }
|
|
8
6
|
|
|
9
7
|
it 'should require at least two distributions' do
|
|
10
|
-
|
|
8
|
+
expect{
|
|
11
9
|
ERV::MixtureDistribution.new([ { distribution: :exponential, args: { rate: 1.0 }, weight: 0.5 } ])
|
|
12
|
-
|
|
10
|
+
}.to raise_exception(ArgumentError)
|
|
13
11
|
end
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
let :md do
|
|
13
|
+
with 'sampling' do
|
|
14
|
+
let(:distribution) do
|
|
18
15
|
ERV::MixtureDistribution.new([ { distribution: :exponential, args: { rate: 1.0 }, weight: 0.3 },
|
|
19
16
|
{ distribution: :exponential, args: { rate: 2.0 }, weight: 0.2 },
|
|
20
17
|
{ distribution: :exponential, args: { rate: 3.0 }, weight: 0.5 } ])
|
|
21
18
|
end
|
|
22
19
|
|
|
23
20
|
it 'should allow sampling from the mixture' do
|
|
24
|
-
|
|
21
|
+
expect{ distribution.sample }.not.to raise_exception(ArgumentError).and(! be_nil)
|
|
25
22
|
end
|
|
26
|
-
|
|
27
23
|
end
|
|
28
24
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
let :amd do
|
|
25
|
+
with 'moments' do
|
|
26
|
+
with 'with normalized weights' do
|
|
27
|
+
let(:distribution) do
|
|
34
28
|
ERV::MixtureDistribution.new([ { distribution: :gaussian, args: { mean: 1.0, sd: 0.1 }, weight: 0.3 },
|
|
35
29
|
{ distribution: :gaussian, args: { mean: 2.0, sd: 0.2 }, weight: 0.2 },
|
|
36
30
|
{ distribution: :gaussian, args: { mean: 3.0, sd: 0.3 }, weight: 0.5 } ])
|
|
37
31
|
end
|
|
38
32
|
|
|
39
|
-
let
|
|
33
|
+
let(:expected_mean) do
|
|
40
34
|
0.3 * 1.0 +
|
|
41
35
|
0.2 * 2.0 +
|
|
42
36
|
0.5 * 3.0
|
|
43
37
|
end
|
|
44
38
|
|
|
45
|
-
let
|
|
46
|
-
0.3 * ((1.0 -
|
|
47
|
-
0.2 * ((2.0 -
|
|
48
|
-
0.5 * ((3.0 -
|
|
39
|
+
let(:expected_variance) do
|
|
40
|
+
0.3 * ((1.0 - expected_mean) ** 2 + 0.1 ** 2) +
|
|
41
|
+
0.2 * ((2.0 - expected_mean) ** 2 + 0.2 ** 2) +
|
|
42
|
+
0.5 * ((3.0 - expected_mean) ** 2 + 0.3 ** 2)
|
|
49
43
|
end
|
|
50
44
|
|
|
51
45
|
it 'should correctly calculate the mean of the mixture' do
|
|
52
|
-
|
|
46
|
+
expect(distribution.mean).to be == expected_mean
|
|
53
47
|
end
|
|
54
48
|
|
|
55
49
|
it 'should correctly calculate the variance of the mixture' do
|
|
56
|
-
|
|
50
|
+
expect(distribution.variance).to be == expected_variance
|
|
57
51
|
end
|
|
58
52
|
|
|
59
|
-
let
|
|
60
|
-
|
|
61
|
-
|
|
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
|
|
53
|
+
let(:num_samples) { 200_000 }
|
|
54
|
+
let(:samples) { num_samples.times.map { distribution.sample } }
|
|
55
|
+
let(:epsilon) { 5E-2 }
|
|
72
56
|
|
|
57
|
+
include ERV::DistributionBehavior
|
|
73
58
|
end
|
|
74
59
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
let :uwmd do
|
|
60
|
+
with 'with unnormalized weights' do
|
|
61
|
+
let(:distribution) do
|
|
78
62
|
ERV::MixtureDistribution.new([ { distribution: :exponential, args: { rate: 1.0 }, weight: 300 },
|
|
79
63
|
{ distribution: :exponential, args: { rate: 2.0 }, weight: 200 },
|
|
80
64
|
{ distribution: :exponential, args: { rate: 3.0 }, weight: 500 } ])
|
|
81
65
|
end
|
|
82
66
|
|
|
83
|
-
let
|
|
67
|
+
let(:expected_mean) do
|
|
84
68
|
0.3 * 1/1.0 + 0.2 * 1/2.0 + 0.5 * 1/3.0
|
|
85
69
|
end
|
|
86
70
|
|
|
87
|
-
let
|
|
88
|
-
0.3 * ((1/1.0 -
|
|
89
|
-
0.2 * ((1/2.0 -
|
|
90
|
-
0.5 * ((1/3.0 -
|
|
71
|
+
let(:expected_variance) do
|
|
72
|
+
0.3 * ((1/1.0 - expected_mean) ** 2 + (1/1.0) ** 2) +
|
|
73
|
+
0.2 * ((1/2.0 - expected_mean) ** 2 + (1/2.0) ** 2) +
|
|
74
|
+
0.5 * ((1/3.0 - expected_mean) ** 2 + (1/3.0) ** 2)
|
|
91
75
|
end
|
|
92
76
|
|
|
93
77
|
it 'should correctly calculate the mean of the mixture' do
|
|
94
|
-
|
|
78
|
+
expect(distribution.mean).to be == expected_mean
|
|
95
79
|
end
|
|
96
80
|
|
|
97
81
|
it 'should correctly calculate the variance of the mixture' do
|
|
98
|
-
|
|
82
|
+
expect(distribution.variance).to be == expected_variance
|
|
99
83
|
end
|
|
100
84
|
|
|
101
|
-
let
|
|
102
|
-
|
|
103
|
-
|
|
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
|
|
85
|
+
let(:num_samples) { 200_000 }
|
|
86
|
+
let(:samples) { num_samples.times.map { distribution.sample } }
|
|
87
|
+
let(:epsilon) { 5E-2 }
|
|
114
88
|
|
|
89
|
+
include ERV::DistributionBehavior
|
|
115
90
|
end
|
|
116
|
-
|
|
117
91
|
end
|
|
118
92
|
|
|
119
|
-
|
|
120
|
-
let
|
|
93
|
+
with 'mixture of mixtures' do
|
|
94
|
+
let(:distribution) do
|
|
121
95
|
ERV::MixtureDistribution.new([ { distribution: :mixture,
|
|
122
96
|
args: [ { distribution: :exponential, args: { rate: 4.0 }, weight: 300 },
|
|
123
97
|
{ distribution: :exponential, args: { rate: 5.0 }, weight: 200 },
|
|
@@ -132,9 +106,7 @@ describe ERV::MixtureDistribution do
|
|
|
132
106
|
end
|
|
133
107
|
|
|
134
108
|
it 'should allow sampling from the mixture' do
|
|
135
|
-
|
|
109
|
+
expect{ distribution.sample }.not.to raise_exception(ArgumentError).and(! be_nil)
|
|
136
110
|
end
|
|
137
|
-
|
|
138
111
|
end
|
|
139
|
-
|
|
140
112
|
end
|
|
@@ -1,19 +1,13 @@
|
|
|
1
|
-
require 'test_helper'
|
|
2
|
-
|
|
3
|
-
require 'erv/random_variable'
|
|
4
|
-
|
|
5
1
|
describe ERV::SequentialRandomVariable do
|
|
6
2
|
|
|
7
3
|
it 'should require the :first_value parameter' do
|
|
8
|
-
|
|
9
|
-
ERV::SequentialRandomVariable.new
|
|
10
|
-
end.must_raise ArgumentError
|
|
4
|
+
expect{ ERV::SequentialRandomVariable.new }.to raise_exception(ArgumentError)
|
|
11
5
|
end
|
|
12
6
|
|
|
13
7
|
it 'should consider starting value' do
|
|
14
8
|
first = 1.0
|
|
15
9
|
srv = ERV::SequentialRandomVariable.new(first_value: first, distribution: :exponential, args: { rate: 2.0 })
|
|
16
|
-
srv.next.
|
|
10
|
+
expect(srv.next).to (be > first)
|
|
17
11
|
end
|
|
18
12
|
|
|
19
13
|
it 'should consider previous sample' do
|
|
@@ -22,7 +16,7 @@ describe ERV::SequentialRandomVariable do
|
|
|
22
16
|
previous_sample = srv.next
|
|
23
17
|
10.times do
|
|
24
18
|
new_sample = srv.next
|
|
25
|
-
new_sample.
|
|
19
|
+
expect(new_sample).to (be > previous_sample)
|
|
26
20
|
previous_sample = new_sample
|
|
27
21
|
end
|
|
28
22
|
end
|