rubystats 0.2.3 → 0.4.1

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.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/test.yml +21 -0
  3. data/.gitignore +20 -0
  4. data/Gemfile +3 -0
  5. data/History.txt +34 -0
  6. data/{README.txt → README.rdoc} +18 -7
  7. data/Rakefile +11 -44
  8. data/examples/uniform.rb +14 -0
  9. data/lib/rubystats/beta_distribution.rb +4 -0
  10. data/lib/rubystats/binomial_distribution.rb +42 -131
  11. data/lib/rubystats/cauchy_distribution.rb +50 -0
  12. data/lib/rubystats/exponential_distribution.rb +2 -2
  13. data/lib/rubystats/fishers_exact_test.rb +9 -9
  14. data/lib/rubystats/gamma_distribution.rb +70 -0
  15. data/lib/rubystats/lognormal_distribution.rb +59 -0
  16. data/lib/rubystats/modules.rb +57 -48
  17. data/lib/rubystats/multivariate_normal_distribution.rb +73 -0
  18. data/lib/rubystats/normal_distribution.rb +4 -3
  19. data/lib/rubystats/poisson_distribution.rb +78 -0
  20. data/lib/rubystats/probability_distribution.rb +4 -4
  21. data/lib/rubystats/student_t_distribution.rb +62 -0
  22. data/lib/rubystats/uniform_distribution.rb +70 -0
  23. data/lib/rubystats/version.rb +3 -0
  24. data/lib/rubystats/weibull_distribution.rb +56 -0
  25. data/lib/rubystats.rb +39 -5
  26. data/rubystats.gemspec +28 -0
  27. data/test/tc_beta.rb +90 -69
  28. data/test/tc_binomial.rb +30 -16
  29. data/test/tc_cauchy.rb +39 -0
  30. data/test/tc_exponential.rb +13 -3
  31. data/test/tc_fisher.rb +15 -15
  32. data/test/tc_gamma.rb +39 -0
  33. data/test/tc_lnorm.rb +45 -0
  34. data/test/tc_multivariate_normal.rb +53 -0
  35. data/test/tc_norm.rb +35 -6
  36. data/test/tc_poisson.rb +35 -0
  37. data/test/tc_require_all.rb +5 -5
  38. data/test/tc_studentt.rb +43 -0
  39. data/test/tc_unif.rb +48 -0
  40. data/test/tc_weibull.rb +51 -0
  41. data/test/ts_stats.rb +1 -1
  42. metadata +115 -47
@@ -0,0 +1,56 @@
1
+ require 'rubystats/probability_distribution'
2
+ module Rubystats
3
+ class WeibullDistribution < Rubystats::ProbabilityDistribution
4
+ include Rubystats::NumericalConstants
5
+
6
+ def initialize(scale=1.0, shape=1.0)
7
+ if scale <= 0.0
8
+ raise ArgumentError.new("Scale parameter should be greater than zero.")
9
+ end
10
+ if shape <= 0.0
11
+ raise ArgumentError.new("Shape parameter should be greater than zero.")
12
+ end
13
+ @scale = scale.to_f
14
+ @shape = shape.to_f
15
+ end
16
+
17
+ private
18
+
19
+ def get_mean
20
+ @scale * Math.gamma(1.0 + 1.0 / @shape)
21
+ end
22
+
23
+ def get_variance
24
+ @scale**2 * (Math.gamma(1.0 + 2.0 / @shape) - (Math.gamma(1.0 + 1.0 / @shape))**2)
25
+ end
26
+
27
+ # Private method to obtain single PDF value.
28
+ # x should be greater than or equal to 0.0
29
+ # returns the probability that a stochastic variable x has the value X, i.e. P(x=X).
30
+ def get_pdf(x)
31
+ check_range(x, 0.0, MAX_VALUE)
32
+ (@shape / @scale) * (x / @scale)**(@shape-1.0) * Math.exp(-1.0 * ((x/@scale)**@shape))
33
+ end
34
+
35
+ # Private method to obtain single CDF value.
36
+ # param x should be greater than 0
37
+ # return the probability that a stochastic variable x is less then X, i.e. P(x<X).
38
+ def get_cdf(x)
39
+ check_range(x,0.0,MAX_VALUE)
40
+ 1.0 - Math.exp(-1.0 * ((x.to_f/@scale)**@shape))
41
+ end
42
+
43
+ # Private method to obtain single inverse CDF value.
44
+ # return the value X for which P(x<X).
45
+ def get_icdf(p)
46
+ check_range(p)
47
+ @scale * (-1.0 * Math.log(1.0 - p.to_f))**(1.0 / @shape)
48
+ end
49
+
50
+ # Private method to obtain single RNG value.
51
+ def get_rng
52
+ self.icdf(Kernel.rand)
53
+ end
54
+
55
+ end
56
+ end
data/lib/rubystats.rb CHANGED
@@ -1,10 +1,44 @@
1
- module Rubystats
2
- VERSION = '0.2.3'
3
- end
4
-
5
1
  require 'rubystats/normal_distribution'
