rubystats 0.2.1 → 0.2.2

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/History.txt CHANGED
@@ -1,3 +1,7 @@
1
+ === 0.2.2 / 2008-05-09
2
+ * Added exponential distribution class
3
+ * Replaced constants in NumericalConstants module with uppercase versions to follow Ruby convention
4
+
1
5
  === 0.2.1 / 2008-05-08
2
6
  * Bug fix for Normal Distribution RNG function (RubyForge bug #20044)
3
7
  * thanks, Daniel Moore (yahivin)
@@ -8,4 +12,4 @@
8
12
  * Added lib/rubystats subdirectory and namespaced all classes under the Rubystats module.
9
13
  * Added another example or two and fixed bug #16827.
10
14
  * Should not break old API
11
- *Now using Hoe to manage gem.
15
+ * Now using Hoe to manage gem.
data/Manifest.txt CHANGED
@@ -4,18 +4,21 @@ README.txt
4
4
  Rakefile
5
5
  examples/beta.rb
6
6
  examples/binomial.rb
7
+ examples/exponential.rb
7
8
  examples/failrate_vs_goal.rb
8
9
  examples/fisher.rb
9
10
  examples/norm.rb
10
11
  lib/rubystats.rb
11
12
  lib/rubystats/beta_distribution.rb
12
13
  lib/rubystats/binomial_distribution.rb
14
+ lib/rubystats/exponential_distribution.rb
13
15
  lib/rubystats/fishers_exact_test.rb
14
16
  lib/rubystats/modules.rb
15
17
  lib/rubystats/normal_distribution.rb
16
18
  lib/rubystats/probability_distribution.rb
17
19
  test/tc_beta.rb
18
20
  test/tc_binomial.rb
21
+ test/tc_exponential.rb
19
22
  test/tc_fisher.rb
20
23
  test/tc_norm.rb
21
24
  test/tc_require_all.rb
data/README.txt CHANGED
@@ -1,4 +1,4 @@
1
- = rubystats
1
+ = Rubystats
2
2
 
3
3
  * http://rubyforge.org/projects/rubystats/
4
4
 
@@ -9,6 +9,9 @@
9
9
  various sources).
10
10
  See http://www.phpmath.com/ for PHPMath libraries.
11
11
 
12
+ Currently includes classes for normal, binomial, beta and exponential distributions, with more
13
+ planned to be added.
14
+
12
15
  See examples and tests for usage.
13
16
 
14
17
  == NOTE for version 0.2.0:
@@ -30,7 +33,7 @@
30
33
  2006-2008
31
34
 
32
35
 
33
- == WARNING
36
+ == WARNING:
34
37
  This is beta-quality software. It works well according to my tests, but the API may change and other features may be added.
35
38
 
36
39
  == FEATURES:
@@ -39,6 +42,7 @@ Classes for distributions:
39
42
  * Normal
40
43
  * Binomial
41
44
  * Beta
45
+ * Exponential
42
46
 
43
47
  Also includes Fisher's Exact Test
44
48
 
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # -*- ruby -*-
2
+
1
3
  require 'rubygems'
2
4
  require 'hoe'
3
5
  $:.unshift(File.dirname(__FILE__) + "/lib")
@@ -17,3 +19,24 @@ end
17
19
  rule '' do |t|
18
20
  system "cd test && ruby ts_stats.rb"
19
21
  end
22
+
23
+ ALLISON = "/opt/local/lib/ruby/gems/1.8/gems/allison-2.0.3/lib/allison.rb"
24
+
25
+ Rake::RDocTask.new do |rd|
26
+ rd.main = "README.txt"
27
+ rd.rdoc_dir = "doc"
28
+ rd.rdoc_files.include(
29
+ "README.txt",
30
+ "History.txt",
31
+ "Manifest.txt",
32
+ "lib/**/*.rb",
33
+ "examples/**/*.rb",
34
+ "test/**/*.rb")
35
+ rd.title = "Rubystats RDoc"
36
+
37
+ rd.options << '-S' # inline source
38
+
39
+ rd.template = ALLISON if File.exist?(ALLISON)
40
+ end
41
+
42
+ # vim: syntax=Ruby
@@ -0,0 +1,5 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+ require 'rubystats/exponential_distribution'
3
+ lmbda = 1
4
+ expd = Rubystats::ExponentialDistribution.new(lmbda)
5
+ puts expd.pdf(2)
data/lib/rubystats.rb CHANGED
@@ -1,9 +1,10 @@
1
1
  module Rubystats
