blob: 424a9052b23c0f1144a6edd4c39ea377498e9687 [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:
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000109 """Random number generator base class used by bound module functions.
110
111 Used to instantiate instances of Random to get generators that don't
112 share state. Especially useful for multi-threaded programs, creating
113 a different instance of Random for each thread, and using the jumpahead()
114 method to ensure that the generated sequences seen by each thread don't
115 overlap.
116
117 Class Random can also be subclassed if you want to use a different basic
118 generator of your own devising: in that case, override the following
119 methods: random(), seed(), getstate(), setstate() and jumpahead().
120
121 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000122
123 VERSION = 1 # used by getstate/setstate
124
125 def __init__(self, x=None):
126 """Initialize an instance.
127
128 Optional argument x controls seeding, as for Random.seed().
129 """
130
131 self.seed(x)
Tim Petersd7b5e882001-01-25 03:36:26 +0000132
Tim Peterscd804102001-01-25 20:25:57 +0000133## -------------------- core generator -------------------
134
Tim Petersd7b5e882001-01-25 03:36:26 +0000135 # Specific to Wichmann-Hill generator. Subclasses wishing to use a
Tim Petersd52269b2001-01-25 06:23:18 +0000136 # different core generator should override the seed(), random(),
Tim Peterscd804102001-01-25 20:25:57 +0000137 # getstate(), setstate() and jumpahead() methods.
Tim Petersd7b5e882001-01-25 03:36:26 +0000138
Tim Peters0de88fc2001-02-01 04:59:18 +0000139 def seed(self, a=None):
140 """Initialize internal state from hashable object.
Tim Petersd7b5e882001-01-25 03:36:26 +0000141
Tim Peters0de88fc2001-02-01 04:59:18 +0000142 None or no argument seeds from current time.
143
Tim Petersbcd725f2001-02-01 10:06:53 +0000144 If a is not None or an int or long, hash(a) is used instead.
Tim Peters0de88fc2001-02-01 04:59:18 +0000145
146 If a is an int or long, a is used directly. Distinct values between
147 0 and 27814431486575L inclusive are guaranteed to yield distinct
148 internal states (this guarantee is specific to the default
149 Wichmann-Hill generator).
Tim Petersd7b5e882001-01-25 03:36:26 +0000150 """
151
Tim Peters0de88fc2001-02-01 04:59:18 +0000152 if a is None:
Tim Petersd7b5e882001-01-25 03:36:26 +0000153 # Initialize from current time
154 import time
Tim Peters0de88fc2001-02-01 04:59:18 +0000155 a = long(time.time() * 256)
156
157 if type(a) not in (type(3), type(3L)):
158 a = hash(a)
159
160 a, x = divmod(a, 30268)
161 a, y = divmod(a, 30306)
162 a, z = divmod(a, 30322)
163 self._seed = int(x)+1, int(y)+1, int(z)+1
Tim Petersd7b5e882001-01-25 03:36:26 +0000164
Tim Peters46c04e12002-05-05 20:40:00 +0000165 self.gauss_next = None
166
Tim Petersd7b5e882001-01-25 03:36:26 +0000167 def random(self):
168 """Get the next random number in the range [0.0, 1.0)."""
169
170 # Wichman-Hill random number generator.
171 #
172 # Wichmann, B. A. & Hill, I. D. (1982)
173 # Algorithm AS 183:
174 # An efficient and portable pseudo-random number generator
175 # Applied Statistics 31 (1982) 188-190
176 #
177 # see also:
178 # Correction to Algorithm AS 183
179 # Applied Statistics 33 (1984) 123
180 #
181 # McLeod, A. I. (1985)
182 # A remark on Algorithm AS 183
183 # Applied Statistics 34 (1985),198-200
184
185 # This part is thread-unsafe:
186 # BEGIN CRITICAL SECTION
187 x, y, z = self._seed
188 x = (171 * x) % 30269
189 y = (172 * y) % 30307
190 z = (170 * z) % 30323
191 self._seed = x, y, z
192 # END CRITICAL SECTION
193
194 # Note: on a platform using IEEE-754 double arithmetic, this can
195 # never return 0.0 (asserted by Tim; proof too long for a comment).
196 return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
197
Tim Peterscd804102001-01-25 20:25:57 +0000198 def getstate(self):
199 """Return internal state; can be passed to setstate() later."""
200 return self.VERSION, self._seed, self.gauss_next
201
202 def setstate(self, state):
203 """Restore internal state from object returned by getstate()."""
204 version = state[0]
205 if version == 1:
206 version, self._seed, self.gauss_next = state
207 else:
208 raise ValueError("state with version %s passed to "
209 "Random.setstate() of version %s" %
210 (version, self.VERSION))
211
212 def jumpahead(self, n):
213 """Act as if n calls to random() were made, but quickly.
214
215 n is an int, greater than or equal to 0.
216
217 Example use: If you have 2 threads and know that each will
218 consume no more than a million random numbers, create two Random
219 objects r1 and r2, then do
220 r2.setstate(r1.getstate())
221 r2.jumpahead(1000000)
222 Then r1 and r2 will use guaranteed-disjoint segments of the full
223 period.
224 """
225
226 if not n >= 0:
227 raise ValueError("n must be >= 0")
228 x, y, z = self._seed
229 x = int(x * pow(171, n, 30269)) % 30269
230 y = int(y * pow(172, n, 30307)) % 30307
231 z = int(z * pow(170, n, 30323)) % 30323
232 self._seed = x, y, z
233
Tim Peters0de88fc2001-02-01 04:59:18 +0000234 def __whseed(self, x=0, y=0, z=0):
235 """Set the Wichmann-Hill seed from (x, y, z).
236
237 These must be integers in the range [0, 256).
238 """
239
240 if not type(x) == type(y) == type(z) == type(0):
241 raise TypeError('seeds must be integers')
242 if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256):
243 raise ValueError('seeds must be in range(0, 256)')
244 if 0 == x == y == z:
245 # Initialize from current time
246 import time
247 t = long(time.time() * 256)
248 t = int((t&0xffffff) ^ (t>>24))
249 t, x = divmod(t, 256)
250 t, y = divmod(t, 256)
251 t, z = divmod(t, 256)
252 # Zero is a poor seed, so substitute 1
253 self._seed = (x or 1, y or 1, z or 1)
254
Tim Peters46c04e12002-05-05 20:40:00 +0000255 self.gauss_next = None
256
Tim Peters0de88fc2001-02-01 04:59:18 +0000257 def whseed(self, a=None):
258 """Seed from hashable object's hash code.
259
260 None or no argument seeds from current time. It is not guaranteed
261 that objects with distinct hash codes lead to distinct internal
262 states.
263
264 This is obsolete, provided for compatibility with the seed routine
265 used prior to Python 2.1. Use the .seed() method instead.
266 """
267
268 if a is None:
269 self.__whseed()
270 return
271 a = hash(a)
272 a, x = divmod(a, 256)
273 a, y = divmod(a, 256)
274 a, z = divmod(a, 256)
275 x = (x + a) % 256 or 1
276 y = (y + a) % 256 or 1
277 z = (z + a) % 256 or 1
278 self.__whseed(x, y, z)
279
Tim Peterscd804102001-01-25 20:25:57 +0000280## ---- Methods below this point do not need to be overridden when
281## ---- subclassing for the purpose of using a different core generator.
282
283## -------------------- pickle support -------------------
284
285 def __getstate__(self): # for pickle
286 return self.getstate()
287
288 def __setstate__(self, state): # for pickle
289 self.setstate(state)
290
291## -------------------- integer methods -------------------
292
Tim Petersd7b5e882001-01-25 03:36:26 +0000293 def randrange(self, start, stop=None, step=1, int=int, default=None):
294 """Choose a random item from range(start, stop[, step]).
295
296 This fixes the problem with randint() which includes the
297 endpoint; in Python this is usually not what you want.
298 Do not supply the 'int' and 'default' arguments.
299 """
300
301 # This code is a bit messy to make it fast for the
302 # common case while still doing adequate error checking
303 istart = int(start)
304 if istart != start:
305 raise ValueError, "non-integer arg 1 for randrange()"
306 if stop is default:
307 if istart > 0:
308 return int(self.random() * istart)
309 raise ValueError, "empty range for randrange()"
310 istop = int(stop)
311 if istop != stop:
312 raise ValueError, "non-integer stop for randrange()"
313 if step == 1:
314 if istart < istop:
315 return istart + int(self.random() *
316 (istop - istart))
317 raise ValueError, "empty range for randrange()"
318 istep = int(step)
319 if istep != step:
320 raise ValueError, "non-integer step for randrange()"
321 if istep > 0:
322 n = (istop - istart + istep - 1) / istep
323 elif istep < 0:
324 n = (istop - istart + istep + 1) / istep
325 else:
326 raise ValueError, "zero step for randrange()"
327
328 if n <= 0:
329 raise ValueError, "empty range for randrange()"
330 return istart + istep*int(self.random() * n)
331
332 def randint(self, a, b):
Tim Peterscd804102001-01-25 20:25:57 +0000333 """Return random integer in range [a, b], including both end points.
Tim Petersd7b5e882001-01-25 03:36:26 +0000334 """
335
336 return self.randrange(a, b+1)
337
Tim Peterscd804102001-01-25 20:25:57 +0000338## -------------------- sequence methods -------------------
339
Tim Petersd7b5e882001-01-25 03:36:26 +0000340 def choice(self, seq):
341 """Choose a random element from a non-empty sequence."""
342 return seq[int(self.random() * len(seq))]
343
344 def shuffle(self, x, random=None, int=int):
345 """x, random=random.random -> shuffle list x in place; return None.
346
347 Optional arg random is a 0-argument function returning a random
348 float in [0.0, 1.0); by default, the standard random.random.
349
350 Note that for even rather small len(x), the total number of
351 permutations of x is larger than the period of most random number
352 generators; this implies that "most" permutations of a long
353 sequence can never be generated.
354 """
355
356 if random is None:
357 random = self.random
358 for i in xrange(len(x)-1, 0, -1):
Tim Peterscd804102001-01-25 20:25:57 +0000359 # pick an element in x[:i+1] with which to exchange x[i]
Tim Petersd7b5e882001-01-25 03:36:26 +0000360 j = int(random() * (i+1))
361 x[i], x[j] = x[j], x[i]
362
Tim Peterscd804102001-01-25 20:25:57 +0000363## -------------------- real-valued distributions -------------------
364
365## -------------------- uniform distribution -------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000366
367 def uniform(self, a, b):
368 """Get a random number in the range [a, b)."""
369 return a + (b-a) * self.random()
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000370
Tim Peterscd804102001-01-25 20:25:57 +0000371## -------------------- normal distribution --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000372
Tim Petersd7b5e882001-01-25 03:36:26 +0000373 def normalvariate(self, mu, sigma):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000374 """Normal distribution.
375
376 mu is the mean, and sigma is the standard deviation.
377
378 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000379 # mu = mean, sigma = standard deviation
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000380
Tim Petersd7b5e882001-01-25 03:36:26 +0000381 # Uses Kinderman and Monahan method. Reference: Kinderman,
382 # A.J. and Monahan, J.F., "Computer generation of random
383 # variables using the ratio of uniform deviates", ACM Trans
384 # Math Software, 3, (1977), pp257-260.
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000385
Tim Petersd7b5e882001-01-25 03:36:26 +0000386 random = self.random
Tim Peters0c9886d2001-01-15 01:18:21 +0000387 while 1:
388 u1 = random()
389 u2 = random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000390 z = NV_MAGICCONST*(u1-0.5)/u2
391 zz = z*z/4.0
392 if zz <= -_log(u2):
393 break
394 return mu + z*sigma
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000395
Tim Peterscd804102001-01-25 20:25:57 +0000396## -------------------- lognormal distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000397
398 def lognormvariate(self, mu, sigma):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000399 """Log normal distribution.
400
401 If you take the natural logarithm of this distribution, you'll get a
402 normal distribution with mean mu and standard deviation sigma.
403 mu can have any value, and sigma must be greater than zero.
404
405 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000406 return _exp(self.normalvariate(mu, sigma))
407
Tim Peterscd804102001-01-25 20:25:57 +0000408## -------------------- circular uniform --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000409
410 def cunifvariate(self, mean, arc):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000411 """Circular uniform distribution.
412
413 mean is the mean angle, and arc is the range of the distribution,
414 centered around the mean angle. Both values must be expressed in
415 radians. Returned values range between mean - arc/2 and
416 mean + arc/2 and are normalized to between 0 and pi.
417
418 Deprecated in version 2.3. Use:
419 (mean + arc * (Random.random() - 0.5)) % Math.pi
420
421 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000422 # mean: mean angle (in radians between 0 and pi)
423 # arc: range of distribution (in radians between 0 and pi)
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000424 import warnings
425 warnings.warn("The cunifvariate function is deprecated; Use (mean "
426 "+ arc * (Random.random() - 0.5)) % Math.pi instead",
427 DeprecationWarning)
Tim Petersd7b5e882001-01-25 03:36:26 +0000428
429 return (mean + arc * (self.random() - 0.5)) % _pi
430
Tim Peterscd804102001-01-25 20:25:57 +0000431## -------------------- exponential distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000432
433 def expovariate(self, lambd):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000434 """Exponential distribution.
435
436 lambd is 1.0 divided by the desired mean. (The parameter would be
437 called "lambda", but that is a reserved word in Python.) Returned
438 values range from 0 to positive infinity.
439
440 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000441 # lambd: rate lambd = 1/mean
442 # ('lambda' is a Python reserved word)
443
444 random = self.random
Tim Peters0c9886d2001-01-15 01:18:21 +0000445 u = random()
446 while u <= 1e-7:
447 u = random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000448 return -_log(u)/lambd
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000449
Tim Peterscd804102001-01-25 20:25:57 +0000450## -------------------- von Mises distribution --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000451
Tim Petersd7b5e882001-01-25 03:36:26 +0000452 def vonmisesvariate(self, mu, kappa):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000453 """Circular data distribution.
454
455 mu is the mean angle, expressed in radians between 0 and 2*pi, and
456 kappa is the concentration parameter, which must be greater than or
457 equal to zero. If kappa is equal to zero, this distribution reduces
458 to a uniform random angle over the range 0 to 2*pi.
459
460 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000461 # mu: mean angle (in radians between 0 and 2*pi)
462 # kappa: concentration parameter kappa (>= 0)
463 # if kappa = 0 generate uniform random angle
464
465 # Based upon an algorithm published in: Fisher, N.I.,
466 # "Statistical Analysis of Circular Data", Cambridge
467 # University Press, 1993.
468
469 # Thanks to Magnus Kessler for a correction to the
470 # implementation of step 4.
471
472 random = self.random
473 if kappa <= 1e-6:
474 return TWOPI * random()
475
476 a = 1.0 + _sqrt(1.0 + 4.0 * kappa * kappa)
477 b = (a - _sqrt(2.0 * a))/(2.0 * kappa)
478 r = (1.0 + b * b)/(2.0 * b)
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000479
Tim Peters0c9886d2001-01-15 01:18:21 +0000480 while 1:
Tim Peters0c9886d2001-01-15 01:18:21 +0000481 u1 = random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000482
483 z = _cos(_pi * u1)
484 f = (1.0 + r * z)/(r + z)
485 c = kappa * (r - f)
486
487 u2 = random()
488
489 if not (u2 >= c * (2.0 - c) and u2 > c * _exp(1.0 - c)):
Tim Peters0c9886d2001-01-15 01:18:21 +0000490 break
Tim Petersd7b5e882001-01-25 03:36:26 +0000491
492 u3 = random()
493 if u3 > 0.5:
494 theta = (mu % TWOPI) + _acos(f)
495 else:
496 theta = (mu % TWOPI) - _acos(f)
497
498 return theta
499
Tim Peterscd804102001-01-25 20:25:57 +0000500## -------------------- gamma distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000501
502 def gammavariate(self, alpha, beta):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000503 """Gamma distribution. Not the gamma function!
504
505 Conditions on the parameters are alpha > 0 and beta > 0.
506
507 """
Tim Peters8ac14952002-05-23 15:15:30 +0000508
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000509 # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2
Tim Peters8ac14952002-05-23 15:15:30 +0000510
Guido van Rossum570764d2002-05-14 14:08:12 +0000511 # Warning: a few older sources define the gamma distribution in terms
512 # of alpha > -1.0
513 if alpha <= 0.0 or beta <= 0.0:
514 raise ValueError, 'gammavariate: alpha and beta must be > 0.0'
Tim Peters8ac14952002-05-23 15:15:30 +0000515
Tim Petersd7b5e882001-01-25 03:36:26 +0000516 random = self.random
Tim Petersd7b5e882001-01-25 03:36:26 +0000517 if alpha > 1.0:
518
519 # Uses R.C.H. Cheng, "The generation of Gamma
520 # variables with non-integral shape parameters",
521 # Applied Statistics, (1977), 26, No. 1, p71-74
522
Raymond Hettingerca6cdc22002-05-13 23:40:14 +0000523 ainv = _sqrt(2.0 * alpha - 1.0)
524 bbb = alpha - LOG4
525 ccc = alpha + ainv
Tim Peters8ac14952002-05-23 15:15:30 +0000526
Tim Petersd7b5e882001-01-25 03:36:26 +0000527 while 1:
528 u1 = random()
529 u2 = random()
530 v = _log(u1/(1.0-u1))/ainv
531 x = alpha*_exp(v)
532 z = u1*u1*u2
533 r = bbb+ccc*v-x
534 if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z):
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000535 return x * beta
Tim Petersd7b5e882001-01-25 03:36:26 +0000536
537 elif alpha == 1.0:
538 # expovariate(1)
539 u = random()
540 while u <= 1e-7:
541 u = random()
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000542 return -_log(u) * beta
Tim Petersd7b5e882001-01-25 03:36:26 +0000543
544 else: # alpha is between 0 and 1 (exclusive)
545
546 # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
547
548 while 1:
549 u = random()
550 b = (_e + alpha)/_e
551 p = b*u
552 if p <= 1.0:
553 x = pow(p, 1.0/alpha)
554 else:
555 # p > 1
556 x = -_log((b-p)/alpha)
557 u1 = random()
558 if not (((p <= 1.0) and (u1 > _exp(-x))) or
559 ((p > 1) and (u1 > pow(x, alpha - 1.0)))):
560 break
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000561 return x * beta
562
563
564 def stdgamma(self, alpha, ainv, bbb, ccc):
565 # This method was (and shall remain) undocumented.
566 # This method is deprecated
567 # for the following reasons:
568 # 1. Returns same as .gammavariate(alpha, 1.0)
569 # 2. Requires caller to provide 3 extra arguments
570 # that are functions of alpha anyway
571 # 3. Can't be used for alpha < 0.5
572
573 # ainv = sqrt(2 * alpha - 1)
574 # bbb = alpha - log(4)
575 # ccc = alpha + ainv
576 import warnings
577 warnings.warn("The stdgamma function is deprecated; "
578 "use gammavariate() instead",
579 DeprecationWarning)
580 return self.gammavariate(alpha, 1.0)
581
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000582
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000583
Tim Peterscd804102001-01-25 20:25:57 +0000584## -------------------- Gauss (faster alternative) --------------------
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000585
Tim Petersd7b5e882001-01-25 03:36:26 +0000586 def gauss(self, mu, sigma):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000587 """Gaussian distribution.
588
589 mu is the mean, and sigma is the standard deviation. This is
590 slightly faster than the normalvariate() function.
591
592 Not thread-safe without a lock around calls.
593
594 """
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000595
Tim Petersd7b5e882001-01-25 03:36:26 +0000596 # When x and y are two variables from [0, 1), uniformly
597 # distributed, then
598 #
599 # cos(2*pi*x)*sqrt(-2*log(1-y))
600 # sin(2*pi*x)*sqrt(-2*log(1-y))
601 #
602 # are two *independent* variables with normal distribution
603 # (mu = 0, sigma = 1).
604 # (Lambert Meertens)
605 # (corrected version; bug discovered by Mike Miller, fixed by LM)
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000606
Tim Petersd7b5e882001-01-25 03:36:26 +0000607 # Multithreading note: When two threads call this function
608 # simultaneously, it is possible that they will receive the
609 # same return value. The window is very small though. To
610 # avoid this, you have to use a lock around all calls. (I
611 # didn't want to slow this down in the serial case by using a
612 # lock here.)
Guido van Rossumd03e1191998-05-29 17:51:31 +0000613
Tim Petersd7b5e882001-01-25 03:36:26 +0000614 random = self.random
615 z = self.gauss_next
616 self.gauss_next = None
617 if z is None:
618 x2pi = random() * TWOPI
619 g2rad = _sqrt(-2.0 * _log(1.0 - random()))
620 z = _cos(x2pi) * g2rad
621 self.gauss_next = _sin(x2pi) * g2rad
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000622
Tim Petersd7b5e882001-01-25 03:36:26 +0000623 return mu + z*sigma
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000624
Tim Peterscd804102001-01-25 20:25:57 +0000625## -------------------- beta --------------------
Tim Peters85e2e472001-01-26 06:49:56 +0000626## See
627## http://sourceforge.net/bugs/?func=detailbug&bug_id=130030&group_id=5470
628## for Ivan Frohne's insightful analysis of why the original implementation:
629##
630## def betavariate(self, alpha, beta):
631## # Discrete Event Simulation in C, pp 87-88.
632##
633## y = self.expovariate(alpha)
634## z = self.expovariate(1.0/beta)
635## return z/(y+z)
636##
637## was dead wrong, and how it probably got that way.
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000638
Tim Petersd7b5e882001-01-25 03:36:26 +0000639 def betavariate(self, alpha, beta):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000640 """Beta distribution.
641
642 Conditions on the parameters are alpha > -1 and beta} > -1.
643 Returned values range between 0 and 1.
644
645 """
646
Tim Peters85e2e472001-01-26 06:49:56 +0000647 # This version due to Janne Sinkkonen, and matches all the std
648 # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution").
649 y = self.gammavariate(alpha, 1.)
650 if y == 0:
651 return 0.0
652 else:
653 return y / (y + self.gammavariate(beta, 1.))
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000654
Tim Peterscd804102001-01-25 20:25:57 +0000655## -------------------- Pareto --------------------
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000656
Tim Petersd7b5e882001-01-25 03:36:26 +0000657 def paretovariate(self, alpha):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000658 """Pareto distribution. alpha is the shape parameter."""
Tim Petersd7b5e882001-01-25 03:36:26 +0000659 # Jain, pg. 495
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000660
Tim Petersd7b5e882001-01-25 03:36:26 +0000661 u = self.random()
662 return 1.0 / pow(u, 1.0/alpha)
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000663
Tim Peterscd804102001-01-25 20:25:57 +0000664## -------------------- Weibull --------------------
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000665
Tim Petersd7b5e882001-01-25 03:36:26 +0000666 def weibullvariate(self, alpha, beta):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000667 """Weibull distribution.
668
669 alpha is the scale parameter and beta is the shape parameter.
670
671 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000672 # Jain, pg. 499; bug fix courtesy Bill Arms
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000673
Tim Petersd7b5e882001-01-25 03:36:26 +0000674 u = self.random()
675 return alpha * pow(-_log(u), 1.0/beta)
Guido van Rossum6c395ba1999-08-18 13:53:28 +0000676
Tim Peterscd804102001-01-25 20:25:57 +0000677## -------------------- test program --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000678
Tim Petersd7b5e882001-01-25 03:36:26 +0000679def _test_generator(n, funccall):
Tim Peters0c9886d2001-01-15 01:18:21 +0000680 import time
681 print n, 'times', funccall
682 code = compile(funccall, funccall, 'eval')
683 sum = 0.0
684 sqsum = 0.0
685 smallest = 1e10
686 largest = -1e10
687 t0 = time.time()
688 for i in range(n):
689 x = eval(code)
690 sum = sum + x
691 sqsum = sqsum + x*x
692 smallest = min(x, smallest)
693 largest = max(x, largest)
694 t1 = time.time()
695 print round(t1-t0, 3), 'sec,',
696 avg = sum/n
Tim Petersd7b5e882001-01-25 03:36:26 +0000697 stddev = _sqrt(sqsum/n - avg*avg)
Tim Peters0c9886d2001-01-15 01:18:21 +0000698 print 'avg %g, stddev %g, min %g, max %g' % \
699 (avg, stddev, smallest, largest)
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000700
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000701def _test(N=20000):
Tim Petersd7b5e882001-01-25 03:36:26 +0000702 print 'TWOPI =', TWOPI
703 print 'LOG4 =', LOG4
704 print 'NV_MAGICCONST =', NV_MAGICCONST
705 print 'SG_MAGICCONST =', SG_MAGICCONST
706 _test_generator(N, 'random()')
707 _test_generator(N, 'normalvariate(0.0, 1.0)')
708 _test_generator(N, 'lognormvariate(0.0, 1.0)')
709 _test_generator(N, 'cunifvariate(0.0, 1.0)')
710 _test_generator(N, 'expovariate(1.0)')
711 _test_generator(N, 'vonmisesvariate(0.0, 1.0)')
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000712 _test_generator(N, 'gammavariate(0.01, 1.0)')
713 _test_generator(N, 'gammavariate(0.1, 1.0)')
Tim Peters8ac14952002-05-23 15:15:30 +0000714 _test_generator(N, 'gammavariate(0.1, 2.0)')
Tim Petersd7b5e882001-01-25 03:36:26 +0000715 _test_generator(N, 'gammavariate(0.5, 1.0)')
716 _test_generator(N, 'gammavariate(0.9, 1.0)')
717 _test_generator(N, 'gammavariate(1.0, 1.0)')
718 _test_generator(N, 'gammavariate(2.0, 1.0)')
719 _test_generator(N, 'gammavariate(20.0, 1.0)')
720 _test_generator(N, 'gammavariate(200.0, 1.0)')
721 _test_generator(N, 'gauss(0.0, 1.0)')
722 _test_generator(N, 'betavariate(3.0, 3.0)')
723 _test_generator(N, 'paretovariate(1.0)')
724 _test_generator(N, 'weibullvariate(1.0, 1.0)')
725
Tim Peterscd804102001-01-25 20:25:57 +0000726 # Test jumpahead.
727 s = getstate()
728 jumpahead(N)
729 r1 = random()
730 # now do it the slow way
731 setstate(s)
732 for i in range(N):
733 random()
734 r2 = random()
735 if r1 != r2:
736 raise ValueError("jumpahead test failed " + `(N, r1, r2)`)
737
Tim Peters715c4c42001-01-26 22:56:56 +0000738# Create one instance, seeded from current time, and export its methods
739# as module-level functions. The functions are not threadsafe, and state
740# is shared across all uses (both in the user's code and in the Python
741# libraries), but that's fine for most programs and is easier for the
742# casual user than making them instantiate their own Random() instance.
Tim Petersd7b5e882001-01-25 03:36:26 +0000743_inst = Random()
744seed = _inst.seed
745random = _inst.random
746uniform = _inst.uniform
747randint = _inst.randint
748choice = _inst.choice
749randrange = _inst.randrange
750shuffle = _inst.shuffle
751normalvariate = _inst.normalvariate
752lognormvariate = _inst.lognormvariate
753cunifvariate = _inst.cunifvariate
754expovariate = _inst.expovariate
755vonmisesvariate = _inst.vonmisesvariate
756gammavariate = _inst.gammavariate
757stdgamma = _inst.stdgamma
758gauss = _inst.gauss
759betavariate = _inst.betavariate
760paretovariate = _inst.paretovariate
761weibullvariate = _inst.weibullvariate
762getstate = _inst.getstate
763setstate = _inst.setstate
Tim Petersd52269b2001-01-25 06:23:18 +0000764jumpahead = _inst.jumpahead
Tim Peters0de88fc2001-02-01 04:59:18 +0000765whseed = _inst.whseed
Tim Petersd7b5e882001-01-25 03:36:26 +0000766
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000767if __name__ == '__main__':
Tim Petersd7b5e882001-01-25 03:36:26 +0000768 _test()