blob: f57ddb7dbdea348bbf75f256abb00de23afd1273 [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
Raymond Hettingerf24eb352002-11-12 17:41:57 +000010 pick random sample
Tim Petersd7b5e882001-01-25 03:36:26 +000011 generate random permutation
12
Guido van Rossume7b146f2000-02-04 15:28:42 +000013 distributions on the real line:
14 ------------------------------
Tim Petersd7b5e882001-01-25 03:36:26 +000015 uniform
Guido van Rossume7b146f2000-02-04 15:28:42 +000016 normal (Gaussian)
17 lognormal
18 negative exponential
19 gamma
20 beta
Guido van Rossumff03b1a1994-03-09 12:55:02 +000021
Guido van Rossume7b146f2000-02-04 15:28:42 +000022 distributions on the circle (angles 0 to 2pi)
23 ---------------------------------------------
24 circular uniform
25 von Mises
26
27Translated from anonymously contributed C/C++ source.
28
Tim Peterse360d952001-01-26 10:00:39 +000029Multi-threading note: the random number generator used here is not thread-
30safe; it is possible that two calls return the same random value. However,
31you can instantiate a different instance of Random() in each thread to get
32generators that don't share state, then use .setstate() and .jumpahead() to
33move the generators to disjoint segments of the full period. For example,
34
35def create_generators(num, delta, firstseed=None):
36 ""\"Return list of num distinct generators.
37 Each generator has its own unique segment of delta elements from
38 Random.random()'s full period.
39 Seed the first generator with optional arg firstseed (default is
40 None, to seed from current time).
41 ""\"
42
43 from random import Random
44 g = Random(firstseed)
45 result = [g]
46 for i in range(num - 1):
47 laststate = g.getstate()
48 g = Random()
49 g.setstate(laststate)
50 g.jumpahead(delta)
51 result.append(g)
52 return result
53
54gens = create_generators(10, 1000000)
55
56That creates 10 distinct generators, which can be passed out to 10 distinct
57threads. The generators don't share state so can be called safely in
58parallel. So long as no thread calls its g.random() more than a million
59times (the second argument to create_generators), the sequences seen by
60each thread will not overlap.
61
62The period of the underlying Wichmann-Hill generator is 6,953,607,871,644,
63and that limits how far this technique can be pushed.
64
65Just for fun, note that since we know the period, .jumpahead() can also be
66used to "move backward in time":
67
68>>> g = Random(42) # arbitrary
69>>> g.random()
Tim Peters0de88fc2001-02-01 04:59:18 +0000700.25420336316883324
Tim Peterse360d952001-01-26 10:00:39 +000071>>> g.jumpahead(6953607871644L - 1) # move *back* one
72>>> g.random()
Tim Peters0de88fc2001-02-01 04:59:18 +0000730.25420336316883324
Guido van Rossume7b146f2000-02-04 15:28:42 +000074"""
Tim Petersd7b5e882001-01-25 03:36:26 +000075# XXX The docstring sucks.
Guido van Rossumd03e1191998-05-29 17:51:31 +000076
Tim Petersd7b5e882001-01-25 03:36:26 +000077from math import log as _log, exp as _exp, pi as _pi, e as _e
78from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin
Tim Peters9146f272002-08-16 03:41:39 +000079from math import floor as _floor
Guido van Rossumff03b1a1994-03-09 12:55:02 +000080
Raymond Hettingerf24eb352002-11-12 17:41:57 +000081__all__ = ["Random","seed","random","uniform","randint","choice","sample",
Skip Montanaro0de65802001-02-15 22:15:14 +000082 "randrange","shuffle","normalvariate","lognormvariate",
83 "cunifvariate","expovariate","vonmisesvariate","gammavariate",
84 "stdgamma","gauss","betavariate","paretovariate","weibullvariate",
85 "getstate","setstate","jumpahead","whseed"]
Tim Peters0e6d2132001-02-15 23:56:39 +000086
Tim Petersdc47a892001-11-25 21:12:43 +000087def _verify(name, computed, expected):
Tim Peters0c9886d2001-01-15 01:18:21 +000088 if abs(computed - expected) > 1e-7:
Tim Petersd7b5e882001-01-25 03:36:26 +000089 raise ValueError(
90 "computed value for %s deviates too much "
91 "(computed %g, expected %g)" % (name, computed, expected))
92
93NV_MAGICCONST = 4 * _exp(-0.5)/_sqrt(2.0)
Tim Petersdc47a892001-11-25 21:12:43 +000094_verify('NV_MAGICCONST', NV_MAGICCONST, 1.71552776992141)
Tim Petersd7b5e882001-01-25 03:36:26 +000095
96TWOPI = 2.0*_pi
Tim Petersdc47a892001-11-25 21:12:43 +000097_verify('TWOPI', TWOPI, 6.28318530718)
Tim Petersd7b5e882001-01-25 03:36:26 +000098
99LOG4 = _log(4.0)
Tim Petersdc47a892001-11-25 21:12:43 +0000100_verify('LOG4', LOG4, 1.38629436111989)
Tim Petersd7b5e882001-01-25 03:36:26 +0000101
102SG_MAGICCONST = 1.0 + _log(4.5)
Tim Petersdc47a892001-11-25 21:12:43 +0000103_verify('SG_MAGICCONST', SG_MAGICCONST, 2.50407739677627)
Tim Petersd7b5e882001-01-25 03:36:26 +0000104
105del _verify
106
107# Translated by Guido van Rossum from C source provided by
108# Adrian Baddeley.
109
110class Random:
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000111 """Random number generator base class used by bound module functions.
112
113 Used to instantiate instances of Random to get generators that don't
114 share state. Especially useful for multi-threaded programs, creating
115 a different instance of Random for each thread, and using the jumpahead()
116 method to ensure that the generated sequences seen by each thread don't
117 overlap.
118
119 Class Random can also be subclassed if you want to use a different basic
120 generator of your own devising: in that case, override the following
121 methods: random(), seed(), getstate(), setstate() and jumpahead().
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000122
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000123 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000124
125 VERSION = 1 # used by getstate/setstate
126
127 def __init__(self, x=None):
128 """Initialize an instance.
129
130 Optional argument x controls seeding, as for Random.seed().
131 """
132
133 self.seed(x)
Tim Petersd7b5e882001-01-25 03:36:26 +0000134
Tim Peterscd804102001-01-25 20:25:57 +0000135## -------------------- core generator -------------------
136
Tim Petersd7b5e882001-01-25 03:36:26 +0000137 # Specific to Wichmann-Hill generator. Subclasses wishing to use a
Tim Petersd52269b2001-01-25 06:23:18 +0000138 # different core generator should override the seed(), random(),
Tim Peterscd804102001-01-25 20:25:57 +0000139 # getstate(), setstate() and jumpahead() methods.
Tim Petersd7b5e882001-01-25 03:36:26 +0000140
Tim Peters0de88fc2001-02-01 04:59:18 +0000141 def seed(self, a=None):
142 """Initialize internal state from hashable object.
Tim Petersd7b5e882001-01-25 03:36:26 +0000143
Tim Peters0de88fc2001-02-01 04:59:18 +0000144 None or no argument seeds from current time.
145
Tim Petersbcd725f2001-02-01 10:06:53 +0000146 If a is not None or an int or long, hash(a) is used instead.
Tim Peters0de88fc2001-02-01 04:59:18 +0000147
148 If a is an int or long, a is used directly. Distinct values between
149 0 and 27814431486575L inclusive are guaranteed to yield distinct
150 internal states (this guarantee is specific to the default
151 Wichmann-Hill generator).
Tim Petersd7b5e882001-01-25 03:36:26 +0000152 """
153
Tim Peters0de88fc2001-02-01 04:59:18 +0000154 if a is None:
Tim Petersd7b5e882001-01-25 03:36:26 +0000155 # Initialize from current time
156 import time
Tim Peters0de88fc2001-02-01 04:59:18 +0000157 a = long(time.time() * 256)
158
159 if type(a) not in (type(3), type(3L)):
160 a = hash(a)
161
162 a, x = divmod(a, 30268)
163 a, y = divmod(a, 30306)
164 a, z = divmod(a, 30322)
165 self._seed = int(x)+1, int(y)+1, int(z)+1
Tim Petersd7b5e882001-01-25 03:36:26 +0000166
Tim Peters46c04e12002-05-05 20:40:00 +0000167 self.gauss_next = None
168
Tim Petersd7b5e882001-01-25 03:36:26 +0000169 def random(self):
170 """Get the next random number in the range [0.0, 1.0)."""
171
172 # Wichman-Hill random number generator.
173 #
174 # Wichmann, B. A. & Hill, I. D. (1982)
175 # Algorithm AS 183:
176 # An efficient and portable pseudo-random number generator
177 # Applied Statistics 31 (1982) 188-190
178 #
179 # see also:
180 # Correction to Algorithm AS 183
181 # Applied Statistics 33 (1984) 123
182 #
183 # McLeod, A. I. (1985)
184 # A remark on Algorithm AS 183
185 # Applied Statistics 34 (1985),198-200
186
187 # This part is thread-unsafe:
188 # BEGIN CRITICAL SECTION
189 x, y, z = self._seed
190 x = (171 * x) % 30269
191 y = (172 * y) % 30307
192 z = (170 * z) % 30323
193 self._seed = x, y, z
194 # END CRITICAL SECTION
195
196 # Note: on a platform using IEEE-754 double arithmetic, this can
197 # never return 0.0 (asserted by Tim; proof too long for a comment).
198 return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
199
Tim Peterscd804102001-01-25 20:25:57 +0000200 def getstate(self):
201 """Return internal state; can be passed to setstate() later."""
202 return self.VERSION, self._seed, self.gauss_next
203
204 def setstate(self, state):
205 """Restore internal state from object returned by getstate()."""
206 version = state[0]
207 if version == 1:
208 version, self._seed, self.gauss_next = state
209 else:
210 raise ValueError("state with version %s passed to "
211 "Random.setstate() of version %s" %
212 (version, self.VERSION))
213
214 def jumpahead(self, n):
215 """Act as if n calls to random() were made, but quickly.
216
217 n is an int, greater than or equal to 0.
218
219 Example use: If you have 2 threads and know that each will
220 consume no more than a million random numbers, create two Random
221 objects r1 and r2, then do
222 r2.setstate(r1.getstate())
223 r2.jumpahead(1000000)
224 Then r1 and r2 will use guaranteed-disjoint segments of the full
225 period.
226 """
227
228 if not n >= 0:
229 raise ValueError("n must be >= 0")
230 x, y, z = self._seed
231 x = int(x * pow(171, n, 30269)) % 30269
232 y = int(y * pow(172, n, 30307)) % 30307
233 z = int(z * pow(170, n, 30323)) % 30323
234 self._seed = x, y, z
235
Tim Peters0de88fc2001-02-01 04:59:18 +0000236 def __whseed(self, x=0, y=0, z=0):
237 """Set the Wichmann-Hill seed from (x, y, z).
238
239 These must be integers in the range [0, 256).
240 """
241
242 if not type(x) == type(y) == type(z) == type(0):
243 raise TypeError('seeds must be integers')
244 if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256):
245 raise ValueError('seeds must be in range(0, 256)')
246 if 0 == x == y == z:
247 # Initialize from current time
248 import time
249 t = long(time.time() * 256)
250 t = int((t&0xffffff) ^ (t>>24))
251 t, x = divmod(t, 256)
252 t, y = divmod(t, 256)
253 t, z = divmod(t, 256)
254 # Zero is a poor seed, so substitute 1
255 self._seed = (x or 1, y or 1, z or 1)
256
Tim Peters46c04e12002-05-05 20:40:00 +0000257 self.gauss_next = None
258
Tim Peters0de88fc2001-02-01 04:59:18 +0000259 def whseed(self, a=None):
260 """Seed from hashable object's hash code.
261
262 None or no argument seeds from current time. It is not guaranteed
263 that objects with distinct hash codes lead to distinct internal
264 states.
265
266 This is obsolete, provided for compatibility with the seed routine
267 used prior to Python 2.1. Use the .seed() method instead.
268 """
269
270 if a is None:
271 self.__whseed()
272 return
273 a = hash(a)
274 a, x = divmod(a, 256)
275 a, y = divmod(a, 256)
276 a, z = divmod(a, 256)
277 x = (x + a) % 256 or 1
278 y = (y + a) % 256 or 1
279 z = (z + a) % 256 or 1
280 self.__whseed(x, y, z)
281
Tim Peterscd804102001-01-25 20:25:57 +0000282## ---- Methods below this point do not need to be overridden when
283## ---- subclassing for the purpose of using a different core generator.
284
285## -------------------- pickle support -------------------
286
287 def __getstate__(self): # for pickle
288 return self.getstate()
289
290 def __setstate__(self, state): # for pickle
291 self.setstate(state)
292
293## -------------------- integer methods -------------------
294
Tim Petersd7b5e882001-01-25 03:36:26 +0000295 def randrange(self, start, stop=None, step=1, int=int, default=None):
296 """Choose a random item from range(start, stop[, step]).
297
298 This fixes the problem with randint() which includes the
299 endpoint; in Python this is usually not what you want.
300 Do not supply the 'int' and 'default' arguments.
301 """
302
303 # This code is a bit messy to make it fast for the
Tim Peters9146f272002-08-16 03:41:39 +0000304 # common case while still doing adequate error checking.
Tim Petersd7b5e882001-01-25 03:36:26 +0000305 istart = int(start)
306 if istart != start:
307 raise ValueError, "non-integer arg 1 for randrange()"
308 if stop is default:
309 if istart > 0:
310 return int(self.random() * istart)
311 raise ValueError, "empty range for randrange()"
Tim Peters9146f272002-08-16 03:41:39 +0000312
313 # stop argument supplied.
Tim Petersd7b5e882001-01-25 03:36:26 +0000314 istop = int(stop)
315 if istop != stop:
316 raise ValueError, "non-integer stop for randrange()"
Tim Peters9146f272002-08-16 03:41:39 +0000317 if step == 1 and istart < istop:
318 try:
319 return istart + int(self.random()*(istop - istart))
320 except OverflowError:
321 # This can happen if istop-istart > sys.maxint + 1, and
322 # multiplying by random() doesn't reduce it to something
323 # <= sys.maxint. We know that the overall result fits
324 # in an int, and can still do it correctly via math.floor().
325 # But that adds another function call, so for speed we
326 # avoided that whenever possible.
327 return int(istart + _floor(self.random()*(istop - istart)))
Tim Petersd7b5e882001-01-25 03:36:26 +0000328 if step == 1:
Tim Petersd7b5e882001-01-25 03:36:26 +0000329 raise ValueError, "empty range for randrange()"
Tim Peters9146f272002-08-16 03:41:39 +0000330
331 # Non-unit step argument supplied.
Tim Petersd7b5e882001-01-25 03:36:26 +0000332 istep = int(step)
333 if istep != step:
334 raise ValueError, "non-integer step for randrange()"
335 if istep > 0:
336 n = (istop - istart + istep - 1) / istep
337 elif istep < 0:
338 n = (istop - istart + istep + 1) / istep
339 else:
340 raise ValueError, "zero step for randrange()"
341
342 if n <= 0:
343 raise ValueError, "empty range for randrange()"
344 return istart + istep*int(self.random() * n)
345
346 def randint(self, a, b):
Tim Peterscd804102001-01-25 20:25:57 +0000347 """Return random integer in range [a, b], including both end points.
Tim Petersd7b5e882001-01-25 03:36:26 +0000348 """
349
350 return self.randrange(a, b+1)
351
Tim Peterscd804102001-01-25 20:25:57 +0000352## -------------------- sequence methods -------------------
353
Tim Petersd7b5e882001-01-25 03:36:26 +0000354 def choice(self, seq):
355 """Choose a random element from a non-empty sequence."""
356 return seq[int(self.random() * len(seq))]
357
358 def shuffle(self, x, random=None, int=int):
359 """x, random=random.random -> shuffle list x in place; return None.
360
361 Optional arg random is a 0-argument function returning a random
362 float in [0.0, 1.0); by default, the standard random.random.
363
364 Note that for even rather small len(x), the total number of
365 permutations of x is larger than the period of most random number
366 generators; this implies that "most" permutations of a long
367 sequence can never be generated.
368 """
369
370 if random is None:
371 random = self.random
372 for i in xrange(len(x)-1, 0, -1):
Tim Peterscd804102001-01-25 20:25:57 +0000373 # pick an element in x[:i+1] with which to exchange x[i]
Tim Petersd7b5e882001-01-25 03:36:26 +0000374 j = int(random() * (i+1))
375 x[i], x[j] = x[j], x[i]
376
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000377 def sample(self, population, k, random=None, int=int):
378 """Chooses k unique random elements from a population sequence.
379
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000380 Returns a new list containing elements from the population while
381 leaving the original population unchanged. The resulting list is
382 in selection order so that all sub-slices will also be valid random
383 samples. This allows raffle winners (the sample) to be partitioned
384 into grand prize and second place winners (the subslices).
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000385
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000386 Members of the population need not be hashable or unique. If the
387 population contains repeats, then each occurrence is a possible
388 selection in the sample.
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000389
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000390 To choose a sample in a range of integers, use xrange as an argument.
391 This is especially fast and space efficient for sampling from a
392 large population: sample(xrange(10000000), 60)
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000393
394 Optional arg random is a 0-argument function returning a random
395 float in [0.0, 1.0); by default, the standard random.random.
396 """
397
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000398 # Sampling without replacement entails tracking either potential
399 # selections (the pool) or previous selections.
400
401 # Pools are stored in lists which provide __getitem__ for selection
402 # and provide a way to remove selections. But each list.remove()
403 # rebuilds the entire list, so it is better to rearrange the list,
404 # placing non-selected elements at the head of the list. Tracking
405 # the selection pool is only space efficient with small populations.
406
407 # Previous selections are stored in dictionaries which provide
408 # __contains__ for detecting repeat selections. Discarding repeats
409 # is efficient unless most of the population has already been chosen.
410 # So, tracking selections is useful when sample sizes are much
411 # smaller than the total population.
412
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000413 n = len(population)
414 if not 0 <= k <= n:
415 raise ValueError, "sample larger than population"
416 if random is None:
417 random = self.random
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000418 result = [None] * k
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000419 if n < 6 * k: # if n len list takes less space than a k len dict
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000420 pool = list(population) # track potential selections
421 for i in xrange(k):
422 j = int(random() * (n-i)) # non-selected at [0,n-i)
423 result[i] = pool[j] # save selected element
424 pool[j] = pool[n-i-1] # non-selected to head of list
425 else:
426 selected = {} # track previous selections
427 for i in xrange(k):
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000428 j = int(random() * n)
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000429 while j in selected: # discard and replace repeats
430 j = int(random() * n)
431 result[i] = selected[j] = population[j]
432 return result # return selections in the order they were picked
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000433
Tim Peterscd804102001-01-25 20:25:57 +0000434## -------------------- real-valued distributions -------------------
435
436## -------------------- uniform distribution -------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000437
438 def uniform(self, a, b):
439 """Get a random number in the range [a, b)."""
440 return a + (b-a) * self.random()
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000441
Tim Peterscd804102001-01-25 20:25:57 +0000442## -------------------- normal distribution --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000443
Tim Petersd7b5e882001-01-25 03:36:26 +0000444 def normalvariate(self, mu, sigma):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000445 """Normal distribution.
446
447 mu is the mean, and sigma is the standard deviation.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000448
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000449 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000450 # mu = mean, sigma = standard deviation
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000451
Tim Petersd7b5e882001-01-25 03:36:26 +0000452 # Uses Kinderman and Monahan method. Reference: Kinderman,
453 # A.J. and Monahan, J.F., "Computer generation of random
454 # variables using the ratio of uniform deviates", ACM Trans
455 # Math Software, 3, (1977), pp257-260.
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000456
Tim Petersd7b5e882001-01-25 03:36:26 +0000457 random = self.random
Tim Peters0c9886d2001-01-15 01:18:21 +0000458 while 1:
459 u1 = random()
460 u2 = random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000461 z = NV_MAGICCONST*(u1-0.5)/u2
462 zz = z*z/4.0
463 if zz <= -_log(u2):
464 break
465 return mu + z*sigma
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000466
Tim Peterscd804102001-01-25 20:25:57 +0000467## -------------------- lognormal distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000468
469 def lognormvariate(self, mu, sigma):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000470 """Log normal distribution.
471
472 If you take the natural logarithm of this distribution, you'll get a
473 normal distribution with mean mu and standard deviation sigma.
474 mu can have any value, and sigma must be greater than zero.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000475
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000476 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000477 return _exp(self.normalvariate(mu, sigma))
478
Tim Peterscd804102001-01-25 20:25:57 +0000479## -------------------- circular uniform --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000480
481 def cunifvariate(self, mean, arc):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000482 """Circular uniform distribution.
483
484 mean is the mean angle, and arc is the range of the distribution,
485 centered around the mean angle. Both values must be expressed in
486 radians. Returned values range between mean - arc/2 and
487 mean + arc/2 and are normalized to between 0 and pi.
488
489 Deprecated in version 2.3. Use:
490 (mean + arc * (Random.random() - 0.5)) % Math.pi
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000491
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000492 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000493 # mean: mean angle (in radians between 0 and pi)
494 # arc: range of distribution (in radians between 0 and pi)
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000495 import warnings
496 warnings.warn("The cunifvariate function is deprecated; Use (mean "
497 "+ arc * (Random.random() - 0.5)) % Math.pi instead",
498 DeprecationWarning)
Tim Petersd7b5e882001-01-25 03:36:26 +0000499
500 return (mean + arc * (self.random() - 0.5)) % _pi
501
Tim Peterscd804102001-01-25 20:25:57 +0000502## -------------------- exponential distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000503
504 def expovariate(self, lambd):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000505 """Exponential distribution.
506
507 lambd is 1.0 divided by the desired mean. (The parameter would be
508 called "lambda", but that is a reserved word in Python.) Returned
509 values range from 0 to positive infinity.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000510
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000511 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000512 # lambd: rate lambd = 1/mean
513 # ('lambda' is a Python reserved word)
514
515 random = self.random
Tim Peters0c9886d2001-01-15 01:18:21 +0000516 u = random()
517 while u <= 1e-7:
518 u = random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000519 return -_log(u)/lambd
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000520
Tim Peterscd804102001-01-25 20:25:57 +0000521## -------------------- von Mises distribution --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000522
Tim Petersd7b5e882001-01-25 03:36:26 +0000523 def vonmisesvariate(self, mu, kappa):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000524 """Circular data distribution.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000525
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000526 mu is the mean angle, expressed in radians between 0 and 2*pi, and
527 kappa is the concentration parameter, which must be greater than or
528 equal to zero. If kappa is equal to zero, this distribution reduces
529 to a uniform random angle over the range 0 to 2*pi.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000530
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000531 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000532 # mu: mean angle (in radians between 0 and 2*pi)
533 # kappa: concentration parameter kappa (>= 0)
534 # if kappa = 0 generate uniform random angle
535
536 # Based upon an algorithm published in: Fisher, N.I.,
537 # "Statistical Analysis of Circular Data", Cambridge
538 # University Press, 1993.
539
540 # Thanks to Magnus Kessler for a correction to the
541 # implementation of step 4.
542
543 random = self.random
544 if kappa <= 1e-6:
545 return TWOPI * random()
546
547 a = 1.0 + _sqrt(1.0 + 4.0 * kappa * kappa)
548 b = (a - _sqrt(2.0 * a))/(2.0 * kappa)
549 r = (1.0 + b * b)/(2.0 * b)
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000550
Tim Peters0c9886d2001-01-15 01:18:21 +0000551 while 1:
Tim Peters0c9886d2001-01-15 01:18:21 +0000552 u1 = random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000553
554 z = _cos(_pi * u1)
555 f = (1.0 + r * z)/(r + z)
556 c = kappa * (r - f)
557
558 u2 = random()
559
560 if not (u2 >= c * (2.0 - c) and u2 > c * _exp(1.0 - c)):
Tim Peters0c9886d2001-01-15 01:18:21 +0000561 break
Tim Petersd7b5e882001-01-25 03:36:26 +0000562
563 u3 = random()
564 if u3 > 0.5:
565 theta = (mu % TWOPI) + _acos(f)
566 else:
567 theta = (mu % TWOPI) - _acos(f)
568
569 return theta
570
Tim Peterscd804102001-01-25 20:25:57 +0000571## -------------------- gamma distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000572
573 def gammavariate(self, alpha, beta):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000574 """Gamma distribution. Not the gamma function!
575
576 Conditions on the parameters are alpha > 0 and beta > 0.
577
578 """
Tim Peters8ac14952002-05-23 15:15:30 +0000579
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000580 # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2
Tim Peters8ac14952002-05-23 15:15:30 +0000581
Guido van Rossum570764d2002-05-14 14:08:12 +0000582 # Warning: a few older sources define the gamma distribution in terms
583 # of alpha > -1.0
584 if alpha <= 0.0 or beta <= 0.0:
585 raise ValueError, 'gammavariate: alpha and beta must be > 0.0'
Tim Peters8ac14952002-05-23 15:15:30 +0000586
Tim Petersd7b5e882001-01-25 03:36:26 +0000587 random = self.random
Tim Petersd7b5e882001-01-25 03:36:26 +0000588 if alpha > 1.0:
589
590 # Uses R.C.H. Cheng, "The generation of Gamma
591 # variables with non-integral shape parameters",
592 # Applied Statistics, (1977), 26, No. 1, p71-74
593
Raymond Hettingerca6cdc22002-05-13 23:40:14 +0000594 ainv = _sqrt(2.0 * alpha - 1.0)
595 bbb = alpha - LOG4
596 ccc = alpha + ainv
Tim Peters8ac14952002-05-23 15:15:30 +0000597
Tim Petersd7b5e882001-01-25 03:36:26 +0000598 while 1:
599 u1 = random()
600 u2 = random()
601 v = _log(u1/(1.0-u1))/ainv
602 x = alpha*_exp(v)
603 z = u1*u1*u2
604 r = bbb+ccc*v-x
605 if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z):
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000606 return x * beta
Tim Petersd7b5e882001-01-25 03:36:26 +0000607
608 elif alpha == 1.0:
609 # expovariate(1)
610 u = random()
611 while u <= 1e-7:
612 u = random()
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000613 return -_log(u) * beta
Tim Petersd7b5e882001-01-25 03:36:26 +0000614
615 else: # alpha is between 0 and 1 (exclusive)
616
617 # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
618
619 while 1:
620 u = random()
621 b = (_e + alpha)/_e
622 p = b*u
623 if p <= 1.0:
624 x = pow(p, 1.0/alpha)
625 else:
626 # p > 1
627 x = -_log((b-p)/alpha)
628 u1 = random()
629 if not (((p <= 1.0) and (u1 > _exp(-x))) or
630 ((p > 1) and (u1 > pow(x, alpha - 1.0)))):
631 break
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000632 return x * beta
633
634
635 def stdgamma(self, alpha, ainv, bbb, ccc):
636 # This method was (and shall remain) undocumented.
637 # This method is deprecated
638 # for the following reasons:
639 # 1. Returns same as .gammavariate(alpha, 1.0)
640 # 2. Requires caller to provide 3 extra arguments
641 # that are functions of alpha anyway
642 # 3. Can't be used for alpha < 0.5
643
644 # ainv = sqrt(2 * alpha - 1)
645 # bbb = alpha - log(4)
646 # ccc = alpha + ainv
647 import warnings
648 warnings.warn("The stdgamma function is deprecated; "
649 "use gammavariate() instead",
650 DeprecationWarning)
651 return self.gammavariate(alpha, 1.0)
652
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000653
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000654
Tim Peterscd804102001-01-25 20:25:57 +0000655## -------------------- Gauss (faster alternative) --------------------
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000656
Tim Petersd7b5e882001-01-25 03:36:26 +0000657 def gauss(self, mu, sigma):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000658 """Gaussian distribution.
659
660 mu is the mean, and sigma is the standard deviation. This is
661 slightly faster than the normalvariate() function.
662
663 Not thread-safe without a lock around calls.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000664
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000665 """
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000666
Tim Petersd7b5e882001-01-25 03:36:26 +0000667 # When x and y are two variables from [0, 1), uniformly
668 # distributed, then
669 #
670 # cos(2*pi*x)*sqrt(-2*log(1-y))
671 # sin(2*pi*x)*sqrt(-2*log(1-y))
672 #
673 # are two *independent* variables with normal distribution
674 # (mu = 0, sigma = 1).
675 # (Lambert Meertens)
676 # (corrected version; bug discovered by Mike Miller, fixed by LM)
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000677
Tim Petersd7b5e882001-01-25 03:36:26 +0000678 # Multithreading note: When two threads call this function
679 # simultaneously, it is possible that they will receive the
680 # same return value. The window is very small though. To
681 # avoid this, you have to use a lock around all calls. (I
682 # didn't want to slow this down in the serial case by using a
683 # lock here.)
Guido van Rossumd03e1191998-05-29 17:51:31 +0000684
Tim Petersd7b5e882001-01-25 03:36:26 +0000685 random = self.random
686 z = self.gauss_next
687 self.gauss_next = None
688 if z is None:
689 x2pi = random() * TWOPI
690 g2rad = _sqrt(-2.0 * _log(1.0 - random()))
691 z = _cos(x2pi) * g2rad
692 self.gauss_next = _sin(x2pi) * g2rad
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000693
Tim Petersd7b5e882001-01-25 03:36:26 +0000694 return mu + z*sigma
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000695
Tim Peterscd804102001-01-25 20:25:57 +0000696## -------------------- beta --------------------
Tim Peters85e2e472001-01-26 06:49:56 +0000697## See
698## http://sourceforge.net/bugs/?func=detailbug&bug_id=130030&group_id=5470
699## for Ivan Frohne's insightful analysis of why the original implementation:
700##
701## def betavariate(self, alpha, beta):
702## # Discrete Event Simulation in C, pp 87-88.
703##
704## y = self.expovariate(alpha)
705## z = self.expovariate(1.0/beta)
706## return z/(y+z)
707##
708## was dead wrong, and how it probably got that way.
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000709
Tim Petersd7b5e882001-01-25 03:36:26 +0000710 def betavariate(self, alpha, beta):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000711 """Beta distribution.
712
713 Conditions on the parameters are alpha > -1 and beta} > -1.
714 Returned values range between 0 and 1.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000715
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000716 """
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000717
Tim Peters85e2e472001-01-26 06:49:56 +0000718 # This version due to Janne Sinkkonen, and matches all the std
719 # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution").
720 y = self.gammavariate(alpha, 1.)
721 if y == 0:
722 return 0.0
723 else:
724 return y / (y + self.gammavariate(beta, 1.))
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000725
Tim Peterscd804102001-01-25 20:25:57 +0000726## -------------------- Pareto --------------------
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000727
Tim Petersd7b5e882001-01-25 03:36:26 +0000728 def paretovariate(self, alpha):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000729 """Pareto distribution. alpha is the shape parameter."""
Tim Petersd7b5e882001-01-25 03:36:26 +0000730 # Jain, pg. 495
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000731
Tim Petersd7b5e882001-01-25 03:36:26 +0000732 u = self.random()
733 return 1.0 / pow(u, 1.0/alpha)
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000734
Tim Peterscd804102001-01-25 20:25:57 +0000735## -------------------- Weibull --------------------
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000736
Tim Petersd7b5e882001-01-25 03:36:26 +0000737 def weibullvariate(self, alpha, beta):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000738 """Weibull distribution.
739
740 alpha is the scale parameter and beta is the shape parameter.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000741
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000742 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000743 # Jain, pg. 499; bug fix courtesy Bill Arms
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000744
Tim Petersd7b5e882001-01-25 03:36:26 +0000745 u = self.random()
746 return alpha * pow(-_log(u), 1.0/beta)
Guido van Rossum6c395ba1999-08-18 13:53:28 +0000747
Tim Peterscd804102001-01-25 20:25:57 +0000748## -------------------- test program --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000749
Tim Petersd7b5e882001-01-25 03:36:26 +0000750def _test_generator(n, funccall):
Tim Peters0c9886d2001-01-15 01:18:21 +0000751 import time
752 print n, 'times', funccall
753 code = compile(funccall, funccall, 'eval')
754 sum = 0.0
755 sqsum = 0.0
756 smallest = 1e10
757 largest = -1e10
758 t0 = time.time()
759 for i in range(n):
760 x = eval(code)
761 sum = sum + x
762 sqsum = sqsum + x*x
763 smallest = min(x, smallest)
764 largest = max(x, largest)
765 t1 = time.time()
766 print round(t1-t0, 3), 'sec,',
767 avg = sum/n
Tim Petersd7b5e882001-01-25 03:36:26 +0000768 stddev = _sqrt(sqsum/n - avg*avg)
Tim Peters0c9886d2001-01-15 01:18:21 +0000769 print 'avg %g, stddev %g, min %g, max %g' % \
770 (avg, stddev, smallest, largest)
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000771
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000772def _test_sample(n):
773 # For the entire allowable range of 0 <= k <= n, validate that
774 # the sample is of the correct length and contains only unique items
775 population = xrange(n)
776 for k in xrange(n+1):
777 s = sample(population, k)
778 assert len(dict([(elem,True) for elem in s])) == len(s) == k
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000779 assert None not in s
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000780
781def _sample_generator(n, k):
782 # Return a fixed element from the sample. Validates random ordering.
783 return sample(xrange(n), k)[k//2]
784
785def _test(N=2000):
Tim Petersd7b5e882001-01-25 03:36:26 +0000786 print 'TWOPI =', TWOPI
787 print 'LOG4 =', LOG4
788 print 'NV_MAGICCONST =', NV_MAGICCONST
789 print 'SG_MAGICCONST =', SG_MAGICCONST
790 _test_generator(N, 'random()')
791 _test_generator(N, 'normalvariate(0.0, 1.0)')
792 _test_generator(N, 'lognormvariate(0.0, 1.0)')
793 _test_generator(N, 'cunifvariate(0.0, 1.0)')
794 _test_generator(N, 'expovariate(1.0)')
795 _test_generator(N, 'vonmisesvariate(0.0, 1.0)')
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000796 _test_generator(N, 'gammavariate(0.01, 1.0)')
797 _test_generator(N, 'gammavariate(0.1, 1.0)')
Tim Peters8ac14952002-05-23 15:15:30 +0000798 _test_generator(N, 'gammavariate(0.1, 2.0)')
Tim Petersd7b5e882001-01-25 03:36:26 +0000799 _test_generator(N, 'gammavariate(0.5, 1.0)')
800 _test_generator(N, 'gammavariate(0.9, 1.0)')
801 _test_generator(N, 'gammavariate(1.0, 1.0)')
802 _test_generator(N, 'gammavariate(2.0, 1.0)')
803 _test_generator(N, 'gammavariate(20.0, 1.0)')
804 _test_generator(N, 'gammavariate(200.0, 1.0)')
805 _test_generator(N, 'gauss(0.0, 1.0)')
806 _test_generator(N, 'betavariate(3.0, 3.0)')
807 _test_generator(N, 'paretovariate(1.0)')
808 _test_generator(N, 'weibullvariate(1.0, 1.0)')
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000809 _test_generator(N, '_sample_generator(50, 5)') # expected s.d.: 14.4
810 _test_generator(N, '_sample_generator(50, 45)') # expected s.d.: 14.4
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000811 _test_sample(500)
Tim Petersd7b5e882001-01-25 03:36:26 +0000812
Tim Peterscd804102001-01-25 20:25:57 +0000813 # Test jumpahead.
814 s = getstate()
815 jumpahead(N)
816 r1 = random()
817 # now do it the slow way
818 setstate(s)
819 for i in range(N):
820 random()
821 r2 = random()
822 if r1 != r2:
823 raise ValueError("jumpahead test failed " + `(N, r1, r2)`)
824
Tim Peters715c4c42001-01-26 22:56:56 +0000825# Create one instance, seeded from current time, and export its methods
826# as module-level functions. The functions are not threadsafe, and state
827# is shared across all uses (both in the user's code and in the Python
828# libraries), but that's fine for most programs and is easier for the
829# casual user than making them instantiate their own Random() instance.
Tim Petersd7b5e882001-01-25 03:36:26 +0000830_inst = Random()
831seed = _inst.seed
832random = _inst.random
833uniform = _inst.uniform
834randint = _inst.randint
835choice = _inst.choice
836randrange = _inst.randrange
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000837sample = _inst.sample
Tim Petersd7b5e882001-01-25 03:36:26 +0000838shuffle = _inst.shuffle
839normalvariate = _inst.normalvariate
840lognormvariate = _inst.lognormvariate
841cunifvariate = _inst.cunifvariate
842expovariate = _inst.expovariate
843vonmisesvariate = _inst.vonmisesvariate
844gammavariate = _inst.gammavariate
845stdgamma = _inst.stdgamma
846gauss = _inst.gauss
847betavariate = _inst.betavariate
848paretovariate = _inst.paretovariate
849weibullvariate = _inst.weibullvariate
850getstate = _inst.getstate
851setstate = _inst.setstate
Tim Petersd52269b2001-01-25 06:23:18 +0000852jumpahead = _inst.jumpahead
Tim Peters0de88fc2001-02-01 04:59:18 +0000853whseed = _inst.whseed
Tim Petersd7b5e882001-01-25 03:36:26 +0000854
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000855if __name__ == '__main__':
Tim Petersd7b5e882001-01-25 03:36:26 +0000856 _test()