blob: f502d1dee7c1f83d4ae861248bb7d8605d2ad526 [file] [log] [blame]
Guido van Rossume7b146f2000-02-04 15:28:42 +00001"""Random variable generators.
Guido van Rossumff03b1a1994-03-09 12:55:02 +00002
Tim Petersd7b5e882001-01-25 03:36:26 +00003 integers
4 --------
5 uniform within range
6
7 sequences
8 ---------
9 pick random element
10 generate random permutation
11
Guido van Rossume7b146f2000-02-04 15:28:42 +000012 distributions on the real line:
13 ------------------------------
Tim Petersd7b5e882001-01-25 03:36:26 +000014 uniform
Guido van Rossume7b146f2000-02-04 15:28:42 +000015 normal (Gaussian)
16 lognormal
17 negative exponential
18 gamma
19 beta
Guido van Rossumff03b1a1994-03-09 12:55:02 +000020
Guido van Rossume7b146f2000-02-04 15:28:42 +000021 distributions on the circle (angles 0 to 2pi)
22 ---------------------------------------------
23 circular uniform
24 von Mises
25
26Translated from anonymously contributed C/C++ source.
27
Tim Peterse360d952001-01-26 10:00:39 +000028Multi-threading note: the random number generator used here is not thread-
29safe; it is possible that two calls return the same random value. However,
30you can instantiate a different instance of Random() in each thread to get
31generators that don't share state, then use .setstate() and .jumpahead() to
32move the generators to disjoint segments of the full period. For example,
33
34def create_generators(num, delta, firstseed=None):
35 ""\"Return list of num distinct generators.
36 Each generator has its own unique segment of delta elements from
37 Random.random()'s full period.
38 Seed the first generator with optional arg firstseed (default is
39 None, to seed from current time).
40 ""\"
41
42 from random import Random
43 g = Random(firstseed)
44 result = [g]
45 for i in range(num - 1):
46 laststate = g.getstate()
47 g = Random()
48 g.setstate(laststate)
49 g.jumpahead(delta)
50 result.append(g)
51 return result
52
53gens = create_generators(10, 1000000)
54
55That creates 10 distinct generators, which can be passed out to 10 distinct
56threads. The generators don't share state so can be called safely in
57parallel. So long as no thread calls its g.random() more than a million
58times (the second argument to create_generators), the sequences seen by
59each thread will not overlap.
60
61The period of the underlying Wichmann-Hill generator is 6,953,607,871,644,
62and that limits how far this technique can be pushed.
63
64Just for fun, note that since we know the period, .jumpahead() can also be
65used to "move backward in time":
66
67>>> g = Random(42) # arbitrary
68>>> g.random()
Tim Peters0de88fc2001-02-01 04:59:18 +0000690.25420336316883324
Tim Peterse360d952001-01-26 10:00:39 +000070>>> g.jumpahead(6953607871644L - 1) # move *back* one
71>>> g.random()
Tim Peters0de88fc2001-02-01 04:59:18 +0000720.25420336316883324
Guido van Rossume7b146f2000-02-04 15:28:42 +000073"""
Tim Petersd7b5e882001-01-25 03:36:26 +000074# XXX The docstring sucks.
Guido van Rossumd03e1191998-05-29 17:51:31 +000075
Tim Petersd7b5e882001-01-25 03:36:26 +000076from math import log as _log, exp as _exp, pi as _pi, e as _e
77from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin
Guido van Rossumff03b1a1994-03-09 12:55:02 +000078
Skip Montanaro0de65802001-02-15 22:15:14 +000079__all__ = ["Random","seed","random","uniform","randint","choice",
80 "randrange","shuffle","normalvariate","lognormvariate",
81 "cunifvariate","expovariate","vonmisesvariate","gammavariate",
82 "stdgamma","gauss","betavariate","paretovariate","weibullvariate",
83 "getstate","setstate","jumpahead","whseed"]
Tim Peters0e6d2132001-02-15 23:56:39 +000084
Tim Petersdc47a892001-11-25 21:12:43 +000085def _verify(name, computed, expected):
Tim Peters0c9886d2001-01-15 01:18:21 +000086 if abs(computed - expected) > 1e-7:
Tim Petersd7b5e882001-01-25 03:36:26 +000087 raise ValueError(
88 "computed value for %s deviates too much "
89 "(computed %g, expected %g)" % (name, computed, expected))
90
91NV_MAGICCONST = 4 * _exp(-0.5)/_sqrt(2.0)
Tim Petersdc47a892001-11-25 21:12:43 +000092_verify('NV_MAGICCONST', NV_MAGICCONST, 1.71552776992141)
Tim Petersd7b5e882001-01-25 03:36:26 +000093
94TWOPI = 2.0*_pi
Tim Petersdc47a892001-11-25 21:12:43 +000095_verify('TWOPI', TWOPI, 6.28318530718)
Tim Petersd7b5e882001-01-25 03:36:26 +000096
97LOG4 = _log(4.0)
Tim Petersdc47a892001-11-25 21:12:43 +000098_verify('LOG4', LOG4, 1.38629436111989)
Tim Petersd7b5e882001-01-25 03:36:26 +000099
100SG_MAGICCONST = 1.0 + _log(4.5)
Tim Petersdc47a892001-11-25 21:12:43 +0000101_verify('SG_MAGICCONST', SG_MAGICCONST, 2.50407739677627)
Tim Petersd7b5e882001-01-25 03:36:26 +0000102
103del _verify
104
105# Translated by Guido van Rossum from C source provided by
106# Adrian Baddeley.
107
108class Random:
109
110 VERSION = 1 # used by getstate/setstate
111
112 def __init__(self, x=None):
113 """Initialize an instance.
114
115 Optional argument x controls seeding, as for Random.seed().
116 """
117
118 self.seed(x)
119 self.gauss_next = None
120
Tim Peterscd804102001-01-25 20:25:57 +0000121## -------------------- core generator -------------------
122
Tim Petersd7b5e882001-01-25 03:36:26 +0000123 # Specific to Wichmann-Hill generator. Subclasses wishing to use a
Tim Petersd52269b2001-01-25 06:23:18 +0000124 # different core generator should override the seed(), random(),
Tim Peterscd804102001-01-25 20:25:57 +0000125 # getstate(), setstate() and jumpahead() methods.
Tim Petersd7b5e882001-01-25 03:36:26 +0000126
Tim Peters0de88fc2001-02-01 04:59:18 +0000127 def seed(self, a=None):
128 """Initialize internal state from hashable object.
Tim Petersd7b5e882001-01-25 03:36:26 +0000129
Tim Peters0de88fc2001-02-01 04:59:18 +0000130 None or no argument seeds from current time.
131
Tim Petersbcd725f2001-02-01 10:06:53 +0000132 If a is not None or an int or long, hash(a) is used instead.
Tim Peters0de88fc2001-02-01 04:59:18 +0000133
134 If a is an int or long, a is used directly. Distinct values between
135 0 and 27814431486575L inclusive are guaranteed to yield distinct
136 internal states (this guarantee is specific to the default
137 Wichmann-Hill generator).
Tim Petersd7b5e882001-01-25 03:36:26 +0000138 """
139
Tim Peters0de88fc2001-02-01 04:59:18 +0000140 if a is None:
Tim Petersd7b5e882001-01-25 03:36:26 +0000141 # Initialize from current time
142 import time
Tim Peters0de88fc2001-02-01 04:59:18 +0000143 a = long(time.time() * 256)
144
145 if type(a) not in (type(3), type(3L)):
146 a = hash(a)
147
148 a, x = divmod(a, 30268)
149 a, y = divmod(a, 30306)
150 a, z = divmod(a, 30322)
151 self._seed = int(x)+1, int(y)+1, int(z)+1
Tim Petersd7b5e882001-01-25 03:36:26 +0000152
Tim Petersd7b5e882001-01-25 03:36:26 +0000153 def random(self):
154 """Get the next random number in the range [0.0, 1.0)."""
155
156 # Wichman-Hill random number generator.
157 #
158 # Wichmann, B. A. & Hill, I. D. (1982)
159 # Algorithm AS 183:
160 # An efficient and portable pseudo-random number generator
161 # Applied Statistics 31 (1982) 188-190
162 #
163 # see also:
164 # Correction to Algorithm AS 183
165 # Applied Statistics 33 (1984) 123
166 #
167 # McLeod, A. I. (1985)
168 # A remark on Algorithm AS 183
169 # Applied Statistics 34 (1985),198-200
170
171 # This part is thread-unsafe:
172 # BEGIN CRITICAL SECTION
173 x, y, z = self._seed
174 x = (171 * x) % 30269
175 y = (172 * y) % 30307
176 z = (170 * z) % 30323
177 self._seed = x, y, z
178 # END CRITICAL SECTION
179
180 # Note: on a platform using IEEE-754 double arithmetic, this can
181 # never return 0.0 (asserted by Tim; proof too long for a comment).
182 return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
183
Tim Peterscd804102001-01-25 20:25:57 +0000184 def getstate(self):
185 """Return internal state; can be passed to setstate() later."""
186 return self.VERSION, self._seed, self.gauss_next
187
188 def setstate(self, state):
189 """Restore internal state from object returned by getstate()."""
190 version = state[0]
191 if version == 1:
192 version, self._seed, self.gauss_next = state
193 else:
194 raise ValueError("state with version %s passed to "
195 "Random.setstate() of version %s" %
196 (version, self.VERSION))
197
198 def jumpahead(self, n):
199 """Act as if n calls to random() were made, but quickly.
200
201 n is an int, greater than or equal to 0.
202
203 Example use: If you have 2 threads and know that each will
204 consume no more than a million random numbers, create two Random
205 objects r1 and r2, then do
206 r2.setstate(r1.getstate())
207 r2.jumpahead(1000000)
208 Then r1 and r2 will use guaranteed-disjoint segments of the full
209 period.
210 """
211
212 if not n >= 0:
213 raise ValueError("n must be >= 0")
214 x, y, z = self._seed
215 x = int(x * pow(171, n, 30269)) % 30269
216 y = int(y * pow(172, n, 30307)) % 30307
217 z = int(z * pow(170, n, 30323)) % 30323
218 self._seed = x, y, z
219
Tim Peters0de88fc2001-02-01 04:59:18 +0000220 def __whseed(self, x=0, y=0, z=0):
221 """Set the Wichmann-Hill seed from (x, y, z).
222
223 These must be integers in the range [0, 256).
224 """
225
226 if not type(x) == type(y) == type(z) == type(0):
227 raise TypeError('seeds must be integers')
228 if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256):
229 raise ValueError('seeds must be in range(0, 256)')
230 if 0 == x == y == z:
231 # Initialize from current time
232 import time
233 t = long(time.time() * 256)
234 t = int((t&0xffffff) ^ (t>>24))
235 t, x = divmod(t, 256)
236 t, y = divmod(t, 256)
237 t, z = divmod(t, 256)
238 # Zero is a poor seed, so substitute 1
239 self._seed = (x or 1, y or 1, z or 1)
240
241 def whseed(self, a=None):
242 """Seed from hashable object's hash code.
243
244 None or no argument seeds from current time. It is not guaranteed
245 that objects with distinct hash codes lead to distinct internal
246 states.
247
248 This is obsolete, provided for compatibility with the seed routine
249 used prior to Python 2.1. Use the .seed() method instead.
250 """
251
252 if a is None:
253 self.__whseed()
254 return
255 a = hash(a)
256 a, x = divmod(a, 256)
257 a, y = divmod(a, 256)
258 a, z = divmod(a, 256)
259 x = (x + a) % 256 or 1
260 y = (y + a) % 256 or 1
261 z = (z + a) % 256 or 1
262 self.__whseed(x, y, z)
263
Tim Peterscd804102001-01-25 20:25:57 +0000264## ---- Methods below this point do not need to be overridden when
265## ---- subclassing for the purpose of using a different core generator.
266
267## -------------------- pickle support -------------------
268
269 def __getstate__(self): # for pickle
270 return self.getstate()
271
272 def __setstate__(self, state): # for pickle
273 self.setstate(state)
274
275## -------------------- integer methods -------------------
276
Tim Petersd7b5e882001-01-25 03:36:26 +0000277 def randrange(self, start, stop=None, step=1, int=int, default=None):
278 """Choose a random item from range(start, stop[, step]).
279
280 This fixes the problem with randint() which includes the
281 endpoint; in Python this is usually not what you want.
282 Do not supply the 'int' and 'default' arguments.
283 """
284
285 # This code is a bit messy to make it fast for the
286 # common case while still doing adequate error checking
287 istart = int(start)
288 if istart != start:
289 raise ValueError, "non-integer arg 1 for randrange()"
290 if stop is default:
291 if istart > 0:
292 return int(self.random() * istart)
293 raise ValueError, "empty range for randrange()"
294 istop = int(stop)
295 if istop != stop:
296 raise ValueError, "non-integer stop for randrange()"
297 if step == 1:
298 if istart < istop:
299 return istart + int(self.random() *
300 (istop - istart))
301 raise ValueError, "empty range for randrange()"
302 istep = int(step)
303 if istep != step:
304 raise ValueError, "non-integer step for randrange()"
305 if istep > 0:
306 n = (istop - istart + istep - 1) / istep
307 elif istep < 0:
308 n = (istop - istart + istep + 1) / istep
309 else:
310 raise ValueError, "zero step for randrange()"
311
312 if n <= 0:
313 raise ValueError, "empty range for randrange()"
314 return istart + istep*int(self.random() * n)
315
316 def randint(self, a, b):
Tim Peterscd804102001-01-25 20:25:57 +0000317 """Return random integer in range [a, b], including both end points.
Tim Petersd7b5e882001-01-25 03:36:26 +0000318 """
319
320 return self.randrange(a, b+1)
321
Tim Peterscd804102001-01-25 20:25:57 +0000322## -------------------- sequence methods -------------------
323
Tim Petersd7b5e882001-01-25 03:36:26 +0000324 def choice(self, seq):
325 """Choose a random element from a non-empty sequence."""
326 return seq[int(self.random() * len(seq))]
327
328 def shuffle(self, x, random=None, int=int):
329 """x, random=random.random -> shuffle list x in place; return None.
330
331 Optional arg random is a 0-argument function returning a random
332 float in [0.0, 1.0); by default, the standard random.random.
333
334 Note that for even rather small len(x), the total number of
335 permutations of x is larger than the period of most random number
336 generators; this implies that "most" permutations of a long
337 sequence can never be generated.
338 """
339
340 if random is None:
341 random = self.random
342 for i in xrange(len(x)-1, 0, -1):
Tim Peterscd804102001-01-25 20:25:57 +0000343 # pick an element in x[:i+1] with which to exchange x[i]
Tim Petersd7b5e882001-01-25 03:36:26 +0000344 j = int(random() * (i+1))
345 x[i], x[j] = x[j], x[i]
346
Tim Peterscd804102001-01-25 20:25:57 +0000347## -------------------- real-valued distributions -------------------
348
349## -------------------- uniform distribution -------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000350
351 def uniform(self, a, b):
352 """Get a random number in the range [a, b)."""
353 return a + (b-a) * self.random()
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000354
Tim Peterscd804102001-01-25 20:25:57 +0000355## -------------------- normal distribution --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000356
Tim Petersd7b5e882001-01-25 03:36:26 +0000357 def normalvariate(self, mu, sigma):
358 # mu = mean, sigma = standard deviation
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000359
Tim Petersd7b5e882001-01-25 03:36:26 +0000360 # Uses Kinderman and Monahan method. Reference: Kinderman,
361 # A.J. and Monahan, J.F., "Computer generation of random
362 # variables using the ratio of uniform deviates", ACM Trans
363 # Math Software, 3, (1977), pp257-260.
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000364
Tim Petersd7b5e882001-01-25 03:36:26 +0000365 random = self.random
Tim Peters0c9886d2001-01-15 01:18:21 +0000366 while 1:
367 u1 = random()
368 u2 = random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000369 z = NV_MAGICCONST*(u1-0.5)/u2
370 zz = z*z/4.0
371 if zz <= -_log(u2):
372 break
373 return mu + z*sigma
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000374
Tim Peterscd804102001-01-25 20:25:57 +0000375## -------------------- lognormal distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000376
377 def lognormvariate(self, mu, sigma):
378 return _exp(self.normalvariate(mu, sigma))
379
Tim Peterscd804102001-01-25 20:25:57 +0000380## -------------------- circular uniform --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000381
382 def cunifvariate(self, mean, arc):
383 # mean: mean angle (in radians between 0 and pi)
384 # arc: range of distribution (in radians between 0 and pi)
385
386 return (mean + arc * (self.random() - 0.5)) % _pi
387
Tim Peterscd804102001-01-25 20:25:57 +0000388## -------------------- exponential distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000389
390 def expovariate(self, lambd):
391 # lambd: rate lambd = 1/mean
392 # ('lambda' is a Python reserved word)
393
394 random = self.random
Tim Peters0c9886d2001-01-15 01:18:21 +0000395 u = random()
396 while u <= 1e-7:
397 u = random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000398 return -_log(u)/lambd
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000399
Tim Peterscd804102001-01-25 20:25:57 +0000400## -------------------- von Mises distribution --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000401
Tim Petersd7b5e882001-01-25 03:36:26 +0000402 def vonmisesvariate(self, mu, kappa):
403 # mu: mean angle (in radians between 0 and 2*pi)
404 # kappa: concentration parameter kappa (>= 0)
405 # if kappa = 0 generate uniform random angle
406
407 # Based upon an algorithm published in: Fisher, N.I.,
408 # "Statistical Analysis of Circular Data", Cambridge
409 # University Press, 1993.
410
411 # Thanks to Magnus Kessler for a correction to the
412 # implementation of step 4.
413
414 random = self.random
415 if kappa <= 1e-6:
416 return TWOPI * random()
417
418 a = 1.0 + _sqrt(1.0 + 4.0 * kappa * kappa)
419 b = (a - _sqrt(2.0 * a))/(2.0 * kappa)
420 r = (1.0 + b * b)/(2.0 * b)
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000421
Tim Peters0c9886d2001-01-15 01:18:21 +0000422 while 1:
Tim Peters0c9886d2001-01-15 01:18:21 +0000423 u1 = random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000424
425 z = _cos(_pi * u1)
426 f = (1.0 + r * z)/(r + z)
427 c = kappa * (r - f)
428
429 u2 = random()
430
431 if not (u2 >= c * (2.0 - c) and u2 > c * _exp(1.0 - c)):
Tim Peters0c9886d2001-01-15 01:18:21 +0000432 break
Tim Petersd7b5e882001-01-25 03:36:26 +0000433
434 u3 = random()
435 if u3 > 0.5:
436 theta = (mu % TWOPI) + _acos(f)
437 else:
438 theta = (mu % TWOPI) - _acos(f)
439
440 return theta
441
Tim Peterscd804102001-01-25 20:25:57 +0000442## -------------------- gamma distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000443
444 def gammavariate(self, alpha, beta):
445 # beta times standard gamma
446 ainv = _sqrt(2.0 * alpha - 1.0)
447 return beta * self.stdgamma(alpha, ainv, alpha - LOG4, alpha + ainv)
448
449 def stdgamma(self, alpha, ainv, bbb, ccc):
450 # ainv = sqrt(2 * alpha - 1)
451 # bbb = alpha - log(4)
452 # ccc = alpha + ainv
453
454 random = self.random
455 if alpha <= 0.0:
456 raise ValueError, 'stdgamma: alpha must be > 0.0'
457
458 if alpha > 1.0:
459
460 # Uses R.C.H. Cheng, "The generation of Gamma
461 # variables with non-integral shape parameters",
462 # Applied Statistics, (1977), 26, No. 1, p71-74
463
464 while 1:
465 u1 = random()
466 u2 = random()
467 v = _log(u1/(1.0-u1))/ainv
468 x = alpha*_exp(v)
469 z = u1*u1*u2
470 r = bbb+ccc*v-x
471 if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z):
472 return x
473
474 elif alpha == 1.0:
475 # expovariate(1)
476 u = random()
477 while u <= 1e-7:
478 u = random()
479 return -_log(u)
480
481 else: # alpha is between 0 and 1 (exclusive)
482
483 # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
484
485 while 1:
486 u = random()
487 b = (_e + alpha)/_e
488 p = b*u
489 if p <= 1.0:
490 x = pow(p, 1.0/alpha)
491 else:
492 # p > 1
493 x = -_log((b-p)/alpha)
494 u1 = random()
495 if not (((p <= 1.0) and (u1 > _exp(-x))) or
496 ((p > 1) and (u1 > pow(x, alpha - 1.0)))):
497 break
498 return x
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000499
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000500
Tim Peterscd804102001-01-25 20:25:57 +0000501## -------------------- Gauss (faster alternative) --------------------
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000502
Tim Petersd7b5e882001-01-25 03:36:26 +0000503 def gauss(self, mu, sigma):
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000504
Tim Petersd7b5e882001-01-25 03:36:26 +0000505 # When x and y are two variables from [0, 1), uniformly
506 # distributed, then
507 #
508 # cos(2*pi*x)*sqrt(-2*log(1-y))
509 # sin(2*pi*x)*sqrt(-2*log(1-y))
510 #
511 # are two *independent* variables with normal distribution
512 # (mu = 0, sigma = 1).
513 # (Lambert Meertens)
514 # (corrected version; bug discovered by Mike Miller, fixed by LM)
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000515
Tim Petersd7b5e882001-01-25 03:36:26 +0000516 # Multithreading note: When two threads call this function
517 # simultaneously, it is possible that they will receive the
518 # same return value. The window is very small though. To
519 # avoid this, you have to use a lock around all calls. (I
520 # didn't want to slow this down in the serial case by using a
521 # lock here.)
Guido van Rossumd03e1191998-05-29 17:51:31 +0000522
Tim Petersd7b5e882001-01-25 03:36:26 +0000523 random = self.random
524 z = self.gauss_next
525 self.gauss_next = None
526 if z is None:
527 x2pi = random() * TWOPI
528 g2rad = _sqrt(-2.0 * _log(1.0 - random()))
529 z = _cos(x2pi) * g2rad
530 self.gauss_next = _sin(x2pi) * g2rad
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000531
Tim Petersd7b5e882001-01-25 03:36:26 +0000532 return mu + z*sigma
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000533
Tim Peterscd804102001-01-25 20:25:57 +0000534## -------------------- beta --------------------
Tim Peters85e2e472001-01-26 06:49:56 +0000535## See
536## http://sourceforge.net/bugs/?func=detailbug&bug_id=130030&group_id=5470
537## for Ivan Frohne's insightful analysis of why the original implementation:
538##
539## def betavariate(self, alpha, beta):
540## # Discrete Event Simulation in C, pp 87-88.
541##
542## y = self.expovariate(alpha)
543## z = self.expovariate(1.0/beta)
544## return z/(y+z)
545##
546## was dead wrong, and how it probably got that way.
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000547
Tim Petersd7b5e882001-01-25 03:36:26 +0000548 def betavariate(self, alpha, beta):
Tim Peters85e2e472001-01-26 06:49:56 +0000549 # This version due to Janne Sinkkonen, and matches all the std
550 # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution").
551 y = self.gammavariate(alpha, 1.)
552 if y == 0:
553 return 0.0
554 else:
555 return y / (y + self.gammavariate(beta, 1.))
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000556
Tim Peterscd804102001-01-25 20:25:57 +0000557## -------------------- Pareto --------------------
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000558
Tim Petersd7b5e882001-01-25 03:36:26 +0000559 def paretovariate(self, alpha):
560 # Jain, pg. 495
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000561
Tim Petersd7b5e882001-01-25 03:36:26 +0000562 u = self.random()
563 return 1.0 / pow(u, 1.0/alpha)
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000564
Tim Peterscd804102001-01-25 20:25:57 +0000565## -------------------- Weibull --------------------
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000566
Tim Petersd7b5e882001-01-25 03:36:26 +0000567 def weibullvariate(self, alpha, beta):
568 # Jain, pg. 499; bug fix courtesy Bill Arms
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000569
Tim Petersd7b5e882001-01-25 03:36:26 +0000570 u = self.random()
571 return alpha * pow(-_log(u), 1.0/beta)
Guido van Rossum6c395ba1999-08-18 13:53:28 +0000572
Tim Peterscd804102001-01-25 20:25:57 +0000573## -------------------- test program --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000574
Tim Petersd7b5e882001-01-25 03:36:26 +0000575def _test_generator(n, funccall):
Tim Peters0c9886d2001-01-15 01:18:21 +0000576 import time
577 print n, 'times', funccall
578 code = compile(funccall, funccall, 'eval')
579 sum = 0.0
580 sqsum = 0.0
581 smallest = 1e10
582 largest = -1e10
583 t0 = time.time()
584 for i in range(n):
585 x = eval(code)
586 sum = sum + x
587 sqsum = sqsum + x*x
588 smallest = min(x, smallest)
589 largest = max(x, largest)
590 t1 = time.time()
591 print round(t1-t0, 3), 'sec,',
592 avg = sum/n
Tim Petersd7b5e882001-01-25 03:36:26 +0000593 stddev = _sqrt(sqsum/n - avg*avg)
Tim Peters0c9886d2001-01-15 01:18:21 +0000594 print 'avg %g, stddev %g, min %g, max %g' % \
595 (avg, stddev, smallest, largest)
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000596
Tim Petersd7b5e882001-01-25 03:36:26 +0000597def _test(N=200):
598 print 'TWOPI =', TWOPI
599 print 'LOG4 =', LOG4
600 print 'NV_MAGICCONST =', NV_MAGICCONST
601 print 'SG_MAGICCONST =', SG_MAGICCONST
602 _test_generator(N, 'random()')
603 _test_generator(N, 'normalvariate(0.0, 1.0)')
604 _test_generator(N, 'lognormvariate(0.0, 1.0)')
605 _test_generator(N, 'cunifvariate(0.0, 1.0)')
606 _test_generator(N, 'expovariate(1.0)')
607 _test_generator(N, 'vonmisesvariate(0.0, 1.0)')
608 _test_generator(N, 'gammavariate(0.5, 1.0)')
609 _test_generator(N, 'gammavariate(0.9, 1.0)')
610 _test_generator(N, 'gammavariate(1.0, 1.0)')
611 _test_generator(N, 'gammavariate(2.0, 1.0)')
612 _test_generator(N, 'gammavariate(20.0, 1.0)')
613 _test_generator(N, 'gammavariate(200.0, 1.0)')
614 _test_generator(N, 'gauss(0.0, 1.0)')
615 _test_generator(N, 'betavariate(3.0, 3.0)')
616 _test_generator(N, 'paretovariate(1.0)')
617 _test_generator(N, 'weibullvariate(1.0, 1.0)')
618
Tim Peterscd804102001-01-25 20:25:57 +0000619 # Test jumpahead.
620 s = getstate()
621 jumpahead(N)
622 r1 = random()
623 # now do it the slow way
624 setstate(s)
625 for i in range(N):
626 random()
627 r2 = random()
628 if r1 != r2:
629 raise ValueError("jumpahead test failed " + `(N, r1, r2)`)
630
Tim Peters715c4c42001-01-26 22:56:56 +0000631# Create one instance, seeded from current time, and export its methods
632# as module-level functions. The functions are not threadsafe, and state
633# is shared across all uses (both in the user's code and in the Python
634# libraries), but that's fine for most programs and is easier for the
635# casual user than making them instantiate their own Random() instance.
Tim Petersd7b5e882001-01-25 03:36:26 +0000636_inst = Random()
637seed = _inst.seed
638random = _inst.random
639uniform = _inst.uniform
640randint = _inst.randint
641choice = _inst.choice
642randrange = _inst.randrange
643shuffle = _inst.shuffle
644normalvariate = _inst.normalvariate
645lognormvariate = _inst.lognormvariate
646cunifvariate = _inst.cunifvariate
647expovariate = _inst.expovariate
648vonmisesvariate = _inst.vonmisesvariate
649gammavariate = _inst.gammavariate
650stdgamma = _inst.stdgamma
651gauss = _inst.gauss
652betavariate = _inst.betavariate
653paretovariate = _inst.paretovariate
654weibullvariate = _inst.weibullvariate
655getstate = _inst.getstate
656setstate = _inst.setstate
Tim Petersd52269b2001-01-25 06:23:18 +0000657jumpahead = _inst.jumpahead
Tim Peters0de88fc2001-02-01 04:59:18 +0000658whseed = _inst.whseed
Tim Petersd7b5e882001-01-25 03:36:26 +0000659
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000660if __name__ == '__main__':
Tim Petersd7b5e882001-01-25 03:36:26 +0000661 _test()