2
- VERSION = '0.2.1'
2
+ VERSION = '0.2.2'
3
3
  end
4
4
 
5
5
  require 'rubystats/normal_distribution'
6
6
  require 'rubystats/binomial_distribution'
7
7
  require 'rubystats/beta_distribution'
8
8
  require 'rubystats/fishers_exact_test'
9
+ require 'rubystats/exponential_distribution'
9
10
  include Rubystats
@@ -10,36 +10,39 @@ module Rubystats
10
10
  include Rubystats::SpecialMath
11
11
  include Rubystats::ExtraMath
12
12
 
13
+ attr_reader :p, :n
14
+ attr_writer :p, :n
15
+
13
16
  # Constructs a binomial distribution
14
17
  def initialize (trials, prob)
15
18
  if trials <= 0
16
- raise "Error: trials must be greater than 0"
19
+ raise ArgumentError.new("Error: trials must be greater than 0")
17
20
  end
18
21
  @n = trials
19
22
  if prob < 0.0 || prob > 1.0
20
- raise "Error: prob must be between 0 and 1"
23
+ raise ArgumentError.new("prob must be between 0 and 1")
21
24
  end
22
25
  @p = prob
23
26
  end
24
27
 
25
28
  #returns the number of trials
26
29
  def get_trials_parameter
27
- return @n
30
+ @n
28
31
  end
29
32
 
30
33
  #returns the probability
31
34
  def get_probability_parameter
32
- return @p
35
+ @p
33
36
  end
34
37
 
35
38
  #returns the mean
36
39
  def get_mean
37
- return @n * @p
40
+ @n * @p
38
41
  end
39
42
 
40
43
  #returns the variance
41
- def variance
42
- return @n * @p * (1.0 - @p)
44
+ def get_variance
45
+ @n * @p * (1.0 - @p)
43
46
  end
44
47
 
45
48
  # Probability density function of a binomial distribution (equivalent
@@ -0,0 +1,60 @@
1
+ require 'rubystats/probability_distribution'
2
+ # This class provides an object for encapsulating exponential distributions
3
+ # Ported to Ruby from PHPMath class by Bryan Donovan
4
+ # Author:: Mark Hale
5
+ # Author:: Paul Meagher
6
+ # Author:: Bryan Donovan (http://www.bryandonovan.com)
7
+ module Rubystats
8
+ class ExponentialDistribution < Rubystats::ProbabilityDistribution
9
+ include Rubystats::NumericalConstants
10
+ include Rubystats::SpecialMath
11
+ include Rubystats::ExtraMath
12
+
13
+ def initialize(decay=1)
14
+ if decay < 0.0
15
+ raise ArgumentError.new("Decay parameter should be positive.")
16
+ end
17
+ @rate = decay
18
+ end
19
+
20
+ private
21
+
22
+ def get_mean
23
+ @rate
24
+ end
25
+
26
+ def get_variance
27
+ @rate * @rate
28
+ end
29
+
30
+ # Private method to obtain single PDF value.
31
+ # x should be greater than 0
32
+ # returns the probability that a stochastic variable x has the value X, i.e. P(x=X).
33
+ def get_pdf(x)
34
+ check_range(x, 0.0, MAX_VALUE)
35
+ @rate * Math.exp(-1 * @rate * x)
36
+ end
37
+
38
+ # Private method to obtain single CDF value.
39
+ # param x should be greater than 0
40
+ # return the probability that a stochastic variable x is less then X, i.e. P(x<X).
41
+ def get_cdf(x)
42
+ check_range(x,0.0,MAX_VALUE)
43
+ 1.0 - Math.exp(-1 * @rate * x)
44
+ end
45
+
46
+ # Private method to obtain single inverse CDF value.
47
+ # return the value X for which P(x<X).
48
+ def get_icdf(p)
49
+ check_range(p)
50
+ -1 * Math.log(1.0 - p) / @rate
51
+ end
52
+
53
+ # Private method to obtain single RNG value.
54
+ # return exponential random deviate
55
+ def get_rng
56
+ -(Math.log(Kernel.rand) / @rate)
57
+ end
58
+
59
+ end
60
+ end
@@ -7,19 +7,19 @@ module Rubystats
7
7
  end
