rubystats 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,7 @@
1
+ === 0.2.3 / 2008-07-06
2
+ * Fixing bug #21100 - problem with Beta distribution calculations when p and q values are small.
3
+ * Minor code cleanup for readability in a few places.
4
+
1
5
  === 0.2.2 / 2008-05-09
2
6
  * Added exponential distribution class
3
7
  * Replaced constants in NumericalConstants module with uppercase versions to follow Ruby convention
data/README.txt CHANGED
@@ -49,11 +49,11 @@ Also includes Fisher's Exact Test
49
49
  == SYNOPSIS:
50
50
  === Example: normal distribution with mean of 10 and standard deviation of 2
51
51
 
52
- norm = Rubystats::NormalDistribution.new(10, 2)
53
- cdf = norm.cdf(11)
54
- pdf = norm.pdf(11)
55
- puts "CDF(11): #{cdf}"
56
- puts "PDF(11): #{pdf}"
52
+ norm = Rubystats::NormalDistribution.new(10, 2)
53
+ cdf = norm.cdf(11)
54
+ pdf = norm.pdf(11)
55
+ puts "CDF(11): #{cdf}"
56
+ puts "PDF(11): #{pdf}"
57
57
 
58
58
  Output:
59
59
  CDF(11): 0.691462461274013
@@ -61,10 +61,10 @@ Output:
61
61
 
62
62
  === Example: get some random numbers from a normal distribution
63
63
 
64
- puts "Random numbers from normal distribution:"
65
- 10.times do
66
- puts norm.rng
67
- end
64
+ puts "Random numbers from normal distribution:"
65
+ 10.times do
66
+ puts norm.rng
67
+ end
68
68
 
69
69
  (sample) Output:
70
70
 
data/Rakefile CHANGED
@@ -4,6 +4,7 @@ require 'rubygems'
4
4
  require 'hoe'
5
5
  $:.unshift(File.dirname(__FILE__) + "/lib")
6
6
  require 'rubystats'
7
+ #require './lib/rubystats.rb'
7
8
 
8
9
  Hoe.new('rubystats', Rubystats::VERSION) do |p|
9
10
  p.name = "rubystats"
@@ -16,10 +17,15 @@ Hoe.new('rubystats', Rubystats::VERSION) do |p|
16
17
  p.remote_rdoc_dir = '' # Release to root
17
18
  end
18
19
 
19
- rule '' do |t|
20
- system "cd test && ruby ts_stats.rb"
20
+ desc "Run all tests"
21
+ task :test do
22
+ Rake::TestTask.new("test") do |t|
23
+ t.test_files = FileList['test/tc*.rb']
24
+ t.verbose = false
25
+ end
21
26
  end
22
27
 
28
+ #Use Allison template if available
23
29
  ALLISON = "/opt/local/lib/ruby/gems/1.8/gems/allison-2.0.3/lib/allison.rb"
24
30
 
25
31
  Rake::RDocTask.new do |rd|
@@ -1,5 +1,5 @@
1
1
  module Rubystats
2
- VERSION = '0.2.2'
2
+ VERSION = '0.2.3'
3
3
  end
4
4
 
5
5
  require 'rubystats/normal_distribution'
@@ -10,7 +10,7 @@ module Rubystats
10
10
  #dgr_q = degrees of freedom q
11
11
  def initialize(dgr_p, dgr_q)
12
12
  if dgr_p <= 0 || dgr_q <= 0
13
- return nil
13
+ raise ArgumentError.new("Paramters must be greater than zero.")
14
14
  end
15
15
  @p = dgr_p.to_f
16
16
  @q = dgr_q.to_f
@@ -41,8 +41,9 @@ module Rubystats
41
41
  if (x == 0.0) || (x == 1.0)
42
42
  return 0.0
43
43
  else
44
- return Math.exp( - log_beta(@p, @q) + (@p - 1.0) * Math.log(x) + (@q - 1.0) * Math.log(1.0 - x)
45
- )
44
+ return Math.exp( -1.0 * log_beta(@p, @q) +
45
+ (@p - 1.0) * Math.log(x) +
46
+ (@q - 1.0) * Math.log(1.0 - x))
46
47
  end
47
48
  end
48
49
  end
@@ -36,26 +36,26 @@ module Rubystats
36
36
 
37
37
  include Rubystats::NumericalConstants
38
38
 
