rubystats 0.1.2 → 0.2.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.
@@ -0,0 +1,114 @@
1
+ require 'rubystats/probability_distribution'
2
+ # This class provides an object for encapsulating normal distributions
3
+ # Ported to Ruby from PHPMath class by Bryan Donovan
4
+ # Author:: Jaco van Kooten
5
+ # Author:: Paul Meagher
6
+ # Author:: Bryan Donovan (http://www.bryandonovan.com)
7
+ module Rubystats
8
+ class NormalDistribution < Rubystats::ProbabilityDistribution
9
+ include Rubystats::SpecialMath
10
+
11
+ # Constructs a normal distribution (defaults to zero mean and
12
+ # unity variance).
13
+ def initialize(mu=0.0, sigma=1.0)
14
+ @mean = mu
15
+ if sigma <= 0.0
16
+ return "error"
17
+ end
18
+ @stdev = sigma
19
+ @variance = sigma**2
20
+ @pdf_denominator = Sqrt2pi * Math.sqrt(@variance)
21
+ @cdf_denominator = Sqrt2 * Math.sqrt(@variance)
22
+ end
23
+
24
+ # Returns the mean of the distribution
25
+ def get_mean
26
+ return @mean
27
+ end
28
+
29
+ # Returns the standard deviation of the distribution
30
+ def get_standard_deviation
31
+ return @stdev
32
+ end
33
+
34
+ # Returns the variance of the distribution
35
+ def get_variance
36
+ return @variance
37
+ end
38
+
39
+ private
40
+
41
+ # Obtain single PDF value
42
+ # Returns the probability that a stochastic variable x has the value X,
43
+ # i.e. P(x=X)
44
+ def get_pdf(x)
45
+ Math.exp( -((x-@mean)**2) / (2 * @variance)) / @pdf_denominator
46
+ end
47
+
48
+ # Obtain single CDF value
49
+ # Returns the probability that a stochastic variable x is less than X,
50
+ # i.e. P(x<X)
51
+ def get_cdf(x)
52
+ complementary_error( -(x - @mean) / @cdf_denominator) / 2
53
+ end
54
+
55
+ # Obtain single inverse CDF value.
56
+ # returns the value X for which P(x&lt;X).
57
+ def get_icdf(p)
58
+ check_range(p)
59
+ if p == 0.0
60
+ return -Max_value
61
+ end
62
+ if p == 1.0
63
+ return Max_value
64
+ end
65
+ if p == 0.5
66
+ return @mean
67
+ end
68
+
69
+ mean_save = @mean
70
+ var_save = @variance
71
+ pdf_D_save = @pdf_denominator
72
+ cdf_D_save = @cdf_denominator
73
+ @mean = 0.0
74
+ @variance = 1.0
75
+ @pdf_denominator = Math.sqrt(Two_pi)
76
+ @cdf_denominator = Sqrt2
77
+ x = find_root(p, 0.0, -100.0, 100.0)
78
+ #scale back
79
+ @mean = mean_save
80
+ @variance = var_save
81
+ @pdf_denominator = pdf_D_save
82
+ @cdf_denominator = cdf_D_save
83
+ return x * Math.sqrt(@variance) + @mean
84
+ end
85
+
86
+ # Uses the polar form of the Box-Muller transformation which
87
+ # is both faster and more robust numerically than basic Box-Muller
88
+ # transform. To speed up repeated RNG computations, two random values
89
+ # are computed after the while loop and the second one is saved and
90
+ # directly used if the method is called again.
91
+ # see http://www.taygeta.com/random/gaussian.html
92
+ # returns single normal deviate
93
+ def get_rng
94
+ if @use_last
95
+ y1 = @last
96
+ @use_last = false
97
+ else
98
+ w = 1
99
+ until w < 1.0 do
100
+ r1 = Kernel.rand
101
+ r2 = Kernel.rand
102
+ x1 = 2.0 * r1 - 1.0
103
+ x2 = 2.0 * r2 - 1.0
104
+ w = x1 * x1 * x2 * x2
105
+ end
106
+ w = Math.sqrt((-2.0 * Math.log(w)) / w)
107
+ y1 = x1 * w
108
+ @last = x2 * w
109
+ @use_last = true
110
+ end
111
+ return @mean + y1 * Math.sqrt(@variance)
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,131 @@
1
+ require 'rubystats/modules'
2
+
3
+ module Rubystats
4
+ class ProbabilityDistribution
5
+ include Rubystats::NumericalConstants
6
+ include Rubystats::SpecialMath
7
+ include Rubystats::ExtraMath
8
+
9
+ def initialize
10
+ end
11
+
12
+ def mean
13
+ get_mean
14
+ end
15
+
16
+ def get_mean
17
+ end
18
+
19
+
20
+ def pdf(x)
21
+ if x.class == Array
22
+ pdf_vals = []
23
+ for i in (0..x.length)
24
+ pdf_vals[i] = get_pdf(x[i])
25
+ end
26
+ return pdf_vals
27
+ else
28
+ return get_pdf(x)
29
+ end
30
+ end
31
+
32
+ def get_pdf(x)
33
+ end
34
+
35
+ def cdf(x)
36
+ if x.class == Array
37
+ cdf_vals = []
38
+ for i in (0...x.size)
39
+ cdf_vals[i] = get_cdf(x[i])
40
+ end
41
+ return cdf_vals
42
+ else
43
+ return get_cdf(x)
44
+ end
45
+ end
46
+
47
+ def get_cdf(x)
48
+ end
49
+
50
+ def icdf(p)
51
+ if p.class == Array
52
+ inv_vals = []
53
+ for i in (0..p.length)
54
+ inv_vals[i] = get_icdf(p[i])
55
+ end
56
+ return inv_vals
57
+ else
58
+ return get_icdf(p)
59
+ end
60
+ end
61
+
62
+ def get_icdf(p)
63
+ end
64
+
65
+ def rng(n=1)
66
+ if n < 1
67
+ return "Number of random numbers to return must be 1 or greater"
68
+ end
69
+ if (n > 1)
70
+ rnd_vals = []
71
+ for i in (0..n)
72
+ rnd_vals[i] = get_rng()
73
+ end
74
+ return rnd_vals
75
+ else
76
+ return get_rng()
77
+ end
78
+ end
79
+
80
+ def get_rng()
81
+ end
82
+
83
+ def check_range(x, lo=0.0, hi=1.0)
84
+ if (x < lo) || (x > hi)
85
+ return "error"
86
+ end
87
+ end
88
+
89
+ def get_factorial(n)
90
+ if n <= 1
91
+ return 1
92
+ else
93
+ return n * get_factorial(n-1)
94
+ end
95
+ end
96
+
97
+ def find_root (prob, guess, x_lo, x_hi)
98
+ accuracy = 1.0e-10
99
+ max_iteration = 150
100
+ x = guess
101
+ x_new = guess
102
+ error = 0.0
103
+ pdf = 0.0
104
+ dx = 1000.0
105
+ i = 0
106
+ while ( dx.abs > accuracy && (i += 1) < max_iteration )
107
+ #Apply Newton-Raphson step
108
+ error = cdf(x) - prob
109
+ if error < 0.0
110
+ x_lo = x
111
+ else
112
+ x_hi = x
113
+ end
114
+ pdf = pdf(x)
115
+ if pdf != 0.0
116
+ dx = error / pdf
117
+ x_new = x -dx
118
+ end
119
+ # If the NR fails to converge (which for example may be the
120
+ # case if the initial guess is too rough) we apply a bisection
121
+ # step to determine a more narrow interval around the root.
122
+ if x_new < x_lo || x_new > x_hi || pdf == 0.0
123
+ x_new = (x_lo + x_hi) / 2.0
124
+ dx = x_new - x
125
+ end
126
+ x = x_new
127
+ end
128
+ return x
129
+ end
130
+ end
131
+ end
@@ -1,12 +1,12 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
2
  require 'test/unit'