8
8
 
9
9
  module NumericalConstants
10
- Max_float = 3.40282346638528860e292
11
- Eps = 2.22e-16
12
- Max_value = 1.2e290
13
- Log_gamma_x_max_value = 2.55e292
14
- Gamma_x_max_value = 171.624
15
- Sqrt2pi = 2.5066282746310005024157652848110452530069867406099
16
- Sqrt2 = 1.4142135623730950488016887242096980785696718753769
17
- Xminin = 2.23e-303
18
- Max_iterations = 1000
19
- Precision = 8.88e-016
20
- Two_pi = 6.2831853071795864769252867665590057683943387987502
21
- Gamma = 0.57721566490153286060651209008240243104215933593992
22
- Golden_ratio = 1.6180339887498948482045868343656381177203091798058
10
+ MAX_FLOAT = 3.40282346638528860e292
11
+ EPS = 2.22e-16
12
+ MAX_VALUE = 1.2e290
13
+ LOG_GAMMA_X_MAX_VALUE = 2.55e292
14
+ GAMMA_X_MAX_VALUE = 171.624
15
+ SQRT2PI = 2.5066282746310005024157652848110452530069867406099
16
+ SQRT2 = 1.4142135623730950488016887242096980785696718753769
17
+ XMININ = 2.23e-303
18
+ MAX_ITERATIONS = 1000
19
+ PRECISION = 8.88e-016
20
+ TWO_PI = 6.2831853071795864769252867665590057683943387987502
21
+ GAMMA = 0.57721566490153286060651209008240243104215933593992
22
+ GOLDEN_RATIO = 1.6180339887498948482045868343656381177203091798058
23
23
  end
24
24
 
25
25
 
@@ -36,8 +36,8 @@ module Rubystats
36
36
 
37
37
  include Rubystats::NumericalConstants
38
38
 
39
- @logGammaCache_res = 0.0
40
- @logGammaCache_x = 0.0
39
+ @logGAMMACache_res = 0.0
40
+ @logGAMMACache_x = 0.0
41
41
  @logBetaCache_res = 0.0
42
42
  @logBetaCache_p = 0.0
43
43
  @logBetaCache_q = 0.0
@@ -46,7 +46,7 @@ module Rubystats
46
46
  if p != @logBetaCache_p || q != @logBetaCache_q
47
47
  logBetaCache_p = p
48
48
  logBetaCache_q = q
49
- if p <= 0.0 || q <= 0.0 || (p + q) > Log_gamma_x_max_value
49
+ if p <= 0.0 || q <= 0.0 || (p + q) > LOG_GAMMA_X_MAX_VALUE
50
50
  logBetaCache_res = 0.0
51
51
  else
52
52
  logBetaCache_res = log_gamma(p) + log_gamma(q) - log_gamma(p + q)
@@ -55,7 +55,7 @@ module Rubystats
55
55
  end
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>
@@ -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 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,
@@ -116,21 +116,21 @@ module Rubystats
116
116
  y += 1
117
117
  end
118
118
  else
119
- return Max_value
119
+ return MAX_VALUE
120
120
  end
121
121
  end
122
122
 
123
123
  # ----------------------------------------------------------------------
124
124
  # Argument is positive
125
125
  # ----------------------------------------------------------------------
126
- if y < Eps
126
+ if y < EPS
127
127
  # ----------------------------------------------------------------------
128
128
  # Argument .LT. EPS
129
129
  # ----------------------------------------------------------------------
130
- if y >= Xminin
130
+ if y >= XMININ
131
131
  res = 1.0 / y
132
132
  else
133
- return Max_value
133
+ return MAX_VALUE
134
134
  end
