croupier 1.6.0 → 2.0.0.rc1
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 +7 -0
- data/README.md +2 -2
- data/Rakefile +7 -0
- data/lib/croupier/distribution.rb +115 -36
- data/lib/croupier/distribution_generator.rb +57 -0
- data/lib/croupier/distribution_generators/enumerator_block_generator.rb +23 -0
- data/lib/croupier/distribution_generators/enumerator_generator.rb +21 -0
- data/lib/croupier/distribution_generators/inverse_cdf_generator.rb +21 -0
- data/lib/croupier/distribution_generators/minimum_sample_generator.rb +24 -0
- data/lib/croupier/distribution_generators.rb +18 -0
- data/lib/croupier/distributions/bernoulli.rb +18 -25
- data/lib/croupier/distributions/binomial.rb +30 -29
- data/lib/croupier/distributions/cauchy.rb +22 -19
- data/lib/croupier/distributions/credit_card.rb +39 -29
- data/lib/croupier/distributions/degenerate.rb +16 -19
- data/lib/croupier/distributions/exponential.rb +18 -19
- data/lib/croupier/distributions/gamma.rb +66 -37
- data/lib/croupier/distributions/geometric.rb +19 -20
- data/lib/croupier/distributions/nbinomial.rb +22 -33
- data/lib/croupier/distributions/normal.rb +30 -34
- data/lib/croupier/distributions/poisson.rb +26 -25
- data/lib/croupier/distributions/triangular.rb +39 -25
- data/lib/croupier/distributions/uniform.rb +43 -19
- data/lib/croupier/distributions.rb +3 -4
- data/lib/croupier/version.rb +1 -1
- data/lib/croupier.rb +43 -6
- data/test/minitest/distribution_class/test_class_methods.rb +142 -0
- data/test/{test_distribution_class.rb → minitest/distribution_class/test_instance_methods.rb} +26 -28
- data/test/minitest/distribution_generator_class/test_class_methods.rb +24 -0
- data/test/minitest/distribution_generator_class/test_instance_methods.rb +35 -0
- data/test/minitest/distribution_generators/test_enumerator_block_generator.rb +31 -0
- data/test/minitest/distribution_generators/test_enumerator_generator.rb +33 -0
- data/test/minitest/distribution_generators/test_inverse_cdf_generator.rb +36 -0
- data/test/minitest/distribution_generators/test_minimum_sample_generator.rb +33 -0
- data/test/minitest/distributions/test_bernoulli_distribution.rb +13 -0
- data/test/minitest/distributions/test_binomial_distribution.rb +18 -0
- data/test/minitest/distributions/test_cauchy_distribution.rb +18 -0
- data/test/{distributions/minitest/test_credit_card.rb → minitest/distributions/test_credit_card_distribution.rb} +5 -0
- data/test/{distributions/minitest → minitest/distributions}/test_degenerate_distribution.rb +2 -2
- data/test/minitest/distributions/test_exponential_distribution.rb +13 -0
- data/test/minitest/distributions/test_gamma_distribution.rb +23 -0
- data/test/minitest/distributions/test_geometric_distribution.rb +13 -0
- data/test/minitest/distributions/test_normal_distribution.rb +17 -0
- data/test/minitest/distributions/test_poisson_distribution.rb +13 -0
- data/test/minitest/distributions/test_triangular_distribution.rb +26 -0
- data/test/minitest/distributions/test_uniform_distribution.rb +54 -0
- data/test/{test_croupier_module.rb → minitest/test_croupier_module.rb} +0 -0
- data/test/minitest/test_distribution_generators_module.rb +37 -0
- data/test/{test_distributions_module.rb → minitest/test_distributions_module.rb} +0 -0
- data/test/rtests.R +1 -0
- metadata +62 -44
- data/test/distributions/R_tests/test_bernoulli.R +0 -17
- data/test/distributions/R_tests/test_binomial.R +0 -17
- data/test/distributions/R_tests/test_cauchy.R +0 -28
- data/test/distributions/R_tests/test_exponential.R +0 -28
- data/test/distributions/R_tests/test_gamma.R +0 -27
- data/test/distributions/R_tests/test_geometric.R +0 -23
- data/test/distributions/R_tests/test_nbinomial.R +0 -17
- data/test/distributions/R_tests/test_normal.R +0 -52
- data/test/distributions/R_tests/test_poisson.R +0 -17
- data/test/distributions/R_tests/test_triangular.R +0 -28
- data/test/distributions/R_tests/test_uniform.R +0 -30
- data/test/testsuite.R +0 -37
@@ -6,30 +6,27 @@ module Croupier
|
|
6
6
|
# Discrete probability distribution that returns the same value.
|
7
7
|
class Degenerate < ::Croupier::Distribution
|
8
8
|
|
9
|
-
|
10
|
-
@name = "Degenerate distribution"
|
11
|
-
@description = "Discrete probability distribution that returns the same value each time."
|
12
|
-
configure(options)
|
13
|
-
end
|
9
|
+
distribution_name "Degenerate distribution"
|
14
10
|
|
15
|
-
|
16
|
-
params[:constant]
|
17
|
-
end
|
11
|
+
distribution_description "Discrete probability distribution that returns the same value each time."
|
18
12
|
|
19
|
-
|
20
|
-
|
21
|
-
|
13
|
+
cli_name "degenerate"
|
14
|
+
|
15
|
+
cli_options({
|
16
|
+
options: [
|
17
|
+
[:constant, 'value to be returned', {type: :float, default: 42.0}]
|
18
|
+
],
|
19
|
+
banner: "Degenerate distribution. Discrete probability distribution that returns the same value each time."
|
20
|
+
})
|
22
21
|
|
23
|
-
|
24
|
-
|
22
|
+
enumerator_block do |y|
|
23
|
+
loop do
|
24
|
+
y << params[:constant]
|
25
|
+
end
|
25
26
|
end
|
26
27
|
|
27
|
-
def
|
28
|
-
|
29
|
-
[:constant, 'value to be returned', {:type=>:float, :default => 42.0}]
|
30
|
-
],
|
31
|
-
:banner => "Degenerate distribution. Discrete probability distribution that returns the same value each time."
|
32
|
-
}
|
28
|
+
def initialize(options={})
|
29
|
+
super(options)
|
33
30
|
end
|
34
31
|
end
|
35
32
|
end
|
@@ -8,31 +8,30 @@ module Croupier
|
|
8
8
|
#
|
9
9
|
class Exponential < ::Croupier::Distribution
|
10
10
|
|
11
|
-
|
12
|
-
@name = "Exponential distribution"
|
13
|
-
@description = "Continuous probability distribution with a lambda param rate describing the time between events in a Poisson process"
|
14
|
-
configure(options)
|
15
|
-
raise Croupier::InputParamsError, "Invalid interval values" if params[:lambda] <= 0
|
16
|
-
end
|
11
|
+
distribution_name "Exponential distribution"
|
17
12
|
|
18
|
-
|
19
|
-
(-1/params[:lambda]) * Math.log(n)
|
20
|
-
end
|
13
|
+
distribution_description "Continuous probability distribution with a lambda param rate describing the time between events in a Poisson process"
|
21
14
|
|
22
|
-
|
23
|
-
|
15
|
+
cli_name "exponential"
|
16
|
+
|
17
|
+
cli_options({
|
18
|
+
options: [
|
19
|
+
[:lambda, 'rate param', {type: :float, default: 1.0}]
|
20
|
+
],
|
21
|
+
banner: "Exponential distribution. Generate numbers following a exponential distribution for a given lambda rate"
|
22
|
+
})
|
23
|
+
|
24
|
+
inv_cdf do |n|
|
25
|
+
(-1 / lambda) * Math.log(1 - n)
|
24
26
|
end
|
25
27
|
|
26
|
-
def
|
27
|
-
|
28
|
+
def initialize(options={})
|
29
|
+
super(options)
|
30
|
+
raise Croupier::InputParamsError, "lambda cannot be negative" if params[:lambda] <= 0
|
28
31
|
end
|
29
32
|
|
30
|
-
def
|
31
|
-
|
32
|
-
[:lambda, 'rate param', {:type=>:float, :default => 1.0}]
|
33
|
-
],
|
34
|
-
:banner => "Exponential distribution. Generate numbers following a exponential distribution for a given lambda rate"
|
35
|
-
}
|
33
|
+
def lambda
|
34
|
+
params[:lambda]
|
36
35
|
end
|
37
36
|
end
|
38
37
|
end
|
@@ -7,58 +7,87 @@ module Croupier
|
|
7
7
|
# (defaults to 1) and scale (defaults to 1).
|
8
8
|
class Gamma < ::Croupier::Distribution
|
9
9
|
|
10
|
+
distribution_name "Gamma distribution"
|
11
|
+
|
12
|
+
distribution_description "Family of continuous distributions with two parameters, shape and scale"
|
13
|
+
|
14
|
+
cli_name "gamma"
|
15
|
+
|
16
|
+
cli_options({
|
17
|
+
options: [
|
18
|
+
[:shape, 'shape of the distribution', {type: :float, default: 1.0}],
|
19
|
+
[:scale, 'scale of the distribution', {type: :float, default: 1.0}]
|
20
|
+
],
|
21
|
+
banner: "Family of continuous distributions with two parameters, shape and scale."
|
22
|
+
})
|
23
|
+
|
24
|
+
enumerator do |c|
|
25
|
+
c.degenerate(constant: scale).to_enum.lazy.zip(xi_enum, adjust_enum).map do |s,x,a|
|
26
|
+
s * (x - a)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
10
30
|
def initialize(options={})
|
11
|
-
|
12
|
-
@description = "Family of continuous distributions with two parameters, shape and scale"
|
13
|
-
configure(options)
|
31
|
+
super(options)
|
14
32
|
end
|
15
33
|
|
16
|
-
def
|
17
|
-
params[:
|
34
|
+
def shape
|
35
|
+
params[:shape]
|
18
36
|
end
|
19
37
|
|
20
|
-
def
|
21
|
-
|
38
|
+
def scale
|
39
|
+
params[:scale]
|
22
40
|
end
|
23
41
|
|
24
|
-
def
|
25
|
-
|
42
|
+
def delta
|
43
|
+
@delta ||= shape - shape.floor
|
26
44
|
end
|
27
45
|
|
28
|
-
def
|
29
|
-
|
30
|
-
[:shape, 'shape of the distribution', {:type=>:float, :default => 1.0}],
|
31
|
-
[:scale, 'scale of the distribution', {:type=>:float, :default => 1.0}]
|
32
|
-
],
|
33
|
-
:banner => "Family of continuous distributions with two parameters, shape and scale."
|
34
|
-
}
|
46
|
+
def v_0
|
47
|
+
@v_0 ||= Math::E / (delta + Math::E)
|
35
48
|
end
|
36
49
|
|
37
50
|
protected
|
51
|
+
|
52
|
+
def adjust_enum
|
53
|
+
uniform.map{|n| Math.log(n) }.each_slice(shape.floor).map do |slice|
|
54
|
+
slice.inject &:+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
38
58
|
# Based on Ahrens-Dieter acceptance-rejection method
|
39
59
|
# as described on Wikipedia:
|
40
60
|
# http://en.wikipedia.org/wiki/Gamma_distribution#Generating_gamma-distributed_random_variables
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
61
|
+
|
62
|
+
def xi_enum
|
63
|
+
uniform.zip(uniform, uniform).map do |v1, v2, v3|
|
64
|
+
x = xi v1, v2, v3
|
65
|
+
[x, eta(x, v1, v2, v3)]
|
66
|
+
end.reject do |x,e|
|
67
|
+
e > (x** (delta - 1)) * (Math.exp(-x))
|
68
|
+
end.map do |x,e|
|
69
|
+
x
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def xi v1, v2, v3
|
74
|
+
if v1 < v_0
|
75
|
+
v2** (1/delta)
|
76
|
+
else
|
77
|
+
1 - Math.log(v2)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def eta xi, v1, v2, v3
|
82
|
+
if v1 < v_0
|
83
|
+
v3 * (xi** (delta - 1))
|
84
|
+
else
|
85
|
+
v3 * Math.exp(-xi)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def uniform
|
90
|
+
::Croupier::Distributions.uniform(included: 1, excluded: 0).to_enum.lazy
|
62
91
|
end
|
63
92
|
end
|
64
93
|
end
|
@@ -12,33 +12,32 @@ module Croupier
|
|
12
12
|
# (The Art of Computer Programming, Volume 2, 3.4.1.F )
|
13
13
|
class Geometric < ::Croupier::Distribution
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
15
|
+
distribution_name "Geometric distribution"
|
16
|
+
|
17
|
+
distribution_description "Discrete probability distribution that expresses the number of X Bernoulli trials needed to get one success, supported on the set { 1, 2, 3, ...}"
|
18
|
+
|
19
|
+
cli_name "geometric"
|
20
|
+
|
21
|
+
cli_options({
|
22
|
+
options: [
|
23
|
+
[:success, 'success probability of each trial', {type: :float, short: "-p", default: 0.5}]
|
24
|
+
],
|
25
|
+
banner: "Geometric distribution. Discrete probability distribution that expresses the number of X Bernoulli trials needed to get one success, supported on the set { 1, 2, 3, ...} }"
|
26
|
+
})
|
21
27
|
|
22
28
|
# Fair point: it is not the inverse of the cdf,
|
23
29
|
# but it generates the distribution from an uniform.
|
24
|
-
|
25
|
-
(Math.log(1-n) / Math.log(1-
|
26
|
-
end
|
27
|
-
|
28
|
-
def default_parameters
|
29
|
-
{:success => 0.5}
|
30
|
+
inv_cdf do |n|
|
31
|
+
(Math.log(1.0-n) / Math.log(1.0-success)).ceil
|
30
32
|
end
|
31
33
|
|
32
|
-
def
|
33
|
-
|
34
|
+
def initialize(options={})
|
35
|
+
super(options)
|
36
|
+
raise Croupier::InputParamsError, "Probability of success must be in the interval [0,1]" if params[:success] > 1 || params[:success] < 0
|
34
37
|
end
|
35
38
|
|
36
|
-
def
|
37
|
-
|
38
|
-
[:success, 'success probability of each trial', {:type=>:float, :short => "-p", :default => 0.5}]
|
39
|
-
],
|
40
|
-
:banner => "Geometric distribution. Discrete probability distribution that expresses the number of X Bernoulli trials needed to get one success, supported on the set { 1, 2, 3, ...} }"
|
41
|
-
}
|
39
|
+
def success
|
40
|
+
params[:success]
|
42
41
|
end
|
43
42
|
end
|
44
43
|
end
|
@@ -10,49 +10,38 @@ module Croupier
|
|
10
10
|
# Wikipedia -- http://en.wikipedia.org/wiki/Negative_binomial_distribution
|
11
11
|
class Nbinomial < ::Croupier::Distribution
|
12
12
|
|
13
|
-
|
14
|
-
@name = "Negative binomial distribution"
|
15
|
-
@description = "Discrete probability distribution of the number of successes in a sequence of Bernoulli trials before a specified (non-random) number of failures (denoted size) occur."
|
16
|
-
configure(options)
|
17
|
-
raise Croupier::InputParamsError, "Probability of success must be in the interval [0,1]" if params[:success] > 1 || params[:success] < 0
|
18
|
-
end
|
13
|
+
distribution_name "Negative binomial distribution"
|
19
14
|
|
20
|
-
|
21
|
-
# but it generates the distribution from an uniform.
|
22
|
-
def generate_sample n=1
|
23
|
-
generate_geometrics(n).each_slice(params[:size]).map do |sample|
|
24
|
-
sample.inject(-params[:size], &:+) # Inject starts on -size because
|
25
|
-
# this way it is equivalent to:
|
26
|
-
# sample.map{|x| x - 1}.inject(&:+)
|
27
|
-
end
|
28
|
-
end
|
15
|
+
distribution_description "Discrete probability distribution of the number of successes in a sequence of Bernoulli trials before a specified (non-random) number of failures (denoted size) occur."
|
29
16
|
|
30
|
-
|
31
|
-
{:success => 0.5, :size => 1}
|
32
|
-
end
|
17
|
+
cli_name "nbinomial"
|
33
18
|
|
34
|
-
|
35
|
-
|
36
|
-
|
19
|
+
cli_options({
|
20
|
+
options: [
|
21
|
+
[:size, 'number of errors', {type: :integer, default: 1}],
|
22
|
+
[:success, 'success probability of each trial', {type: :float, short: "-p", default: 0.5}]
|
23
|
+
],
|
24
|
+
banner: "Negative binomial distribution. Discrete probability distribution of the number of successes in a sequence of Bernoulli trials before a specified (non-random) number of failures (denoted size) occur."
|
25
|
+
})
|
37
26
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
],
|
43
|
-
:banner => "Negative binomial distribution. Discrete probability distribution of the number of successes in a sequence of Bernoulli trials before a specified (non-random) number of failures (denoted size) occur."
|
44
|
-
}
|
27
|
+
enumerator do |c|
|
28
|
+
c.geometric(success: success).to_enum.lazy.each_slice(size).map do |x|
|
29
|
+
x.inject(-size,&:+)
|
30
|
+
end
|
45
31
|
end
|
46
32
|
|
47
|
-
|
48
|
-
|
49
|
-
|
33
|
+
def initialize(options={})
|
34
|
+
super(options)
|
35
|
+
raise Croupier::InputParamsError, "Probability of success must be in the interval [0,1]" if params[:success] > 1 || params[:success] < 0
|
50
36
|
end
|
51
37
|
|
52
|
-
def
|
53
|
-
|
38
|
+
def success
|
39
|
+
params[:success]
|
54
40
|
end
|
55
41
|
|
42
|
+
def size
|
43
|
+
params[:size]
|
44
|
+
end
|
56
45
|
end
|
57
46
|
end
|
58
47
|
end
|
@@ -8,48 +8,44 @@ module Croupier
|
|
8
8
|
#
|
9
9
|
class Normal < ::Croupier::Distribution
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
distribution_name "Normal distribution"
|
12
|
+
|
13
|
+
distribution_description "Continuous distribution (mu,sigma) (defaults to (0,1) ) where mu is the mean and sigma the standard deviation."
|
14
|
+
|
15
|
+
cli_name "normal"
|
16
|
+
|
17
|
+
cli_options({
|
18
|
+
options: [
|
19
|
+
[:mean, 'mean of the distribution', {type: :float, default: 0.0}],
|
20
|
+
[:std, 'standard deviation of the distribution', {type: :float, default: 1.0}]
|
21
|
+
],
|
22
|
+
banner: "Normal distribution. Generate numbers following a continuous distribution in the real line with mean :mean and standard deviation :std."
|
23
|
+
})
|
24
|
+
|
25
|
+
minimum_sample do
|
26
|
+
x, y = 1 - ::Croupier.rand, 1 - ::Croupier.rand
|
27
|
+
[
|
28
|
+
Math.sqrt(-2*Math.log(x)) * Math.cos(2*Math::PI*y),
|
29
|
+
Math.sqrt(-2*Math.log(x)) * Math.sin(2*Math::PI*y)
|
30
|
+
]
|
15
31
|
end
|
16
32
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
# Generate
|
21
|
-
gen = (1..sample).map do |x|
|
22
|
-
1 - rand # because uniform need to be in (0,1]
|
23
|
-
end.each_slice(2).flat_map do |x, y|
|
24
|
-
[
|
25
|
-
Math.sqrt(-2*Math.log(x)) * Math.cos(2*Math::PI*y),
|
26
|
-
Math.sqrt(-2*Math.log(x)) * Math.sin(2*Math::PI*y)
|
27
|
-
]
|
28
|
-
end
|
29
|
-
|
30
|
-
# Adjust parameters.
|
31
|
-
gen.map!{ |x| x * params[:std] } if params[:std] != 1
|
32
|
-
gen.map!{ |x| x + params[:mean] } if params[:mean] != 0
|
33
|
-
|
34
|
-
# Adjust length
|
35
|
-
n.odd? ? gen[0..-2] : gen
|
33
|
+
def initialize(options={})
|
34
|
+
super(options)
|
36
35
|
end
|
37
36
|
|
38
|
-
def
|
39
|
-
|
37
|
+
def std
|
38
|
+
params[:std]
|
40
39
|
end
|
41
40
|
|
42
|
-
def
|
43
|
-
|
41
|
+
def mean
|
42
|
+
params[:mean]
|
44
43
|
end
|
45
44
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
],
|
51
|
-
:banner => "Normal distribution. Generate numbers following a continuous distribution in the real line with mean :mean and standard deviation :std."
|
52
|
-
}
|
45
|
+
def to_enum
|
46
|
+
@generator.to_enum.
|
47
|
+
map {|x| x * std}. # Adjust standard deviation
|
48
|
+
map {|x| x + mean} # Adjust mean
|
53
49
|
end
|
54
50
|
end
|
55
51
|
end
|
@@ -4,43 +4,44 @@ module Croupier
|
|
4
4
|
#####################################################################
|
5
5
|
# Poisson Distribution
|
6
6
|
# Discrete probability distribution that expresses the probability
|
7
|
-
# of a given number of event
|
7
|
+
# of a given number of event occurring in a fixed interval of time
|
8
8
|
# and/or space if these events occur with a known average rate
|
9
9
|
# and independently of the time since the las event.
|
10
10
|
#
|
11
11
|
# Wikipedia http://en.wikipedia.org/wiki/Poisson_distribution
|
12
12
|
class Poisson < ::Croupier::Distribution
|
13
13
|
|
14
|
-
|
15
|
-
@name = "Poisson distribution"
|
16
|
-
@description = "Discrete probability distribution that expresses the probability of a given number of events occurring in a fixed interval of time."
|
17
|
-
configure(options)
|
18
|
-
end
|
14
|
+
distribution_name "Poisson distribution"
|
19
15
|
|
20
|
-
|
21
|
-
l = Math.exp(-params[:lambda])
|
22
|
-
k = 0; p = 1;
|
23
|
-
while p > l
|
24
|
-
p *= rand
|
25
|
-
k += 1;
|
26
|
-
end
|
27
|
-
k-1
|
28
|
-
end
|
16
|
+
distribution_description "Discrete probability distribution that expresses the probability of a given number of events occurring in a fixed interval of time."
|
29
17
|
|
30
|
-
|
31
|
-
|
18
|
+
cli_name "poisson"
|
19
|
+
|
20
|
+
cli_options({
|
21
|
+
options: [
|
22
|
+
[:lambda, 'rate parameter (equal to the mean of the distribution)', {type: :integer, default: 50}]
|
23
|
+
],
|
24
|
+
banner: "Poisson distribution. Discrete probability distribution that expresses the probability of a given number of events occurring in a fixed interval of time."
|
25
|
+
})
|
26
|
+
|
27
|
+
enumerator_block do |y|
|
28
|
+
l = Math.exp(-lambda)
|
29
|
+
loop do
|
30
|
+
k = 0; p = 1
|
31
|
+
while p > l
|
32
|
+
p *= ::Croupier.rand
|
33
|
+
k += 1
|
34
|
+
end
|
35
|
+
y << (k-1)
|
36
|
+
end
|
32
37
|
end
|
33
38
|
|
34
|
-
def
|
35
|
-
|
39
|
+
def initialize(options={})
|
40
|
+
super(options)
|
36
41
|
end
|
37
42
|
|
38
|
-
def
|
39
|
-
|
40
|
-
[:lambda, 'rate parameter (equal to the mean of the distribution)', {:type=>:integer, :default => 50}]
|
41
|
-
],
|
42
|
-
:banner => "Poisson distribution. Discrete probability distribution that expresses the probability of a given number of events occurring in a fixed interval of time."
|
43
|
-
}
|
43
|
+
def lambda
|
44
|
+
params[:lambda]
|
44
45
|
end
|
45
46
|
end
|
46
47
|
end
|
@@ -7,42 +7,56 @@ module Croupier
|
|
7
7
|
# is a, upper limit b and mode c (a <= c <= b).
|
8
8
|
class Triangular < ::Croupier::Distribution
|
9
9
|
|
10
|
+
distribution_name "Triangular distribution"
|
11
|
+
|
12
|
+
distribution_description "Continuous probability distribution whose lower limit is a, upper limit b and mode c (a <= c <= b)"
|
13
|
+
|
14
|
+
cli_name "triangular"
|
15
|
+
|
16
|
+
cli_options({
|
17
|
+
options: [
|
18
|
+
[:lower, 'lower limit', {type: :float, short: '-a', default: 0.0}],
|
19
|
+
[:upper, 'upper limit', {type: :float, short: '-b', default: 1.0}],
|
20
|
+
[:mode, 'mode', {type: :float, short: '-c', default: 0.5}]
|
21
|
+
],
|
22
|
+
banner: "Triangular distribution. Continuous distribution whose support is the interval (a,b), with mode c."
|
23
|
+
})
|
24
|
+
|
25
|
+
inv_cdf do |n|
|
26
|
+
if n < @F_c
|
27
|
+
lower + Math.sqrt( n * range * (mode - lower) )
|
28
|
+
else
|
29
|
+
upper - Math.sqrt( (1-n) * range * (upper - mode) )
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
10
33
|
def initialize(options={})
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
34
|
+
super(options)
|
35
|
+
if params[:lower] >= params[:upper]
|
36
|
+
warn("Lower limit is greater than upper limit. Changing their values.")
|
37
|
+
params[:lower], params[:upper] = params[:upper], params[:lower]
|
38
|
+
end
|
39
|
+
if params[:mode] < params[:lower] || params[:upper] < params[:mode]
|
16
40
|
warn("Mode is not in the support. Mode value will be change to median.")
|
17
|
-
params[:
|
41
|
+
params[:mode] = (params[:lower]+params[:upper])/2.0;
|
18
42
|
end
|
19
|
-
@F_c = (params[:
|
43
|
+
@F_c = (params[:mode]-params[:lower]).to_f/(params[:upper]-params[:lower])
|
20
44
|
end
|
21
45
|
|
22
|
-
def
|
23
|
-
|
24
|
-
params[:a] + Math.sqrt( n * (params[:b] - params[:a]) * (params[:c] - params[:a]) )
|
25
|
-
else
|
26
|
-
params[:b] - Math.sqrt( (1-n) * (params[:b] - params[:a]) * (params[:b] - params[:c]) )
|
27
|
-
end
|
46
|
+
def lower
|
47
|
+
params[:lower]
|
28
48
|
end
|
29
49
|
|
30
|
-
def
|
31
|
-
|
50
|
+
def upper
|
51
|
+
params[:upper]
|
32
52
|
end
|
33
53
|
|
34
|
-
def
|
35
|
-
|
54
|
+
def mode
|
55
|
+
params[:mode]
|
36
56
|
end
|
37
57
|
|
38
|
-
def
|
39
|
-
|
40
|
-
[:a, 'lower limit', {:type=>:float, :default => 0.0}],
|
41
|
-
[:b, 'upper limit', {:type=>:float, :default => 1.0}],
|
42
|
-
[:c, 'mode' , {:type=>:float, :default => 0.5}]
|
43
|
-
],
|
44
|
-
:banner => "Triangular distribution. Continuous distribution whose support is the interval (a,b), with mode c."
|
45
|
-
}
|
58
|
+
def range
|
59
|
+
@range ||= upper - lower
|
46
60
|
end
|
47
61
|
end
|
48
62
|
end
|
@@ -3,37 +3,61 @@ module Croupier
|
|
3
3
|
|
4
4
|
#####################################################################
|
5
5
|
# Uniform Distribution
|
6
|
-
#
|
6
|
+
# Continuous distribution where all points in an interval have
|
7
7
|
# the same probability.
|
8
8
|
#
|
9
9
|
class Uniform < ::Croupier::Distribution
|
10
10
|
|
11
|
+
distribution_name "Uniform distribution"
|
12
|
+
|
13
|
+
distribution_description "Continuous distribution on [a,b] (defaults to [0,1]) where all points in the interval are equally likely"
|
14
|
+
|
15
|
+
cli_name "uniform"
|
16
|
+
|
17
|
+
cli_options({
|
18
|
+
options: [
|
19
|
+
[:included, 'interval included value', {type: :float, short: "-i", default: 0.0}],
|
20
|
+
[:excluded, 'interval excluded value', {type: :float, short: "-e", default: 1.0}]
|
21
|
+
],
|
22
|
+
banner: "Uniform distribution. Generate numbers following a continuous distribution on [a,b] (given a=min(included, excluded) and b=max(included,excluded)) where all points in the interval are equally likely."
|
23
|
+
})
|
24
|
+
|
11
25
|
def initialize(options={})
|
12
|
-
|
13
|
-
@
|
14
|
-
|
26
|
+
super options
|
27
|
+
@exclude_value = if self.inverted?
|
28
|
+
->(n) { 1-n }
|
29
|
+
else
|
30
|
+
->(n) { n }
|
31
|
+
end
|
32
|
+
@min, @max = if self.inverted?
|
33
|
+
[params[:excluded], params[:included]]
|
34
|
+
else
|
35
|
+
[params[:included], params[:excluded]]
|
36
|
+
end
|
37
|
+
@range = @max - @min
|
15
38
|
end
|
16
39
|
|
17
|
-
|
18
|
-
raise Croupier::InputParamsError, "Invalid interval values" if params[:b] < params[:a]
|
19
|
-
rand Range.new(params[:a], params[:b])
|
20
|
-
end
|
40
|
+
attr_reader :exclude_value, :min, :max, :range
|
21
41
|
|
22
|
-
def
|
23
|
-
|
42
|
+
def inverted?
|
43
|
+
params[:included] > params[:excluded]
|
24
44
|
end
|
25
45
|
|
26
|
-
def
|
27
|
-
|
46
|
+
def to_enum
|
47
|
+
@enum ||= base_enum.lazy.
|
48
|
+
map(&exclude_value).
|
49
|
+
map do |n|
|
50
|
+
min + range * n
|
51
|
+
end
|
28
52
|
end
|
29
53
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
54
|
+
protected
|
55
|
+
def base_enum
|
56
|
+
Enumerator.new do |y|
|
57
|
+
loop do
|
58
|
+
y << Croupier.rand
|
59
|
+
end
|
60
|
+
end
|
37
61
|
end
|
38
62
|
end
|
39
63
|
end
|