3
- require 'beta_distribution'
3
+ require 'rubystats/beta_distribution'
4
4
 
5
5
  class TestBeta < Test::Unit::TestCase
6
6
  def test_simple
7
7
  p = 12
8
8
  q = 59
9
- beta = BetaDistribution.new(p,q)
9
+ beta = Rubystats::BetaDistribution.new(p,q)
10
10
  assert_equal("0.169014084507042", beta.mean.to_s)
11
11
  assert_equal("0.0441664031038187", beta.standard_deviation.to_s)
12
12
  assert_equal("6.26075815849967", beta.pdf(0.2).to_s)
@@ -61,7 +61,7 @@ class TestBeta < Test::Unit::TestCase
61
61
  lcl=0
62
62
  else
63
63
  q=trials-p+1
64
- bin= BetaDistribution.new(p,q)
64
+ bin= Rubystats::BetaDistribution.new(p,q)
65
65
  lcl=bin.icdf(alpha)
66
66
  end
67
67
  return lcl
@@ -70,7 +70,7 @@ class TestBeta < Test::Unit::TestCase
70
70
  def get_upper_limit(trials,alpha,p)
71
71
  q=trials-p
72
72
  p=p+1
73
- bin= BetaDistribution.new(p,q)
73
+ bin= Rubystats::BetaDistribution.new(p,q)
74
74
  ucl=bin.icdf(1-alpha)
