distribution 0.7.3 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +4 -6
  3. data/.yardopts +5 -0
  4. data/History.txt +3 -0
  5. data/README.md +87 -44
  6. data/benchmark/binomial_coefficient.rb +19 -23
  7. data/benchmark/binomial_coefficient/experiment.rb +33 -36
  8. data/benchmark/factorial_hash.rb +7 -8
  9. data/benchmark/factorial_method.rb +4 -6
  10. data/benchmark/odd.rb +6 -7
  11. data/benchmark/power.rb +11 -11
  12. data/bin/distribution +26 -26
  13. data/distribution.gemspec +3 -4
  14. data/lib/distribution.rb +55 -96
  15. data/lib/distribution/beta/gsl.rb +10 -5
  16. data/lib/distribution/beta/ruby.rb +3 -1
  17. data/lib/distribution/binomial/ruby.rb +5 -2
  18. data/lib/distribution/bivariatenormal.rb +4 -5
  19. data/lib/distribution/bivariatenormal/gsl.rb +2 -2
  20. data/lib/distribution/bivariatenormal/java.rb +1 -1
  21. data/lib/distribution/bivariatenormal/ruby.rb +245 -254
  22. data/lib/distribution/chisquare.rb +8 -10
  23. data/lib/distribution/chisquare/gsl.rb +24 -19
  24. data/lib/distribution/chisquare/java.rb +1 -1
  25. data/lib/distribution/chisquare/ruby.rb +25 -25
  26. data/lib/distribution/chisquare/statistics2.rb +16 -13
  27. data/lib/distribution/distributable.rb +40 -0
  28. data/lib/distribution/exponential.rb +4 -5
  29. data/lib/distribution/exponential/gsl.rb +13 -9
  30. data/lib/distribution/exponential/ruby.rb +14 -9
  31. data/lib/distribution/f.rb +1 -1
  32. data/lib/distribution/f/gsl.rb +26 -22
  33. data/lib/distribution/f/java.rb +1 -1
  34. data/lib/distribution/f/ruby.rb +16 -19
  35. data/lib/distribution/f/statistics2.rb +22 -19
  36. data/lib/distribution/gamma.rb +5 -7
  37. data/lib/distribution/gamma/gsl.rb +13 -9
  38. data/lib/distribution/gamma/java.rb +1 -1
  39. data/lib/distribution/gamma/ruby.rb +5 -11
  40. data/lib/distribution/hypergeometric.rb +5 -8
  41. data/lib/distribution/hypergeometric/gsl.rb +4 -5
  42. data/lib/distribution/hypergeometric/java.rb +1 -1
  43. data/lib/distribution/hypergeometric/ruby.rb +34 -35
  44. data/lib/distribution/logistic.rb +5 -8
  45. data/lib/distribution/logistic/ruby.rb +13 -8
  46. data/lib/distribution/lognormal.rb +5 -7
  47. data/lib/distribution/lognormal/gsl.rb +8 -6
  48. data/lib/distribution/lognormal/ruby.rb +5 -9
  49. data/lib/distribution/math_extension.rb +6 -15
  50. data/lib/distribution/math_extension/chebyshev_series.rb +281 -272
  51. data/lib/distribution/math_extension/erfc.rb +26 -29
  52. data/lib/distribution/math_extension/exponential_integral.rb +17 -17
  53. data/lib/distribution/math_extension/gammastar.rb +19 -20
  54. data/lib/distribution/math_extension/gsl_utilities.rb +12 -12
  55. data/lib/distribution/math_extension/incomplete_beta.rb +52 -61
  56. data/lib/distribution/math_extension/incomplete_gamma.rb +166 -168
  57. data/lib/distribution/math_extension/log_utilities.rb +20 -22
  58. data/lib/distribution/normal.rb +11 -13
  59. data/lib/distribution/normal/gsl.rb +13 -10
  60. data/lib/distribution/normal/java.rb +14 -13
  61. data/lib/distribution/normal/ruby.rb +68 -58
  62. data/lib/distribution/normal/statistics2.rb +5 -2
  63. data/lib/distribution/normalmultivariate.rb +64 -64
  64. data/lib/distribution/poisson.rb +11 -13
  65. data/lib/distribution/poisson/gsl.rb +7 -7
  66. data/lib/distribution/poisson/java.rb +19 -24
  67. data/lib/distribution/poisson/ruby.rb +38 -9
  68. data/lib/distribution/shorthand.rb +17 -0
  69. data/lib/distribution/t.rb +13 -15
  70. data/lib/distribution/t/gsl.rb +27 -24
  71. data/lib/distribution/t/java.rb +1 -1
  72. data/lib/distribution/t/ruby.rb +99 -100
  73. data/lib/distribution/t/statistics2.rb +19 -19
  74. data/lib/distribution/uniform.rb +26 -0
  75. data/lib/distribution/uniform/gsl.rb +36 -0
  76. data/lib/distribution/uniform/ruby.rb +91 -0
  77. data/lib/distribution/version.rb +1 -1
  78. data/lib/distribution/weibull.rb +6 -7
  79. data/lib/distribution/weibull/gsl.rb +16 -16
  80. data/lib/distribution/weibull/ruby.rb +30 -23
  81. data/spec/beta_spec.rb +45 -47
  82. data/spec/binomial_spec.rb +77 -85
  83. data/spec/bivariatenormal_spec.rb +28 -35
  84. data/spec/chisquare_spec.rb +48 -52
  85. data/spec/distribution_spec.rb +10 -10
  86. data/spec/exponential_spec.rb +44 -49
  87. data/spec/f_spec.rb +4 -4
  88. data/spec/gamma_spec.rb +50 -53
  89. data/spec/hypergeometric_spec.rb +63 -69
  90. data/spec/logistic_spec.rb +32 -37
  91. data/spec/lognormal_spec.rb +25 -31
  92. data/spec/math_extension_spec.rb +192 -210
  93. data/spec/normal_spec.rb +80 -73
  94. data/spec/poisson_spec.rb +63 -41
  95. data/spec/shorthand_spec.rb +19 -22
  96. data/spec/spec_helper.rb +8 -9
  97. data/spec/t_spec.rb +63 -77
  98. data/spec/uniform_spec.rb +154 -0
  99. data/spec/weibull_spec.rb +13 -14
  100. metadata +17 -8
