distribution 0.3.0 → 0.4.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.
- data.tar.gz.sig +0 -0
- data/History.txt +10 -0
- data/Manifest.txt +16 -0
- data/README.txt +13 -4
- data/benchmark/binomial_coefficient.rb +12 -11
- data/benchmark/binomial_coefficient/binomial_coefficient.ds +0 -0
- data/benchmark/binomial_coefficient/binomial_coefficient.xls +0 -0
- data/benchmark/binomial_coefficient/experiment.rb +54 -0
- data/benchmark/factorial_hash.rb +24 -0
- data/bin/distribution +49 -1
- data/data/template/distribution.erb +23 -0
- data/data/template/distribution/gsl.erb +14 -0
- data/data/template/distribution/ruby.erb +14 -0
- data/data/template/spec.erb +54 -0
- data/lib/distribution.rb +4 -2
- data/lib/distribution/binomial/ruby.rb +4 -3
- data/lib/distribution/chisquare/ruby.rb +1 -2
- data/lib/distribution/exponential.rb +34 -0
- data/lib/distribution/exponential/gsl.rb +19 -0
- data/lib/distribution/exponential/ruby.rb +19 -0
- data/lib/distribution/math_extension.rb +107 -74
- data/lib/distribution/poisson.rb +34 -0
- data/lib/distribution/poisson/gsl.rb +17 -0
- data/lib/distribution/poisson/ruby.rb +21 -0
- data/spec/binomial_spec.rb +8 -0
- data/spec/exponential_spec.rb +80 -0
- data/spec/math_extension_spec.rb +27 -12
- data/spec/poisson_spec.rb +72 -0
- metadata +23 -6
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
|
Binary file
|
data/History.txt
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
=== 0.4.0 / 2011-02-01
|
|
2
|
+
|
|
3
|
+
* Poisson and exponential distributions implemented. Implementation of inverse cdf for poisson is not perfect, yet.
|
|
4
|
+
* +distribution+ executable can create template files for new distributions.
|
|
5
|
+
* MathExtension should work fine with Ruby 1.8. Fixed shadowed variable on MathExtension.naive_factorial
|
|
6
|
+
* Added factorial lookup table for n<20.
|
|
7
|
+
* Added exact cdf for Binomial
|
|
8
|
+
* Binomial coefficient in function of permutations. Deleted incomplete beta until we found a faster way to calculate it
|
|
9
|
+
|
|
10
|
+
|
|
1
11
|
=== 0.3.0 / 2011-01-28
|
|
2
12
|
|
|
3
13
|
* Included support for binomial distribution. p_value is not accurate
|
data/Manifest.txt
CHANGED
|
@@ -4,9 +4,17 @@ Manifest.txt
|
|
|
4
4
|
README.txt
|
|
5
5
|
Rakefile
|
|
6
6
|
benchmark/binomial_coefficient.rb
|
|
7
|
+
benchmark/binomial_coefficient/binomial_coefficient.ds
|
|
8
|
+
benchmark/binomial_coefficient/binomial_coefficient.xls
|
|
9
|
+
benchmark/binomial_coefficient/experiment.rb
|
|
10
|
+
benchmark/factorial_hash.rb
|
|
7
11
|
benchmark/factorial_method.rb
|
|
8
12
|
benchmark/odd.rb
|
|
9
13
|
bin/distribution
|
|
14
|
+
data/template/distribution.erb
|
|
15
|
+
data/template/distribution/gsl.erb
|
|
16
|
+
data/template/distribution/ruby.erb
|
|
17
|
+
data/template/spec.erb
|
|
10
18
|
lib/distribution.rb
|
|
11
19
|
lib/distribution/binomial.rb
|
|
12
20
|
lib/distribution/binomial/gsl.rb
|
|
@@ -22,6 +30,9 @@ lib/distribution/chisquare/gsl.rb
|
|
|
22
30
|
lib/distribution/chisquare/java.rb
|
|
23
31
|
lib/distribution/chisquare/ruby.rb
|
|
24
32
|
lib/distribution/chisquare/statistics2.rb
|
|
33
|
+
lib/distribution/exponential.rb
|
|
34
|
+
lib/distribution/exponential/gsl.rb
|
|
35
|
+
lib/distribution/exponential/ruby.rb
|
|
25
36
|
lib/distribution/f.rb
|
|
26
37
|
lib/distribution/f/gsl.rb
|
|
27
38
|
lib/distribution/f/java.rb
|
|
@@ -38,6 +49,9 @@ lib/distribution/normal/java.rb
|
|
|
38
49
|
lib/distribution/normal/ruby.rb
|
|
39
50
|
lib/distribution/normal/statistics2.rb
|
|
40
51
|
lib/distribution/normalmultivariate.rb
|
|
52
|
+
lib/distribution/poisson.rb
|
|
53
|
+
lib/distribution/poisson/gsl.rb
|
|
54
|
+
lib/distribution/poisson/ruby.rb
|
|
41
55
|
lib/distribution/t.rb
|
|
42
56
|
lib/distribution/t/gsl.rb
|
|
43
57
|
lib/distribution/t/java.rb
|
|
@@ -47,10 +61,12 @@ spec/binomial_spec.rb
|
|
|
47
61
|
spec/bivariatenormal_spec.rb
|
|
48
62
|
spec/chisquare_spec.rb
|
|
49
63
|
spec/distribution_spec.rb
|
|
64
|
+
spec/exponential_spec.rb
|
|
50
65
|
spec/f_spec.rb
|
|
51
66
|
spec/hypergeometric_spec.rb
|
|
52
67
|
spec/math_extension_spec.rb
|
|
53
68
|
spec/normal_spec.rb
|
|
69
|
+
spec/poisson_spec.rb
|
|
54
70
|
spec/shorthand_spec.rb
|
|
55
71
|
spec/spec.opts
|
|
56
72
|
spec/spec_helper.rb
|
data/README.txt
CHANGED
|
@@ -4,16 +4,17 @@
|
|
|
4
4
|
|
|
5
5
|
== DESCRIPTION:
|
|
6
6
|
|
|
7
|
-
Statistical Distributions
|
|
7
|
+
Statistical Distributions library. Includes Normal univariate and bivariate, T, F, Chi Square, Binomial, Hypergeometric, Exponential and Poisson.
|
|
8
|
+
|
|
8
9
|
Uses Ruby by default and C (statistics2/GSL) or Java extensions where available.
|
|
9
10
|
|
|
10
|
-
Includes code from statistics2
|
|
11
|
+
Includes code from statistics2 on Normal, T, F and Chi Square ruby code [http://blade.nagaokaut.ac.jp/~sinara/ruby/math/statistics2]
|
|
11
12
|
|
|
12
13
|
== FEATURES/PROBLEMS:
|
|
13
14
|
|
|
14
15
|
* Very fast ruby 1.8.7/1.9.+ implementation, with improved method to calculate factorials and others common functions
|
|
15
16
|
* All methods tested on several ranges. See spec/
|
|
16
|
-
* On Jruby, BivariateNormal returns incorrect pdf
|
|
17
|
+
* On Jruby and Rubinius, BivariateNormal returns incorrect pdf
|
|
17
18
|
|
|
18
19
|
== API structure
|
|
19
20
|
|
|
@@ -31,7 +32,7 @@ On discrete distributions, exact cdf, pdf and p_value are
|
|
|
31
32
|
|
|
32
33
|
<Distribution shortname>_(ecdf|epdf|ep)
|
|
33
34
|
|
|
34
|
-
Shortnames
|
|
35
|
+
Shortnames for distributions:
|
|
35
36
|
|
|
36
37
|
* Normal: norm
|
|
37
38
|
* Bivariate Normal: bnor
|
|
@@ -40,6 +41,8 @@ Shortnames are:
|
|
|
40
41
|
* Chi Square: chisq
|
|
41
42
|
* Binomial: bino
|
|
42
43
|
* Hypergeometric: hypg
|
|
44
|
+
* Exponential: expo
|
|
45
|
+
* Poisson: pois
|
|
43
46
|
|
|
44
47
|
For example
|
|
45
48
|
|
|
@@ -83,6 +86,12 @@ After checking out the source, run:
|
|
|
83
86
|
This task will install any missing dependencies, run the tests/specs,
|
|
84
87
|
and generate the RDoc.
|
|
85
88
|
|
|
89
|
+
If you want to provide a new distribution, /lib/distribution run
|
|
90
|
+
|
|
91
|
+
$ distribution --new your_distribution
|
|
92
|
+
|
|
93
|
+
This should create the main distribution file, the directory with ruby and gsl engines and the rspec on /spec directory.
|
|
94
|
+
|
|
86
95
|
== LICENSE:
|
|
87
96
|
|
|
88
97
|
GPL V2
|
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
$:.unshift(File.dirname(__FILE__)+"/../lib")
|
|
1
|
+
$:.unshift(File.expand_path(File.dirname(__FILE__)+"/../lib"))
|
|
2
2
|
require 'distribution'
|
|
3
3
|
require 'bench_press'
|
|
4
4
|
|
|
5
5
|
extend BenchPress
|
|
6
6
|
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
samples=10.times.map {|i| 2**(i+1)}
|
|
10
|
+
|
|
7
11
|
name 'binomial coefficient: multiplicative, factorial and optimized factorial methods'
|
|
8
12
|
author 'Claudio Bustos'
|
|
9
13
|
date '2011-01-27'
|
|
10
|
-
summary "Exact calculation of Binomial Coefficient could be obtained using multiplicative, pure factorial or optimized factorial algorithm.
|
|
14
|
+
summary "Exact calculation of Binomial Coefficient could be obtained using multiplicative, pure factorial or optimized factorial algorithm (failing + factorial).
|
|
11
15
|
Which one is faster?
|
|
12
16
|
|
|
13
17
|
Lower k is the best for all
|
|
14
|
-
k=n/2 is the worst case
|
|
15
|
-
k near n is the worst for multiplicative
|
|
18
|
+
k=n/2 is the worst case.
|
|
16
19
|
|
|
17
20
|
The factorial method uses the fastest Swing Prime Algorithm."
|
|
18
21
|
|
|
@@ -23,31 +26,29 @@ x=100
|
|
|
23
26
|
n=100
|
|
24
27
|
k=50
|
|
25
28
|
|
|
26
|
-
samples=10.times.map {|i| 2**(i+1)}
|
|
27
|
-
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
measure "Multiplicative" do
|
|
31
32
|
samples.each do |n|
|
|
32
|
-
[5,n/2
|
|
33
|
+
[5,n/2].each do |k|
|
|
33
34
|
k=[k,n-k].min
|
|
34
35
|
(1..k).inject(1) {|ac, i| (ac*(n-k+i).quo(i))}
|
|
35
36
|
end
|
|
36
37
|
end
|
|
37
38
|
end
|
|
38
39
|
|
|
39
|
-
measure "Factorial" do
|
|
40
|
+
measure "Pure Factorial" do
|
|
40
41
|
samples.each do |n|
|
|
41
|
-
[5,n/2
|
|
42
|
+
[5,n/2].each do |k|
|
|
42
43
|
k=[k,n-k].min
|
|
43
44
|
Math.factorial(n).quo(Math.factorial(k) * Math.factorial(n - k))
|
|
44
45
|
end
|
|
45
46
|
end
|
|
46
47
|
end
|
|
47
48
|
|
|
48
|
-
measure "
|
|
49
|
+
measure "Failing factorial + factorial" do
|
|
49
50
|
samples.each do |n|
|
|
50
|
-
[5,n/2
|
|
51
|
+
[5,n/2].each do |k|
|
|
51
52
|
k=[k,n-k].min
|
|
52
53
|
(((n-k+1)..n).inject(1) {|ac,v| ac * v}).quo(Math.factorial(k))
|
|
53
54
|
end
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# This test create a database to adjust the best algorithm
|
|
2
|
+
# to use on correlation matrix
|
|
3
|
+
$:.unshift(File.expand_path(File.dirname(__FILE__)+"/../../lib"))
|
|
4
|
+
require 'distribution'
|
|
5
|
+
require 'statsample'
|
|
6
|
+
require 'benchmark'
|
|
7
|
+
|
|
8
|
+
if !File.exists?("binomial_coefficient.ds") or File.mtime(__FILE__) > File.mtime("binomial_coefficient.ds")
|
|
9
|
+
reps=100 #number of repetitions
|
|
10
|
+
ns={
|
|
11
|
+
5=> [1,3],
|
|
12
|
+
10=> [1,3,5],
|
|
13
|
+
50=> [1,3,5,10,25],
|
|
14
|
+
100=> [1,3,5,10,25,50],
|
|
15
|
+
500=> [1,3,5,10,25,50,100,250],
|
|
16
|
+
1000=> [1,3,5,10,25,50,100,250,500],
|
|
17
|
+
5000=> [1,3,5,10,25,50,100,250,500,1000,2500],
|
|
18
|
+
10000=>[1,3,5,10,25,50,100,250,500,1000,2500,5000]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
rs=Statsample::Dataset.new(%w{n k mixed_factorial multiplicative})
|
|
22
|
+
|
|
23
|
+
ns.each do |n,ks|
|
|
24
|
+
ks.each do |k|
|
|
25
|
+
|
|
26
|
+
time_factorial= Benchmark.realtime do
|
|
27
|
+
reps.times {
|
|
28
|
+
(((n-k+1)..n).inject(1) {|ac,v| ac * v}).quo(Math.factorial(k))
|
|
29
|
+
}
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
time_multiplicative= Benchmark.realtime do
|
|
33
|
+
reps.times {
|
|
34
|
+
(1..k).inject(1) {|ac, i| (ac*(n-k+i).quo(i))}
|
|
35
|
+
}
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
puts "n:#{n}, k:#{k} -> factorial:%0.3f | multiplicative: %0.3f " % [time_factorial, time_multiplicative]
|
|
39
|
+
|
|
40
|
+
rs.add_case({'n'=>n,'k'=>k,'mixed_factorial'=>time_factorial, 'multiplicative'=>time_multiplicative})
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
else
|
|
45
|
+
rs=Statsample.load("binomial_coefficient.ds")
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
rs.fields.each {|f| rs[f].type=:scale}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
rs.update_valid_data
|
|
53
|
+
rs.save("binomial_coefficient.ds")
|
|
54
|
+
Statsample::Excel.write(rs,"binomial_coefficient.xls")
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
$:.unshift(File.expand_path(File.dirname(__FILE__)+"/../lib"))
|
|
2
|
+
require 'bench_press'
|
|
3
|
+
require 'distribution'
|
|
4
|
+
extend BenchPress
|
|
5
|
+
|
|
6
|
+
name 'calculate factorial vs looking on a Hash'
|
|
7
|
+
author 'Claudio Bustos'
|
|
8
|
+
date '2011-01-31'
|
|
9
|
+
summary "
|
|
10
|
+
Is better create a lookup table for factorial or just calculate it?
|
|
11
|
+
Distribution::MathExtension::SwingFactorial has a lookup table
|
|
12
|
+
for factorials n<20
|
|
13
|
+
"
|
|
14
|
+
|
|
15
|
+
reps 1000 #number of repetitions
|
|
16
|
+
|
|
17
|
+
measure "Lookup" do
|
|
18
|
+
Math.factorial(19)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
measure "calculate" do
|
|
22
|
+
Distribution::MathExtension::SwingFactorial.naive_factorial(19)
|
|
23
|
+
end
|
|
24
|
+
|
data/bin/distribution
CHANGED
|
@@ -1,3 +1,51 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
require 'optparse'
|
|
4
|
+
require 'fileutils'
|
|
5
|
+
require 'erb'
|
|
6
|
+
gem_base=File.expand_path(File.dirname(__FILE__)+"/..")
|
|
7
|
+
require gem_base+"/lib/distribution"
|
|
8
|
+
|
|
9
|
+
new=false
|
|
10
|
+
parameters=""
|
|
11
|
+
OptionParser.new do |opts|
|
|
12
|
+
opts.banner="Usage: distribution [--new] [--params parameters] distribution"
|
|
13
|
+
opts.on("-n", "--new", "Create a new template for distribution") do
|
|
14
|
+
new=true
|
|
15
|
+
end
|
|
16
|
+
opts.on("-PMANDATORY", "--params MANDATORY", String, "Parameters for distribution") do |n_param|
|
|
17
|
+
parameters=", #{n_param}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
opts.on("-h", "--help", "Show this message") do
|
|
21
|
+
puts opts
|
|
22
|
+
exit
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
begin
|
|
26
|
+
ARGV << "-h" if ARGV.empty?
|
|
27
|
+
opts.parse!(ARGV)
|
|
28
|
+
rescue OptionParser::ParseError => e
|
|
29
|
+
STDERR.puts e.message, "\n", opts
|
|
30
|
+
exit(-1)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
ARGV.each do |distribution|
|
|
35
|
+
if new
|
|
36
|
+
basename=distribution.downcase
|
|
37
|
+
raise "You should be inside distribution lib directory" unless File.exists? "../distribution.rb"
|
|
38
|
+
raise "Distribution already created" if File.exists? basename+".rb"
|
|
39
|
+
main=ERB.new(File.read(gem_base+"/data/template/distribution.erb"),)
|
|
40
|
+
ruby=ERB.new(File.read(gem_base+"/data/template/distribution/ruby.erb"))
|
|
41
|
+
gsl=ERB.new(File.read(gem_base+"/data/template/distribution/gsl.erb"))
|
|
42
|
+
spec=ERB.new(File.read(gem_base+"/data/template/spec.erb"))
|
|
43
|
+
|
|
44
|
+
FileUtils.mkdir(basename) unless File.exists? basename
|
|
45
|
+
File.open(basename+".rb","w") {|fp| fp.write(main.result(binding))}
|
|
46
|
+
File.open(basename+"/ruby.rb","w") {|fp| fp.write(ruby.result(binding))}
|
|
47
|
+
File.open(basename+"/gsl.rb","w") {|fp| fp.write(gsl.result(binding))}
|
|
48
|
+
File.open("../../spec/#{basename}_spec.rb","w") {|fp| fp.write(spec.result(binding))}
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'distribution/<%= distribution.downcase %>/ruby'
|
|
2
|
+
require 'distribution/<%= distribution.downcase %>/gsl'
|
|
3
|
+
#require 'distribution/<%= distribution.downcase %>/java'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
module Distribution
|
|
7
|
+
# TODO: Document this Distribution
|
|
8
|
+
module <%= distribution.capitalize %>
|
|
9
|
+
SHORTHAND='<%= distribution.downcase[0,4] %>'
|
|
10
|
+
extend Distributable
|
|
11
|
+
create_distribution_methods
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
# :singleton-method: pdf(x <%= parameters %>)
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
# :singleton-method: cdf(x <%= parameters %>)
|
|
18
|
+
|
|
19
|
+
##
|
|
20
|
+
# :singleton-method: p_value(pr <%= parameters %>)
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb")
|
|
2
|
+
|
|
3
|
+
describe Distribution::<%= distribution.capitalize %> do
|
|
4
|
+
|
|
5
|
+
shared_examples_for "<%= distribution %> engine" do
|
|
6
|
+
it "should return correct pdf" do
|
|
7
|
+
if @engine.respond_to? :pdf
|
|
8
|
+
else
|
|
9
|
+
pending("No #{@engine}.pdf")
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should return correct cdf" do
|
|
14
|
+
if @engine.respond_to? :cdf
|
|
15
|
+
else
|
|
16
|
+
pending("No #{@engine}.cdf")
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
it "should return correct p_value" do
|
|
22
|
+
if @engine.respond_to? :p_value
|
|
23
|
+
else
|
|
24
|
+
pending("No #{@engine}.cdf")
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
describe "singleton" do
|
|
31
|
+
before do
|
|
32
|
+
@engine=Distribution::<%= distribution.capitalize %>
|
|
33
|
+
end
|
|
34
|
+
it_should_behave_like "<%= distribution %> engine"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe Distribution::<%= distribution.capitalize %>::Ruby_ do
|
|
38
|
+
before do
|
|
39
|
+
@engine=Distribution::<%= distribution.capitalize %>::Ruby_
|
|
40
|
+
end
|
|
41
|
+
it_should_behave_like "<%= distribution %> engine"
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe Distribution::<%= distribution.capitalize %>::GSL_ do
|
|
46
|
+
before do
|
|
47
|
+
@engine=Distribution::<%= distribution.capitalize %>::GSL_
|
|
48
|
+
end
|
|
49
|
+
it_should_behave_like "<%= distribution %> engine"
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
end
|
data/lib/distribution.rb
CHANGED
|
@@ -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.
|
|
52
|
+
VERSION="0.4.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}
|
|
@@ -144,8 +144,10 @@ module Distribution
|
|
|
144
144
|
autoload(:F, 'distribution/f')
|
|
145
145
|
autoload(:BivariateNormal, 'distribution/bivariatenormal')
|
|
146
146
|
autoload(:Binomial, 'distribution/binomial')
|
|
147
|
-
|
|
148
147
|
autoload(:Hypergeometric, 'distribution/hypergeometric')
|
|
148
|
+
autoload(:Exponential, 'distribution/exponential')
|
|
149
|
+
autoload(:Poisson, 'distribution/poisson')
|
|
150
|
+
|
|
149
151
|
end
|
|
150
152
|
|
|
151
153
|
|
|
@@ -9,17 +9,18 @@ module Distribution
|
|
|
9
9
|
#(0..x.floor).inject(0) {|ac,i| ac+pdf(i,n,pr)}
|
|
10
10
|
Math.regularized_beta_function(1-pr,n - k,k+1)
|
|
11
11
|
end
|
|
12
|
+
def exact_cdf(k,n,pr)
|
|
13
|
+
(0..k).inject(0) {|ac,i| ac+pdf(i,n,pr)}
|
|
14
|
+
end
|
|
12
15
|
def p_value(prob,n,pr)
|
|
13
16
|
ac=0
|
|
14
17
|
(0..n).each do |i|
|
|
15
18
|
ac+=pdf(i,n,pr)
|
|
16
|
-
return i if ac
|
|
19
|
+
return i if prob<=ac
|
|
17
20
|
end
|
|
18
21
|
end
|
|
19
22
|
|
|
20
23
|
alias :exact_pdf :pdf
|
|
21
|
-
|
|
22
|
-
|
|
23
24
|
end
|
|
24
25
|
end
|
|
25
26
|
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require 'distribution/exponential/ruby'
|
|
2
|
+
require 'distribution/exponential/gsl'
|
|
3
|
+
#require 'distribution/exponential/java'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
module Distribution
|
|
7
|
+
# From Wikipedia:
|
|
8
|
+
# In probability theory and statistics, the exponential distribution
|
|
9
|
+
# (a.k.a. negative exponential distribution) is a family of continuous
|
|
10
|
+
# probability distributions. It describes the time between events in a
|
|
11
|
+
# Poisson process, i.e. a process in which events occur continuously
|
|
12
|
+
# and independently at a constant average rate.
|
|
13
|
+
#
|
|
14
|
+
# Parameter +l+ is the rate parameter, the number of occurrences/unit time.
|
|
15
|
+
module Exponential
|
|
16
|
+
SHORTHAND='expo'
|
|
17
|
+
extend Distributable
|
|
18
|
+
create_distribution_methods
|
|
19
|
+
|
|
20
|
+
##
|
|
21
|
+
# :singleton-method: pdf(x,l)
|
|
22
|
+
# PDF of exponential distribution, with parameters +x+ and +l+.
|
|
23
|
+
# +l+ is rate parameter
|
|
24
|
+
|
|
25
|
+
##
|
|
26
|
+
# :singleton-method: cdf(x,l)
|
|
27
|
+
# CDF of exponential distribution, with parameters +x+ and +l+.
|
|
28
|
+
# +l+ is rate parameter
|
|
29
|
+
##
|
|
30
|
+
# :singleton-method: p_value(pr,l)
|
|
31
|
+
# Inverse CDF of exponential distribution, with parameters +pr+ and +l+.
|
|
32
|
+
# +l+ is rate parameter
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Distribution
|
|
2
|
+
module Exponential
|
|
3
|
+
module GSL_
|
|
4
|
+
class << self
|
|
5
|
+
def pdf(x,l)
|
|
6
|
+
return 0 if x<0
|
|
7
|
+
GSL::Ran.exponential_pdf(x,1/l.to_f)
|
|
8
|
+
end
|
|
9
|
+
def cdf(x,l)
|
|
10
|
+
return 0 if x<0
|
|
11
|
+
GSL::Cdf.exponential_P(x,1/l.to_f)
|
|
12
|
+
end
|
|
13
|
+
def p_value(pr,l)
|
|
14
|
+
GSL::Cdf.exponential_Pinv(pr,1/l.to_f)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Distribution
|
|
2
|
+
module Exponential
|
|
3
|
+
module Ruby_
|
|
4
|
+
class << self
|
|
5
|
+
def pdf(x,l)
|
|
6
|
+
return 0 if x<0
|
|
7
|
+
l*Math.exp(-l*x)
|
|
8
|
+
end
|
|
9
|
+
def cdf(x,l)
|
|
10
|
+
return 0 if x<0
|
|
11
|
+
1-Math.exp(-l*x)
|
|
12
|
+
end
|
|
13
|
+
def p_value(pr,l)
|
|
14
|
+
(-Math.log(1-pr)).quo(l)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -14,8 +14,52 @@ end
|
|
|
14
14
|
require 'bigdecimal'
|
|
15
15
|
require 'bigdecimal/math'
|
|
16
16
|
|
|
17
|
-
# Useful additions to Math
|
|
18
17
|
module Distribution
|
|
18
|
+
# Extension for Ruby18
|
|
19
|
+
# Includes gamma and lgamma
|
|
20
|
+
module MathExtension18
|
|
21
|
+
LOG_2PI = Math.log(2 * Math::PI)# log(2PI)
|
|
22
|
+
N = 8
|
|
23
|
+
B0 = 1.0
|
|
24
|
+
B1 = -1.0 / 2.0
|
|
25
|
+
B2 = 1.0 / 6.0
|
|
26
|
+
B4 = -1.0 / 30.0
|
|
27
|
+
B6 = 1.0 / 42.0
|
|
28
|
+
B8 = -1.0 / 30.0
|
|
29
|
+
B10 = 5.0 / 66.0
|
|
30
|
+
B12 = -691.0 / 2730.0
|
|
31
|
+
B14 = 7.0 / 6.0
|
|
32
|
+
B16 = -3617.0 / 510.0
|
|
33
|
+
# From statistics2
|
|
34
|
+
def loggamma(x)
|
|
35
|
+
v = 1.0
|
|
36
|
+
while (x < N)
|
|
37
|
+
v *= x
|
|
38
|
+
x += 1.0
|
|
39
|
+
end
|
|
40
|
+
w = 1.0 / (x * x)
|
|
41
|
+
ret = B16 / (16 * 15)
|
|
42
|
+
ret = ret * w + B14 / (14 * 13)
|
|
43
|
+
ret = ret * w + B12 / (12 * 11)
|
|
44
|
+
ret = ret * w + B10 / (10 * 9)
|
|
45
|
+
ret = ret * w + B8 / ( 8 * 7)
|
|
46
|
+
ret = ret * w + B6 / ( 6 * 5)
|
|
47
|
+
ret = ret * w + B4 / ( 4 * 3)
|
|
48
|
+
ret = ret * w + B2 / ( 2 * 1)
|
|
49
|
+
ret = ret / x + 0.5 * LOG_2PI - Math.log(v) - x + (x - 0.5) * Math.log(x)
|
|
50
|
+
ret
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Gamma function.
|
|
54
|
+
# From statistics2
|
|
55
|
+
def gamma(x)
|
|
56
|
+
if (x < 0.0)
|
|
57
|
+
return Math::PI / (Math.sin(Math.PI * x) * Math.exp(loggamma(1 - x))) #/
|
|
58
|
+
end
|
|
59
|
+
Math.exp(loggamma(x))
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
# Useful additions to Math
|
|
19
63
|
module MathExtension
|
|
20
64
|
# Factorization based on Prime Swing algorithm, by Luschny (the king of factorial numbers analysis :P )
|
|
21
65
|
# == Reference
|
|
@@ -24,6 +68,7 @@ module Distribution
|
|
|
24
68
|
class SwingFactorial
|
|
25
69
|
attr_reader :result
|
|
26
70
|
SmallOddSwing=[ 1, 1, 1, 3, 3, 15, 5, 35, 35, 315, 63, 693, 231, 3003, 429, 6435, 6435, 109395, 12155, 230945, 46189, 969969, 88179, 2028117, 676039, 16900975, 1300075, 35102025, 5014575,145422675, 9694845, 300540195, 300540195]
|
|
71
|
+
SmallFactorial=[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000, 20922789888000, 355687428096000, 6402373705728000, 121645100408832000, 2432902008176640000]
|
|
27
72
|
def bitcount(n)
|
|
28
73
|
bc = n - ((n >> 1) & 0x55555555);
|
|
29
74
|
bc = (bc & 0x33333333) + ((bc >> 2) & 0x33333333);
|
|
@@ -35,7 +80,8 @@ module Distribution
|
|
|
35
80
|
end
|
|
36
81
|
def initialize(n)
|
|
37
82
|
if (n<20)
|
|
38
|
-
|
|
83
|
+
@result=SmallFactorial[n]
|
|
84
|
+
#naive_factorial(n)
|
|
39
85
|
else
|
|
40
86
|
@prime_list=[]
|
|
41
87
|
exp2 = n - bitcount(n);
|
|
@@ -89,7 +135,7 @@ module Distribution
|
|
|
89
135
|
@result=(self.class).naive_factorial(n)
|
|
90
136
|
end
|
|
91
137
|
def self.naive_factorial(n)
|
|
92
|
-
(2..n).inject(1) { |f,
|
|
138
|
+
(2..n).inject(1) { |f,nn| f * nn }
|
|
93
139
|
end
|
|
94
140
|
end
|
|
95
141
|
# Module to calculate approximated factorial
|
|
@@ -140,8 +186,8 @@ module Distribution
|
|
|
140
186
|
end
|
|
141
187
|
end
|
|
142
188
|
# Exact factorial.
|
|
143
|
-
# Use
|
|
144
|
-
# and Prime Swing algorithm for higher values
|
|
189
|
+
# Use lookup on a Hash table on n<20
|
|
190
|
+
# and Prime Swing algorithm for higher values.
|
|
145
191
|
def factorial(n)
|
|
146
192
|
SwingFactorial.new(n).result
|
|
147
193
|
end
|
|
@@ -150,14 +196,6 @@ module Distribution
|
|
|
150
196
|
def fast_factorial(n)
|
|
151
197
|
ApproxFactorial.stieltjes_factorial(n)
|
|
152
198
|
end
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
# Quick, accurate approximation of factorial for very small n. Special case, generally you want to use stirling instead.
|
|
156
|
-
# ==Reference
|
|
157
|
-
# * http://mathworld.wolfram.com/StirlingsApproximation.html
|
|
158
|
-
def gosper(n)
|
|
159
|
-
Math.sqrt( (2*n + 1/3.0) * Math::PI ) * (n/Math::E)**n
|
|
160
|
-
end
|
|
161
199
|
|
|
162
200
|
# Beta function.
|
|
163
201
|
# Source:
|
|
@@ -166,14 +204,14 @@ module Distribution
|
|
|
166
204
|
(gamma(x)*gamma(y)).quo(gamma(x+y))
|
|
167
205
|
end
|
|
168
206
|
# I_x(a,b): Regularized incomplete beta function
|
|
169
|
-
#
|
|
207
|
+
# TODO: Find a faster version.
|
|
170
208
|
# Source:
|
|
171
|
-
#
|
|
209
|
+
# * http://dlmf.nist.gov/8.17
|
|
172
210
|
def regularized_beta_function(x,a,b)
|
|
173
211
|
return 1 if x==1
|
|
174
212
|
#incomplete_beta(x,a,b).quo(beta(a,b))
|
|
175
|
-
m=a
|
|
176
|
-
n=b+a-1
|
|
213
|
+
m=a.to_i
|
|
214
|
+
n=(b+a-1).to_i
|
|
177
215
|
(m..n).inject(0) {|sum,j|
|
|
178
216
|
sum+(binomial_coefficient(n,j)* x**j * (1-x)**(n-j))
|
|
179
217
|
}
|
|
@@ -183,65 +221,38 @@ module Distribution
|
|
|
183
221
|
# Should be replaced by
|
|
184
222
|
# http://lib.stat.cmu.edu/apstat/63
|
|
185
223
|
def incomplete_beta(x,a,b)
|
|
186
|
-
raise "
|
|
187
|
-
return beta(a,b) if x==1
|
|
188
|
-
|
|
189
|
-
((x**a * (1-x)**b).quo(a)) * hyper_f(a+b,1,a+1,x)
|
|
190
|
-
end
|
|
191
|
-
def permutations(x,n)
|
|
192
|
-
factorial(x).quo(factorial(x-n))
|
|
224
|
+
raise "Doesn't work"
|
|
193
225
|
end
|
|
194
226
|
|
|
227
|
+
# Rising factorial
|
|
195
228
|
def rising_factorial(x,n)
|
|
196
229
|
factorial(x+n-1).quo(factorial(x-1))
|
|
197
230
|
end
|
|
198
231
|
|
|
199
|
-
|
|
200
|
-
LOG_2PI = Math.log(2 * Math::PI)# log(2PI)
|
|
201
|
-
N = 8
|
|
202
|
-
B0 = 1.0
|
|
203
|
-
B1 = -1.0 / 2.0
|
|
204
|
-
B2 = 1.0 / 6.0
|
|
205
|
-
B4 = -1.0 / 30.0
|
|
206
|
-
B6 = 1.0 / 42.0
|
|
207
|
-
B8 = -1.0 / 30.0
|
|
208
|
-
B10 = 5.0 / 66.0
|
|
209
|
-
B12 = -691.0 / 2730.0
|
|
210
|
-
B14 = 7.0 / 6.0
|
|
211
|
-
B16 = -3617.0 / 510.0
|
|
212
|
-
# From statistics2
|
|
232
|
+
# Ln of gamma
|
|
213
233
|
def loggamma(x)
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
v *= x
|
|
217
|
-
x += 1.0
|
|
218
|
-
end
|
|
219
|
-
w = 1.0 / (x * x)
|
|
220
|
-
ret = B16 / (16 * 15)
|
|
221
|
-
ret = ret * w + B14 / (14 * 13)
|
|
222
|
-
ret = ret * w + B12 / (12 * 11)
|
|
223
|
-
ret = ret * w + B10 / (10 * 9)
|
|
224
|
-
ret = ret * w + B8 / ( 8 * 7)
|
|
225
|
-
ret = ret * w + B6 / ( 6 * 5)
|
|
226
|
-
ret = ret * w + B4 / ( 4 * 3)
|
|
227
|
-
ret = ret * w + B2 / ( 2 * 1)
|
|
228
|
-
ret = ret / x + 0.5 * LOG_2PI - Math.log(v) - x + (x - 0.5) * Math.log(x)
|
|
229
|
-
ret
|
|
234
|
+
lg=Math.lgamma(x)
|
|
235
|
+
lg[0]*lg[1]
|
|
230
236
|
end
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
# Sequences without repetition. n^k'
|
|
240
|
+
# Also called 'failing factorial'
|
|
241
|
+
def permutations(n,k)
|
|
242
|
+
return 1 if k==0
|
|
243
|
+
return n if k==1
|
|
244
|
+
return factorial(n) if k==n
|
|
245
|
+
(((n-k+1)..n).inject(1) {|ac,v| ac * v})
|
|
246
|
+
#factorial(x).quo(factorial(x-n))
|
|
238
247
|
end
|
|
248
|
+
|
|
239
249
|
# Binomial coeffients, or:
|
|
240
250
|
# ( n )
|
|
241
251
|
# ( k )
|
|
242
|
-
#
|
|
252
|
+
#
|
|
253
|
+
# Gives the number of *different* k size subsets of a set size n
|
|
243
254
|
#
|
|
244
|
-
#
|
|
255
|
+
# Uses:
|
|
245
256
|
#
|
|
246
257
|
# (n) n^k' (n)..(n-k+1)
|
|
247
258
|
# ( ) = ---- = ------------
|
|
@@ -250,41 +261,63 @@ module Distribution
|
|
|
250
261
|
def binomial_coefficient(n,k)
|
|
251
262
|
return 1 if (k==0 or k==n)
|
|
252
263
|
k=[k, n-k].min
|
|
253
|
-
(
|
|
254
|
-
#
|
|
264
|
+
permutations(n,k).quo(factorial(k))
|
|
265
|
+
# The factorial way is
|
|
266
|
+
# factorial(n).quo(factorial(k)*(factorial(n-k)))
|
|
267
|
+
# The multiplicative way is
|
|
255
268
|
# (1..k).inject(1) {|ac, i| (ac*(n-k+i).quo(i))}
|
|
256
269
|
end
|
|
270
|
+
# Binomial coefficient using multiplicative algorithm
|
|
271
|
+
# On benchmarks, is faster that raising factorial method
|
|
272
|
+
# when k is little. Use only when you're sure of that.
|
|
273
|
+
def binomial_coefficient_multiplicative(n,k)
|
|
274
|
+
return 1 if (k==0 or k==n)
|
|
275
|
+
k=[k, n-k].min
|
|
276
|
+
(1..k).inject(1) {|ac, i| (ac*(n-k+i).quo(i))}
|
|
277
|
+
end
|
|
278
|
+
|
|
257
279
|
# Approximate binomial coefficient, using gamma function.
|
|
258
280
|
# The fastest method, until we fall on BigDecimal!
|
|
259
281
|
def binomial_coefficient_gamma(n,k)
|
|
260
282
|
return 1 if (k==0 or k==n)
|
|
261
|
-
k=[k, n-k].min
|
|
262
|
-
|
|
263
|
-
|
|
283
|
+
k=[k, n-k].min
|
|
284
|
+
# First, we try direct gamma calculation for max precission
|
|
285
|
+
|
|
286
|
+
val=gamma(n + 1).quo(gamma(k+1)*gamma(n-k+1))
|
|
287
|
+
# Ups. Outside float point range. We try with logs
|
|
264
288
|
if (val.nan?)
|
|
265
|
-
|
|
289
|
+
#puts "nan"
|
|
290
|
+
lg=loggamma( n + 1 ) - (loggamma(k+1)+ loggamma(n-k+1))
|
|
266
291
|
val=Math.exp(lg)
|
|
267
292
|
# Crash again! We require BigDecimals
|
|
268
293
|
if val.infinite?
|
|
294
|
+
#puts "infinite"
|
|
269
295
|
val=BigMath.exp(BigDecimal(lg.to_s),16)
|
|
270
296
|
end
|
|
271
297
|
end
|
|
272
|
-
|
|
273
298
|
val
|
|
274
299
|
end
|
|
300
|
+
alias :combinations :binomial_coefficient
|
|
275
301
|
end
|
|
276
302
|
end
|
|
277
303
|
|
|
278
304
|
module Math
|
|
279
305
|
include Distribution::MathExtension
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
module_function :factorial, :beta, :gamma, :gosper, :loggamma, :lgamma, :binomial_coefficient, :binomial_coefficient_gamma, :regularized_beta_function, :incomplete_beta, :permutations, :rising_factorial , :fast_factorial
|
|
306
|
+
module_function :factorial, :beta, :loggamma, :binomial_coefficient, :binomial_coefficient_gamma, :regularized_beta_function, :incomplete_beta, :permutations, :rising_factorial , :fast_factorial, :combinations
|
|
283
307
|
end
|
|
284
308
|
|
|
285
309
|
# Necessary on Ruby 1.9
|
|
286
310
|
module CMath # :nodoc:
|
|
287
311
|
include Distribution::MathExtension
|
|
288
|
-
module_function :factorial, :beta, :
|
|
312
|
+
module_function :factorial, :beta, :loggamma, :binomial_coefficient, :binomial_coefficient_gamma, :regularized_beta_function, :incomplete_beta, :permutations, :rising_factorial, :fast_factorial, :combinations
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
if RUBY_VERSION<"1.9"
|
|
316
|
+
module Math
|
|
317
|
+
remove_method :loggamma
|
|
318
|
+
include Distribution::MathExtension18
|
|
319
|
+
module_function :gamma, :loggamma
|
|
320
|
+
end
|
|
289
321
|
end
|
|
290
322
|
|
|
323
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require 'distribution/poisson/ruby'
|
|
2
|
+
require 'distribution/poisson/gsl'
|
|
3
|
+
#require 'distribution/poisson/java'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
module Distribution
|
|
7
|
+
# From Wikipedia
|
|
8
|
+
# In probability theory and statistics, the Poisson distribution is
|
|
9
|
+
# a discrete probability distribution that expresses the probability of
|
|
10
|
+
# a number of events occurring in a fixed period of time if these
|
|
11
|
+
# events occur with a known average rate and independently of the time
|
|
12
|
+
# since the last event.
|
|
13
|
+
module Poisson
|
|
14
|
+
SHORTHAND='pois'
|
|
15
|
+
extend Distributable
|
|
16
|
+
create_distribution_methods
|
|
17
|
+
|
|
18
|
+
##
|
|
19
|
+
# :singleton-method: pdf(k , l)
|
|
20
|
+
# PDF for Poisson distribution,
|
|
21
|
+
# [+k+] is the number of occurrences of an event
|
|
22
|
+
# [+l+] is a positive real number, equal to the expected number of occurrences that occur during the given interval.
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
# :singleton-method: cdf(k , l)
|
|
26
|
+
# CDF for Poisson distribution
|
|
27
|
+
# [+k+] is the number of occurrences of an event
|
|
28
|
+
# [+l+] is a positive real number, equal to the expected number of occurrences that occur during the given interval.
|
|
29
|
+
|
|
30
|
+
# TODO: Not implemented yet
|
|
31
|
+
# :singleton-method: p_value(pr , l)
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Distribution
|
|
2
|
+
module Poisson
|
|
3
|
+
module Ruby_
|
|
4
|
+
class << self
|
|
5
|
+
def pdf(k,l )
|
|
6
|
+
(l**k*Math.exp(-l)).quo(Math.factorial(k))
|
|
7
|
+
end
|
|
8
|
+
def cdf(k,l)
|
|
9
|
+
Math.exp(-l)*(0..k).inject(0) {|ac,i| ac+ (l**i).quo(Math.factorial(i))}
|
|
10
|
+
end
|
|
11
|
+
def p_value(prob,l)
|
|
12
|
+
ac=0
|
|
13
|
+
(0..100).each do |i|
|
|
14
|
+
ac+=pdf(i,l)
|
|
15
|
+
return i if prob<=ac
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/spec/binomial_spec.rb
CHANGED
|
@@ -51,6 +51,14 @@ end
|
|
|
51
51
|
pending("No exact_p_value")
|
|
52
52
|
@engine.should respond_to(:exact_p_value)
|
|
53
53
|
}
|
|
54
|
+
it "exact_cdf should return same values as cdf for n=50" do
|
|
55
|
+
pr=rand()*0.8+0.1
|
|
56
|
+
n=rand(10)+10
|
|
57
|
+
[1,(n/2).to_i,n-1].each do |k|
|
|
58
|
+
|
|
59
|
+
@engine.exact_cdf(k,n,pr).should be_within(1e-10).of(@engine.cdf(k,n,pr))
|
|
60
|
+
end
|
|
61
|
+
end
|
|
54
62
|
|
|
55
63
|
it "exact_pdf should not return a Float if not float is used as parameter" do
|
|
56
64
|
@engine.exact_pdf(1,1,1).should_not be_a(Float)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb")
|
|
2
|
+
|
|
3
|
+
describe Distribution::Exponential do
|
|
4
|
+
|
|
5
|
+
shared_examples_for "exponential engine" do
|
|
6
|
+
it "should return correct pdf" do
|
|
7
|
+
if @engine.respond_to? :pdf
|
|
8
|
+
[0.5,1,1.5].each {|l|
|
|
9
|
+
1.upto(5) {|x|
|
|
10
|
+
@engine.pdf(x,l).should be_within(1e-10).of(l*Math.exp(-l*x))
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
else
|
|
14
|
+
pending("No #{@engine}.pdf")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should return correct cdf" do
|
|
19
|
+
if @engine.respond_to? :cdf
|
|
20
|
+
[0.5,1,1.5].each {|l|
|
|
21
|
+
1.upto(5) {|x|
|
|
22
|
+
@engine.cdf(x,l).should be_within(1e-10).of(1-Math.exp(-l*x))
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
else
|
|
26
|
+
pending("No #{@engine}.cdf")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
it "should return correct p_value" do
|
|
32
|
+
if @engine.respond_to? :p_value
|
|
33
|
+
[0.5,1,1.5].each {|l|
|
|
34
|
+
1.upto(5) {|x|
|
|
35
|
+
pr=@engine.cdf(x,l)
|
|
36
|
+
@engine.p_value(pr,l).should be_within(1e-10).of(x)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else
|
|
40
|
+
pending("No #{@engine}.p_value")
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
describe "singleton" do
|
|
47
|
+
before do
|
|
48
|
+
@engine=Distribution::Exponential
|
|
49
|
+
end
|
|
50
|
+
it_should_behave_like "exponential engine"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
describe Distribution::Exponential::Ruby_ do
|
|
54
|
+
before do
|
|
55
|
+
@engine=Distribution::Exponential::Ruby_
|
|
56
|
+
end
|
|
57
|
+
it_should_behave_like "exponential engine"
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
if Distribution.has_gsl?
|
|
62
|
+
describe Distribution::Exponential::GSL_ do
|
|
63
|
+
before do
|
|
64
|
+
@engine=Distribution::Exponential::GSL_
|
|
65
|
+
end
|
|
66
|
+
it_should_behave_like "exponential engine"
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# if Distribution.has_java?
|
|
71
|
+
# describe Distribution::Exponential::Java_ do
|
|
72
|
+
# before do
|
|
73
|
+
# @engine=Distribution::Exponential::Java_
|
|
74
|
+
# end
|
|
75
|
+
# it_should_behave_like "exponential engine"
|
|
76
|
+
#
|
|
77
|
+
# end
|
|
78
|
+
# end
|
|
79
|
+
|
|
80
|
+
end
|
data/spec/math_extension_spec.rb
CHANGED
|
@@ -8,13 +8,7 @@ describe Distribution::MathExtension do
|
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
[1,5,10,25,48].each {|n|
|
|
14
|
-
k=(n/2).to_i
|
|
15
|
-
Math.binomial_coefficient_gamma(n,k).round.should eq(Math.binomial_coefficient(n,k))
|
|
16
|
-
}
|
|
17
|
-
end
|
|
11
|
+
|
|
18
12
|
it "rising_factorial should return correct values" do
|
|
19
13
|
|
|
20
14
|
x=rand(10)+1
|
|
@@ -25,6 +19,17 @@ describe Distribution::MathExtension do
|
|
|
25
19
|
Math.rising_factorial(x,4).should eq x**4+6*x**3+11*x**2+6*x
|
|
26
20
|
|
|
27
21
|
end
|
|
22
|
+
|
|
23
|
+
it "permutations should return correct values" do
|
|
24
|
+
n=rand(50)+50
|
|
25
|
+
10.times { |k|
|
|
26
|
+
Math.permutations(n,k).should eq(Math.factorial(n) / Math.factorial(n-k))
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
Math.permutations(n,n).should eq(Math.factorial(n) / Math.factorial(n-n))
|
|
31
|
+
end
|
|
32
|
+
|
|
28
33
|
it "incomplete beta function should return similar results to R" do
|
|
29
34
|
pending("Not working yet")
|
|
30
35
|
Math.incomplete_beta(0.5,5,6).should be_within(1e-6).of(Math.beta(5,6)*0.6230469)
|
|
@@ -46,12 +51,22 @@ describe Distribution::MathExtension do
|
|
|
46
51
|
|
|
47
52
|
|
|
48
53
|
end
|
|
49
|
-
|
|
54
|
+
|
|
55
|
+
it "binomial coefficient(gamma) with n<=48 should be correct " do
|
|
56
|
+
|
|
57
|
+
[1,5,10,25,48].each {|n|
|
|
58
|
+
k=(n/2).to_i
|
|
59
|
+
Math.binomial_coefficient_gamma(n,k).round.should eq(Math.binomial_coefficient(n,k))
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "binomial coefficient(gamma) with 48<n<1000 should have 11 correct digits" do
|
|
50
64
|
|
|
51
|
-
[50,100,1000].each {|n|
|
|
52
|
-
k=n/2.to_i
|
|
53
|
-
obs=Math.binomial_coefficient_gamma(n,k).to_i.to_s[0,
|
|
54
|
-
exp=Math.binomial_coefficient(n,k).to_i.to_s[0,
|
|
65
|
+
[50,100,200,1000].each {|n|
|
|
66
|
+
k=(n/2).to_i
|
|
67
|
+
obs=Math.binomial_coefficient_gamma(n, k).to_i.to_s[0,11]
|
|
68
|
+
exp=Math.binomial_coefficient(n, k).to_i.to_s[0,11]
|
|
69
|
+
|
|
55
70
|
obs.should eq(exp)
|
|
56
71
|
}
|
|
57
72
|
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb")
|
|
2
|
+
include ExampleWithGSL
|
|
3
|
+
describe Distribution::Poisson do
|
|
4
|
+
|
|
5
|
+
shared_examples_for "poisson engine" do
|
|
6
|
+
it "should return correct pdf" do
|
|
7
|
+
if @engine.respond_to? :pdf
|
|
8
|
+
[0.5,1,1.5].each {|l|
|
|
9
|
+
1.upto(5) {|k|
|
|
10
|
+
@engine.pdf(k,l).should be_within(1e-10).of((l**k*Math.exp(-l)).quo(Math.factorial(k)))
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
else
|
|
14
|
+
pending("No #{@engine}.pdf")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it_only_with_gsl "should return correct cdf" do
|
|
19
|
+
if @engine.respond_to? :cdf
|
|
20
|
+
[0.5,1,1.5,4,10].each {|l|
|
|
21
|
+
1.upto(5) {|k|
|
|
22
|
+
@engine.cdf(k,l).should be_within(1e-10).of(GSL::Cdf.poisson_P(k,l))
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
else
|
|
27
|
+
pending("No #{@engine}.cdf")
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
it "should return correct p_value" do
|
|
33
|
+
pending("No exact p_value")
|
|
34
|
+
if @engine.respond_to? :p_value
|
|
35
|
+
[0.1,1,5,10].each {|l|
|
|
36
|
+
1.upto(20) {|k|
|
|
37
|
+
pr=@engine.cdf(k,l)
|
|
38
|
+
@engine.p_value(pr,l).should eq(k)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else
|
|
42
|
+
pending("No #{@engine}.p_value")
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
describe "singleton" do
|
|
49
|
+
before do
|
|
50
|
+
@engine=Distribution::Poisson
|
|
51
|
+
end
|
|
52
|
+
it_should_behave_like "poisson engine"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe Distribution::Poisson::Ruby_ do
|
|
56
|
+
before do
|
|
57
|
+
@engine=Distribution::Poisson::Ruby_
|
|
58
|
+
end
|
|
59
|
+
it_should_behave_like "poisson engine"
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe Distribution::Poisson::GSL_ do
|
|
64
|
+
before do
|
|
65
|
+
@engine=Distribution::Poisson::GSL_
|
|
66
|
+
end
|
|
67
|
+
it_should_behave_like "poisson engine"
|
|
68
|
+
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
end
|
metadata
CHANGED
|
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
|
4
4
|
prerelease: false
|
|
5
5
|
segments:
|
|
6
6
|
- 0
|
|
7
|
-
-
|
|
7
|
+
- 4
|
|
8
8
|
- 0
|
|
9
|
-
version: 0.
|
|
9
|
+
version: 0.4.0
|
|
10
10
|
platform: ruby
|
|
11
11
|
authors:
|
|
12
12
|
- Claudio Bustos
|
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
|
35
35
|
rpP0jjs0
|
|
36
36
|
-----END CERTIFICATE-----
|
|
37
37
|
|
|
38
|
-
date: 2011-01
|
|
38
|
+
date: 2011-02-01 00:00:00 -03:00
|
|
39
39
|
default_executable:
|
|
40
40
|
dependencies:
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
@@ -96,10 +96,11 @@ dependencies:
|
|
|
96
96
|
type: :development
|
|
97
97
|
version_requirements: *id004
|
|
98
98
|
description: |-
|
|
99
|
-
Statistical Distributions
|
|
99
|
+
Statistical Distributions library. Includes Normal univariate and bivariate, T, F, Chi Square, Binomial, Hypergeometric, Exponential and Poisson.
|
|
100
|
+
|
|
100
101
|
Uses Ruby by default and C (statistics2/GSL) or Java extensions where available.
|
|
101
102
|
|
|
102
|
-
Includes code from statistics2
|
|
103
|
+
Includes code from statistics2 on Normal, T, F and Chi Square ruby code [http://blade.nagaokaut.ac.jp/~sinara/ruby/math/statistics2]
|
|
103
104
|
email:
|
|
104
105
|
- clbustos_at_gmail.com
|
|
105
106
|
executables:
|
|
@@ -117,9 +118,17 @@ files:
|
|
|
117
118
|
- README.txt
|
|
118
119
|
- Rakefile
|
|
119
120
|
- benchmark/binomial_coefficient.rb
|
|
121
|
+
- benchmark/binomial_coefficient/binomial_coefficient.ds
|
|
122
|
+
- benchmark/binomial_coefficient/binomial_coefficient.xls
|
|
123
|
+
- benchmark/binomial_coefficient/experiment.rb
|
|
124
|
+
- benchmark/factorial_hash.rb
|
|
120
125
|
- benchmark/factorial_method.rb
|
|
121
126
|
- benchmark/odd.rb
|
|
122
127
|
- bin/distribution
|
|
128
|
+
- data/template/distribution.erb
|
|
129
|
+
- data/template/distribution/gsl.erb
|
|
130
|
+
- data/template/distribution/ruby.erb
|
|
131
|
+
- data/template/spec.erb
|
|
123
132
|
- lib/distribution.rb
|
|
124
133
|
- lib/distribution/binomial.rb
|
|
125
134
|
- lib/distribution/binomial/gsl.rb
|
|
@@ -135,6 +144,9 @@ files:
|
|
|
135
144
|
- lib/distribution/chisquare/java.rb
|
|
136
145
|
- lib/distribution/chisquare/ruby.rb
|
|
137
146
|
- lib/distribution/chisquare/statistics2.rb
|
|
147
|
+
- lib/distribution/exponential.rb
|
|
148
|
+
- lib/distribution/exponential/gsl.rb
|
|
149
|
+
- lib/distribution/exponential/ruby.rb
|
|
138
150
|
- lib/distribution/f.rb
|
|
139
151
|
- lib/distribution/f/gsl.rb
|
|
140
152
|
- lib/distribution/f/java.rb
|
|
@@ -151,6 +163,9 @@ files:
|
|
|
151
163
|
- lib/distribution/normal/ruby.rb
|
|
152
164
|
- lib/distribution/normal/statistics2.rb
|
|
153
165
|
- lib/distribution/normalmultivariate.rb
|
|
166
|
+
- lib/distribution/poisson.rb
|
|
167
|
+
- lib/distribution/poisson/gsl.rb
|
|
168
|
+
- lib/distribution/poisson/ruby.rb
|
|
154
169
|
- lib/distribution/t.rb
|
|
155
170
|
- lib/distribution/t/gsl.rb
|
|
156
171
|
- lib/distribution/t/java.rb
|
|
@@ -160,10 +175,12 @@ files:
|
|
|
160
175
|
- spec/bivariatenormal_spec.rb
|
|
161
176
|
- spec/chisquare_spec.rb
|
|
162
177
|
- spec/distribution_spec.rb
|
|
178
|
+
- spec/exponential_spec.rb
|
|
163
179
|
- spec/f_spec.rb
|
|
164
180
|
- spec/hypergeometric_spec.rb
|
|
165
181
|
- spec/math_extension_spec.rb
|
|
166
182
|
- spec/normal_spec.rb
|
|
183
|
+
- spec/poisson_spec.rb
|
|
167
184
|
- spec/shorthand_spec.rb
|
|
168
185
|
- spec/spec.opts
|
|
169
186
|
- spec/spec_helper.rb
|
|
@@ -200,6 +217,6 @@ rubyforge_project: distribution
|
|
|
200
217
|
rubygems_version: 1.3.7
|
|
201
218
|
signing_key:
|
|
202
219
|
specification_version: 3
|
|
203
|
-
summary: Statistical Distributions
|
|
220
|
+
summary: Statistical Distributions library
|
|
204
221
|
test_files: []
|
|
205
222
|
|
metadata.gz.sig
CHANGED
|
Binary file
|