39
- @logGAMMACache_res = 0.0
40
- @logGAMMACache_x = 0.0
41
- @logBetaCache_res = 0.0
42
- @logBetaCache_p = 0.0
43
- @logBetaCache_q = 0.0
39
+ @log_gamma_cache_res = 0.0
40
+ @log_gamma_cache_x = 0.0
41
+ @log_beta_cache_res = 0.0
42
+ @log_beta_cache_p = 0.0
43
+ @log_beta_cache_q = 0.0
44
44
 
45
45
  def log_beta(p,q)
46
- if p != @logBetaCache_p || q != @logBetaCache_q
47
- logBetaCache_p = p
48
- logBetaCache_q = q
49
- if p <= 0.0 || q <= 0.0 || (p + q) > LOG_GAMMA_X_MAX_VALUE
50
- logBetaCache_res = 0.0
46
+ if p != @log_beta_cache_p || q != @log_beta_cache_q
47
+ @log_beta_cache_p = p
48
+ @log_beta_cache_q = q
49
+ if (p <= 0.0) || (q <= 0.0) || (p + q) > LOG_GAMMA_X_MAX_VALUE
50
+ @log_beta_cache_res = 0.0
51
51
  else
52
- logBetaCache_res = log_gamma(p) + log_gamma(q) - log_gamma(p + q)
52
+ @log_beta_cache_res = log_gamma(p) + log_gamma(q) - log_gamma(p + q)
53
53
  end
54
- return logBetaCache_res
55
54
  end
55
+ return @log_beta_cache_res
56
56
  end
57
57
 
58
- # GAMMA function.
58
+ # Gamma function.
59
59
  # Based on public domain NETLIB (Fortran) code by W. J. Cody and L. Stoltz<BR>
60
60
  # Applied Mathematics Division<BR>
61
61
  # Argonne National Laboratory<BR>
@@ -68,9 +68,9 @@ module Rubystats
68
68
  # </OL></P><P>
69
69
  # From the original documentation:
70
70
  # </P><P>
71
- # This routine calculates the GAMMA function for a real argument X.
71
+ # This routine calculates the Gamma function for a real argument X.
72
72
  # Computation is based on an algorithm outlined in reference 1.
73
- # The program uses rational functions that approximate the GAMMA
73
+ # The program uses rational functions that approximate the Gamma
74
74
  # function to at least 20 significant decimal digits. Coefficients
75
75
  # for the approximation over the interval (1,2) are unpublished.
76
76
  # Those for the approximation for X .GE. 12 are from reference 2.
@@ -84,8 +84,8 @@ module Rubystats
84
84
  # </P>
85
85
  # Author:: Jaco van Kooten
86
86
 
87
- def GAMMA(x)
88
- # GAMMA related constants
87
+ def orig_gamma(x)
88
+ # Gamma related constants
89
89
  g_p = [ -1.71618513886549492533811, 24.7656508055759199108314,
90
90
  -379.804256470945635097577, 629.331155312818442661052,
91
91
  866.966202790413211295064, -31451.2729688483675254357,
@@ -97,11 +97,11 @@ module Rubystats
97
97
  g_c = [-0.001910444077728, 8.4171387781295e-4, -5.952379913043012e-4,
98
98
  7.93650793500350248e-4, -0.002777777777777681622553,
99
99
  0.08333333333333333331554247, 0.0057083835261 ]
100
- fact=1.0
101
- i=0
102
- n=0
103
- y=x
104
- parity=false
100
+ fact = 1.0
101
+ i = 0
102
+ n = 0
103
+ y = x
104
+ parity = false
105
105
  if y <= 0.0
106
106
  # ----------------------------------------------------------------------
107
107
  # Argument is negative
@@ -202,10 +202,31 @@ module Rubystats
202
202
  end
203
203
  end
204
204
 
205
- def log_gamma(x)
206
- logGAMMACache_res = @logGAMMACache_res
207
- logGAMMACache_x = @logGAMMACache_x
205
+ #TODO test this
206
+ def gamma(_x)
207
+ return 0 if _x == 0.0
208
+
209
+ p0 = 1.000000000190015
210
+ p = {1 => 76.18009172947146,
211
+ 2 => -86.50532032941677,
212
+ 3 => 24.01409824083091,
213
+ 4 => -1.231739572450155,
214
+ 5 => 1.208650973866179e-3,
215
+ 6 => -5.395239384953e-6}
216
+
217
+ y = x = _x
218
+ tmp = x + 5.5
219
+ tmp -= (x + 0.5) * Math.log(tmp)
220
+
221
+ summer = p0
222
+ for j in (1 ... 6)
223
+ y += 1
224
+ summer += (p[j] / y)
225
+ end
226
+ return Math.exp(0 - tmp + Math.log(2.5066282746310005 * summer / x))
227
+ end
208
228
 
229
+ def log_gamma(x)
209
230
  lg_d1 = -0.5772156649015328605195174
210
231
  lg_d2 = 0.4227843350984671393993777
211
232
  lg_d4 = 1.791759469228055000094023
@@ -251,12 +272,12 @@ module Rubystats
251
272
  -0.002777777777777681622553, 0.08333333333333333331554247,
252
273
  0.0057083835261 ]
