1 # R A N D O M V A R I A B L E G E N E R A T O R S
3 # distributions on the real line:
4 # ------------------------------
11 # distributions on the circle (angles 0 to 2pi)
12 # ---------------------------------------------
16 # Translated from anonymously contributed C/C++ source.
18 from whrandom
import random
, uniform
, randint
, choice
# Also for export!
19 from math
import log
, exp
, pi
, e
, sqrt
, acos
, cos
, sin
21 # Housekeeping function to verify that magic constants have been
24 def verify(name
, expected
):
26 if abs(computed
- expected
) > 1e-7:
28 'computed value for %s deviates too much (computed %g, expected %g)' % \
29 (name
, computed
, expected
)
31 # -------------------- normal distribution --------------------
33 NV_MAGICCONST
= 4*exp(-0.5)/sqrt(2.0)
34 verify('NV_MAGICCONST', 1.71552776992141)
35 def normalvariate(mu
, sigma
):
36 # mu = mean, sigma = standard deviation
38 # Uses Kinderman and Monahan method. Reference: Kinderman,
39 # A.J. and Monahan, J.F., "Computer generation of random
40 # variables using the ratio of uniform deviates", ACM Trans
41 # Math Software, 3, (1977), pp257-260.
46 z
= NV_MAGICCONST
*(u1
-0.5)/u2
52 # -------------------- lognormal distribution --------------------
54 def lognormvariate(mu
, sigma
):
55 return exp(normalvariate(mu
, sigma
))
57 # -------------------- circular uniform --------------------
59 def cunifvariate(mean
, arc
):
60 # mean: mean angle (in radians between 0 and pi)
61 # arc: range of distribution (in radians between 0 and pi)
63 return (mean
+ arc
* (random() - 0.5)) % pi
65 # -------------------- exponential distribution --------------------
67 def expovariate(lambd
):
68 # lambd: rate lambd = 1/mean
69 # ('lambda' is a Python reserved word)
76 # -------------------- von Mises distribution --------------------
79 verify('TWOPI', 6.28318530718)
81 def vonmisesvariate(mu
, kappa
):
82 # mu: mean angle (in radians between 0 and 180 degrees)
83 # kappa: concentration parameter kappa (>= 0)
85 # if kappa = 0 generate uniform random angle
87 return TWOPI
* random()
89 a
= 1.0 + sqrt(1.0 + 4.0 * kappa
* kappa
)
90 b
= (a
- sqrt(2.0 * a
))/(2.0 * kappa
)
91 r
= (1.0 + b
* b
)/(2.0 * b
)
97 f
= (1.0 + r
* z
)/(r
+ z
)
102 if not (u2
>= c
* (2.0 - c
) and u2
> c
* exp(1.0 - c
)):
107 theta
= mu
+ 0.5*acos(f
)
109 theta
= mu
- 0.5*acos(f
)
113 # -------------------- gamma distribution --------------------
116 verify('LOG4', 1.38629436111989)
118 def gammavariate(alpha
, beta
):
119 # beta times standard gamma
120 ainv
= sqrt(2.0 * alpha
- 1.0)
121 return beta
* stdgamma(alpha
, ainv
, alpha
- LOG4
, alpha
+ ainv
)
123 SG_MAGICCONST
= 1.0 + log(4.5)
124 verify('SG_MAGICCONST', 2.50407739677627)
126 def stdgamma(alpha
, ainv
, bbb
, ccc
):
127 # ainv = sqrt(2 * alpha - 1)
128 # bbb = alpha - log(4)
132 raise ValueError, 'stdgamma: alpha must be > 0.0'
136 # Uses R.C.H. Cheng, "The generation of Gamma
137 # variables with non-integral shape parameters",
138 # Applied Statistics, (1977), 26, No. 1, p71-74
143 v
= log(u1
/(1.0-u1
))/ainv
147 if r
+ SG_MAGICCONST
- 4.5*z
>= 0.0 or r
>= log(z
):
157 else: # alpha is between 0 and 1 (exclusive)
159 # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
166 x
= pow(p
, 1.0/alpha
)
169 x
= -log((b
-p
)/alpha
)
171 if not (((p
<= 1.0) and (u1
> exp(-x
))) or
172 ((p
> 1) and (u1
> pow(x
, alpha
- 1.0)))):
177 # -------------------- Gauss (faster alternative) --------------------
180 def gauss(mu
, sigma
):
182 # When x and y are two variables from [0, 1), uniformly
185 # cos(2*pi*x)*log(1-y)
186 # sin(2*pi*x)*log(1-y)
188 # are two *independent* variables with normal distribution
189 # (mu = 0, sigma = 1).
194 if gauss_next
!= None:
198 x2pi
= random() * TWOPI
199 log1_y
= log(1.0 - random())
200 z
= cos(x2pi
) * log1_y
201 gauss_next
= sin(x2pi
) * log1_y
205 # -------------------- beta --------------------
207 def betavariate(alpha
, beta
):
209 # Discrete Event Simulation in C, pp 87-88.
211 y
= expovariate(alpha
)
212 z
= expovariate(1.0/beta
)
215 # -------------------- test program --------------------
218 print 'TWOPI =', TWOPI
220 print 'NV_MAGICCONST =', NV_MAGICCONST
221 print 'SG_MAGICCONST =', SG_MAGICCONST
222 test_generator(N
, 'random()')
223 test_generator(N
, 'normalvariate(0.0, 1.0)')
224 test_generator(N
, 'lognormvariate(0.0, 1.0)')
225 test_generator(N
, 'cunifvariate(0.0, 1.0)')
226 test_generator(N
, 'expovariate(1.0)')
227 test_generator(N
, 'vonmisesvariate(0.0, 1.0)')
228 test_generator(N
, 'gammavariate(0.5, 1.0)')
229 test_generator(N
, 'gammavariate(0.9, 1.0)')
230 test_generator(N
, 'gammavariate(1.0, 1.0)')
231 test_generator(N
, 'gammavariate(2.0, 1.0)')
232 test_generator(N
, 'gammavariate(20.0, 1.0)')
233 test_generator(N
, 'gammavariate(200.0, 1.0)')
234 test_generator(N
, 'gauss(0.0, 1.0)')
235 test_generator(N
, 'betavariate(3.0, 3.0)')
237 def test_generator(n
, funccall
):
239 print n
, 'times', funccall
240 code
= compile(funccall
, funccall
, 'eval')
250 smallest
= min(x
, smallest
)
251 largest
= max(x
, largest
)
253 print round(t1
-t0
, 3), 'sec,',
255 stddev
= sqrt(sqsum
/n
- avg
*avg
)
256 print 'avg %g, stddev %g, min %g, max %g' % \
257 (avg
, stddev
, smallest
, largest
)
259 if __name__
== '__main__':