135
135
  elsif y < 12.0
136
136
  y1 = y
@@ -177,17 +177,17 @@ module Rubystats
177
177
  # ----------------------------------------------------------------------
178
178
  # Evaluate for argument .GE. 12.0
179
179
  # ----------------------------------------------------------------------
180
- if y <= Gamma_x_max_value
180
+ if y <= GAMMA_X_MAX_VALUE
181
181
  ysq = y * y
182
182
  sum = g_c[6]
183
183
  for i in(0...6)
184
184
  sum = sum / ysq + g_c[i]
185
- sum = sum / y - y + log(sqrt2pi)
185
+ sum = sum / y - y + log(SQRT2PI)
186
186
  sum += (y - 0.5) * log(y)
187
187
  res = Math.exp(sum)
188
188
  end
189
189
  else
190
- return Max_value
190
+ return MAX_VALUE
191
191
  end
192
192
  # ----------------------------------------------------------------------
193
193
  # Final adjustments and return
@@ -203,8 +203,8 @@ module Rubystats
203
203
  end
204
204
 
205
205
  def log_gamma(x)
206
- logGammaCache_res = @logGammaCache_res
207
- logGammaCache_x = @logGammaCache_x
206
+ logGAMMACache_res = @logGAMMACache_res
207
+ logGAMMACache_x = @logGAMMACache_x
208
208
 
209
209
  lg_d1 = -0.5772156649015328605195174
210
210
  lg_d2 = 0.4227843350984671393993777
@@ -251,17 +251,17 @@ module Rubystats
251
251
  -0.002777777777777681622553, 0.08333333333333333331554247,
252
252
  0.0057083835261 ]
253
253
 
254
- # Rough estimate of the fourth root of logGamma_xBig
254
+ # Rough estimate of the fourth root of logGAMMA_xBig
255
255
  lg_frtbig = 2.25e76
256
256
  pnt68 = 0.6796875
257
257
 
258
- if x == logGammaCache_x
259
- return logGammaCache_res
258
+ if x == logGAMMACache_x
259
+ return logGAMMACache_res
260
260
  end
261
261
 
262
262
  y = x
263
- if y > 0.0 && y <= Log_gamma_x_max_value
264
- if y <= Eps
263
+ if y > 0.0 && y <= LOG_GAMMA_X_MAX_VALUE
264
+ if y <= EPS
265
265
  res = -Math.log(y)
266
266
  elsif y <= 1.5
267
267
  # EPS .LT. X .LE. 1.5
@@ -323,21 +323,21 @@ module Rubystats
323
323
  end
324
324
  res = res/y
325
325
  corr = Math.log(y)
326
- res = res + Math.log(Sqrt2pi) - 0.5 * corr
326
+ res = res + Math.log(SQRT2PI) - 0.5 * corr
327
327
  res = res + y * (corr - 1.0)
328
328
  end
329
329
  else
330
330
  #return for bad arguments
331
- res = Max_value
331
+ res = MAX_VALUE
332
332
  end
333
333
  # final adjustments and return
334
- logGammaCache_x = x
335
- logGammaCache_res = res
334
+ logGAMMACache_x = x
335
+ logGAMMACache_res = res
336
336
  return res
337
337
  end
338
338
 
339
339
 
340
- # Incomplete gamma function.
340
+ # Incomplete GAMMA function.
341
341
  # The computation is based on approximations presented in
342
342
  # Numerical Recipes, Chapter 6.2 (W.H. Press et al, 1992).
343
343
  # @param a require a>=0
@@ -345,26 +345,26 @@ module Rubystats
345
345
  # @return 0 if x<0, a<=0 or a>2.55E305 to avoid errors and over/underflow
346
346
  # @author Jaco van Kooten
347
347
 
348
- def incomplete_gamma(a, x)
349
- if x <= 0.0 || a <= 0.0 || a > Log_gamma_x_max_value
348
+ def incomplete_GAMMA(a, x)
349
+ if x <= 0.0 || a <= 0.0 || a > LOG_GAMMA_X_MAX_VALUE
350
350
  return 0.0
351
351
  elsif x < (a + 1.0)