253
274
 
254
- # Rough estimate of the fourth root of logGAMMA_xBig
275
+ # Rough estimate of the fourth root of logGamma_xBig
255
276
  lg_frtbig = 2.25e76
256
277
  pnt68 = 0.6796875
257
278
 
258
- if x == logGAMMACache_x
259
- return logGAMMACache_res
279
+ if x == @log_gamma_cache_x
280
+ return @log_gamma_cache_res
260
281
  end
261
282
 
262
283
  y = x
@@ -280,7 +301,7 @@ module Rubystats
280
301
  xnum = xnum * xm1 + lg_p1[i]
281
302
  xden = xden * xm1 + lg_q1[i]
282
303
  end
283
- res = corr * xm1 * (lg_d1 + xm1 * (xnum / xden))
304
+ res = corr + xm1 * (lg_d1 + xm1 * (xnum / xden))
284
305
  else
285
306
  xm2 = y - 1.0
286
307
  xden = 1.0
@@ -331,13 +352,13 @@ module Rubystats
331
352
  res = MAX_VALUE
332
353
  end
333
354
  # final adjustments and return
334
- logGAMMACache_x = x
335
- logGAMMACache_res = res
355
+ @log_gamma_cache_x = x
356
+ @log_gamma_cache_res = res
336
357
  return res
337
358
  end
338
359
 
339
360
 
340
- # Incomplete GAMMA function.
361
+ # Incomplete Gamma function.
341
362
  # The computation is based on approximations presented in
342
363
  # Numerical Recipes, Chapter 6.2 (W.H. Press et al, 1992).
343
364
  # @param a require a>=0
@@ -345,18 +366,18 @@ module Rubystats
345
366
  # @return 0 if x<0, a<=0 or a>2.55E305 to avoid errors and over/underflow
346
367
  # @author Jaco van Kooten
347
368
 
348
- def incomplete_GAMMA(a, x)
369
+ def incomplete_gamma(a, x)
349
370
  if x <= 0.0 || a <= 0.0 || a > LOG_GAMMA_X_MAX_VALUE
350
371
  return 0.0
351
372
  elsif x < (a + 1.0)
352
- return GAMMA_series_expansion(a, x)
373
+ return gamma_series_expansion(a, x)
353
374
  else
354
- return 1.0-GAMMA_fraction(a, x)
375
+ return 1.0-gamma_fraction(a, x)
355
376
  end
356
377
  end
357
378
 
358
379
  # Author:: Jaco van Kooten
359
- def GAMMA_series_expansion(a, x)
380
+ def gamma_series_expansion(a, x)
360
381
  ap = a
361
382
  del = 1.0 / a
362
383
  sum = del
@@ -372,7 +393,7 @@ module Rubystats
372
393
  end
373
394
 
374
395
  # Author:: Jaco van Kooten
375
- def GAMMA_fraction(a, x)
396
+ def gamma_fraction(a, x)
376
397
  b = x + 1.0 - a
377
398
  c = 1.0 / XMININ
378
399
  d = 1.0 / b
@@ -424,14 +445,13 @@ module Rubystats
424
445
  return 0.0
425
446
  elsif x >= 1.0
426
447
  return 1.0
427
- elsif p <= 0.0 || q <= 0.0 || (p + q) > LOG_GAMMA_X_MAX_VALUE
448
+ elsif (p <= 0.0) || (q <= 0.0) || (p + q) > LOG_GAMMA_X_MAX_VALUE
428
449
  return 0.0
429
450
  else
430
451
  beta_gam = Math.exp( -log_beta(p, q) + p * Math.log(x) + q * Math.log(1.0 - x) )
431
452
  if x < (p + 1.0) / (p + q + 2.0)
432
453
  return beta_gam * beta_fraction(x, p, q) / p
433
454
  else
434
- beta_frac = beta_fraction(1.0 - x, p, q)
435
455
  return 1.0 - (beta_gam * beta_fraction(1.0 - x, q, p) / q)
436
456
  end
437
457
  end
@@ -469,7 +489,7 @@ module Rubystats
469
489
  if c.abs < XMININ
470
490
  c = XMININ