@@ -3,26 +3,26 @@ module Distribution
3
3
  module T
4
4
  module Statistics2_
5
5
  class << self
6
- # Return the P-value of the corresponding integral with
7
- # k degrees of freedom
8
- def p_value(pr,k)
9
- Statistics2.ptdist(k, pr)
10
- end
11
-
12
-
13
- # There are some problem on i686 with t on statistics2
14
- if true or !RbConfig::CONFIG['arch']=~/i686/
15
- # T cumulative distribution function (cdf).
16
- #
17
- # Returns the integral of t-distribution
18
- # with n degrees of freedom over (-Infty, x].
19
- #
20
- def cdf(x,k)
21
- Statistics2.tdist(k,x)
6
+ # There are some problem on i686 with t on statistics2
7
+ if true || !RbConfig::CONFIG['arch'] =~ /i686/
8
+ # T cumulative distribution function (cdf).
9
+ #
10
+ # Returns the integral of t-distribution
11
+ # with n degrees of freedom over (-Infty, x].
12
+ #
13
+ def cdf(x, k)
14
+ Statistics2.tdist(k, x)
15
+ end
16
+
17
+ # Return the P-value of the corresponding integral with
18
+ # k degrees of freedom
19
+ def quantile(pr, k)
20
+ Statistics2.ptdist(k, pr)
21
+ end
22
+
23
+ alias_method :p_value, :quantile
22
24
  end
23
25
  end
24
-
25
- end
26
26
  end
27
27
  end