6
2
  require 'rubystats/binomial_distribution'
3
+ require 'rubystats/poisson_distribution'
7
4
  require 'rubystats/beta_distribution'
8
5
  require 'rubystats/fishers_exact_test'
9
6
  require 'rubystats/exponential_distribution'
10
- include Rubystats
7
+ require 'rubystats/uniform_distribution'
8
+ require 'rubystats/lognormal_distribution'
9
+ require 'rubystats/student_t_distribution'
10
+ require 'rubystats/weibull_distribution'
11
+ require 'rubystats/cauchy_distribution'
12
+ require 'rubystats/gamma_distribution'
13
+ require 'rubystats/multivariate_normal_distribution'
14
+ require 'rubystats/version'
15
+
16
+ module Rubystats
17
+ end
18
+
19
+ NormalDistribution = Rubystats::NormalDistribution
20
+ BinomialDistribution = Rubystats::BinomialDistribution
21
+ PoissonDistribution = Rubystats::PoissonDistribution
22
+ BetaDistribution = Rubystats::BetaDistribution
23
+ FishersExactTest = Rubystats::FishersExactTest
24
+ ExponentialDistribution = Rubystats::ExponentialDistribution
25
+ UniformDistribution = Rubystats::UniformDistribution
26
+ LognormalDistribution = Rubystats::LognormalDistribution
27
+ StudentTDistribution = Rubystats::StudentTDistribution
28
+ WeibullDistribution = Rubystats::WeibullDistribution
29
+ CauchyDistribution = Rubystats::CauchyDistribution
30
+ GammaDistribution = Rubystats::GammaDistribution
31
+ MultivariateNormalDistribution = Rubystats::MultivariateNormalDistribution
32
+
33
+ #short-hand notation
34
+ Normal = Rubystats::NormalDistribution
35
+ Binomial = Rubystats::BinomialDistribution
36
+ Poisson = Rubystats::PoissonDistribution
37
+ Beta = Rubystats::BetaDistribution
38
+ Exponential = Rubystats::ExponentialDistribution
39
+ Uniform = Rubystats::UniformDistribution
40
+ Lognormal = Rubystats::LognormalDistribution
41
+ Weibull = Rubystats::WeibullDistribution
42
+ Cauchy = Rubystats::CauchyDistribution
43
+ Gamma = Rubystats::GammaDistribution
44
+ MultivariateNormal = Rubystats::MultivariateNormalDistribution
data/rubystats.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ $LOAD_PATH << File.expand_path("../lib", __FILE__)
2
+ require 'rubystats/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'rubystats'
6
+ s.version = Rubystats::VERSION
7
+ s.license = "MIT"
8
+ s.summary = ''
9
+ s.description = "Ruby Stats is a port of the statistics libraries from PHPMath. Probability distributions include binomial, beta, and normal distributions with PDF, CDF and inverse CDF as well as Fisher's Exact Test."
10
+
11
+ s.files = `git ls-files`.split("\n")
12
+ s.test_files = `git ls-files -- Appraisals {test,spec,features,gemfiles}/*`.split("\n")
13
+
14
+ s.require_paths = ['lib']
15
+ s.required_ruby_version = Gem::Requirement.new(">= 1.9.3")
16
+
17
+ s.authors = ['Ilya Scharrenbroich', 'Bryan Donovan - http://www.bryandonovan.com', 'Phillip Baker']
18
+
19
+ s.homepage = 'https://github.com/phillbaker/rubystats'
20
+
21
+ s.add_development_dependency("minitest", ">= 4.2", "< 5.0")
22
+ s.add_development_dependency("hoe", ">= 1.7.0")
23
+
24
+ # matrix was removed from default gems in Ruby 3.1, see
25
+ # https://github.com/ruby/ruby/pull/4530 and https://stdgems.org/
26
+ s.add_runtime_dependency("matrix")
27
+ end
28
+
data/test/tc_beta.rb CHANGED
@@ -1,51 +1,51 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
- require 'test/unit'
2
+ require 'minitest/autorun'
3
3
  require 'rubystats/beta_distribution'