75
75
  return ucl
76
76
  end
@@ -1,6 +1,6 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
2
  require 'test/unit'
3
- require 'binomial_distribution'
3
+ require 'rubystats/binomial_distribution'
4
4
 
5
5
  class TestBinomial < Test::Unit::TestCase
6
6
  def test_simple
@@ -8,14 +8,14 @@ class TestBinomial < Test::Unit::TestCase
8
8
  f = 7
9
9
  p = 0.05
10
10
 
11
- bin = BinomialDistribution.new(t,p)
11
+ bin = Rubystats::BinomialDistribution.new(t,p)
12
12
  cdf = bin.cdf(f)
13
13
  pdf = bin.pdf(f)
14
14
  mean = bin.mean
15
15
  inv_cdf = bin.icdf(cdf)
16
16
 
17
- assert_equal("0.10602553736479",pdf.to_s)
18
- assert_equal("0.87203952137960", cdf.to_s[0,16])
17
+ assert_in_delta(0.10602553736479, pdf, 0.00000000000001 )
18
+ assert_in_delta(0.87203952137960, cdf, 0.00000000000001)
19
19
  assert_equal("5.0",mean.to_s)
20
20
  assert_equal(f,inv_cdf)
21
21
  end
@@ -1,6 +1,6 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
2
  require 'test/unit'
3
- require 'fishers_exact_test'
3
+ require 'rubystats/fishers_exact_test'
4
4
 
5
5
  class TestFisher < Test::Unit::TestCase
6
6
  def test_simple
@@ -10,7 +10,7 @@ class TestFisher < Test::Unit::TestCase
10
10
  f2 = 10
11
11
  t1 = tested1 - f1
12
12
  t2 = tested2 - f2
13
- fet = FishersExactTest.new
13
+ fet = Rubystats::FishersExactTest.new
14
14
  fisher = fet.calculate(t1,t2,f1,f2)
15
15
 
16
16
  assert_equal("0.188301375769922",fisher[:left].to_s)
@@ -0,0 +1,14 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+ require 'test/unit'
3
+ require 'rubystats/normal_distribution'
4
+
5
+ class TestNormal < Test::Unit::TestCase
6
+ def test_simple
7
+
8
+ norm = Rubystats::NormalDistribution.new(10,2)
9
+ cdf = norm.cdf(11)
10
+
11
+ assert_equal("0.691462461274013",cdf.to_s)
12
+ assert_not_nil(norm.rng)
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+
3
+ #
4
+ # test that we can use old api that wasn't namespaced
5
+ #
6
+
7
+ require 'test/unit'
8
+ require 'rubystats'
9
+
10
+ class TestNormal < Test::Unit::TestCase
11
+ def test_simple
12
+ norm = NormalDistribution.new(10,2)
13
+ cdf = norm.cdf(11)
14
+
15
+ assert_equal("0.691462461274013",cdf.to_s)
16
+ assert_not_nil(norm.rng)
17
+ end
18
+ end
File without changes
metadata CHANGED
@@ -1,64 +1,85 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.0
3
- specification_version: 1
4
2
  name: rubystats