28
- end
28
+ end
@@ -0,0 +1,26 @@
1
+ require 'distribution/uniform/ruby'
2
+ require 'distribution/uniform/gsl'
3
+ #require 'distribution/uniform/java'
4
+
5
+
6
+ module Distribution
7
+ # Expresses the uniformly spread probability over a finite interval
8
+ module Uniform
9
+ SHORTHAND='unif'
10
+ extend Distributable
11
+ create_distribution_methods
12
+
13
+ ##
14
+ # :singleton-method: pdf(x, lower, upper)
15
+ # Returns the uniform PDF
16
+
17
+ ##
18
+ # :singleton-method: cdf(x, lower, upper)
19
+ # Returns the uniform CDF
20
+
21
+ ##
22
+ # :singleton-method: quantile(qn, lower, upper)
23
+ # Returns the uniform inverse CDF or P-value
24
+
25
+ end
26
+ end
@@ -0,0 +1,36 @@
1
+ module Distribution
2
+ module Uniform
3
+ module GSL_
4
+ class << self
5
+ # Returns a lambda to call for uniformly distributed random numbers
6
+ # returns a double precision float in [0, 1]
7
+ def rng(lower = 0, upper = 1, seed = nil)
8
+ seed = Random.new_seed.modulo 100000007 if seed.nil?
9
+ rng = GSL::Rng.alloc(GSL::Rng::MT19937, seed)
10
+
11
+ -> { lower + (upper - lower) * rng.uniform }
12
+ end
13
+
14
+ # :nodoc:
15
+ def pdf(x, lower = 0, upper = 1)
16
+ # rb-gsl/blob/master/ext/gsl_native/randist.c#L1732
17
+ GSL::Ran.flat_pdf(x, lower, upper)
18
+ end
19
+
20
+ # :nodoc:
21
+ def cdf(x, lower = 0, upper = 1)
22
+ # rb-gsl/blob/master/ext/gsl_native/cdf.c#L644
23
+ GSL::Cdf.flat_P(x, lower, upper)
24
+ end
25
+
26
+ # :nodoc:
27
+ def quantile(qn, lower, upper)
28
+ # rb-gsl/blob/master/ext/gsl_native/cdf.c#L646
29
+ GSL::Cdf.flat_Pinv(qn, lower, upper)
30
+ end
31
+
32
+ alias_method :p_value, :quantile
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,91 @@
1
+ module Distribution
2
+ module Uniform
3
+ module Ruby_
4
+ # Module contain pure ruby implementation of the
5
+ # uniform distribution (rng, pdf, cdf and quantile functions)
6
+ class << self
7
+ # Returns a lambda that emits a uniformly distributed
8
+ # sequence of random numbers between the defined limits
9
+ #
10
+ # == Arguments
11
+ # * +lower+ - Lower limit of the distribution
12
+ # * +upper+ - Upper limit of the distribution
13
+ # * +seed+ - Seed to set the initial state, randomized if ommited
14
+ #
15
+ def rng(lower = 0, upper = 1, seed = nil)
16
+ seed = Random.new_seed if seed.nil?
17
+ prng = Random.new(seed)
18
+ -> { prng.rand * (upper - lower) + lower }
19
+ end
20
+
21
+ # Uniform probability density function on [a, b]
22
+ #
23
+ # == Arguments
24
+ # If you are referring the wiki page for this continuous distribution
25
+ # the arguments can be translated as follows
26
+ # * +x+ - same as continuous random variable
27
+ # * +lower+ - lower limit or a, must be a real number
28
+ # * +upper+ - upper limit or b, must be a real number
29
+ #
30
+ # == Reference
31
+ # * https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)
32
+ #
33
+ # The implementation has been adopted from GSL-1.9 gsl/randist/flat.c
34
+ #
35
+ def pdf(x, lower = 0, upper = 1)
36
+ upper, lower = lower, upper if lower > upper
37
+ return 1 / (upper - lower) if (lower..upper).member? x
38
+ 0
39
+ end
40
+
41
+ # The uniform cumulative density function (CDF)
42
+ # == Arguments
43
+ # If you are referring the wiki page for this continuous distribution
44
+ # the arguments can be translated as follows
45
+ # * +x+ - same as continuous random variable
46
+ # * +lower+ - lower limit or a, must be a real number
47
+ # * +upper+ - upper limit or b, must be a real number
48
+ #
49
+ # == Reference
50
+ # * https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)
51
+ #
52
+ # The implementation has been adpoted from GSL-1.9 gsl/cdf/flat.c
53
+ #
54
+ def cdf(x, lower = 0, upper = 1)
55
+ if x < lower
56
+ 0
57
+ elsif x > upper
58
+ 1
59
+ else
60
+ (x - lower) / (upper - lower)
61
+ end
62
+ end
63
+
64
+ # The uniform inverse CDF density function / P-value function
65
+ # == Arguments
66
+ # If you are referring the wiki page for this continuous distribution
67
+ # the arguments can be translated as follows
68
+ # * +qn+ - same as integral value
69
+ # * +lower+ - lower limit or a, must be a real number
70
+ # * +upper+ - upper limit or b, must be a real number
71
+ #
72
+ # == Returns
73
+ # * nil if the integral value is not in [0, 1]
74
+ # * inverse cdf otherwise
75
+ # == Reference
76
+ # * https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)
77
+ #
78
+ # The implementation has been adpoted from GSL-1.9 gsl/cdf/flatinv.c
79
+ #
80
+ def quantile(qn, lower = 0, upper = 1)
81
+ fail RangeError, 'cdf value(qn) must be from [0, 1]. '\
82
+ "Cannot find quantile for qn=#{qn}" if qn > 1 || qn < 0
83
+
84
+ qn * upper + (1 - qn) * lower
85
+ end
86
+
87
+ alias p_value quantile
88
+ end
89
+ end
90
+ end
91
+ end
@@ -1,3 +1,3 @@
1
1
  module Distribution
