public
Description: Random number generation for common lisp
Homepage: http://code.google.com/p/cl-randist/
Clone URL: git://github.com/lvaruzza/cl-randist.git
Add documentation.
lvaruzza (author)
Fri Mar 07 19:49:34 -0800 2008
commit  bae34807469e77168f1889c962efdfb0f0faca37
tree    311d5e00eb09b4670d3cfbe22ab49574515042b0
parent  bc4ac5c99c62e0d3cd792f55f5ff0f1dbce93e57
...
15
16
17
 
18
19
20
...
60
61
62
 
 
 
 
 
 
63
64
65
...
15
16
17
18
19
20
21
...
61
62
63
64
65
66
67
68
69
70
71
72
0
@@ -15,6 +15,7 @@
0
 ;; It needs only one call to RANDOM for every value produced.
0
 ;;
0
 ;; For the licence, see at the end of the file.
0
+
0
 (defun create-alias-method-vectors (probabilities)
0
   (let* ((N (length probabilities))
0
    (threshold (/ 1.0d0 N))
0
@@ -60,6 +61,12 @@
0
     (values p_keep alternatives)))
0
 
0
 (defun make-discrete-random-var (probabilities &optional values)
0
+" The function MAKE-DISCRETE-RANDOM-VAR takes an array of
0
+probabilities and an (optional) array of values. Produces a
0
+function which returns each of the values with the specified
0
+probability (or the corresponding integer no values have been
0
+given)."
0
+
0
   (when (and values (/= (length values) (length probabilities)))
0
     (error "different number of values and probabilities."))
0
 
...
17
18
19
 
 
 
 
 
20
21
22
...
17
18
19
20
21
22
23
24
25
26
27
0
@@ -17,6 +17,11 @@
0
 
0
 (declaim (ftype (function (double-float double-float) double-float) random-beta))
0
 (defun random-beta (a b)
0
+"The beta distribution has the form
0
+
0
+ p(x) dx = (Gamma(a + b)/(Gamma(a) Gamma(b))) x^(a-1) (1-x)^(b-1) dx
0
+
0
+The method used here is the one described in Knuth "
0
   (declare (double-float a b))
0
   (let ((x1 (random-gamma a 1d0))
0
   (x2 (random-gamma b 1d0)))
...
47
48
49
50
51
 
 
 
 
 
52
53
54
...
47
48
49
 
50
51
52
53
54
55
56
57
58
0
@@ -47,8 +47,12 @@
0
 ;; }
0
 
0
 (declaim (ftype (function (double-float integer) integer) random-binomial))
0
-
0
 (defun random-binomial (p n)
0
+"The binomial distribution has the form,
0
+
0
+ prob(k) = n!/(k!(n-k)!) * p^k (1-p)^(n-k) for k = 0, 1, ..., n
0
+
0
+This is the algorithm from Knuth"
0
   (let ((a 0) (b 0) (k 0)
0
   (X 0d0)
0
   (p p) (n n))
...
205
206
207
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
209
210
...
267
268
269
 
 
 
 
270
271
272
...
299
300
301
 
302
...
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
...
284
285
286
287
288
289
290
291
292
293
...
320
321
322
323
324
0
@@ -205,6 +205,23 @@
0
    (inline random-gamma1))
0
 
0
 (defun random-gamma1 (a b)
0
+"The Gamma distribution of order a>0 is defined by:
0
+
0
+ p(x) dx = {1 / \Gamma(a) b^a } x^{a-1} e^{-x/b} dx
0
+
0
+ for x>0. If X and Y are independent gamma-distributed random
0
+ variables of order a1 and a2 with the same scale parameter b, then
0
+ X+Y has gamma distribution of order a1+a2.
0
+
0
+ The algorithms below are from Knuth, vol 2, 2nd ed, p. 129.
0
+
0
+
0
+ Works only if a > 1, and is most efficient if a is large
0
+
0
+ This algorithm, reported in Knuth, is attributed to Ahrens. A
0
+ faster one, we are told, can be found in: J. H. Ahrens and
0
+ U. Dieter, Computing 12 (1974) 223-246."
0
+
0
   (declare (double-float a b))
0
   (assert (> a 0d0))
0
   (multiple-value-bind (na frac) (truncate a)
0
@@ -267,6 +284,10 @@
0
 (declaim (ftype (function (double-float double-float) double-float)
0
     random-gamma-mt))
0
 (defun random-gamma-mt (a b)
0
+"New version based on Marsaglia and Tsang, 'A Simple Method for
0
+generating gamma variables', ACM Transactions on Mathematical
0
+Software, Vol 26, No 3 (2000), p363-372."
0
+
0
   (declare (double-float a b))
0
   (if (< a 1d0)
0
       (* (random-gamma-mt (+ 1d0 a) b) (expt (random-uniform) (/ a)))
0
@@ -299,4 +320,5 @@
0
 (declaim (inline random-gamma))
0
 
0
 (defun random-gamma (a &optional (b 1d0))
0
+ "[syntax suggar] Generate a random variable with gamma distribution using the MT method (see random-gamma-mt)"
0
   (random-gamma-mt a b))
...
59
60
61
 
62
63
64
...
81
82
83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
85
86
...
59
60
61
62
63
64
65
...
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
0
@@ -59,6 +59,7 @@ gsl_ran_multinomial (const gsl_rng * r, const size_t K,
0
 |#
0
 
0
 (defun random-multinomial1 (NN p n)
0
+ "Return the genrated values in the n vector"
0
   (let ((norm 0d0)
0
   (k (1- (array-dimension p 0))))
0
 
0
@@ -81,6 +82,22 @@ gsl_ran_multinomial (const gsl_rng * r, const size_t K,
0
     
0
 
0
 (defun random-multinomial (NN p)
0
+" The multinomial distribution has the form
0
+
0
+ N! n_1 n_2 n_K
0
+ prob(n_1, n_2, ... n_K) = -------------------- p_1 p_2 ... p_K
0
+ (n_1! n_2! ... n_K!)
0
+
0
+ where n_1, n_2, ... n_K are nonnegative integers, sum_{k=1,K} n_k = N,
0
+ and p = (p_1, p_2, ..., p_K) is a probability distribution.
0
+
0
+ Random variates are generated using the conditional binomial method.
0
+ This scales well with N and does not require a setup step.
0
+
0
+ Ref:
0
+ C.S. David, The computer generation of multinomial random variates,
0
+ Comp. Stat. Data Anal. 16 (1993) 205-217"
0
+
0
   (let ((n (make-array (array-dimension p 0)
0
      :element-type 'integer
0
      :adjustable nil)))
...
20
21
22
 
 
 
 
 
23
24
25
...
20
21
22
23
24
25
26
27
28
29
30
0
@@ -20,6 +20,11 @@
0
    (inline random-negative-binomial))
0
 
0
 (defun random-negative-binomial (p n)
0
+" The negative binomial distribution has the form,
0
+ prob(k) = Gamma(n + k)/(Gamma(n) Gamma(k + 1)) p^n (1-p)^k
0
+ for k = 0, 1, ... . Note that n does not have to be an integer.
0
+ This is the Leger's algorithm (given in the answers in Knuth)"
0
+
0
   (declare (type double-float p)
0
    (integer n))
0
   (let ((X (random-gamma (coerce n 'double-float) 1d0)))
...
193
194
195
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
197
198
...
241
242
243
 
244
245
246
...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
...
264
265
266
267
268
269
270
0
@@ -193,6 +193,29 @@
0
 (declaim (ftype (function (double-float double-float) double-float) random-normal-ziggurat))
0
 
0
 (defun random-normal-ziggurat (mean sigma)
0
+" This routine is based on the following article, with a couple of
0
+ modifications which simplify the implementation.
0
+
0
+ George Marsaglia, Wai Wan Tsang
0
+ The Ziggurat Method for Generating Random Variables
0
+ Journal of Statistical Software, vol. 5 (2000), no. 8
0
+ http://www.jstatsoft.org/v05/i08/
0
+
0
+ The modifications are:
0
+
0
+ 1) use 128 steps instead of 256 to decrease the amount of static
0
+ data necessary.
0
+
0
+ 2) use an acceptance sampling from an exponential wedge
0
+ exp(-R*(x-R/2)) for the tail of the base strip to simplify the
0
+ implementation. The area of exponential wedge is used in
0
+ calculating 'v' and the coefficients in ziggurat table, so the
0
+ coefficients differ slightly from those in the Marsaglia and Tsang
0
+ paper.
0
+
0
+ See also Leong et al, 'A Comment on the Implementation of the
0
+ Ziggurat Method', Journal of Statistical Software, vol 5 (2005), no 7."
0
+
0
   (let ((i 0) (j 0) (sign 0) (x 0d0) (y 0d0))
0
     (declare (double-float mean sigma))
0
     (declare (double-float x y))
0
@@ -241,5 +264,6 @@
0
 (declaim (inline random-normal))
0
 
0
 (defun random-normal (&optional (mean 0d0) (sigma 1d0))
0
+ "[sintax suggar] Generate random variable with normal distribution using ziggurat method"
0
   (random-normal-ziggurat mean sigma))
0
   
0
\ No newline at end of file
...
51
52
53
 
 
 
 
 
 
54
55
56
...
51
52
53
54
55
56
57
58
59
60
61
62
0
@@ -51,6 +51,12 @@
0
 (declaim (ftype (function (double-float) integer) random-poisson))
0
 
0
 (defun random-poisson (mu)
0
+"The poisson distribution has the form
0
+
0
+ p(n) = (mu^n / n!) exp(-mu)
0
+
0
+ for n = 0, 1, 2, ... . The method used here is the one from Knuth."
0
+
0
   (declare (type double-float mu))
0
   (let ((k 0))
0
     (declare (type integer k))
...
8
9
10
 
11
12
13
...
8
9
10
11
12
13
14
0
@@ -8,6 +8,7 @@
0
     (random x state)))
0
 
0
 (defmacro random-uniform ()
0
+ "[syntax suggar] Random variable with uniform distribution in interval [0,1]"
0
   `(random-mt 1d0))
0
 
0
 (declaim (ftype (function () double-float) random-pos))

Comments

    No one has commented yet.