4
4
 
5
- class TestBeta < Test::Unit::TestCase
6
- def test_simple
7
- p = 12
8
- q = 59
9
- beta = Rubystats::BetaDistribution.new(p,q)
10
- assert_equal("0.169014084507042", beta.mean.to_s)
11
- assert_equal("0.0441664031038187", beta.standard_deviation.to_s)
12
- assert_equal("6.26075815849967", beta.pdf(0.2).to_s)
13
- assert_equal("0.999999997766913", beta.cdf(0.50).to_s)
14
- assert_equal("0.102003194113565", beta.icdf(0.05).to_s)
5
+ class TestBeta < MiniTest::Unit::TestCase
6
+ def test_simple
7
+ p = 12
8
+ q = 59
9
+ beta = Rubystats::BetaDistribution.new(p,q)
10
+ assert_equal("0.16901408450704225", beta.mean.to_s)
11
+ assert_equal("0.04416640310381873", beta.standard_deviation.to_s)
12
+ assert_equal("6.260758158499666", beta.pdf(0.2).to_s)
13
+ assert_equal("0.9999999977669126", beta.cdf(0.50).to_s)
14
+ assert_equal("0.10200319411356515", beta.icdf(0.05).to_s)
15
+
16
+ x_vals = [0.1, 0.15, 0.2, 0.25, 0.3, 0.35]
17
+ p_vals = beta.pdf(x_vals)
18
+ c_vals = beta.cdf(x_vals)
19
+ expected_pvals = [ 2.83232625227534,
20
+ 8.89978000366836,
21
+ 6.26075815849967,
22
+ 1.72572305993386,
23
+ 0.234475706454223,
24
+ 0.0173700433944934]
25
+ expected_cvals = [0.0440640755091473,
26
+ 0.356009606171447,
27
+ 0.768319101921981,
28
+ 0.956058132801147,
29
+ 0.995358286711105,
30
+ 0.99971672771575]
15
31
 
16
- x_vals = [0.1, 0.15, 0.2, 0.25, 0.3, 0.35]
17
- p_vals = beta.pdf(x_vals)
18
- c_vals = beta.cdf(x_vals)
19
- expected_pvals = [ 2.83232625227534,
20
- 8.89978000366836,
21
- 6.26075815849967,
22
- 1.72572305993386,
23
- 0.234475706454223,
24
- 0.0173700433944934]
25
- expected_cvals = [0.0440640755091473,
26
- 0.356009606171447,
27
- 0.768319101921981,
28
- 0.956058132801147,
29
- 0.995358286711105,
30
- 0.99971672771575]
31
-
32
32
  0.upto(x_vals.size - 1) do |i|
33
33
  assert_in_delta expected_pvals[i], p_vals[i], 0.00000001
34
34
  assert_in_delta expected_cvals[i], c_vals[i], 0.00000001
35
35
  i += 1
36
36
  end
37
37
 
38
- x_vals.each do |x|
39
- cdf = beta.cdf(x)
40
- inv_cdf = beta.icdf(cdf)
41
- assert_in_delta(x, inv_cdf, 0.00000001)
42
- end
43
- end
38
+ x_vals.each do |x|
39
+ cdf = beta.cdf(x)
40
+ inv_cdf = beta.icdf(cdf)
41
+ assert_in_delta(x, inv_cdf, 0.00000001)
42
+ end
43
+ end
44
44
 
