distribution 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
Binary file
@@ -1,3 +1,11 @@
1
+ === 0.5.0 / 2011-05-03
2
+
3
+ * Exception raises on calculation of T's cdf with ruby engine. For now, stick to gsl implementation
4
+ * Added logistic distribution.
5
+ * Raises an error on binomial if k>n.
6
+ * New rng for exponential distribution, based on F^-1 [clbustos]
7
+ * Added power benchmark
8
+
1
9
  === 0.4.0 / 2011-02-01
2
10
 
3
11
  * Poisson and exponential distributions implemented. Implementation of inverse cdf for poisson is not perfect, yet.
@@ -10,6 +10,7 @@ benchmark/binomial_coefficient/experiment.rb
10
10
  benchmark/factorial_hash.rb
11
11
  benchmark/factorial_method.rb
12
12
  benchmark/odd.rb
13
+ benchmark/power.rb
13
14
  bin/distribution
14
15
  data/template/distribution.erb
15
16
  data/template/distribution/gsl.erb
@@ -42,6 +43,8 @@ lib/distribution/hypergeometric.rb
42
43
  lib/distribution/hypergeometric/gsl.rb
43
44
  lib/distribution/hypergeometric/java.rb
44
45
  lib/distribution/hypergeometric/ruby.rb
46
+ lib/distribution/logistic.rb
47
+ lib/distribution/logistic/ruby.rb
45
48
  lib/distribution/math_extension.rb
46
49
  lib/distribution/normal.rb
47
50
  lib/distribution/normal/gsl.rb
@@ -64,6 +67,7 @@ spec/distribution_spec.rb
64
67
  spec/exponential_spec.rb
65
68
  spec/f_spec.rb
66
69
  spec/hypergeometric_spec.rb
70
+ spec/logistic_spec.rb
67
71
  spec/math_extension_spec.rb
68
72
  spec/normal_spec.rb
69
73
  spec/poisson_spec.rb