2
- VERSION = '0.7.3'
2
+ VERSION = '0.8.0'
3
3
  end
@@ -2,10 +2,9 @@ require 'distribution/weibull/ruby'
2
2
  require 'distribution/weibull/gsl'
3
3
 
4
4
  module Distribution
5
-
6
- module Weibull
7
- SHORTHAND = 'weibull'
8
- extend Distributable
9
- create_distribution_methods
10
- end
11
- end
5
+ module Weibull
6
+ SHORTHAND = 'weibull'
7
+ extend Distributable
8
+ create_distribution_methods
9
+ end
10
+ end
@@ -1,21 +1,21 @@
1
1
  module Distribution
2
- module Weibull
3
- module GSL_
4
- class << self
5
-
6
- def pdf(x, k, lam)
7
- GSL::Ran.weibull_pdf(x, lam, k)
8
- end
9
-
2
+ module Weibull
3
+ module GSL_
4
+ class << self
5
+ def pdf(x, k, lam)
6
+ GSL::Ran.weibull_pdf(x, lam, k)
7
+ end
10
8
 
11
- def cdf(x, k, lam)
12
- GSL::Cdf.weibull_P(x, lam, k)
13
- end
9
+ def cdf(x, k, lam)
10
+ GSL::Cdf.weibull_P(x, lam, k)
11
+ end
14
12
 
15
- def p_value(y, k, lam)
16
- GSL::Cdf.weibull_Pinv(y, lam, k)
17
- end
18
- end
19
- end
13
+ def quantile(y, k, lam)
14
+ GSL::Cdf.weibull_Pinv(y, lam, k)
20
15
  end
16
+
17
+ alias_method :p_value, :quantile
18
+ end
19
+ end
20
+ end
21
21
  end
@@ -1,27 +1,34 @@
1
1
  module Distribution
2
- module Weibull
3
- module Ruby_
4
- class << self
5
- def pdf(x, k, lam)
6
- return 0.0 if x < 0.0
7
- return ((k.to_f/lam.to_f)*(x.to_f/lam.to_f)**(k-1.0))*Math.exp(-(x.to_f/lam.to_f)**k)
8
- end
2
+ module Weibull
3
+ module Ruby_
4
+ class << self
5
+ def pdf(x, k, lam)
6
+ if x < 0.0
7
+ 0.0
8
+ else
9
+ a = (k.to_f / lam.to_f)
10
+ b = (x.to_f / lam.to_f)
11
+ c = (k - 1.0)
12
+ d = Math.exp(-(x.to_f / lam.to_f)**k)
13
+ (a * b**c) * d
14
+ end
15
+ end
9
16
 