45
45
  def test_low_p_and_q_values
46
- p = 1.5
47
- q = 1.0
48
- beta = Rubystats::BetaDistribution.new(p,q)
46
+ p = 1.5
47
+ q = 1.0
48
+ beta = Rubystats::BetaDistribution.new(p,q)
49
49
 
50
50
  #from PHPExcel/PHPMath output
51
51
  expected_icdf_vals = [
@@ -60,41 +60,62 @@ class TestBeta < Test::Unit::TestCase
60
60
  end
61
61
  end
62
62
 
63
- def test_control_limits
64
- trials = 50
65
- alpha = 0.05
66
- p = 10
67
- lcl = get_lower_limit(trials, alpha, p)
68
- ucl = get_upper_limit(trials, alpha, p)
69
- assert_equal("0.112721613414076",lcl.to_s)
70
- assert_equal("0.315596061420013",ucl.to_s)
63
+ def test_control_limits
64
+ trials = 50
65
+ alpha = 0.05
66
+ p = 10
67
+ lcl = get_lower_limit(trials, alpha, p)
68
+ ucl = get_upper_limit(trials, alpha, p)
69
+ assert_equal("0.1127216134140763",lcl.to_s)
70
+ assert_equal("0.3155960614200132",ucl.to_s)
71
+
72
+ trials = 210
73
+ alpha = 0.10
74
+ p = 47
75
+ lcl = get_lower_limit(trials, alpha, p)
76
+ ucl = get_upper_limit(trials, alpha, p)
77
+ assert_equal("0.18667948526990116",lcl.to_s)
78
+ assert_equal("0.2649576017835441",ucl.to_s)
79
+ end
71
80
 
72
- trials = 210
73
- alpha = 0.10
74
- p = 47
75
- lcl = get_lower_limit(trials, alpha, p)
76
- ucl = get_upper_limit(trials, alpha, p)
77
- assert_equal("0.186679485269901",lcl.to_s)
78
- assert_equal("0.264957601783544",ucl.to_s)
79
- end
81
+ def get_lower_limit(trials,alpha,p)
82
+ if p==0
83
+ lcl=0
84
+ else
85
+ q=trials-p+1
86
+ bin= Rubystats::BetaDistribution.new(p,q)
87
+ lcl=bin.icdf(alpha)
88
+ end
89
+ return lcl
90
+ end
80
91
 
81
- def get_lower_limit(trials,alpha,p)
82
- if p==0
83
- lcl=0
84
- else
85
- q=trials-p+1
86
- bin= Rubystats::BetaDistribution.new(p,q)
87
- lcl=bin.icdf(alpha)
88
- end
89
- return lcl
90
- end
92
+ def get_upper_limit(trials,alpha,p)
93
+ q=trials-p
94
+ p=p+1
95
+ bin= Rubystats::BetaDistribution.new(p,q)
96
+ ucl=bin.icdf(1-alpha)
97
+ return ucl
98
+ end
99
+
100
+ def test_rng_distribution
101
+ p = 4.0
102
+ q = 12.0
103
+ beta = Rubystats::BetaDistribution.new(p,q)
104
+
105
+ total = 10000
106
+ values = Array.new(total).map{ beta.rng }
91
107
 
92
- def get_upper_limit(trials,alpha,p)
93
- q=trials-p
94
- p=p+1
95
- bin= Rubystats::BetaDistribution.new(p,q)
96
- ucl=bin.icdf(1-alpha)
97
- return ucl
98
- end
108
+ mean = values.inject(0.0) {|sum,v| sum + v} / values.size
109
+ assert_in_epsilon 0.25, mean.round(2), 0.01
110
+ end
99
111
 
112
+ def test_integer_input
113
+ pi, qi = 2, 4
114
+ pf, qf = 2.0, 4.0
115
+ x = 0.25
116
+ dbetai = Rubystats::BetaDistribution.new(pi,qi).pdf(x)
117
+ dbetaf = Rubystats::BetaDistribution.new(pf,qf).pdf(x)
118
+ assert_in_delta dbetai, dbetaf, 0.00000001
119
+ end
120
+
100
121
  end
data/test/tc_binomial.rb CHANGED
@@ -1,22 +1,36 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
- require 'test/unit'
2
+ require 'minitest/autorun'
3
3
  require 'rubystats/binomial_distribution'
4
4
 
5
- class TestBinomial < Test::Unit::TestCase
6
- def test_simple
7
- t = 100
8
- f = 7
9
- p = 0.05
5
+ class TestBinomial < MiniTest::Unit::TestCase
6
+ def test_simple
7
+ t = 100
8
+ f = 7
9
+ p = 0.05
10
10
 
11
- bin = Rubystats::BinomialDistribution.new(t,p)
12
- cdf = bin.cdf(f)
13
- pdf = bin.pdf(f)
14
- mean = bin.mean
15
- inv_cdf = bin.icdf(cdf)
11
+ bin = Rubystats::BinomialDistribution.new(t,p)
12
+ cdf = bin.cdf(f)
13
+ pmf = bin.pmf(f)
14
+ pdf = bin.pdf(f)
15
+ mean = bin.mean
16
+ inv_cdf = bin.icdf(cdf)
16
17
 
17
- assert_in_delta(0.10602553736479, pdf, 0.00000000000001 )
18
- assert_in_delta(0.87203952137960, cdf, 0.00000000000001)
19
- assert_equal("5.0",mean.to_s)
20
- assert_equal(f,inv_cdf)
21
- end
18
+ assert_equal pmf, pdf
19
+ assert_in_delta(0.10602553736479, pdf, 0.00000000000001 )
20
+ assert_in_delta(0.87203952137960, cdf, 0.00000000000001)
21
+ assert_equal("5.0",mean.to_s)
22
+ assert_equal(f,inv_cdf)
23
+ end
24
+
25
+ def test_rng
26
+ t, p = 100, 0.75
27
+ bin = Rubystats::BinomialDistribution.new(t,p)
28
+
29
+ rngs = []
30
+ n = 1000
31
+ n.times { rngs << bin.rng.to_f }
32
+ avg = rngs.reduce(:+) / rngs.size
33
+
34
+ assert_in_delta(avg, bin.mean, 0.5)
35
+ end
22
36
  end
data/test/tc_cauchy.rb ADDED
@@ -0,0 +1,39 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+ require 'minitest/autorun'
3
+ require 'rubystats/cauchy_distribution'
4
+
5
+ class TestCauchy < MiniTest::Unit::TestCase
6
+ def test_simple
7
+ location = 0.0
8
+ scale = 0.5
9
+ cd = Rubystats::CauchyDistribution.new(location,scale)
10
+ assert_in_delta(0.6366198, cd.pdf(0.0), 0.000001)
11
+ assert_in_delta(0.5, cd.cdf(0.0), 0.00000001)
12
+ assert_in_delta(3.169765, cd.icdf(0.9502), 0.000001)
13
+
14
+ # make sure the mean of RNG values is close to the expected mean
15
+ rngs = []
16
+ n = 10000
17
+ n.times {|i| rngs << cd.rng }
18
+ quantile = rngs.sort[(0.75*rngs.size).ceil]
19
+ assert_in_delta(quantile, 0.5, 0.1)
20
+
21
+ x_vals = [-2.0, -1.0, -0.5, 0.0, 0.5, 1.0, 2.0]
22
+
23
+ x_vals.each do |x|
24
+ cdf = cd.cdf(x)
25
+ inv_cdf = cd.icdf(cdf)
26
+ assert_in_delta(x, inv_cdf, 0.00000001)
27
+ end
28
+ end
29
+
30
+ def test_integer_input
31
+ locationi, scalei = 3, 1
32
+ locationf, scalef = 3.0, 1.0
33
+ xi = 4
34
+ xf = 4.0
35
+ dcdi = Rubystats::CauchyDistribution.new(locationi,scalei).pdf(xi)
36
+ dcdf = Rubystats::CauchyDistribution.new(locationf,scalef).pdf(xf)
37
+ assert_in_delta dcdi, dcdf, 0.00000001
38
+ end
39
+ end
@@ -1,8 +1,8 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
- require 'test/unit'
2
+ require 'minitest/autorun'
3
3
  require 'rubystats/exponential_distribution'
4
4
 
5
- class TestExponential < Test::Unit::TestCase
5
+ class TestExponential < MiniTest::Unit::TestCase
6
6
  def test_simple
7
7
  lmbda = 1
8
8
  expd = Rubystats::ExponentialDistribution.new(lmbda)
@@ -16,7 +16,7 @@ class TestExponential < Test::Unit::TestCase
16
16
  rngs = []
17
17
  rngsum = 0
18
18
  n = 5000
19
- n.times do
19
+ n.times do
20
20
  rng = expd.rng
21
21
  rngs << rng
22
22
  rngsum += rng
@@ -57,4 +57,14 @@ class TestExponential < Test::Unit::TestCase
57
57
  assert_in_delta(x, inv_cdf, 0.00000001)
58
58
  end
59
59
  end
60
+
61
+ def test_integer_input
62
+ lambdai = 2
63
+ lambdaf = 2.0
64
+ xi = 3
65
+ xf = 3.0
66
+ dexpi = Rubystats::ExponentialDistribution.new(lambdai).pdf(xi)
67
+ dexpf = Rubystats::ExponentialDistribution.new(lambdaf).pdf(xf)
68
+ assert_in_delta dexpi, dexpf, 0.00000001
69
+ end
60
70
  end
data/test/tc_fisher.rb CHANGED
@@ -1,20 +1,20 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
- require 'test/unit'
2
+ require 'minitest/autorun'
3
3
  require 'rubystats/fishers_exact_test'
4
4
 
5
- class TestFisher < Test::Unit::TestCase
6
- def test_simple
7
- tested1 = 20
8
- tested2 = 30
9
- f1 = 10
10
- f2 = 10
11
- t1 = tested1 - f1
12
- t2 = tested2 - f2
13
- fet = Rubystats::FishersExactTest.new
14
- fisher = fet.calculate(t1,t2,f1,f2)
5
+ class TestFisher < MiniTest::Unit::TestCase
6
+ def test_simple
7
+ tested1 = 20
8
+ tested2 = 30
9
+ f1 = 10
10
+ f2 = 10
11
+ t1 = tested1 - f1
12
+ t2 = tested2 - f2
13
+ fet = Rubystats::FishersExactTest.new
14
+ fisher = fet.calculate(t1,t2,f1,f2)
15
15
 
16
- assert_equal("0.188301375769922",fisher[:left].to_s)
17
- assert_equal("0.929481131661052",fisher[:right].to_s)
18
- assert_equal("0.257549242810992",fisher[:twotail].to_s)
19
- end
16
+ assert_equal("0.18830137576992229",fisher[:left].to_s)
17
+ assert_equal("0.9294811316610517",fisher[:right].to_s)
18
+ assert_equal("0.2575492428109919",fisher[:twotail].to_s)
19
+ end
20
20
  end
data/test/tc_gamma.rb ADDED
@@ -0,0 +1,39 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+ require 'minitest/autorun'
3
+ require 'rubystats/gamma_distribution'
4
+
5
+ class TestGamma < MiniTest::Unit::TestCase
6
+ def test_simple
7
+ shape = 3.0
8
+ scale = 2.0
9
+ gamma = Rubystats::GammaDistribution.new(shape,scale)
10
+
11
+ #check properties
12
+ assert_in_delta(6.0, gamma.mean, 0.000001)
13
+ assert_in_delta(12.0, gamma.variance, 0.000001)
14
+
15
+ #check distributions
16
+ assert_in_delta(0.0, gamma.pdf(0.0), 0.000001)
17
+ assert_in_delta(0.1353353, gamma.pdf(4.0), 0.000001)
18
+ assert_in_delta(0.001134998, gamma.pdf(20.0), 0.000001)
19
+ assert_in_delta(0.5768099, gamma.cdf(6.0), 0.01)
20
+ assert_in_delta(0.986246, gamma.cdf(16.0), 0.01)
21
+
22
+ # make sure the mean of RNG values is close to the expected mean
23
+ rngs = []
24
+ n = 10000
25
+ n.times {|i| rngs << gamma.rng }
26
+ quantile = rngs.sort[(0.75*rngs.size).ceil]
27
+ assert_in_delta(quantile, 7.84080, 0.2)
28
+ end
29
+
30
+ def test_integer_input
31
+ shapei, scalei = 3, 1
32
+ shapef, scalef = 3.0, 1.0
33
+ xi = 4
34
+ xf = 4.0
35
+ pdfi = Rubystats::GammaDistribution.new(shapei,scalei).pdf(xi)
36
+ pdff = Rubystats::GammaDistribution.new(shapef,scalef).pdf(xf)
37
+ assert_in_delta pdfi, pdff, 0.00000001
38
+ end
39
+ end
data/test/tc_lnorm.rb ADDED
@@ -0,0 +1,45 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'minitest/autorun'
3
+ require 'rubystats/lognormal_distribution'
4
+
5
+ class TestLognormal < MiniTest::Unit::TestCase
6
+ def test_cdf_pdf
7
+ lnorm = Rubystats::LognormalDistribution.new(2.0,0.2)
8
+
9
+ cdf = lnorm.cdf(8.0)
10
+ assert_in_epsilon cdf, 0.654392, 0.0001, "cdf"
11
+
12
+ pdf = lnorm.pdf(8.0)
13
+ assert_in_epsilon pdf, 0.2304252, 0.000001, "pdf"
14
+
15
+ end
16
+
17
+ def test_properties
18
+ lnorm = Rubystats::LognormalDistribution.new(2.0,0.2)
19
+ assert_in_epsilon lnorm.mean, 7.538325, 0.000001, "mean"
20
+ assert_in_epsilon lnorm.variance, 2.319127, 0.000001, "variance"
21
+ end
22
+
23
+ def test_rng
24
+ lnorm = Rubystats::LognormalDistribution.new(2.0,0.2)
25
+
26
+ total = 100000
27
+ values = Array.new(total).map{lnorm.rng}
28
+
29
+ mean = values.inject(0.0) {|sum, v| sum + v} / values.size
30
+
31
+ assert_in_delta mean, 7.538325, 0.1, "rng mean"
32
+ assert_equal values.min >= 0.0, true, "rng min value"
33
+ end
34
+
35
+ def test_integer_input
36
+ meani, sdi = 2, 1
37
+ meanf, sdf = 2.0, 1.0
38
+ xi = 9
39
+ xf = 9.0
40
+ dlnormi = Rubystats::LognormalDistribution.new(meani,sdi).pdf(xi)
41
+ dlnormf = Rubystats::LognormalDistribution.new(meanf,sdf).pdf(xf)
42
+ assert_in_delta dlnormi, dlnormf, 0.000001
43
+ end
44
+
45
+ end
@@ -0,0 +1,53 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+ require 'minitest/autorun'
3
+ require 'rubystats/multivariate_normal_distribution'
4
+
5
+ class TestMultivariateNormal < MiniTest::Unit::TestCase
6
+ def test_simple
7
+ mu = [1.3,-2.5]
8
+ sigma = [[1.0,0.3],[0.3,1.0]]
9
+
10
+ mvnorm = Rubystats::MultivariateNormalDistribution.new(mu,sigma)
11
+
12
+ assert_in_delta(0.0001340771, mvnorm.pdf([1.0,1.0]), 0.000001)
13
+ assert_in_delta(0.131732, mvnorm.pdf([1.0,-2.0]), 0.000001)
14
+
15
+
16
+ # make sure the mean of RNG values is close to the expected mean
17
+ rngs = []
18
+ n = 5000
19
+ n.times {|i| rngs << mvnorm.rng }
20
+
21
+ a,b = rngs.transpose
22
+
23
+ #check means
24
+ mean_a = a.inject(0.0) {|sum,x| sum + x} / a.size
25
+ assert_in_delta(1.3, mean_a, 0.1)
26
+
27
+ mean_b = b.inject(0.0) {|sum,x| sum + x} / b.size
28
+ assert_in_delta(1.3, mean_a, 0.1)
29
+
30
+ #check variances
31
+ var_a = a.inject(0.0) {|sum,x| sum + (x - mean_a)**2 } / a.size
32
+ assert_in_delta(1.0, var_a, 0.1)
33
+
34
+ var_b = b.inject(0.0) {|sum,x| sum + (x - mean_b)**2 } / b.size
35
+ assert_in_delta(1.0, var_b, 0.1)
36
+
37
+ #check correlation
38
+ covariance = a.zip(b).map{|xa,xb| (xa-mean_a)*(xb-mean_b)}.inject(0.0){|sum,x| sum + x} / a.size
39
+ correlation = covariance / Math.sqrt(var_a * var_b)
40
+ assert_in_delta(0.3, correlation, 0.1)
41
+
42
+ end
43
+
44
+ def test_integer_input
45
+ mui, sigmai = [1,2], [[1,0.3],[0.3,1]]
46
+ muf, sigmaf = [1.0,2.0], [[1.0,0.3],[0.3,1.0]]
47
+ xi = [1,1]
48
+ xf = [1.0,1.0]
49
+ dmvnormi = Rubystats::MultivariateNormalDistribution.new(mui,sigmai).pdf(xi)
50
+ dmvnormf = Rubystats::MultivariateNormalDistribution.new(muf,sigmaf).pdf(xf)
51
+ assert_in_delta dmvnormi, dmvnormf, 0.00000001
52
+ end
53
+ end
data/test/tc_norm.rb CHANGED
@@ -1,14 +1,43 @@
1
- $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
- require 'test/unit'
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'minitest/autorun'
3
3
  require 'rubystats/normal_distribution'
4
4
 
5
- class TestNormal < Test::Unit::TestCase
6
- def test_simple
5
+ class TestNormal < MiniTest::Unit::TestCase
6
+ def test_cdf
7
7
 
8
8
  norm = Rubystats::NormalDistribution.new(10,2)
9
9
  cdf = norm.cdf(11)
10
10
 
11
- assert_equal("0.691462461274013",cdf.to_s)
12
- assert_not_nil(norm.rng)
11
+ assert_equal('0.691462461274013', '%.15f' % cdf)
12
+ refute_nil(norm.rng)
13
13
  end
14
+
15
+ def test_distribution
16
+ norm = Rubystats::NormalDistribution.new(10.0, 1.0)
17
+ assert_instance_of Float, norm.rng
18
+
19
+ total = 10000
20
+ values =Array.new(total).map{norm.rng.to_i}
21
+ histogram = Hash[*values.group_by{ |v| v }.flat_map{ |k, v| [k, v.size] }]
22
+
23
+ one_sigma = histogram[9] + histogram[10]
24
+ assert_in_epsilon 0.682689492137 , one_sigma.to_f / total, 0.02, 'the 1-sigma-environment should contain 68.3%'
25
+
26
+ two_sigma = one_sigma + histogram[8] + histogram[11]
27
+ assert_in_epsilon 0.954499736104 , two_sigma.to_f / total, 0.01, 'the 2-sigma-environment should contain 95.4%'
28
+
29
+ three_sigma = two_sigma + histogram[7] + histogram[12]
30
+ assert_in_epsilon 0.997300203937 , three_sigma.to_f / total, 0.005, 'the 3-sigma-environment should contain 99.7%'
31
+ end
32
+
33
+ def test_integer_input
34
+ meani, sdi = 10, 2
35
+ meanf, sdf = 10.0, 2.0
36
+ xi = 11
37
+ xf = 11.0
38
+ dnormi = Rubystats::NormalDistribution.new(meani,sdi).pdf(xi)
39
+ dnormf = Rubystats::NormalDistribution.new(meanf,sdf).pdf(xf)
40
+ assert_in_delta dnormi, dnormf, 0.00000001
41
+ end
42
+
14
43
  end