distribution 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.autotest +23 -0
  3. data/History.txt +3 -0
  4. data/Manifest.txt +39 -0
  5. data/README.txt +71 -0
  6. data/Rakefile +19 -0
  7. data/bin/distribution +3 -0
  8. data/lib/distribution.rb +148 -0
  9. data/lib/distribution/bivariatenormal.rb +25 -0
  10. data/lib/distribution/bivariatenormal/gsl.rb +11 -0
  11. data/lib/distribution/bivariatenormal/ruby.rb +281 -0
  12. data/lib/distribution/bivariatenormal/statistics2.rb +0 -0
  13. data/lib/distribution/chisquare.rb +29 -0
  14. data/lib/distribution/chisquare/gsl.rb +27 -0
  15. data/lib/distribution/chisquare/ruby.rb +85 -0
  16. data/lib/distribution/chisquare/statistics2.rb +21 -0
  17. data/lib/distribution/f.rb +28 -0
  18. data/lib/distribution/f/gsl.rb +28 -0
  19. data/lib/distribution/f/ruby.rb +117 -0
  20. data/lib/distribution/f/statistics2.rb +26 -0
  21. data/lib/distribution/math_extension.rb +72 -0
  22. data/lib/distribution/normal.rb +36 -0
  23. data/lib/distribution/normal/gsl.rb +24 -0
  24. data/lib/distribution/normal/ruby.rb +99 -0
  25. data/lib/distribution/normal/statistics2.rb +14 -0
  26. data/lib/distribution/normalmultivariate.rb +73 -0
  27. data/lib/distribution/t.rb +27 -0
  28. data/lib/distribution/t/gsl.rb +29 -0
  29. data/lib/distribution/t/ruby.rb +105 -0
  30. data/lib/distribution/t/statistics2.rb +28 -0
  31. data/spec/bivariatenormal_spec.rb +63 -0
  32. data/spec/chisquare_spec.rb +89 -0
  33. data/spec/distribution_spec.rb +19 -0
  34. data/spec/f_spec.rb +107 -0
  35. data/spec/normal_spec.rb +105 -0
  36. data/spec/shorthand_function.rb +6 -0
  37. data/spec/shorthand_spec.rb +14 -0
  38. data/spec/spec.opts +3 -0
  39. data/spec/spec_helper.rb +23 -0
  40. data/spec/t_spec.rb +98 -0
  41. metadata +160 -0
  42. metadata.gz.sig +1 -0
