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 +5 -1
- data/Manifest.txt +3 -0
- data/README.txt +6 -2
- data/Rakefile +23 -0
- data/examples/exponential.rb +5 -0
- data/lib/rubystats.rb +2 -1
- data/lib/rubystats/binomial_distribution.rb +10 -7
- data/lib/rubystats/exponential_distribution.rb +60 -0
- data/lib/rubystats/modules.rb +67 -67
- data/lib/rubystats/normal_distribution.rb +6 -6
- data/lib/rubystats/probability_distribution.rb +56 -16
- data/test/tc_beta.rb +8 -3
- data/test/tc_exponential.rb +60 -0
- data/test/tc_require_all.rb +2 -0
- data/test/ts_stats.rb +2 -0
- metadata +5 -2
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
|
-
=
|
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
|
data/lib/rubystats.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
module Rubystats
|
2
|
-
VERSION = '0.2.
|
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 "
|
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
|
-
|
30
|
+
@n
|
28
31
|
end
|
29
32
|
|
30
33
|
#returns the probability
|
31
34
|
def get_probability_parameter
|
32
|
-
|
35
|
+
@p
|
33
36
|
end
|
34
37
|
|
35
38
|
#returns the mean
|
36
39
|
def get_mean
|
37
|
-
|
40
|
+
@n * @p
|
38
41
|
end
|
39
42
|
|
40
43
|
#returns the variance
|
41
|
-
def
|
42
|
-
|
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
|
data/lib/rubystats/modules.rb
CHANGED
@@ -7,19 +7,19 @@ module Rubystats
|
|
7
7
|
end
|
8
8
|
|
9
9
|
module NumericalConstants
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
@
|
40
|
-
@
|
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) >
|
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
|
-
#
|
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
|
88
|
-
#
|
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
|
119
|
+
return MAX_VALUE
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|
123
123
|
# ----------------------------------------------------------------------
|
124
124
|
# Argument is positive
|
125
125
|
# ----------------------------------------------------------------------
|
126
|
-
if y <
|
126
|
+
if y < EPS
|
127
127
|
# ----------------------------------------------------------------------
|
128
128
|
# Argument .LT. EPS
|
129
129
|
# ----------------------------------------------------------------------
|
130
|
-
if y >=
|
130
|
+
if y >= XMININ
|
131
131
|
res = 1.0 / y
|
132
132
|
else
|
133
|
-
return
|
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 <=
|
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(
|
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
|
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
|
-
|
207
|
-
|
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
|
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 ==
|
259
|
-
return
|
258
|
+
if x == logGAMMACache_x
|
259
|
+
return logGAMMACache_res
|
260
260
|
end
|
261
261
|
|
262
262
|
y = x
|
263
|
-
if y > 0.0 && y <=
|
264
|
-
if y <=
|
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(
|
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 =
|
331
|
+
res = MAX_VALUE
|
332
332
|
end
|
333
333
|
# final adjustments and return
|
334
|
-
|
335
|
-
|
334
|
+
logGAMMACache_x = x
|
335
|
+
logGAMMACache_res = res
|
336
336
|
return res
|
337
337
|
end
|
338
338
|
|
339
339
|
|
340
|
-
# Incomplete
|
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
|
349
|
-
if x <= 0.0 || a <= 0.0 || a >
|
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
|
352
|
+
return GAMMA_series_expansion(a, x)
|
353
353
|
else
|
354
|
-
return 1.0-
|
354
|
+
return 1.0-GAMMA_fraction(a, x)
|
355
355
|
end
|
356
356
|
end
|
357
357
|
|
358
358
|
# Author:: Jaco van Kooten
|
359
|
-
def
|
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...
|
363
|
+
for n in (1...MAX_ITERATIONS)
|
364
364
|
ap += 1
|
365
365
|
del *= x / ap
|
366
366
|
sum += del
|
367
|
-
if del < sum *
|
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
|
375
|
+
def GAMMA_fraction(a, x)
|
376
376
|
b = x + 1.0 - a
|
377
|
-
c = 1.0 /
|
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...
|
383
|
-
if (del-1.0).abs >
|
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 <
|
389
|
-
c =
|
390
|
-
if d.abs <
|
391
|
-
c =
|
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) >
|
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) >
|
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 <
|
452
|
-
h =
|
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 <=
|
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 <
|
465
|
-
h =
|
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 <
|
470
|
-
c =
|
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 <
|
477
|
-
h =
|
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 <
|
482
|
-
c =
|
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
|
-
#
|
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 =
|
21
|
-
@cdf_denominator =
|
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 -
|
60
|
+
return -MAX_VALUE
|
61
61
|
end
|
62
62
|
if p == 1.0
|
63
|
-
return
|
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(
|
76
|
-
@cdf_denominator =
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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<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<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
|
-
|
85
|
-
|
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
|
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
|
-
|
32
|
-
|
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
|
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
|
data/test/tc_require_all.rb
CHANGED
data/test/ts_stats.rb
CHANGED
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.
|
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-
|
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
|