352
- return gamma_series_expansion(a, x)
352
+ return GAMMA_series_expansion(a, x)
353
353
  else
354
- return 1.0-gamma_fraction(a, x)
354
+ return 1.0-GAMMA_fraction(a, x)
355
355
  end
356
356
  end
357
357
 
358
358
  # Author:: Jaco van Kooten
359
- def gamma_series_expansion(a, x)
359
+ def GAMMA_series_expansion(a, x)
360
360
  ap = a
361
361
  del = 1.0 / a
362
362
  sum = del
363
- for n in (1...Max_iterations)
363
+ for n in (1...MAX_ITERATIONS)
364
364
  ap += 1
365
365
  del *= x / ap
366
366
  sum += del
367
- if del < sum * Precision
367
+ if del < sum * PRECISION
368
368
  return sum * Math.exp(-x + a * Math.log(x) - log_gamma(a))
369
369
  end
370
370
  end
@@ -372,23 +372,23 @@ module Rubystats
372
372
  end
373
373
 
374
374
  # Author:: Jaco van Kooten
375
- def gamma_fraction(a, x)
375
+ def GAMMA_fraction(a, x)
376
376
  b = x + 1.0 - a
377
- c = 1.0 / Xminin
377
+ c = 1.0 / XMININ
378
378
  d = 1.0 / b
379
379
  h = d
380
380
  del= 0.0
381
381
  an = 0.0
382
- for i in (1...Max_iterations)
383
- if (del-1.0).abs > Precision
382
+ for i in (1...MAX_ITERATIONS)
383
+ if (del-1.0).abs > PRECISION
384
384
  an = -i * (i - a)
385
385
  b += 2.0
386
386
  d = an * d + b
387
387
  c = b + an / c
388
- if c.abs < Xminin
389
- c = Xminin
390
- if d.abs < Xminin
391
- c = Xminin
388
+ if c.abs < XMININ
389
+ c = XMININ
390
+ if d.abs < XMININ
391
+ c = XMININ
392
392
  d = 1.0 / d
393
393
  del = d * c
394
394
  h *= del
@@ -404,7 +404,7 @@ module Rubystats
404
404
  # Author:: Jaco van Kooten
405
405
 
406
406
  def beta(p, q)
407
- if p <= 0.0 || q <= 0.0 || (p + q) > Log_gamma_x_max_value
407
+ if p <= 0.0 || q <= 0.0 || (p + q) > LOG_GAMMA_X_MAX_VALUE
408
408
  return 0.0
409
409
  else
410
410
  return Math.exp(log_beta(p, q))
@@ -424,7 +424,7 @@ module Rubystats
424
424
  return 0.0
425
425
  elsif x >= 1.0
426
426
  return 1.0
427
- elsif p <= 0.0 || q <= 0.0 || (p + q) > Log_gamma_x_max_value
427
+ elsif p <= 0.0 || q <= 0.0 || (p + q) > LOG_GAMMA_X_MAX_VALUE
428
428
  return 0.0
429
429
  else
430
430
  beta_gam = Math.exp( -log_beta(p, q) + p * Math.log(x) + q * Math.log(1.0 - x) )
@@ -448,38 +448,38 @@ module Rubystats
448
448
  p_plus = p + 1.0
449
449
  p_minus = p - 1.0
450
450
  h = 1.0 - sum_pq * x / p_plus
451
- if h.abs < Xminin
452
- h = Xminin
451
+ if h.abs < XMININ
452
+ h = XMININ
453
453
  end
454
454
  h = 1.0 / h
455
455
  frac = h
456
456
  m = 1
457
457
  delta = 0.0
458
458
 
459
- while (m <= Max_iterations) && ((delta - 1.0).abs > Precision)
459
+ while (m <= MAX_ITERATIONS) && ((delta - 1.0).abs > PRECISION)
460
460
  m2 = 2 * m
461
461
  # even index for d
462
462
  d = m * (q - m) * x / ( (p_minus + m2) * (p + m2))
463
463
  h = 1.0 + d * h
464
- if h.abs < Xminin
465
- h = Xminin
464
+ if h.abs < XMININ
465
+ h = XMININ
466
466
  end