data/README.txt CHANGED
@@ -15,6 +15,7 @@ Includes code from statistics2 on Normal, T, F and Chi Square ruby code [http://
15
15
  * Very fast ruby 1.8.7/1.9.+ implementation, with improved method to calculate factorials and others common functions
16
16
  * All methods tested on several ranges. See spec/
17
17
  * On Jruby and Rubinius, BivariateNormal returns incorrect pdf
18
+ * Ruby t distribution's cdf can't calculate fractional df. Install gsl, for now.
18
19
 
19
20
  == API structure
20
21
 
@@ -0,0 +1,27 @@
1
+ require 'bench_press'
2
+ require 'bigdecimal'
3
+ extend BenchPress
4
+
5
+ name 'Float vs Rational power'
6
+ author 'Claudio Bustos'
7
+ date '2011-02-02'
8
+ summary "
9
+ On ruby, the maximum size of a float is #{Float::MAX}.
10
+ With Rational, we can raise to integer numbers and surpass Float maximum.
11
+ What is the speed reduction using Rational?"
12
+
13
+ reps 1000 #number of repetitions
14
+ int=10
15
+ rat=10.quo(1)
16
+ bd=BigDecimal("10")
17
+ measure "Using float pow" do
18
+ int**307
19
+ end
20
+
21
+ measure "Using rational" do
22
+ rat**307
23
+ end
24
+
25
+ measure "Using big decimal pow" do
26
+ bd**307
27
+ end
@@ -19,7 +19,7 @@
19
19
  #
20
20
  # == Other Sources
21
21
  #
22
- # * Code of Ruby engines came from statistics2.rb,
22
+ # * Code of several Ruby engines came from statistics2.rb,
23
23
  # created by Shin-ichiro HARA(sinara@blade.nagaokaut.ac.jp).
24
24
  # Retrieve from http://blade.nagaokaut.ac.jp/~sinara/ruby/math/statistics2/
25
25
  #
@@ -49,7 +49,7 @@ require 'distribution/math_extension'
49
49
  # Distribution::Normal.p_value(0.95)
50
50
  # => 1.64485364660836
51
51
  module Distribution
52
- VERSION="0.4.0"
52
+ VERSION="0.5.0"
53
53
 
54
54
  module Shorthand
55
55
  EQUIVALENCES={:p_value=>:p, :cdf=>:cdf, :pdf=>:pdf, :rng=>:r, :exact_pdf=>:epdf, :exact_cdf=>:ecdf, :exact_p_value=>:ep}
@@ -147,7 +147,7 @@ module Distribution
147
147
  autoload(:Hypergeometric, 'distribution/hypergeometric')
148
148
  autoload(:Exponential, 'distribution/exponential')
149
149
  autoload(:Poisson, 'distribution/poisson')
150
-
150
+ autoload(:Logistic, 'distribution/logistic')
151
151
  end
152
152
 
153
153
 
@@ -3,7 +3,8 @@ module Distribution
3
3
  module Ruby_
4
4
  class << self
5
5
  def pdf(k,n,pr)
6
- Math.binomial_coefficient(n,k)*(pr**k)*(1-pr)**(n-k)
6
+ raise "k>n" if k>n
7
+ Math.binomial_coefficient(n,k)*(pr**k)*(1-pr)**(n-k)
7
8
  end
8
9
  def cdf(k,n,pr)
9
10
  #(0..x.floor).inject(0) {|ac,i| ac+pdf(i,n,pr)}
@@ -24,4 +25,4 @@ module Distribution
24
25
  end
25
26
  end
26
27
  end
27
- end
28
+ end
@@ -16,6 +16,10 @@ module Distribution
16
16
  SHORTHAND='expo'
17
17
  extend Distributable
18
18
  create_distribution_methods
19
+ ##
20
+ # :singleton-method: rng(l)
21
+ # Returns a lambda, which generates exponential variates
22
+ # with +l+ as rate parameter
19
23
 
20
24
  ##
21
25
  # :singleton-method: pdf(x,l)
@@ -2,7 +2,10 @@ module Distribution
2
2
  module Exponential
3
3
  module Ruby_
4
4
  class << self
5
- def pdf(x,l)
5
+ def rng(l)
6
+ lambda {p_value(rand(),l)}
7
+ end
8
+ def pdf(x,l)
6
9
  return 0 if x<0
7
10
  l*Math.exp(-l*x)
8
11
  end
@@ -16,4 +19,4 @@ module Distribution
16
19
  end
17
20
  end
18
21
  end
19
- end
22
+ end
@@ -0,0 +1,40 @@
1
+ require 'distribution/logistic/ruby'
2
+ #require 'distribution/logistic/gsl'
3
+ #require 'distribution/logistic/java'
4
+
5
+
6
+ module Distribution
7
+ # From Wikipedia:
8
+ # In probability theory and statistics, the logistic distribution is a continuous probability distribution. Its cumulative distribution function is the logistic function, which appears in logistic regression and feedforward neural networks. It resembles the normal distribution in shape but has heavier tails (higher kurtosis).
9
+ module Logistic
10
+ SHORTHAND='logis'
11
+ extend Distributable
12
+ create_distribution_methods
13
+ ##
14
+ # :singleton-method: rng(u,s)
15
+ # Returns a proc, which returns a different logistic
16
+ # variate each time is called
17
+ # * u: mean
18
+ # * s: variance related parameter
19
+ ##
20
+ # :singleton-method: pdf(x , u,s)
21
+ # Returns the pdf for logistic distribution (f(x,u,s))
22
+ # * u: mean
23
+ # * s: variance related parameter
24
+
25
+ ##
26
+ # :singleton-method: cdf(x , u,s)
27
+ # Returns the cdf for logistic distribution (F(x,u,s))
28
+ # * u: mean
29
+ # * s: variance related parameter
30
+
31
+ ##
32
+ # :singleton-method: p_value(pr , u,s)
33
+ # Returns the inverse cdf for logistic distribution
34
+ # (F^-1(pr,u,s))
35
+ # * u: mean
36
+ # * s: variance related parameter
37
+
38
+
39
+ end
40
+ end
@@ -0,0 +1,20 @@
1
+ module Distribution
2
+ module Logistic
3
+ module Ruby_
4
+ class << self
5
+ def rng(u,s)
6
+ lambda {p_value(rand(),u,s)}
7
+ end
8
+ def pdf(x,u,s )
9
+ (Math.exp(-(x-u)/s))/(s*(1+Math.exp(-(x-u)/s)**2))
10
+ end
11
+ def cdf(x,u,s )
12
+ 1/(1+Math.exp(-(x-u)/s))
13
+ end
14
+ def p_value(pr,u,s )
15
+ u+s*Math.log(pr/(1-pr))
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -203,6 +203,9 @@ module Distribution
203
203
  def beta(x,y)
204
204
  (gamma(x)*gamma(y)).quo(gamma(x+y))
205
205
  end
206
+ def logbeta(x,y)
207
+ (loggamma(x)+loggamma(y))-loggamma(x+y)
208
+ end
206
209
  # I_x(a,b): Regularized incomplete beta function
207
210
  # TODO: Find a faster version.
208
211
  # Source:
@@ -303,13 +306,13 @@ end
303
306
 
304
307
  module Math
305
308
  include Distribution::MathExtension
306
- module_function :factorial, :beta, :loggamma, :binomial_coefficient, :binomial_coefficient_gamma, :regularized_beta_function, :incomplete_beta, :permutations, :rising_factorial , :fast_factorial, :combinations
309
+ module_function :factorial, :beta, :loggamma, :binomial_coefficient, :binomial_coefficient_gamma, :regularized_beta_function, :incomplete_beta, :permutations, :rising_factorial , :fast_factorial, :combinations, :logbeta
307
310
  end
308
311
 
309
312
  # Necessary on Ruby 1.9
310
313
  module CMath # :nodoc:
311
314
  include Distribution::MathExtension
312
- module_function :factorial, :beta, :loggamma, :binomial_coefficient, :binomial_coefficient_gamma, :regularized_beta_function, :incomplete_beta, :permutations, :rising_factorial, :fast_factorial, :combinations
315
+ module_function :factorial, :beta, :loggamma, :binomial_coefficient, :binomial_coefficient_gamma, :regularized_beta_function, :incomplete_beta, :permutations, :rising_factorial, :fast_factorial, :combinations, :logbeta
313
316
  end
314
317
 
315
318
  if RUBY_VERSION<"1.9"
@@ -14,6 +14,10 @@ module Distribution
14
14
  # t-distribution ([1])
15
15
  # (-\infty, x]
16
16
  def p_t(df, t)
17
+ if df.to_i!=df
18
+ raise "Can't calculate not integer df"
19
+ end
20
+ df=df.to_i
17
21
  c2 = df.to_f / (df + t * t);
18
22
  s = Math.sqrt(1.0 - c2)
19
23
  s = -s if t < 0.0
@@ -24,6 +28,7 @@ module Distribution
24
28
  s *= (i - 1) * c2 / i
25
29
  i += 2
26
30
  end
31
+
27
32
  if df.is_a? Float or df & 1 != 0
28
33
  0.5+(p*Math.sqrt(c2)+Math.atan(t/Math.sqrt(df))) / Math::PI
29
34
  else
@@ -0,0 +1,68 @@
1
+ require File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb")
2
+
3
+ describe Distribution::Logistic do
4
+
5
+ shared_examples_for "logistic engine" do
6
+ it "should return correct pdf" do
7
+ if @engine.respond_to? :pdf
8
+ 1.upto(10) {
9
+ u=rand()
10
+ s=rand()+1
11
+ x=rand()*100-50
12
+ exp=Math.exp(-(x-u)/s)/(s*(1+Math.exp(-(x-u)/s)**2))
13
+ @engine.pdf(x,u,s).should eq(exp)
14
+ }
15
+ else
16
+ pending("No #{@engine}.pdf")
17
+ end
18
+ end
19
+
20
+ it "should return correct cdf" do
21
+ if @engine.respond_to? :cdf
22
+
23
+
24
+ 1.upto(100) {
25
+ u=rand()
26
+ s=rand()+1
27
+ x=rand()*100-50
28
+ exp=1/(1+Math.exp(-(x-u)/s))
29
+ @engine.cdf(x,u,s).should eq(exp)
30
+ }
31
+
32
+ else
33
+ pending("No #{@engine}.cdf")
34
+ end
35
+ end
36
+
37
+
38
+ it "should return correct p_value" do
39
+ if @engine.respond_to? :p_value
40
+ 1.upto(9) {|i|
41
+ u=rand()
42
+ s=rand()+1
43
+ x=@engine.p_value(i/10,u,s)
44
+ @engine.cdf(x,u,s).should eq i/10
45
+ }
46
+ else
47
+ pending("No #{@engine}.cdf")
48
+ end
49
+ end
50
+ end
51
+
52
+
53
+ describe "singleton" do
54
+ before do
55
+ @engine=Distribution::Logistic
56
+ end
57
+ it_should_behave_like "logistic engine"
58
+ end
59
+
60
+ describe Distribution::Logistic::Ruby_ do
61
+ before do
62
+ @engine=Distribution::Logistic::Ruby_
63
+ end
64
+ it_should_behave_like "logistic engine"
65
+
66
+ end
67
+
68
+ end
@@ -15,6 +15,7 @@ shared_examples_for "T engine(with pdf)" do
15
15
  [-2,0.1,0.5,1,2].each{|t|
16
16
  [2,5,10].each{|n|
17
17
  @engine.pdf(t,n).should be_within(1e-6).of(GSL::Ran.tdist_pdf(t,n))
18
+ @engine.pdf(t,n.to_f).should be_within(1e-6).of(@engine.pdf(t,n))
18
19
 
19
20
  }
20
21
  }
@@ -28,9 +29,16 @@ shared_examples_for "T engine" do
28
29
 
29
30
  it_only_with_gsl "should return correct cdf" do
30
31
  if @engine.respond_to? :cdf
32
+ # Testing with R values
33
+ @engine.cdf(1,2).should be_within(1e-7).of(0.7886751)
34
+ @engine.cdf(1,2.0).should be_within(1e-7).of(0.7886751)
35
+ @engine.cdf(1,3.0).should be_within(1e-7).of(0.8044989)
36
+
31
37
  [-2,0.1,0.5,1,2].each{|t|
32
38
  [2,5,10].each{|n|
33
39
  @engine.cdf(t,n).should be_within(1e-4).of(GSL::Cdf.tdist_P(t,n))
40
+ @engine.cdf(t,n).should be_within(1e-4).of(@engine.cdf(t,n.to_f))
41
+
34
42
  }
35
43
  }
36
44
  else
@@ -65,17 +73,27 @@ end
65
73
  @engine=Distribution::T::Ruby_
66
74
  end
67
75
  it_should_behave_like "T engine"
68
- it_should_behave_like "T engine(with pdf)"
76
+ it_should_behave_like "T engine(with pdf)"
77
+ it "raise error with fractional df on cdf" do
78
+ lambda {@engine.cdf(1,2.5)}.should raise_error
79
+ end
80
+ it "return correct values for cdf with fractional df" do
81
+ pending("we have to implement partial beta");
82
+ end
69
83
  end
70
84
  if Distribution.has_gsl?
71
85
  describe Distribution::T::GSL_ do
72
86
  before do
73
87
  @engine=Distribution::T::GSL_
74
88
  end
89
+ it "return correct values for cdf with fractional df" do
90
+ @engine.cdf(1,2.5).should be_within(1e-7).of(0.7979695)
91
+ end
75
92
  it_should_behave_like "T engine"
76
93
  it_should_behave_like "T engine(with pdf)"
77
94
  end
78
- end
95
+ end
96
+ =begin
79
97
  if Distribution.has_statistics2?
80
98
  describe Distribution::T::Statistics2_ do
81
99
  before do
@@ -84,7 +102,7 @@ end
84
102
  it_should_behave_like "T engine"
85
103
  end
86
104
  end
87
-
105
+ =end
88
106
  if Distribution.has_java?
89
107
  describe Distribution::T::Java_ do
90
108
  before do
metadata CHANGED
@@ -1,12 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: distribution
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 4
8
- - 0
9
- version: 0.4.0
4
+ prerelease:
5
+ version: 0.5.0
10
6
  platform: ruby
11
7
  authors:
12
8
  - Claudio Bustos
@@ -35,7 +31,7 @@ cert_chain:
35
31
  rpP0jjs0
36
32
  -----END CERTIFICATE-----
37
33
 
38
- date: 2011-02-01 00:00:00 -03:00
34
+ date: 2011-05-03 00:00:00 -03:00
39
35
  default_executable:
40
36
  dependencies:
41
37
  - !ruby/object:Gem::Dependency
@@ -46,10 +42,6 @@ dependencies:
46
42
  requirements:
47
43
  - - ">="
48
44
  - !ruby/object:Gem::Version
49
- segments:
50
- - 2
51
- - 0
52
- - 4
53
45
  version: 2.0.4
54
46
  type: :development
55
47
  version_requirements: *id001
@@ -61,9 +53,6 @@ dependencies:
61
53
  requirements:
62
54
  - - ">="
63
55
  - !ruby/object:Gem::Version
64
- segments:
65
- - 2
66
- - 0
67
56
  version: "2.0"
68
57
  type: :development
69
58
  version_requirements: *id002
@@ -75,8 +64,6 @@ dependencies:
75
64
  requirements:
76
65
  - - ">="
77
66
  - !ruby/object:Gem::Version
78
- segments:
79
- - 0
80
67
  version: "0"
81
68
  type: :development
82
69
  version_requirements: *id003
@@ -88,10 +75,6 @@ dependencies:
88
75
  requirements:
89
76
  - - ">="
90
77
  - !ruby/object:Gem::Version
91
- segments:
92
- - 2
93
- - 8
94
- - 0
95
78
  version: 2.8.0
96
79
  type: :development
97
80
  version_requirements: *id004
@@ -124,6 +107,7 @@ files:
124
107
  - benchmark/factorial_hash.rb
125
108
  - benchmark/factorial_method.rb
126
109
  - benchmark/odd.rb
110
+ - benchmark/power.rb
127
111
  - bin/distribution
128
112
  - data/template/distribution.erb
129
113
  - data/template/distribution/gsl.erb
@@ -156,6 +140,8 @@ files:
156
140
  - lib/distribution/hypergeometric/gsl.rb
157
141
  - lib/distribution/hypergeometric/java.rb
158
142
  - lib/distribution/hypergeometric/ruby.rb
143
+ - lib/distribution/logistic.rb
144
+ - lib/distribution/logistic/ruby.rb
159
145
  - lib/distribution/math_extension.rb
160
146
  - lib/distribution/normal.rb
161
147
  - lib/distribution/normal/gsl.rb
@@ -178,6 +164,7 @@ files:
178
164
  - spec/exponential_spec.rb
179
165
  - spec/f_spec.rb
180
166
  - spec/hypergeometric_spec.rb
167
+ - spec/logistic_spec.rb
181
168
  - spec/math_extension_spec.rb
182
169
  - spec/normal_spec.rb
183
170
  - spec/poisson_spec.rb
@@ -200,21 +187,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
200
187
  requirements:
201
188
  - - ">="
202
189
  - !ruby/object:Gem::Version
203
- segments:
204
- - 0
205
190
  version: "0"
206
191
  required_rubygems_version: !ruby/object:Gem::Requirement
207
192
  none: false
208
193
  requirements:
209
194
  - - ">="
210
195
  - !ruby/object:Gem::Version
211
- segments:
212
- - 0
213
196
  version: "0"
214
197
  requirements: []
215
198
 
216
199
  rubyforge_project: distribution
217
- rubygems_version: 1.3.7
200
+ rubygems_version: 1.6.0
218
201
  signing_key:
219
202
  specification_version: 3
220
203
  summary: Statistical Distributions library
metadata.gz.sig CHANGED
Binary file