10
- #Returns the integral of the Weibull distribution from [-Inf to x]
17
+ # Returns the integral of the Weibull distribution from [-Inf to x]
18
+ def cdf(x, k, lam)
19
+ return 0.0 if x < 0.0
20
+ 1.0 - Math.exp(-(x.to_f / lam.to_f)**k)
21
+ end
11
22
 
12
- def cdf(x, k, lam)
13
- return 0.0 if x < 0.0
14
- return 1.0-Math.exp(-(x.to_f/lam.to_f)**k)
15
- end
23
+ # Returns the P-value of weibull
24
+ def quantile(y, k, lam)
25
+ return 1.0 if y > 1.0
26
+ return 0.0 if y < 0.0
27
+ -lam * (Math.log(1.0 - y))**(1.0 / k)
28
+ end
16
29
 
17
- # Returns the P-value of weibull
18
-
19
- def p_value(y, k, lam)
20
- return 1.0 if y > 1.0
21
- return 0.0 if y < 0.0
22
- return -lam*(Math.log(1.0-y))**(1.0/k)
23
- end
24
- end
25
- end
26
- end
27
- end
30
+ alias_method :p_value, :quantile
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,82 +1,80 @@
1
- require File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb")
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper.rb')
2
2
  include ExampleWithGSL
3
3
  describe Distribution::Beta do
4
-
5
- shared_examples_for "Beta engine" do
6
- it_only_with_gsl "should return correct pdf" do
4
+ shared_examples_for 'Beta engine' do
5
+ it_only_with_gsl 'should return correct pdf' do
7
6
  if @engine.respond_to? :pdf
8
7
  1.upto(101) do |x|
9
- a=rand * x
10
- b=1 + rand * 5
11
- g=GSL::Ran.beta_pdf(x,a,b)
12
- @engine.pdf(x,a,b).should be_within(1e-09).of(g)
8
+ a = rand * x
9
+ b = 1 + rand * 5
10
+ g = GSL::Ran.beta_pdf(x, a, b)
11
+ expect(@engine.pdf(x, a, b)).to be_within(1e-09).of(g)
13
12
  end
14
13
  else
15
14
  skip("No #{@engine}.pdf")
16
15
  end
17
16
  end
18
17
 