471
491
  end
472
- frac *= h * c
492
+ frac *= (h * c)
473
493
  # odd index for d
474
494
  d = -(p + m) * (sum_pq + m) * x / ((p + m2) * (p_plus + m2))
475
495
  h = 1.0 + d * h
@@ -140,7 +140,7 @@ module Rubystats
140
140
  x = guess
141
141
  x_new = guess
142
142
  error = 0.0
143
- pdf = 0.0
143
+ _pdf = 0.0
144
144
  dx = 1000.0
145
145
  i = 0
146
146
  while ( dx.abs > accuracy && (i += 1) < max_iteration )
@@ -151,15 +151,15 @@ module Rubystats
151
151
  else
152
152
  x_hi = x
153
153
  end
154
- pdf = pdf(x)
155
- if pdf != 0.0
156
- dx = error / pdf
154
+ _pdf = pdf(x)
155
+ if _pdf != 0.0
156
+ dx = error / _pdf
157
157
  x_new = x -dx
158
158
  end
159
159
  # If the NR fails to converge (which for example may be the
160
160
  # case if the initial guess is too rough) we apply a bisection
161
161
  # step to determine a more narrow interval around the root.
162
- if x_new < x_lo || x_new > x_hi || pdf == 0.0
162
+ if x_new < x_lo || x_new > x_hi || _pdf == 0.0
163
163
  x_new = (x_lo + x_hi) / 2.0
164
164
  dx = x_new - x
165
165
  end
@@ -40,9 +40,26 @@ class TestBeta < Test::Unit::TestCase
40
40
  inv_cdf = beta.icdf(cdf)
41
41
  assert_in_delta(x, inv_cdf, 0.00000001)
42
42
  end
43
-
44
43
  end
45
44
 
45
+ def test_low_p_and_q_values
46
+ p = 1.5
47
+ q = 1.0
48
+ beta = Rubystats::BetaDistribution.new(p,q)
49
+
50
+ #from PHPExcel/PHPMath output
51
+ expected_icdf_vals = [
52
+ 0.096548938, 0.153261886, 0.200829885, 0.243288080, 0.282310809, 0.318797571, 0.353302082, 0.386195754, 0.417742995, 0.448140475, 0.477539492, 0.506059599, 0.533797339, 0.560832096, 0.587230146, 0.613047546, 0.638332246, 0.663125670, 0.687463910, 0.711378661, 0.734897945, 0.758046692, 0.780847206, 0.803319540, 0.825481812, 0.847350458, 0.868940446, 0.890265460, 0.911338047, 0.932169752, 0.952771225, 0.973152319, 0.993322173]
53
+ expected_cdf_vals = [
54
+ 0.005196152, 0.014696938, 0.027000000, 0.041569219, 0.058094750, 0.076367532, 0.096234090, 0.117575508, 0.140296115, 0.164316767, 0.189570567, 0.216000000, 0.243554922, 0.272191109, 0.301869177, 0.332553755, 0.364212850, 0.396817338, 0.430340563, 0.464758002, 0.500046998, 0.536186535, 0.573157047, 0.610940259, 0.649519053, 0.688877348, 0.729000000, 0.769872717, 0.811481978, 0.853814968, 0.896859521, 0.940604061, 0.985037563 ]
55
+ i = 0
56
+ 0.03.step(1.0, 0.03) do |x|
57
+ assert_in_delta expected_icdf_vals[i], beta.icdf(x), 0.00000001
58
+ assert_in_delta expected_cdf_vals[i], beta.cdf(x), 0.00000001
59
+ i += 1
60
+ end
61
+ end
62
+
46
63
  def test_control_limits
47
64
  trials = 50
48
65
  alpha = 0.05
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubystats
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan Donovan - http://www.bryandonovan.com
@@ -9,17 +9,18 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-05-09 00:00:00 -07:00
12
+ date: 2008-07-06 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: hoe
17
+ type: :development
17
18
  version_requirement:
18
19
  version_requirements: !ruby/object:Gem::Requirement
19
20
  requirements:
20
21
  - - ">="
21
22
  - !ruby/object:Gem::Version
22
- version: 1.5.1
23
+ version: 1.7.0
23
24
  version:
24
25
  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
26
  email: b.dondo+rubyforge@gmail.com
@@ -80,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
81
  requirements: []
81
82
 
82
83
  rubyforge_project: rubystats
83
- rubygems_version: 1.1.1
84
+ rubygems_version: 1.2.0
84
85
  signing_key:
85
86
  specification_version: 2
86
87
  summary: Port of PHPMath to Ruby