467
467
  h = 1.0 / h
468
468
  c = 1.0 + d / c
469
- if c.abs < Xminin
470
- c = Xminin
469
+ if c.abs < XMININ
470
+ c = XMININ
471
471
  end
472
472
  frac *= h * c
473
473
  # odd index for d
474
474
  d = -(p + m) * (sum_pq + m) * x / ((p + m2) * (p_plus + m2))
475
475
  h = 1.0 + d * h
476
- if h.abs < Xminin
477
- h = Xminin
476
+ if h.abs < XMININ
477
+ h = XMININ
478
478
  end
479
479
  h = 1.0 / h
480
480
  c = 1.0 + d / c
481
- if c.abs < Xminin
482
- c = Xminin
481
+ if c.abs < XMININ
482
+ c = XMININ
483
483
  end
484
484
  delta = h * c
485
485
  frac *= delta
@@ -563,7 +563,7 @@ module Rubystats
563
563
  #
564
564
  # Note1:
565
565
  # To compute exp(-x*x-0.5625+R/S), let s be a single
566
- # precision number and s := x then
566
+ # PRECISION number and s := x then
567
567
  # -x*x = -s*s + (s-x)*(s+x)
568
568
  # exp(-x*x-0.5626+R/S) =
569
569
  # exp(-s*s-0.5625)*exp((s-x)*(s+x)+R/S)
@@ -17,8 +17,8 @@ module Rubystats
17
17
  end
18
18
  @stdev = sigma
19
19
  @variance = sigma**2
20
- @pdf_denominator = Sqrt2pi * Math.sqrt(@variance)
21
- @cdf_denominator = Sqrt2 * Math.sqrt(@variance)
20
+ @pdf_denominator = SQRT2PI * Math.sqrt(@variance)
21
+ @cdf_denominator = SQRT2 * Math.sqrt(@variance)
22
22
  end
23
23
 
24
24
  # Returns the mean of the distribution
@@ -57,10 +57,10 @@ module Rubystats
57
57
  def get_icdf(p)
58
58
  check_range(p)
59
59
  if p == 0.0
60
- return -Max_value
60
+ return -MAX_VALUE
61
61
  end
62
62
  if p == 1.0
63
- return Max_value
63
+ return MAX_VALUE
64
64
  end
65
65
  if p == 0.5
66
66
  return @mean
@@ -72,8 +72,8 @@ module Rubystats
72
72
  cdf_D_save = @cdf_denominator
73
73
  @mean = 0.0
74
74
  @variance = 1.0
75
- @pdf_denominator = Math.sqrt(Two_pi)
76
- @cdf_denominator = Sqrt2
75
+ @pdf_denominator = Math.sqrt(TWO_PI)
76
+ @cdf_denominator = SQRT2
77
77
  x = find_root(p, 0.0, -100.0, 100.0)
78
78
  #scale back
79
79
  @mean = mean_save
@@ -1,6 +1,15 @@
1
1
  require 'rubystats/modules'
2
2
 
3
3
  module Rubystats
4
+ # The ProbabilityDistribution superclass provides an object
5
+ # for encapsulating probability distributions.
6
+ #
7
+ # Author: Jaco van Kooten
8
+ # Author: Mark Hale
9
+ # Author: Paul Meagher
10
+ # Author: Jesus Castagnetto
11
+ # Author: Bryan Donovan (port from PHPmath to Ruby)
12
+
4
13
  class ProbabilityDistribution
5
14
  include Rubystats::NumericalConstants
6
15
  include Rubystats::SpecialMath
@@ -9,18 +18,21 @@ module Rubystats
9
18
  def initialize
10
19
  end
11
20
 
21
+ #returns the distribution mean
12
22
  def mean
13
23
  get_mean
14
24
  end
15
25
 
16
- def get_mean
26
+ #returns distribution variance
27
+ def variance
28
+ get_variance
17
29
  end
18
30
 
19
-
31
+ #Probability density function
20
32
  def pdf(x)
21
33
  if x.class == Array
22
34
  pdf_vals = []
23
- for i in (0..x.length)
35
+ for i in (0 ... x.length)
24
36
  pdf_vals[i] = get_pdf(x[i])
