distribution 0.1.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.
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
+