File without changes
@@ -0,0 +1,29 @@
1
+ require 'distribution/chisquare/ruby'
2
+ require 'distribution/chisquare/gsl'
3
+ require 'distribution/chisquare/statistics2'
4
+ module Distribution
5
+ # Calculate cdf and inverse cdf for Chi Square Distribution.
6
+ #
7
+ module ChiSquare
8
+ extend Distributable
9
+ SHORTHAND='chisq'
10
+ create_distribution_methods
11
+
12
+ ##
13
+ # :singleton-method: pdf(x)
14
+ # Returns PDF of of Chi-squared distribution
15
+ # with +k+ degrees of freedom
16
+
17
+
18
+ ##
19
+ # :singleton-method: cdf(x,k)
20
+ # Returns the integral of Chi-squared distribution
21
+ # with +k+ degrees of freedom over [0, +x+]
22
+
23
+ ##
24
+ # :singleton-method: p_value(qn, k)
25
+ # Return the P-value of the corresponding integral +qn+ with
26
+ # +k+ degrees of freedom
27
+
28
+ end
29
+ end
@@ -0,0 +1,27 @@
1
+ module Distribution
2
+ module ChiSquare
3
+ module GSL_
4
+ class << self
5
+ def rng(k,seed=nil)
6
+
7
+ end
8
+ def pdf(x,k)
9
+ GSL::Ran::chisq_pdf(x,k)
10
+ end
11
+ # Return the P-value of the corresponding integral with
12
+ # k degrees of freedom
13
+ def p_value(pr,k)
14
+ GSL::Cdf::chisq_Pinv(pr,k)
15
+ end
16
+ # Chi-square cumulative distribution function (cdf).
17
+ #
18
+ # Returns the integral of Chi-squared distribution
19
+ # with k degrees of freedom over [0, x]
20
+ #
21
+ def cdf(x, k)
22
+ GSL::Cdf::chisq_P(x,k)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,85 @@
1
+ module Distribution
2
+ module ChiSquare
3
+ module Ruby_
4
+ class << self
5
+
6
+ include Distribution::MathExtension
7
+
8
+ def pdf(x,n)
9
+ if n == 1
10
+ 1.0/Math.sqrt(2 * Math::PI * x) * Math::E**(-x/2.0)
11
+ elsif n == 2
12
+ 0.5 * Math::E**(-x/2.0)
13
+ else
14
+ n = n.to_f
15
+ n2 = n/2
16
+ x = x.to_f
17
+ 1.0 / 2**n2 / gamma(n2) * x**(n2 - 1.0) * Math.exp(-x/2.0)
18
+ end
19
+ end
20
+
21
+
22
+ # CDF Inverse over [x, \infty)
23
+ # Pr([x, \infty)) = y -> x
24
+ def pchi2(n, y)
25
+ if n == 1
26
+
27
+ w = Distribution::Normal.p_value(1 - y/2) # = p1.0-Distribution::Normal.cdf(y/2)
28
+ w * w
29
+ elsif n == 2
30
+ # v = (1.0 / y - 1.0) / 33.0
31
+ # newton_a(y, v) {|x| [q_chi2(n, x), -chi2dens(n, x)] }
32
+ -2.0 * Math.log(y)
33
+ else
34
+ eps = 1.0e-5
35
+ v = 0.0
36
+ s = 10.0
37
+ loop do
38
+ v += s
39
+ if s <= eps then break end
40
+ if (qe = q_chi2(n, v) - y) == 0.0 then break end
41
+ if qe < 0.0
42
+ v -= s
43
+ s /= 10.0 #/
44
+ end
45
+ end
46
+ v
47
+ end
48
+ end
49
+ def p_value(pr,k)
50
+ pchi2(k, 1.0-pr)
51
+ end
52
+ def cdf(x,k)
53
+ 1.0-q_chi2(k,x)
54
+ end
55
+
56
+ # chi-square distribution ([1])
57
+ # Integral over [x, \infty)
58
+ def q_chi2(df, chi2)
59
+ chi2 = chi2.to_f
60
+ if (df & 1) != 0
61
+ chi = Math.sqrt(chi2)
62
+ if (df == 1) then return 2 * (1.0-Distribution::Normal.cdf(chi)); end
63
+ s = t = chi * Math.exp(-0.5 * chi2) / SQ2PI
64
+ k = 3
65
+ while k < df
66
+ t *= chi2 / k; s += t;
67
+ k += 2
68
+ end
69
+ 2 * (1.0-(Distribution::Normal.cdf(chi)) + s)
70
+ else
71
+ s = t = Math.exp(-0.5 * chi2)
72
+ k = 2
73
+ while k < df
74
+ t *= chi2 / k; s += t;
75
+ k += 2
76
+ end
77
+ s
78
+ end
79
+ end
80
+
81
+
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,21 @@
1
+ module Distribution
2
+ module ChiSquare
3
+ module Statistics2_
4
+ class << self
5
+ # Return the P-value of the corresponding integral with
6
+ # k degrees of freedom
7
+ def p_value(pr,k)
8
+ Statistics2.pchi2X_(k.to_i, pr)
9
+ end
10
+ # Chi-square cumulative distribution function (cdf).
11
+ #
12
+ # Returns the integral of Chi-squared distribution
13
+ # with k degrees of freedom over [0, x]
14
+ #
15
+ def cdf(x, k)
16
+ Statistics2.chi2dist(k.to_i,x)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,28 @@
1
+ require 'distribution/f/ruby'
2
+ require 'distribution/f/gsl'
3
+ require 'distribution/f/statistics2'
4
+ module Distribution
5
+ # Calculate cdf and inverse cdf for Chi Square Distribution.
6
+ #
7
+ module F
8
+ SHORTHAND='f'
9
+ extend Distributable
10
+ create_distribution_methods
11
+
12
+ ##
13
+ # :singleton-method: pdf(x,k1,k2)
14
+ # Returns the PDF of F distribution
15
+ # with +k1+ and +k2+ degrees of freedom over [0, +x+]
16
+
17
+ ##
18
+ # :singleton-method: p_value(qn, k1, k2)
19
+ # Return the P-value of the corresponding integral +qn+ with
20
+ # +k1+ and +k2+ degrees of freedom
21
+
22
+ ##
23
+ # :singleton-method: cdf(x,k1,k2)
24
+ # Returns the integral of F distribution
25
+ # with +k1+ and +k2+ degrees of freedom over [0, +x+]
26
+
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ module Distribution
2
+ module F
3
+ module GSL_
4
+ class << self
5
+ def pdf(x,k1,k2)
6
+ GSL::Ran.fdist_pdf(x,k1,k2)
7
+ end
8
+ # Return the P-value of the corresponding integral with
9
+ # k degrees of freedom
10
+ #
11
+ # Distribution::F.p_value(0.95,1,2)
12
+ def p_value(pr,k1,k2)
13
+ GSL::Cdf.fdist_Pinv(pr,k1,k2)
14
+ end
15
+ # F cumulative distribution function (cdf).
16
+ #
17
+ # Returns the integral of F-distribution
18
+ # with k1 and k2 degrees of freedom
19
+ # over [0, x].
20
+ # Distribution::F.cdf(20,3,2)
21
+ #
22
+ def cdf(x, k1, k2)
23
+ GSL::Cdf.fdist_P(x.to_f,k1,k2)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,117 @@
1
+ module Distribution
2
+ module F
3
+ module Ruby_
4
+ class << self
5
+
6
+ def c_pdf(f,df)
7
+ Distribution::ChiSquare.pdf(f,df)
8
+ end
9
+ def pdf(x,d1,d2)
10
+ Math.sqrt(((d1*x)**d1*(d2**d2)).quo((d1*x+d2)**(d1+d2))).quo( x*Math.beta(d1/2.0, d2/2.0))
11
+ end
12
+ # F-distribution ([1])
13
+ # Integral over [x, \infty)
14
+ def q_f(df1, df2, f)
15
+ if (f <= 0.0) then return 1.0; end
16
+ if (df1 % 2 != 0 && df2 % 2 == 0)
17
+ return 1.0 - q_f(df2, df1, 1.0 / f)
18
+ end
19
+ cos2 = 1.0 / (1.0 + df1.to_f * f / df2.to_f)
20
+ sin2 = 1.0 - cos2
21
+
22
+ if (df1 % 2 == 0)
23
+ prob = cos2 ** (df2.to_f / 2.0)
24
+ temp = prob
25
+ i = 2
26
+ while i < df1
27
+ temp *= (df2.to_f + i - 2) * sin2 / i
28
+ prob += temp
29
+ i += 2
30
+ end
31
+ return prob
32
+ end
33
+ prob = Math.atan(Math.sqrt(df2.to_f / (df1.to_f * f)))
34
+ temp = Math.sqrt(sin2 * cos2)
35
+ i = 3
36
+ while i <= df1
37
+ prob += temp
38
+ temp *= (i - 1).to_f * sin2 / i.to_f;
39
+ i += 2.0
40
+ end
41
+ temp *= df1.to_f
42
+ i = 3
43
+ while i <= df2
44
+ prob -= temp
45
+ temp *= (df1.to_f + i - 2) * cos2 / i.to_f
46
+ i += 2
47
+ end
48
+ prob * 2.0 / Math::PI
49
+ end
50
+
51
+ # inverse of F-distribution ([2])
52
+ def pfsub(x, y, z)
53
+ (Math.sqrt(z) - y) / x / 2.0
54
+ end
55
+
56
+ # Inverse CDF
57
+ # [x, \infty)
58
+ def pf(q, n1, n2)
59
+ if(q < 0.0 || q > 1.0 || n1 < 1 || n2 < 1)
60
+ $stderr.printf("Error : Illegal parameter in pf()!\n")
61
+ return 0.0
62
+ end
63
+
64
+ if n1 <= 240 || n2 <= 240
65
+ eps = 1.0e-5
66
+ if(n2 == 1) then eps = 1.0e-4 end
67
+ fw = 0.0
68
+ s = 1000.0
69
+ loop do
70
+ fw += s
71
+ if s <= eps then return fw end
72
+ if (qe = q_f(n1, n2, fw) - q) == 0.0 then return fw end
73
+ if qe < 0.0
74
+ fw -= s
75
+ s /= 10.0 #/
76
+ end
77
+ end
78
+ end
79
+
80
+ eps = 1.0e-6
81
+ qn = q
82
+ if q < 0.5 then qn = 1.0 - q
83
+ u = pnorm(qn)
84
+ w1 = 2.0 / n1 / 9.0
85
+ w2 = 2.0 / n2 / 9.0
86
+ w3 = 1.0 - w1
87
+ w4 = 1.0 - w2
88
+ u2 = u * u
89
+ a = w4 * w4 - u2 * w2
90
+ b = -2. * w3 * w4
91
+ c = w3 * w3 - u2 * w1
92
+ d = b * b - 4 * a * c
93
+ if(d < 0.0)
94
+ fw = pfsub(a, b, 0.0)
95
+ else
96
+ if(a.abs > eps)
97
+ fw = pfsub(a, b, d)
98
+ else
99
+ if(b.abs > eps) then return -c / b end
100
+ fw = pfsub(a, b, 0.0)
101
+ end
102
+ end
103
+ fw * fw * fw
104
+ end
105
+ end
106
+ # F-distribution interface
107
+ def cdf(f,n1, n2)
108
+ 1.0 - q_f(n1, n2, f)
109
+ end
110
+ def p_value(y, n1, n2)
111
+ pf(1.0 - y, n1, n2)
112
+ end
113
+
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,26 @@
1
+ module Distribution
2
+ module F
3
+ module Statistics2_
4
+ class << self
5
+ # Return the P-value of the corresponding integral with
6
+ # k degrees of freedom
7
+ #
8
+ # Distribution::F.p_value(0.95,1,2)
9
+ # Statistics2 have some problem with extreme values
10
+ def p_value(pr,k1,k2)
11
+ Statistics2.pfdist(k1,k2, pr)
12
+ end
13
+ # F cumulative distribution function (cdf).
14
+ #
15
+ # Returns the integral of F-distribution
16
+ # with k1 and k2 degrees of freedom
17
+ # over [0, x].
18
+ # Distribution::F.cdf(20,3,2)
19
+ #
20
+ def cdf(x, k1, k2)
21
+ Statistics2.fdist(k1, k2,x)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,72 @@
1
+ # Useful additions to Math
2
+ module Distribution
3
+ module MathExtension
4
+ # Factorial for n
5
+ def factorial(n)
6
+ sum=1
7
+ 2.upto(n) do |i|
8
+ sum*=n
9
+ end
10
+ sum
11
+ end
12
+
13
+ # Beta function.
14
+ # Source:
15
+ # * http://mathworld.wolfram.com/BetaFunction.html
16
+ def beta(x,y)
17
+ (gamma(x)*gamma(y)).quo(gamma(x+y))
18
+ end
19
+
20
+ LOG_2PI = Math.log(2 * Math::PI)# log(2PI)
21
+ N = 8
22
+ B0 = 1.0
23
+ B1 = -1.0 / 2.0
24
+ B2 = 1.0 / 6.0
25
+ B4 = -1.0 / 30.0
26
+ B6 = 1.0 / 42.0
27
+ B8 = -1.0 / 30.0
28
+ B10 = 5.0 / 66.0
29
+ B12 = -691.0 / 2730.0
30
+ B14 = 7.0 / 6.0
31
+ B16 = -3617.0 / 510.0
32
+ # From statistics2
33
+ def loggamma(x)
34
+ v = 1.0
35
+ while (x < N)
36
+ v *= x
37
+ x += 1.0
38
+ end
39
+ w = 1.0 / (x * x)
40
+ ret = B16 / (16 * 15)
41
+ ret = ret * w + B14 / (14 * 13)
42
+ ret = ret * w + B12 / (12 * 11)
43
+ ret = ret * w + B10 / (10 * 9)
44
+ ret = ret * w + B8 / ( 8 * 7)
45
+ ret = ret * w + B6 / ( 6 * 5)
46
+ ret = ret * w + B4 / ( 4 * 3)
47
+ ret = ret * w + B2 / ( 2 * 1)
48
+ ret = ret / x + 0.5 * LOG_2PI - Math.log(v) - x + (x - 0.5) * Math.log(x)
49
+ ret
50
+ end
51
+ # Gamma function.
52
+ # From statistics2
53
+ def gamma(x)
54
+ if (x < 0.0)
55
+ return Math::PI / (Math.sin(Math.PI * x) * Math.exp(loggamma(1 - x))) #/
56
+ end
57
+ Math.exp(loggamma(x))
58
+ end
59
+ end
60
+ end
61
+
62
+ module Math
63
+ include Distribution::MathExtension
64
+ module_function :factorial, :beta, :gamma
65
+ end
66
+
67
+ # Necessary on Ruby 1.9
68
+ module CMath # :nodoc:
69
+ include Distribution::MathExtension
70
+ module_function :factorial, :beta, :gamma
71
+ end
72
+