rubystats 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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