19
- it_only_with_gsl "should return correct cdf" do
20
- if @engine.respond_to? :cdf
21
- # From GSL-1.9.
22
- tol = 1048576.0*Float::EPSILON
23
- @engine.cdf(0.0, 1.2, 1.3).should eq(0.0)
24
- @engine.cdf(1e-100, 1.2, 1.3).should be_within(tol).of(1.34434944656489596e-120)
25
- @engine.cdf(0.001, 1.2, 1.3).should be_within(tol).of(3.37630042504535813e-4)
26
- @engine.cdf(0.01, 1.2, 1.3).should be_within(tol).of(5.34317264038929473e-3)
27
- @engine.cdf(0.1, 1.2, 1.3).should be_within(tol).of(8.33997828306748346e-2)
28
- @engine.cdf(0.325, 1.2, 1.3).should be_within(tol).of(3.28698654180583916e-1)
29
- @engine.cdf(0.5, 1.2, 1.3).should be_within(tol).of(5.29781429451299081e-1)
30
- @engine.cdf(0.9, 1.2, 1.3).should be_within(tol).of(9.38529397224430659e-1)
31
- @engine.cdf(0.99, 1.2, 1.3).should be_within(tol).of(9.96886438341254380e-1)
32
- @engine.cdf(0.999, 1.2, 1.3).should be_within(tol).of(9.99843792833067634e-1)
33
- @engine.cdf(1.0, 1.2, 1.3).should be_within(tol).of(1.0)
34
- else
35
- skip("No #{@engine}.cdf")
18
+ it_only_with_gsl 'should return correct cdf' do
19
+ if @engine.respond_to? :cdf
20
+ # From GSL-1.9.
21
+ tol = 1_048_576.0 * Float::EPSILON
22
+ expect(@engine.cdf(0.0, 1.2, 1.3)).to eq(0.0)
23
+ expect(@engine.cdf(1e-100, 1.2, 1.3)).to be_within(tol).of(1.34434944656489596e-120)
24
+ expect(@engine.cdf(0.001, 1.2, 1.3)).to be_within(tol).of(3.37630042504535813e-4)
25
+ expect(@engine.cdf(0.01, 1.2, 1.3)).to be_within(tol).of(5.34317264038929473e-3)
26
+ expect(@engine.cdf(0.1, 1.2, 1.3)).to be_within(tol).of(8.33997828306748346e-2)
27
+ expect(@engine.cdf(0.325, 1.2, 1.3)).to be_within(tol).of(3.28698654180583916e-1)
28
+ expect(@engine.cdf(0.5, 1.2, 1.3)).to be_within(tol).of(5.29781429451299081e-1)
29
+ expect(@engine.cdf(0.9, 1.2, 1.3)).to be_within(tol).of(9.38529397224430659e-1)
30
+ expect(@engine.cdf(0.99, 1.2, 1.3)).to be_within(tol).of(9.96886438341254380e-1)
31
+ expect(@engine.cdf(0.999, 1.2, 1.3)).to be_within(tol).of(9.99843792833067634e-1)
32
+ expect(@engine.cdf(1.0, 1.2, 1.3)).to be_within(tol).of(1.0)
33
+ else
34
+ skip("No #{@engine}.cdf")
35
+ end
36
36
  end
37
- end
38
- it "should return correct p_value" do
39
- if @engine.respond_to? :p_value
40
- 2.upto(99) do |x|
41
- a=rand() * x
42
- b=1 + rand() * 5
43
- pr=@engine.cdf(x/100.0,a,b)
44
- @engine.p_value(pr,a, b).should be_within(1e-09).of(x/100.0)
45
- end
46
- else
47
- skip("No #{@engine}.p_value")
37
+ it 'should return correct p_value' do
38
+ if @engine.respond_to? :p_value
39
+ 2.upto(99) do |x|
40
+ a = rand * x
41
+ b = 1 + rand * 5
42
+ pr = @engine.cdf(x / 100.0, a, b)
43
+ expect(@engine.p_value(pr, a, b)).to be_within(1e-09).of(x / 100.0)
44
+ end
45
+ else
46
+ skip("No #{@engine}.p_value")
47
+ end
48
48
  end
49
49
  end
50
- end
51
50
 
52
- describe "singleton" do
51
+ describe 'singleton' do
53
52
  before do
54
- @engine=Distribution::Beta
53
+ @engine = Distribution::Beta
55
54
  end
56
- it_should_behave_like "Beta engine"
55
+ it_should_behave_like 'Beta engine'
57
56
  end
58
57
 
59
58
  describe Distribution::Beta::Ruby_ do
60
59
  before do
61
- @engine=Distribution::Beta::Ruby_
60
+ @engine = Distribution::Beta::Ruby_
62
61
  end
63
- it_should_behave_like "Beta engine"
62
+ it_should_behave_like 'Beta engine'
64
63
  end
65
64
  if Distribution.has_gsl?
66
65
  describe Distribution::Beta::GSL_ do
67
66
  before do
68
- @engine=Distribution::Beta::GSL_
67
+ @engine = Distribution::Beta::GSL_
69
68
  end
70
- it_should_behave_like "Beta engine"
69
+ it_should_behave_like 'Beta engine'
71
70
  end
72
71
  end
73
72
  if Distribution.has_java?
74
73
  describe Distribution::Beta::Java_ do
75
74
  before do
76
- @engine=Distribution::Beta::Java_
75
+ @engine = Distribution::Beta::Java_
77
76
  end
78
- it_should_behave_like "Beta engine"
77
+ it_should_behave_like 'Beta engine'
79
78
  end
80
79
  end
81
-
82
80
  end