rubystats 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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