blob: 4d290804caf614dcec35ecca0d211b877c12369b [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
Tim Peters9146f272002-08-16 03:41:39 +000078from math import floor as _floor
Guido van Rossumff03b1a1994-03-09 12:55:02 +000079
Skip Montanaro0de65802001-02-15 22:15:14 +000080__all__ = ["Random","seed","random","uniform","randint","choice",
81 "randrange","shuffle","normalvariate","lognormvariate",
82 "cunifvariate","expovariate","vonmisesvariate","gammavariate",
83 "stdgamma","gauss","betavariate","paretovariate","weibullvariate",
84 "getstate","setstate","jumpahead","whseed"]
Tim Peters0e6d2132001-02-15 23:56:39 +000085
Tim Petersdc47a892001-11-25 21:12:43 +000086def _verify(name, computed, expected):
Tim Peters0c9886d2001-01-15 01:18:21 +000087 if abs(computed - expected) > 1e-7:
Tim Petersd7b5e882001-01-25 03:36:26 +000088 raise ValueError(
89 "computed value for %s deviates too much "
90 "(computed %g, expected %g)" % (name, computed, expected))
91
92NV_MAGICCONST = 4 * _exp(-0.5)/_sqrt(2.0)
Tim Petersdc47a892001-11-25 21:12:43 +000093_verify('NV_MAGICCONST', NV_MAGICCONST, 1.71552776992141)
Tim Petersd7b5e882001-01-25 03:36:26 +000094
95TWOPI = 2.0*_pi
Tim Petersdc47a892001-11-25 21:12:43 +000096_verify('TWOPI', TWOPI, 6.28318530718)
Tim Petersd7b5e882001-01-25 03:36:26 +000097
98LOG4 = _log(4.0)
Tim Petersdc47a892001-11-25 21:12:43 +000099_verify('LOG4', LOG4, 1.38629436111989)
Tim Petersd7b5e882001-01-25 03:36:26 +0000100
101SG_MAGICCONST = 1.0 + _log(4.5)
Tim Petersdc47a892001-11-25 21:12:43 +0000102_verify('SG_MAGICCONST', SG_MAGICCONST, 2.50407739677627)
Tim Petersd7b5e882001-01-25 03:36:26 +0000103
104del _verify
105
106# Translated by Guido van Rossum from C source provided by
107# Adrian Baddeley.
108
109class Random:
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000110 """Random number generator base class used by bound module functions.
111
112 Used to instantiate instances of Random to get generators that don't
113 share state. Especially useful for multi-threaded programs, creating
114 a different instance of Random for each thread, and using the jumpahead()
115 method to ensure that the generated sequences seen by each thread don't
116 overlap.
117
118 Class Random can also be subclassed if you want to use a different basic
119 generator of your own devising: in that case, override the following
120 methods: random(), seed(), getstate(), setstate() and jumpahead().
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000121
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000122 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000123
124 VERSION = 1 # used by getstate/setstate
125
126 def __init__(self, x=None):
127 """Initialize an instance.
128
129 Optional argument x controls seeding, as for Random.seed().
130 """
131
132 self.seed(x)
Tim Petersd7b5e882001-01-25 03:36:26 +0000133
Tim Peterscd804102001-01-25 20:25:57 +0000134## -------------------- core generator -------------------
135
Tim Petersd7b5e882001-01-25 03:36:26 +0000136 # Specific to Wichmann-Hill generator. Subclasses wishing to use a
Tim Petersd52269b2001-01-25 06:23:18 +0000137 # different core generator should override the seed(), random(),
Tim Peterscd804102001-01-25 20:25:57 +0000138 # getstate(), setstate() and jumpahead() methods.
Tim Petersd7b5e882001-01-25 03:36:26 +0000139
Tim Peters0de88fc2001-02-01 04:59:18 +0000140 def seed(self, a=None):
141 """Initialize internal state from hashable object.
Tim Petersd7b5e882001-01-25 03:36:26 +0000142
Tim Peters0de88fc2001-02-01 04:59:18 +0000143 None or no argument seeds from current time.
144
Tim Petersbcd725f2001-02-01 10:06:53 +0000145 If a is not None or an int or long, hash(a) is used instead.
Tim Peters0de88fc2001-02-01 04:59:18 +0000146
147 If a is an int or long, a is used directly. Distinct values between
148 0 and 27814431486575L inclusive are guaranteed to yield distinct
149 internal states (this guarantee is specific to the default
150 Wichmann-Hill generator).
Tim Petersd7b5e882001-01-25 03:36:26 +0000151 """
152
Tim Peters0de88fc2001-02-01 04:59:18 +0000153 if a is None:
Tim Petersd7b5e882001-01-25 03:36:26 +0000154 # Initialize from current time
155 import time
Tim Peters0de88fc2001-02-01 04:59:18 +0000156 a = long(time.time() * 256)
157
158 if type(a) not in (type(3), type(3L)):
159 a = hash(a)
160
161 a, x = divmod(a, 30268)
162 a, y = divmod(a, 30306)
163 a, z = divmod(a, 30322)
164 self._seed = int(x)+1, int(y)+1, int(z)+1
Tim Petersd7b5e882001-01-25 03:36:26 +0000165
Tim Peters46c04e12002-05-05 20:40:00 +0000166 self.gauss_next = None
167
Tim Petersd7b5e882001-01-25 03:36:26 +0000168 def random(self):
169 """Get the next random number in the range [0.0, 1.0)."""
170
171 # Wichman-Hill random number generator.
172 #
173 # Wichmann, B. A. & Hill, I. D. (1982)
174 # Algorithm AS 183:
175 # An efficient and portable pseudo-random number generator
176 # Applied Statistics 31 (1982) 188-190
177 #
178 # see also:
179 # Correction to Algorithm AS 183
180 # Applied Statistics 33 (1984) 123
181 #
182 # McLeod, A. I. (1985)
183 # A remark on Algorithm AS 183
184 # Applied Statistics 34 (1985),198-200
185
186 # This part is thread-unsafe:
187 # BEGIN CRITICAL SECTION
188 x, y, z = self._seed
189 x = (171 * x) % 30269
190 y = (172 * y) % 30307
191 z = (170 * z) % 30323
192 self._seed = x, y, z
193 # END CRITICAL SECTION
194
195 # Note: on a platform using IEEE-754 double arithmetic, this can
196 # never return 0.0 (asserted by Tim; proof too long for a comment).
197 return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
198
Tim Peterscd804102001-01-25 20:25:57 +0000199 def getstate(self):
200 """Return internal state; can be passed to setstate() later."""
201 return self.VERSION, self._seed, self.gauss_next
202
203 def setstate(self, state):
204 """Restore internal state from object returned by getstate()."""
205 version = state[0]
206 if version == 1:
207 version, self._seed, self.gauss_next = state
208 else:
209 raise ValueError("state with version %s passed to "
210 "Random.setstate() of version %s" %
211 (version, self.VERSION))
212
213 def jumpahead(self, n):
214 """Act as if n calls to random() were made, but quickly.
215
216 n is an int, greater than or equal to 0.
217
218 Example use: If you have 2 threads and know that each will
219 consume no more than a million random numbers, create two Random
220 objects r1 and r2, then do
221 r2.setstate(r1.getstate())
222 r2.jumpahead(1000000)
223 Then r1 and r2 will use guaranteed-disjoint segments of the full
224 period.
225 """
226
227 if not n >= 0:
228 raise ValueError("n must be >= 0")
229 x, y, z = self._seed
230 x = int(x * pow(171, n, 30269)) % 30269
231 y = int(y * pow(172, n, 30307)) % 30307
232 z = int(z * pow(170, n, 30323)) % 30323
233 self._seed = x, y, z
234
Tim Peters0de88fc2001-02-01 04:59:18 +0000235 def __whseed(self, x=0, y=0, z=0):
236 """Set the Wichmann-Hill seed from (x, y, z).
237
238 These must be integers in the range [0, 256).
239 """
240
241 if not type(x) == type(y) == type(z) == type(0):
242 raise TypeError('seeds must be integers')
243 if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256):
244 raise ValueError('seeds must be in range(0, 256)')
245 if 0 == x == y == z:
246 # Initialize from current time
247 import time
248 t = long(time.time() * 256)
249 t = int((t&0xffffff) ^ (t>>24))
250 t, x = divmod(t, 256)
251 t, y = divmod(t, 256)
252 t, z = divmod(t, 256)
253 # Zero is a poor seed, so substitute 1
254 self._seed = (x or 1, y or 1, z or 1)
255
Tim Peters46c04e12002-05-05 20:40:00 +0000256 self.gauss_next = None
257
Tim Peters0de88fc2001-02-01 04:59:18 +0000258 def whseed(self, a=None):
259 """Seed from hashable object's hash code.
260
261 None or no argument seeds from current time. It is not guaranteed
262 that objects with distinct hash codes lead to distinct internal
263 states.
264
265 This is obsolete, provided for compatibility with the seed routine
266 used prior to Python 2.1. Use the .seed() method instead.
267 """
268
269 if a is None:
270 self.__whseed()
271 return
272 a = hash(a)
273 a, x = divmod(a, 256)
274 a, y = divmod(a, 256)
275 a, z = divmod(a, 256)
276 x = (x + a) % 256 or 1
277 y = (y + a) % 256 or 1
278 z = (z + a) % 256 or 1
279 self.__whseed(x, y, z)
280
Tim Peterscd804102001-01-25 20:25:57 +0000281## ---- Methods below this point do not need to be overridden when
282## ---- subclassing for the purpose of using a different core generator.
283
284## -------------------- pickle support -------------------
285
286 def __getstate__(self): # for pickle
287 return self.getstate()
288
289 def __setstate__(self, state): # for pickle
290 self.setstate(state)
291
292## -------------------- integer methods -------------------
293
Tim Petersd7b5e882001-01-25 03:36:26 +0000294 def randrange(self, start, stop=None, step=1, int=int, default=None):
295 """Choose a random item from range(start, stop[, step]).
296
297 This fixes the problem with randint() which includes the
298 endpoint; in Python this is usually not what you want.
299 Do not supply the 'int' and 'default' arguments.
300 """
301
302 # This code is a bit messy to make it fast for the
Tim Peters9146f272002-08-16 03:41:39 +0000303 # common case while still doing adequate error checking.
Tim Petersd7b5e882001-01-25 03:36:26 +0000304 istart = int(start)
305 if istart != start:
306 raise ValueError, "non-integer arg 1 for randrange()"
307 if stop is default:
308 if istart > 0:
309 return int(self.random() * istart)
310 raise ValueError, "empty range for randrange()"
Tim Peters9146f272002-08-16 03:41:39 +0000311
312 # stop argument supplied.
Tim Petersd7b5e882001-01-25 03:36:26 +0000313 istop = int(stop)
314 if istop != stop:
315 raise ValueError, "non-integer stop for randrange()"
Tim Peters9146f272002-08-16 03:41:39 +0000316 if step == 1 and istart < istop:
317 try:
318 return istart + int(self.random()*(istop - istart))
319 except OverflowError:
320 # This can happen if istop-istart > sys.maxint + 1, and
321 # multiplying by random() doesn't reduce it to something
322 # <= sys.maxint. We know that the overall result fits
323 # in an int, and can still do it correctly via math.floor().
324 # But that adds another function call, so for speed we
325 # avoided that whenever possible.
326 return int(istart + _floor(self.random()*(istop - istart)))
Tim Petersd7b5e882001-01-25 03:36:26 +0000327 if step == 1:
Tim Petersd7b5e882001-01-25 03:36:26 +0000328 raise ValueError, "empty range for randrange()"
Tim Peters9146f272002-08-16 03:41:39 +0000329
330 # Non-unit step argument supplied.
Tim Petersd7b5e882001-01-25 03:36:26 +0000331 istep = int(step)
332 if istep != step:
333 raise ValueError, "non-integer step for randrange()"
334 if istep > 0:
335 n = (istop - istart + istep - 1) / istep
336 elif istep < 0:
337 n = (istop - istart + istep + 1) / istep
338 else:
339 raise ValueError, "zero step for randrange()"
340
341 if n <= 0:
342 raise ValueError, "empty range for randrange()"
343 return istart + istep*int(self.random() * n)
344
345 def randint(self, a, b):
Tim Peterscd804102001-01-25 20:25:57 +0000346 """Return random integer in range [a, b], including both end points.
Tim Petersd7b5e882001-01-25 03:36:26 +0000347 """
348
349 return self.randrange(a, b+1)
350
Tim Peterscd804102001-01-25 20:25:57 +0000351## -------------------- sequence methods -------------------
352
Tim Petersd7b5e882001-01-25 03:36:26 +0000353 def choice(self, seq):
354 """Choose a random element from a non-empty sequence."""
355 return seq[int(self.random() * len(seq))]
356
357 def shuffle(self, x, random=None, int=int):
358 """x, random=random.random -> shuffle list x in place; return None.
359
360 Optional arg random is a 0-argument function returning a random
361 float in [0.0, 1.0); by default, the standard random.random.
362
363 Note that for even rather small len(x), the total number of
364 permutations of x is larger than the period of most random number
365 generators; this implies that "most" permutations of a long
366 sequence can never be generated.
367 """
368
369 if random is None:
370 random = self.random
371 for i in xrange(len(x)-1, 0, -1):
Tim Peterscd804102001-01-25 20:25:57 +0000372 # pick an element in x[:i+1] with which to exchange x[i]
Tim Petersd7b5e882001-01-25 03:36:26 +0000373 j = int(random() * (i+1))
374 x[i], x[j] = x[j], x[i]
375
Tim Peterscd804102001-01-25 20:25:57 +0000376## -------------------- real-valued distributions -------------------
377
378## -------------------- uniform distribution -------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000379
380 def uniform(self, a, b):
381 """Get a random number in the range [a, b)."""
382 return a + (b-a) * self.random()
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000383
Tim Peterscd804102001-01-25 20:25:57 +0000384## -------------------- normal distribution --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000385
Tim Petersd7b5e882001-01-25 03:36:26 +0000386 def normalvariate(self, mu, sigma):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000387 """Normal distribution.
388
389 mu is the mean, and sigma is the standard deviation.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000390
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000391 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000392 # mu = mean, sigma = standard deviation
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000393
Tim Petersd7b5e882001-01-25 03:36:26 +0000394 # Uses Kinderman and Monahan method. Reference: Kinderman,
395 # A.J. and Monahan, J.F., "Computer generation of random
396 # variables using the ratio of uniform deviates", ACM Trans
397 # Math Software, 3, (1977), pp257-260.
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000398
Tim Petersd7b5e882001-01-25 03:36:26 +0000399 random = self.random
Tim Peters0c9886d2001-01-15 01:18:21 +0000400 while 1:
401 u1 = random()
402 u2 = random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000403 z = NV_MAGICCONST*(u1-0.5)/u2
404 zz = z*z/4.0
405 if zz <= -_log(u2):
406 break
407 return mu + z*sigma
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000408
Tim Peterscd804102001-01-25 20:25:57 +0000409## -------------------- lognormal distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000410
411 def lognormvariate(self, mu, sigma):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000412 """Log normal distribution.
413
414 If you take the natural logarithm of this distribution, you'll get a
415 normal distribution with mean mu and standard deviation sigma.
416 mu can have any value, and sigma must be greater than zero.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000417
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000418 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000419 return _exp(self.normalvariate(mu, sigma))
420
Tim Peterscd804102001-01-25 20:25:57 +0000421## -------------------- circular uniform --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000422
423 def cunifvariate(self, mean, arc):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000424 """Circular uniform distribution.
425
426 mean is the mean angle, and arc is the range of the distribution,
427 centered around the mean angle. Both values must be expressed in
428 radians. Returned values range between mean - arc/2 and
429 mean + arc/2 and are normalized to between 0 and pi.
430
431 Deprecated in version 2.3. Use:
432 (mean + arc * (Random.random() - 0.5)) % Math.pi
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000433
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000434 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000435 # mean: mean angle (in radians between 0 and pi)
436 # arc: range of distribution (in radians between 0 and pi)
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000437 import warnings
438 warnings.warn("The cunifvariate function is deprecated; Use (mean "
439 "+ arc * (Random.random() - 0.5)) % Math.pi instead",
440 DeprecationWarning)
Tim Petersd7b5e882001-01-25 03:36:26 +0000441
442 return (mean + arc * (self.random() - 0.5)) % _pi
443
Tim Peterscd804102001-01-25 20:25:57 +0000444## -------------------- exponential distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000445
446 def expovariate(self, lambd):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000447 """Exponential distribution.
448
449 lambd is 1.0 divided by the desired mean. (The parameter would be
450 called "lambda", but that is a reserved word in Python.) Returned
451 values range from 0 to positive infinity.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000452
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000453 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000454 # lambd: rate lambd = 1/mean
455 # ('lambda' is a Python reserved word)
456
457 random = self.random
Tim Peters0c9886d2001-01-15 01:18:21 +0000458 u = random()
459 while u <= 1e-7:
460 u = random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000461 return -_log(u)/lambd
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000462
Tim Peterscd804102001-01-25 20:25:57 +0000463## -------------------- von Mises distribution --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000464
Tim Petersd7b5e882001-01-25 03:36:26 +0000465 def vonmisesvariate(self, mu, kappa):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000466 """Circular data distribution.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000467
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000468 mu is the mean angle, expressed in radians between 0 and 2*pi, and
469 kappa is the concentration parameter, which must be greater than or
470 equal to zero. If kappa is equal to zero, this distribution reduces
471 to a uniform random angle over the range 0 to 2*pi.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000472
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000473 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000474 # mu: mean angle (in radians between 0 and 2*pi)
475 # kappa: concentration parameter kappa (>= 0)
476 # if kappa = 0 generate uniform random angle
477
478 # Based upon an algorithm published in: Fisher, N.I.,
479 # "Statistical Analysis of Circular Data", Cambridge
480 # University Press, 1993.
481
482 # Thanks to Magnus Kessler for a correction to the
483 # implementation of step 4.
484
485 random = self.random
486 if kappa <= 1e-6:
487 return TWOPI * random()
488
489 a = 1.0 + _sqrt(1.0 + 4.0 * kappa * kappa)
490 b = (a - _sqrt(2.0 * a))/(2.0 * kappa)
491 r = (1.0 + b * b)/(2.0 * b)
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000492
Tim Peters0c9886d2001-01-15 01:18:21 +0000493 while 1:
Tim Peters0c9886d2001-01-15 01:18:21 +0000494 u1 = random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000495
496 z = _cos(_pi * u1)
497 f = (1.0 + r * z)/(r + z)
498 c = kappa * (r - f)
499
500 u2 = random()
501
502 if not (u2 >= c * (2.0 - c) and u2 > c * _exp(1.0 - c)):
Tim Peters0c9886d2001-01-15 01:18:21 +0000503 break
Tim Petersd7b5e882001-01-25 03:36:26 +0000504
505 u3 = random()
506 if u3 > 0.5:
507 theta = (mu % TWOPI) + _acos(f)
508 else:
509 theta = (mu % TWOPI) - _acos(f)
510
511 return theta
512
Tim Peterscd804102001-01-25 20:25:57 +0000513## -------------------- gamma distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000514
515 def gammavariate(self, alpha, beta):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000516 """Gamma distribution. Not the gamma function!
517
518 Conditions on the parameters are alpha > 0 and beta > 0.
519
520 """
Tim Peters8ac14952002-05-23 15:15:30 +0000521
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000522 # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2
Tim Peters8ac14952002-05-23 15:15:30 +0000523
Guido van Rossum570764d2002-05-14 14:08:12 +0000524 # Warning: a few older sources define the gamma distribution in terms
525 # of alpha > -1.0
526 if alpha <= 0.0 or beta <= 0.0:
527 raise ValueError, 'gammavariate: alpha and beta must be > 0.0'
Tim Peters8ac14952002-05-23 15:15:30 +0000528
Tim Petersd7b5e882001-01-25 03:36:26 +0000529 random = self.random
Tim Petersd7b5e882001-01-25 03:36:26 +0000530 if alpha > 1.0:
531
532 # Uses R.C.H. Cheng, "The generation of Gamma
533 # variables with non-integral shape parameters",
534 # Applied Statistics, (1977), 26, No. 1, p71-74
535
Raymond Hettingerca6cdc22002-05-13 23:40:14 +0000536 ainv = _sqrt(2.0 * alpha - 1.0)
537 bbb = alpha - LOG4
538 ccc = alpha + ainv
Tim Peters8ac14952002-05-23 15:15:30 +0000539
Tim Petersd7b5e882001-01-25 03:36:26 +0000540 while 1:
541 u1 = random()
542 u2 = random()
543 v = _log(u1/(1.0-u1))/ainv
544 x = alpha*_exp(v)
545 z = u1*u1*u2
546 r = bbb+ccc*v-x
547 if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z):
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000548 return x * beta
Tim Petersd7b5e882001-01-25 03:36:26 +0000549
550 elif alpha == 1.0:
551 # expovariate(1)
552 u = random()
553 while u <= 1e-7:
554 u = random()
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000555 return -_log(u) * beta
Tim Petersd7b5e882001-01-25 03:36:26 +0000556
557 else: # alpha is between 0 and 1 (exclusive)
558
559 # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
560
561 while 1:
562 u = random()
563 b = (_e + alpha)/_e
564 p = b*u
565 if p <= 1.0:
566 x = pow(p, 1.0/alpha)
567 else:
568 # p > 1
569 x = -_log((b-p)/alpha)
570 u1 = random()
571 if not (((p <= 1.0) and (u1 > _exp(-x))) or
572 ((p > 1) and (u1 > pow(x, alpha - 1.0)))):
573 break
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000574 return x * beta
575
576
577 def stdgamma(self, alpha, ainv, bbb, ccc):
578 # This method was (and shall remain) undocumented.
579 # This method is deprecated
580 # for the following reasons:
581 # 1. Returns same as .gammavariate(alpha, 1.0)
582 # 2. Requires caller to provide 3 extra arguments
583 # that are functions of alpha anyway
584 # 3. Can't be used for alpha < 0.5
585
586 # ainv = sqrt(2 * alpha - 1)
587 # bbb = alpha - log(4)
588 # ccc = alpha + ainv
589 import warnings
590 warnings.warn("The stdgamma function is deprecated; "
591 "use gammavariate() instead",
592 DeprecationWarning)
593 return self.gammavariate(alpha, 1.0)
594
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000595
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000596
Tim Peterscd804102001-01-25 20:25:57 +0000597## -------------------- Gauss (faster alternative) --------------------
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000598
Tim Petersd7b5e882001-01-25 03:36:26 +0000599 def gauss(self, mu, sigma):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000600 """Gaussian distribution.
601
602 mu is the mean, and sigma is the standard deviation. This is
603 slightly faster than the normalvariate() function.
604
605 Not thread-safe without a lock around calls.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000606
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000607 """
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000608
Tim Petersd7b5e882001-01-25 03:36:26 +0000609 # When x and y are two variables from [0, 1), uniformly
610 # distributed, then
611 #
612 # cos(2*pi*x)*sqrt(-2*log(1-y))
613 # sin(2*pi*x)*sqrt(-2*log(1-y))
614 #
615 # are two *independent* variables with normal distribution
616 # (mu = 0, sigma = 1).
617 # (Lambert Meertens)
618 # (corrected version; bug discovered by Mike Miller, fixed by LM)
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000619
Tim Petersd7b5e882001-01-25 03:36:26 +0000620 # Multithreading note: When two threads call this function
621 # simultaneously, it is possible that they will receive the
622 # same return value. The window is very small though. To
623 # avoid this, you have to use a lock around all calls. (I
624 # didn't want to slow this down in the serial case by using a
625 # lock here.)
Guido van Rossumd03e1191998-05-29 17:51:31 +0000626
Tim Petersd7b5e882001-01-25 03:36:26 +0000627 random = self.random
628 z = self.gauss_next
629 self.gauss_next = None
630 if z is None:
631 x2pi = random() * TWOPI
632 g2rad = _sqrt(-2.0 * _log(1.0 - random()))
633 z = _cos(x2pi) * g2rad
634 self.gauss_next = _sin(x2pi) * g2rad
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000635
Tim Petersd7b5e882001-01-25 03:36:26 +0000636 return mu + z*sigma
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000637
Tim Peterscd804102001-01-25 20:25:57 +0000638## -------------------- beta --------------------
Tim Peters85e2e472001-01-26 06:49:56 +0000639## See
640## http://sourceforge.net/bugs/?func=detailbug&bug_id=130030&group_id=5470
641## for Ivan Frohne's insightful analysis of why the original implementation:
642##
643## def betavariate(self, alpha, beta):
644## # Discrete Event Simulation in C, pp 87-88.
645##
646## y = self.expovariate(alpha)
647## z = self.expovariate(1.0/beta)
648## return z/(y+z)
649##
650## was dead wrong, and how it probably got that way.
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000651
Tim Petersd7b5e882001-01-25 03:36:26 +0000652 def betavariate(self, alpha, beta):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000653 """Beta distribution.
654
655 Conditions on the parameters are alpha > -1 and beta} > -1.
656 Returned values range between 0 and 1.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000657
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000658 """
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000659
Tim Peters85e2e472001-01-26 06:49:56 +0000660 # This version due to Janne Sinkkonen, and matches all the std
661 # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution").
662 y = self.gammavariate(alpha, 1.)
663 if y == 0:
664 return 0.0
665 else:
666 return y / (y + self.gammavariate(beta, 1.))
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000667
Tim Peterscd804102001-01-25 20:25:57 +0000668## -------------------- Pareto --------------------
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000669
Tim Petersd7b5e882001-01-25 03:36:26 +0000670 def paretovariate(self, alpha):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000671 """Pareto distribution. alpha is the shape parameter."""
Tim Petersd7b5e882001-01-25 03:36:26 +0000672 # Jain, pg. 495
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000673
Tim Petersd7b5e882001-01-25 03:36:26 +0000674 u = self.random()
675 return 1.0 / pow(u, 1.0/alpha)
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000676
Tim Peterscd804102001-01-25 20:25:57 +0000677## -------------------- Weibull --------------------
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000678
Tim Petersd7b5e882001-01-25 03:36:26 +0000679 def weibullvariate(self, alpha, beta):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000680 """Weibull distribution.
681
682 alpha is the scale parameter and beta is the shape parameter.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000683
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000684 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000685 # Jain, pg. 499; bug fix courtesy Bill Arms
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000686
Tim Petersd7b5e882001-01-25 03:36:26 +0000687 u = self.random()
688 return alpha * pow(-_log(u), 1.0/beta)
Guido van Rossum6c395ba1999-08-18 13:53:28 +0000689
Tim Peterscd804102001-01-25 20:25:57 +0000690## -------------------- test program --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000691
Tim Petersd7b5e882001-01-25 03:36:26 +0000692def _test_generator(n, funccall):
Tim Peters0c9886d2001-01-15 01:18:21 +0000693 import time
694 print n, 'times', funccall
695 code = compile(funccall, funccall, 'eval')
696 sum = 0.0
697 sqsum = 0.0
698 smallest = 1e10
699 largest = -1e10
700 t0 = time.time()
701 for i in range(n):
702 x = eval(code)
703 sum = sum + x
704 sqsum = sqsum + x*x
705 smallest = min(x, smallest)
706 largest = max(x, largest)
707 t1 = time.time()
708 print round(t1-t0, 3), 'sec,',
709 avg = sum/n
Tim Petersd7b5e882001-01-25 03:36:26 +0000710 stddev = _sqrt(sqsum/n - avg*avg)
Tim Peters0c9886d2001-01-15 01:18:21 +0000711 print 'avg %g, stddev %g, min %g, max %g' % \
712 (avg, stddev, smallest, largest)
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000713
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000714def _test(N=20000):
Tim Petersd7b5e882001-01-25 03:36:26 +0000715 print 'TWOPI =', TWOPI
716 print 'LOG4 =', LOG4
717 print 'NV_MAGICCONST =', NV_MAGICCONST
718 print 'SG_MAGICCONST =', SG_MAGICCONST
719 _test_generator(N, 'random()')
720 _test_generator(N, 'normalvariate(0.0, 1.0)')
721 _test_generator(N, 'lognormvariate(0.0, 1.0)')
722 _test_generator(N, 'cunifvariate(0.0, 1.0)')
723 _test_generator(N, 'expovariate(1.0)')
724 _test_generator(N, 'vonmisesvariate(0.0, 1.0)')
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000725 _test_generator(N, 'gammavariate(0.01, 1.0)')
726 _test_generator(N, 'gammavariate(0.1, 1.0)')
Tim Peters8ac14952002-05-23 15:15:30 +0000727 _test_generator(N, 'gammavariate(0.1, 2.0)')
Tim Petersd7b5e882001-01-25 03:36:26 +0000728 _test_generator(N, 'gammavariate(0.5, 1.0)')
729 _test_generator(N, 'gammavariate(0.9, 1.0)')
730 _test_generator(N, 'gammavariate(1.0, 1.0)')
731 _test_generator(N, 'gammavariate(2.0, 1.0)')
732 _test_generator(N, 'gammavariate(20.0, 1.0)')
733 _test_generator(N, 'gammavariate(200.0, 1.0)')
734 _test_generator(N, 'gauss(0.0, 1.0)')
735 _test_generator(N, 'betavariate(3.0, 3.0)')
736 _test_generator(N, 'paretovariate(1.0)')
737 _test_generator(N, 'weibullvariate(1.0, 1.0)')
738
Tim Peterscd804102001-01-25 20:25:57 +0000739 # Test jumpahead.
740 s = getstate()
741 jumpahead(N)
742 r1 = random()
743 # now do it the slow way
744 setstate(s)
745 for i in range(N):
746 random()
747 r2 = random()
748 if r1 != r2:
749 raise ValueError("jumpahead test failed " + `(N, r1, r2)`)
750
Tim Peters715c4c42001-01-26 22:56:56 +0000751# Create one instance, seeded from current time, and export its methods
752# as module-level functions. The functions are not threadsafe, and state
753# is shared across all uses (both in the user's code and in the Python
754# libraries), but that's fine for most programs and is easier for the
755# casual user than making them instantiate their own Random() instance.
Tim Petersd7b5e882001-01-25 03:36:26 +0000756_inst = Random()
757seed = _inst.seed
758random = _inst.random
759uniform = _inst.uniform
760randint = _inst.randint
761choice = _inst.choice
762randrange = _inst.randrange
763shuffle = _inst.shuffle
764normalvariate = _inst.normalvariate
765lognormvariate = _inst.lognormvariate
766cunifvariate = _inst.cunifvariate
767expovariate = _inst.expovariate
768vonmisesvariate = _inst.vonmisesvariate
769gammavariate = _inst.gammavariate
770stdgamma = _inst.stdgamma
771gauss = _inst.gauss
772betavariate = _inst.betavariate
773paretovariate = _inst.paretovariate
774weibullvariate = _inst.weibullvariate
775getstate = _inst.getstate
776setstate = _inst.setstate
Tim Petersd52269b2001-01-25 06:23:18 +0000777jumpahead = _inst.jumpahead
Tim Peters0de88fc2001-02-01 04:59:18 +0000778whseed = _inst.whseed
Tim Petersd7b5e882001-01-25 03:36:26 +0000779
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000780if __name__ == '__main__':
Tim Petersd7b5e882001-01-25 03:36:26 +0000781 _test()