25
37
  end
26
38
  return pdf_vals
@@ -29,9 +41,7 @@ module Rubystats
29
41
  end
30
42
  end
31
43
 
32
- def get_pdf(x)
33
- end
34
-
44
+ #Cummulative distribution function
35
45
  def cdf(x)
36
46
  if x.class == Array
37
47
  cdf_vals = []
@@ -44,9 +54,7 @@ module Rubystats
44
54
  end
45
55
  end
46
56
 
47
- def get_cdf(x)
48
- end
49
-
57
+ #Inverse CDF
50
58
  def icdf(p)
51
59
  if p.class == Array
52
60
  inv_vals = []
@@ -59,9 +67,7 @@ module Rubystats
59
67
  end
60
68
  end
61
69
 
62
- def get_icdf(p)
63
- end
64
-
70
+ #Returns random number(s) using subclass's get_rng method
65
71
  def rng(n=1)
66
72
  if n < 1
67
73
  return "Number of random numbers to return must be 1 or greater"
@@ -77,12 +83,46 @@ module Rubystats
77
83
  end
78
84
  end
79
85
 
80
- def get_rng()
86
+
87
+ private
88
+
89
+ #private method to be implemented in subclass
90
+ def get_mean
91
+ end
92
+
93
+ #private method to be implemented in subclass
94
+ def get_variance
95
+ end
96
+
97
+ #private method to be implemented in subclass
98
+ #returns the probability that a stochastic variable x has the value X, i.e. P(x=X).
99
+ def get_pdf(x)
100
+ end
101
+
102
+ #private method to be implemented in subclass
103
+ #returns the probability that a stochastic variable x is less then X, i.e. P(x&lt;X).
104
+ def get_cdf(x)
105
+ end
106
+
107
+ #private method to be implemented in subclass
108
+ #returns the value X for which P(x&lt;X).
109
+ def get_icdf(p)
81
110
  end
82
111
 
112
+ #private method to be implemented in subclass
113
+ #Random number generator
114
+ def get_rng
115
+ end
116
+
117
+
118
+ public
119
+
120
+ #check that variable is between lo and hi limits.
121
+ #lo default is 0.0 and hi default is 1.0
83
122
  def check_range(x, lo=0.0, hi=1.0)
84
- if (x < lo) || (x > hi)
85
- return "error"
123
+ raise ArgumentError.new("x cannot be nil") if x.nil?
124
+ if x < lo or x > hi
125
+ raise ArgumentError.new("x must be less than lo (#{lo}) and greater than hi (#{hi})")
86
126
  end
87
127
  end
88
128
 
@@ -94,7 +134,7 @@ module Rubystats
94
134
  end
95
135
  end
96
136
 
97
- def find_root (prob, guess, x_lo, x_hi)
137
+ def find_root(prob, guess, x_lo, x_hi)
98
138
  accuracy = 1.0e-10
99
139
  max_iteration = 150
100
140
  x = guess
data/test/tc_beta.rb CHANGED
@@ -28,12 +28,17 @@ class TestBeta < Test::Unit::TestCase
28
28
  0.956058132801147,
29
29
  0.995358286711105,
30
30
  0.99971672771575]
31
- assert_equal(expected_pvals.to_s, p_vals.to_s)
32
- assert_equal(expected_cvals.to_s, c_vals.to_s)
31
+
32
+ 0.upto(x_vals.size - 1) do |i|
33
+ assert_in_delta expected_pvals[i], p_vals[i], 0.00000001
34
+ assert_in_delta expected_cvals[i], c_vals[i], 0.00000001
35
+ i += 1
36
+ end
37
+
33
38
  x_vals.each do |x|
34
39
  cdf = beta.cdf(x)
35
40
  inv_cdf = beta.icdf(cdf)
36
- assert_in_delta(x.to_s, inv_cdf.to_s, 0.00000001)
41
+ assert_in_delta(x, inv_cdf, 0.00000001)
37
42
  end
38
43
 
39
44
  end