5
3
  version: !ruby/object:Gem::Version
6
- version: 0.1.2
7
- date: 2007-05-18 00:00:00 -07:00
8
- summary: Classes for statistical calculations, e.g., binomial, beta, and normal distributions with PDF, CDF and inverse CDF (all ported from PHPMath) as well as Fisher's Exact Test
9
- require_paths:
10
- - lib
11
- email: Bryandonovan@myrealbox.com
12
- homepage: http://www.bryandonovan.com
13
- rubyforge_project:
14
- description:
15
- autorequire:
16
- default_executable:
17
- bindir: bin
18
- has_rdoc: true
19
- required_ruby_version: !ruby/object:Gem::Version::Requirement
20
- requirements:
21
- - - ">"
22
- - !ruby/object:Gem::Version
23
- version: 0.0.0
24
- version:
4
+ version: 0.2.0
25
5
  platform: ruby
26
- signing_key:
27
- cert_chain:
28
- post_install_message:
29
6
  authors:
30
- - Bryan Donovan
31
- files:
32
- - lib/beta_distribution.rb
33
- - lib/binomial_distribution.rb
34
- - lib/fishers_exact_test.rb
35
- - lib/modules
36
- - lib/normal_distribution.rb
37
- - lib/probability_distribution.rb
38
- - lib/modules/extra_math.rb
39
- - lib/modules/numerical_constants.rb
40
- - lib/modules/special_math.rb
41
- - tests/tc_beta.rb
42
- - tests/tc_binomial.rb
43
- - tests/tc_fisher.rb
44
- - tests/tc_norm.rb
45
- - tests/ts_stats.rb
46
- - examples/beta.rb
47
- - examples/binomial.rb
48
- - examples/fisher.rb
49
- - examples/norm.rb
50
- - README
51
- test_files:
52
- - tests/ts_stats.rb
53
- rdoc_options: []
7
+ - Bryan Donovan - http://www.bryandonovan.com
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
54
11
 
55
- extra_rdoc_files:
56
- - README
12
+ date: 2008-04-15 00:00:00 +00:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.5.1
23
+ version:
24
+ 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.
25
+ email: b.dondo+rubyforge@gmail.com
57
26
  executables: []
58
27
 
59
28
  extensions: []
60
29
 
30
+ extra_rdoc_files:
31
+ - History.txt
32
+ - Manifest.txt
33
+ - README.txt
34
+ files:
35
+ - History.txt
36
+ - Manifest.txt
37
+ - README.txt
38
+ - Rakefile
39
+ - examples/beta.rb
40
+ - examples/binomial.rb
41
+ - examples/failrate_vs_goal.rb
42
+ - examples/fisher.rb
43
+ - examples/norm.rb
44
+ - lib/rubystats.rb
45
+ - lib/rubystats/beta_distribution.rb
46
+ - lib/rubystats/binomial_distribution.rb
47
+ - lib/rubystats/fishers_exact_test.rb
48
+ - lib/rubystats/modules.rb
49
+ - lib/rubystats/normal_distribution.rb
50
+ - lib/rubystats/probability_distribution.rb
51
+ - test/tc_beta.rb
52
+ - test/tc_binomial.rb
53
+ - test/tc_fisher.rb
54
+ - test/tc_norm.rb
55
+ - test/tc_require_all.rb
56
+ - test/ts_stats.rb
57
+ has_rdoc: true
58
+ homepage: http://rubyforge.org/projects/rubystats/
59
+ post_install_message:
60
+ rdoc_options:
61
+ - --main
62
+ - README.txt
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "0"
70
+ version:
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "0"
76
+ version:
61
77
  requirements: []
62
78
 
63
- dependencies: []
79
+ rubyforge_project: rubystats
80
+ rubygems_version: 1.1.0
81
+ signing_key:
82
+ specification_version: 2
83
+ summary: Port of PHPMath to Ruby
84
+ test_files: []
64
85