@@ -0,0 +1,60 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+ require 'test/unit'
3
+ require 'rubystats/exponential_distribution'
4
+
5
+ class TestExponential < Test::Unit::TestCase
6
+ def test_simple
7
+ lmbda = 1
8
+ expd = Rubystats::ExponentialDistribution.new(lmbda)
9
+ assert_equal(1, expd.mean)
10
+ assert_equal(1, expd.variance)
11
+ assert_in_delta(0.13533528323661, expd.pdf(2), 0.00000001)
12
+ assert_in_delta(0.95021293163214, expd.cdf(3), 0.00000001)
13
+ assert_in_delta(2.9997402949515, expd.icdf(0.9502), 0.00000001)
14
+ assert !expd.rng.nil?
15
+ # make sure the mean of RNG values is close to the expected mean
16
+ rngs = []
17
+ rngsum = 0
18
+ n = 5000
19
+ n.times do
20
+ rng = expd.rng
21
+ rngs << rng
22
+ rngsum += rng
23
+ end
24
+ avg = rngsum / n
25
+ assert_in_delta(avg, 1, 0.1)
26
+
27
+ x_vals = [0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5]
28
+ p_vals = expd.pdf(x_vals)
29
+
30
+ c_vals = expd.cdf(x_vals)
31
+ expected_pvals = [1.0,
32
+ 0.60653065971263,
33
+ 0.36787944117144,
34
+ 0.22313016014843,
35
+ 0.13533528323661,
36
+ 0.082084998623899,
37
+ 0.049787068367864,
38
+ 0.030197383422319 ]
39
+ expected_cvals = [0.0,
40
+ 0.39346934028737,
41
+ 0.63212055882856,
42
+ 0.77686983985157,
43
+ 0.86466471676339,
44
+ 0.9179150013761,
45
+ 0.95021293163214,
46
+ 0.96980261657768 ]
47
+
48
+ 0.upto(x_vals.size - 1) do |i|
49
+ assert_in_delta expected_pvals[i], p_vals[i], 0.00000001
50
+ assert_in_delta expected_cvals[i], c_vals[i], 0.00000001
51
+ i += 1
52
+ end
53
+
54
+ x_vals.each do |x|
55
+ cdf = expd.cdf(x)
56
+ inv_cdf = expd.icdf(cdf)
57
+ assert_in_delta(x, inv_cdf, 0.00000001)
58
+ end
59
+ end
60
+ end
@@ -14,5 +14,7 @@ class TestNormal < Test::Unit::TestCase
14
14
 
15
15
  assert_equal("0.691462461274013",cdf.to_s)
16
16
  assert_not_nil(norm.rng)
17
+
18
+ expd = ExponentialDistribution.new(2)
17
19
  end
18
20
  end
data/test/ts_stats.rb CHANGED
@@ -3,3 +3,5 @@ require 'tc_fisher'
3
3
  require 'tc_binomial'
4
4
  require 'tc_beta'
5
5
  require 'tc_norm'
6
+ require 'tc_exponential'
7
+ require 'tc_require_all'
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.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan Donovan - http://www.bryandonovan.com
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-05-08 00:00:00 -07:00
12
+ date: 2008-05-09 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -38,18 +38,21 @@ files:
38
38
  - Rakefile
39
39
  - examples/beta.rb
40
40
  - examples/binomial.rb
41
+ - examples/exponential.rb
41
42
  - examples/failrate_vs_goal.rb
42
43
  - examples/fisher.rb
43
44
  - examples/norm.rb
44
45
  - lib/rubystats.rb
45
46
  - lib/rubystats/beta_distribution.rb
46
47
  - lib/rubystats/binomial_distribution.rb
48
+ - lib/rubystats/exponential_distribution.rb
47
49
  - lib/rubystats/fishers_exact_test.rb
48
50
  - lib/rubystats/modules.rb
49
51
  - lib/rubystats/normal_distribution.rb
50
52
  - lib/rubystats/probability_distribution.rb
51
53
  - test/tc_beta.rb
52
54
  - test/tc_binomial.rb
55
+ - test/tc_exponential.rb
53
56
  - test/tc_fisher.rb
54
57
  - test/tc_norm.rb
55
58
  - test/tc_require_all.rb