blob: 16ec3658ffc4852b0581357f3af06585f407ea88 [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
Raymond Hettinger311f4192002-11-18 09:01:24 +0000242 if not type(x) == type(y) == type(z) == int:
Tim Peters0de88fc2001-02-01 04:59:18 +0000243 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.
Raymond Hettinger311f4192002-11-18 09:01:24 +0000410 # So, tracking selections is fast only with small sample sizes.
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000411
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000412 n = len(population)
413 if not 0 <= k <= n:
414 raise ValueError, "sample larger than population"
415 if random is None:
416 random = self.random
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000417 result = [None] * k
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000418 if n < 6 * k: # if n len list takes less space than a k len dict
Raymond Hettinger311f4192002-11-18 09:01:24 +0000419 pool = list(population)
420 for i in xrange(k): # invariant: non-selected at [0,n-i)
421 j = int(random() * (n-i))
422 result[i] = pool[j]
423 pool[j] = pool[n-i-1]
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000424 else:
Raymond Hettinger311f4192002-11-18 09:01:24 +0000425 selected = {}
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000426 for i in xrange(k):
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000427 j = int(random() * n)
Raymond Hettinger311f4192002-11-18 09:01:24 +0000428 while j in selected:
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000429 j = int(random() * n)
430 result[i] = selected[j] = population[j]
Raymond Hettinger311f4192002-11-18 09:01:24 +0000431 return result
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000432
Tim Peterscd804102001-01-25 20:25:57 +0000433## -------------------- real-valued distributions -------------------
434
435## -------------------- uniform distribution -------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000436
437 def uniform(self, a, b):
438 """Get a random number in the range [a, b)."""
439 return a + (b-a) * self.random()
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000440
Tim Peterscd804102001-01-25 20:25:57 +0000441## -------------------- normal distribution --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000442
Tim Petersd7b5e882001-01-25 03:36:26 +0000443 def normalvariate(self, mu, sigma):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000444 """Normal distribution.
445
446 mu is the mean, and sigma is the standard deviation.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000447
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000448 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000449 # mu = mean, sigma = standard deviation
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000450
Tim Petersd7b5e882001-01-25 03:36:26 +0000451 # Uses Kinderman and Monahan method. Reference: Kinderman,
452 # A.J. and Monahan, J.F., "Computer generation of random
453 # variables using the ratio of uniform deviates", ACM Trans
454 # Math Software, 3, (1977), pp257-260.
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000455
Tim Petersd7b5e882001-01-25 03:36:26 +0000456 random = self.random
Raymond Hettinger311f4192002-11-18 09:01:24 +0000457 while True:
Tim Peters0c9886d2001-01-15 01:18:21 +0000458 u1 = random()
459 u2 = random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000460 z = NV_MAGICCONST*(u1-0.5)/u2
461 zz = z*z/4.0
462 if zz <= -_log(u2):
463 break
464 return mu + z*sigma
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000465
Tim Peterscd804102001-01-25 20:25:57 +0000466## -------------------- lognormal distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000467
468 def lognormvariate(self, mu, sigma):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000469 """Log normal distribution.
470
471 If you take the natural logarithm of this distribution, you'll get a
472 normal distribution with mean mu and standard deviation sigma.
473 mu can have any value, and sigma must be greater than zero.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000474
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000475 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000476 return _exp(self.normalvariate(mu, sigma))
477
Tim Peterscd804102001-01-25 20:25:57 +0000478## -------------------- circular uniform --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000479
480 def cunifvariate(self, mean, arc):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000481 """Circular uniform distribution.
482
483 mean is the mean angle, and arc is the range of the distribution,
484 centered around the mean angle. Both values must be expressed in
485 radians. Returned values range between mean - arc/2 and
486 mean + arc/2 and are normalized to between 0 and pi.
487
488 Deprecated in version 2.3. Use:
489 (mean + arc * (Random.random() - 0.5)) % Math.pi
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000490
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000491 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000492 # mean: mean angle (in radians between 0 and pi)
493 # arc: range of distribution (in radians between 0 and pi)
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000494 import warnings
495 warnings.warn("The cunifvariate function is deprecated; Use (mean "
496 "+ arc * (Random.random() - 0.5)) % Math.pi instead",
497 DeprecationWarning)
Tim Petersd7b5e882001-01-25 03:36:26 +0000498
499 return (mean + arc * (self.random() - 0.5)) % _pi
500
Tim Peterscd804102001-01-25 20:25:57 +0000501## -------------------- exponential distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000502
503 def expovariate(self, lambd):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000504 """Exponential distribution.
505
506 lambd is 1.0 divided by the desired mean. (The parameter would be
507 called "lambda", but that is a reserved word in Python.) Returned
508 values range from 0 to positive infinity.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000509
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000510 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000511 # lambd: rate lambd = 1/mean
512 # ('lambda' is a Python reserved word)
513
514 random = self.random
Tim Peters0c9886d2001-01-15 01:18:21 +0000515 u = random()
516 while u <= 1e-7:
517 u = random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000518 return -_log(u)/lambd
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000519
Tim Peterscd804102001-01-25 20:25:57 +0000520## -------------------- von Mises distribution --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000521
Tim Petersd7b5e882001-01-25 03:36:26 +0000522 def vonmisesvariate(self, mu, kappa):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000523 """Circular data distribution.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000524
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000525 mu is the mean angle, expressed in radians between 0 and 2*pi, and
526 kappa is the concentration parameter, which must be greater than or
527 equal to zero. If kappa is equal to zero, this distribution reduces
528 to a uniform random angle over the range 0 to 2*pi.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000529
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000530 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000531 # mu: mean angle (in radians between 0 and 2*pi)
532 # kappa: concentration parameter kappa (>= 0)
533 # if kappa = 0 generate uniform random angle
534
535 # Based upon an algorithm published in: Fisher, N.I.,
536 # "Statistical Analysis of Circular Data", Cambridge
537 # University Press, 1993.
538
539 # Thanks to Magnus Kessler for a correction to the
540 # implementation of step 4.
541
542 random = self.random
543 if kappa <= 1e-6:
544 return TWOPI * random()
545
546 a = 1.0 + _sqrt(1.0 + 4.0 * kappa * kappa)
547 b = (a - _sqrt(2.0 * a))/(2.0 * kappa)
548 r = (1.0 + b * b)/(2.0 * b)
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000549
Raymond Hettinger311f4192002-11-18 09:01:24 +0000550 while True:
Tim Peters0c9886d2001-01-15 01:18:21 +0000551 u1 = random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000552
553 z = _cos(_pi * u1)
554 f = (1.0 + r * z)/(r + z)
555 c = kappa * (r - f)
556
557 u2 = random()
558
559 if not (u2 >= c * (2.0 - c) and u2 > c * _exp(1.0 - c)):
Tim Peters0c9886d2001-01-15 01:18:21 +0000560 break
Tim Petersd7b5e882001-01-25 03:36:26 +0000561
562 u3 = random()
563 if u3 > 0.5:
564 theta = (mu % TWOPI) + _acos(f)
565 else:
566 theta = (mu % TWOPI) - _acos(f)
567
568 return theta
569
Tim Peterscd804102001-01-25 20:25:57 +0000570## -------------------- gamma distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000571
572 def gammavariate(self, alpha, beta):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000573 """Gamma distribution. Not the gamma function!
574
575 Conditions on the parameters are alpha > 0 and beta > 0.
576
577 """
Tim Peters8ac14952002-05-23 15:15:30 +0000578
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000579 # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2
Tim Peters8ac14952002-05-23 15:15:30 +0000580
Guido van Rossum570764d2002-05-14 14:08:12 +0000581 # Warning: a few older sources define the gamma distribution in terms
582 # of alpha > -1.0
583 if alpha <= 0.0 or beta <= 0.0:
584 raise ValueError, 'gammavariate: alpha and beta must be > 0.0'
Tim Peters8ac14952002-05-23 15:15:30 +0000585
Tim Petersd7b5e882001-01-25 03:36:26 +0000586 random = self.random
Tim Petersd7b5e882001-01-25 03:36:26 +0000587 if alpha > 1.0:
588
589 # Uses R.C.H. Cheng, "The generation of Gamma
590 # variables with non-integral shape parameters",
591 # Applied Statistics, (1977), 26, No. 1, p71-74
592
Raymond Hettingerca6cdc22002-05-13 23:40:14 +0000593 ainv = _sqrt(2.0 * alpha - 1.0)
594 bbb = alpha - LOG4
595 ccc = alpha + ainv
Tim Peters8ac14952002-05-23 15:15:30 +0000596
Raymond Hettinger311f4192002-11-18 09:01:24 +0000597 while True:
Tim Petersd7b5e882001-01-25 03:36:26 +0000598 u1 = random()
599 u2 = random()
600 v = _log(u1/(1.0-u1))/ainv
601 x = alpha*_exp(v)
602 z = u1*u1*u2
603 r = bbb+ccc*v-x
604 if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z):
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000605 return x * beta
Tim Petersd7b5e882001-01-25 03:36:26 +0000606
607 elif alpha == 1.0:
608 # expovariate(1)
609 u = random()
610 while u <= 1e-7:
611 u = random()
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000612 return -_log(u) * beta
Tim Petersd7b5e882001-01-25 03:36:26 +0000613
614 else: # alpha is between 0 and 1 (exclusive)
615
616 # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
617
Raymond Hettinger311f4192002-11-18 09:01:24 +0000618 while True:
Tim Petersd7b5e882001-01-25 03:36:26 +0000619 u = random()
620 b = (_e + alpha)/_e
621 p = b*u
622 if p <= 1.0:
623 x = pow(p, 1.0/alpha)
624 else:
625 # p > 1
626 x = -_log((b-p)/alpha)
627 u1 = random()
628 if not (((p <= 1.0) and (u1 > _exp(-x))) or
629 ((p > 1) and (u1 > pow(x, alpha - 1.0)))):
630 break
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000631 return x * beta
632
633
634 def stdgamma(self, alpha, ainv, bbb, ccc):
635 # This method was (and shall remain) undocumented.
636 # This method is deprecated
637 # for the following reasons:
638 # 1. Returns same as .gammavariate(alpha, 1.0)
639 # 2. Requires caller to provide 3 extra arguments
640 # that are functions of alpha anyway
641 # 3. Can't be used for alpha < 0.5
642
643 # ainv = sqrt(2 * alpha - 1)
644 # bbb = alpha - log(4)
645 # ccc = alpha + ainv
646 import warnings
647 warnings.warn("The stdgamma function is deprecated; "
648 "use gammavariate() instead",
649 DeprecationWarning)
650 return self.gammavariate(alpha, 1.0)
651
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000652
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000653
Tim Peterscd804102001-01-25 20:25:57 +0000654## -------------------- Gauss (faster alternative) --------------------
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000655
Tim Petersd7b5e882001-01-25 03:36:26 +0000656 def gauss(self, mu, sigma):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000657 """Gaussian distribution.
658
659 mu is the mean, and sigma is the standard deviation. This is
660 slightly faster than the normalvariate() function.
661
662 Not thread-safe without a lock around calls.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000663
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000664 """
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000665
Tim Petersd7b5e882001-01-25 03:36:26 +0000666 # When x and y are two variables from [0, 1), uniformly
667 # distributed, then
668 #
669 # cos(2*pi*x)*sqrt(-2*log(1-y))
670 # sin(2*pi*x)*sqrt(-2*log(1-y))
671 #
672 # are two *independent* variables with normal distribution
673 # (mu = 0, sigma = 1).
674 # (Lambert Meertens)
675 # (corrected version; bug discovered by Mike Miller, fixed by LM)
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000676
Tim Petersd7b5e882001-01-25 03:36:26 +0000677 # Multithreading note: When two threads call this function
678 # simultaneously, it is possible that they will receive the
679 # same return value. The window is very small though. To
680 # avoid this, you have to use a lock around all calls. (I
681 # didn't want to slow this down in the serial case by using a
682 # lock here.)
Guido van Rossumd03e1191998-05-29 17:51:31 +0000683
Tim Petersd7b5e882001-01-25 03:36:26 +0000684 random = self.random
685 z = self.gauss_next
686 self.gauss_next = None
687 if z is None:
688 x2pi = random() * TWOPI
689 g2rad = _sqrt(-2.0 * _log(1.0 - random()))
690 z = _cos(x2pi) * g2rad
691 self.gauss_next = _sin(x2pi) * g2rad
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000692
Tim Petersd7b5e882001-01-25 03:36:26 +0000693 return mu + z*sigma
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000694
Tim Peterscd804102001-01-25 20:25:57 +0000695## -------------------- beta --------------------
Tim Peters85e2e472001-01-26 06:49:56 +0000696## See
697## http://sourceforge.net/bugs/?func=detailbug&bug_id=130030&group_id=5470
698## for Ivan Frohne's insightful analysis of why the original implementation:
699##
700## def betavariate(self, alpha, beta):
701## # Discrete Event Simulation in C, pp 87-88.
702##
703## y = self.expovariate(alpha)
704## z = self.expovariate(1.0/beta)
705## return z/(y+z)
706##
707## was dead wrong, and how it probably got that way.
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000708
Tim Petersd7b5e882001-01-25 03:36:26 +0000709 def betavariate(self, alpha, beta):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000710 """Beta distribution.
711
712 Conditions on the parameters are alpha > -1 and beta} > -1.
713 Returned values range between 0 and 1.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000714
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000715 """
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000716
Tim Peters85e2e472001-01-26 06:49:56 +0000717 # This version due to Janne Sinkkonen, and matches all the std
718 # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution").
719 y = self.gammavariate(alpha, 1.)
720 if y == 0:
721 return 0.0
722 else:
723 return y / (y + self.gammavariate(beta, 1.))
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000724
Tim Peterscd804102001-01-25 20:25:57 +0000725## -------------------- Pareto --------------------
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000726
Tim Petersd7b5e882001-01-25 03:36:26 +0000727 def paretovariate(self, alpha):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000728 """Pareto distribution. alpha is the shape parameter."""
Tim Petersd7b5e882001-01-25 03:36:26 +0000729 # Jain, pg. 495
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000730
Tim Petersd7b5e882001-01-25 03:36:26 +0000731 u = self.random()
732 return 1.0 / pow(u, 1.0/alpha)
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000733
Tim Peterscd804102001-01-25 20:25:57 +0000734## -------------------- Weibull --------------------
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000735
Tim Petersd7b5e882001-01-25 03:36:26 +0000736 def weibullvariate(self, alpha, beta):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000737 """Weibull distribution.
738
739 alpha is the scale parameter and beta is the shape parameter.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000740
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000741 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000742 # Jain, pg. 499; bug fix courtesy Bill Arms
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000743
Tim Petersd7b5e882001-01-25 03:36:26 +0000744 u = self.random()
745 return alpha * pow(-_log(u), 1.0/beta)
Guido van Rossum6c395ba1999-08-18 13:53:28 +0000746
Tim Peterscd804102001-01-25 20:25:57 +0000747## -------------------- test program --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000748
Tim Petersd7b5e882001-01-25 03:36:26 +0000749def _test_generator(n, funccall):
Tim Peters0c9886d2001-01-15 01:18:21 +0000750 import time
751 print n, 'times', funccall
752 code = compile(funccall, funccall, 'eval')
753 sum = 0.0
754 sqsum = 0.0
755 smallest = 1e10
756 largest = -1e10
757 t0 = time.time()
758 for i in range(n):
759 x = eval(code)
760 sum = sum + x
761 sqsum = sqsum + x*x
762 smallest = min(x, smallest)
763 largest = max(x, largest)
764 t1 = time.time()
765 print round(t1-t0, 3), 'sec,',
766 avg = sum/n
Tim Petersd7b5e882001-01-25 03:36:26 +0000767 stddev = _sqrt(sqsum/n - avg*avg)
Tim Peters0c9886d2001-01-15 01:18:21 +0000768 print 'avg %g, stddev %g, min %g, max %g' % \
769 (avg, stddev, smallest, largest)
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000770
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000771def _test_sample(n):
772 # For the entire allowable range of 0 <= k <= n, validate that
773 # the sample is of the correct length and contains only unique items
774 population = xrange(n)
775 for k in xrange(n+1):
776 s = sample(population, k)
777 assert len(dict([(elem,True) for elem in s])) == len(s) == k
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000778 assert None not in s
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000779
780def _sample_generator(n, k):
781 # Return a fixed element from the sample. Validates random ordering.
782 return sample(xrange(n), k)[k//2]
783
784def _test(N=2000):
Tim Petersd7b5e882001-01-25 03:36:26 +0000785 print 'TWOPI =', TWOPI
786 print 'LOG4 =', LOG4
787 print 'NV_MAGICCONST =', NV_MAGICCONST
788 print 'SG_MAGICCONST =', SG_MAGICCONST
789 _test_generator(N, 'random()')
790 _test_generator(N, 'normalvariate(0.0, 1.0)')
791 _test_generator(N, 'lognormvariate(0.0, 1.0)')
792 _test_generator(N, 'cunifvariate(0.0, 1.0)')
793 _test_generator(N, 'expovariate(1.0)')
794 _test_generator(N, 'vonmisesvariate(0.0, 1.0)')
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000795 _test_generator(N, 'gammavariate(0.01, 1.0)')
796 _test_generator(N, 'gammavariate(0.1, 1.0)')
Tim Peters8ac14952002-05-23 15:15:30 +0000797 _test_generator(N, 'gammavariate(0.1, 2.0)')
Tim Petersd7b5e882001-01-25 03:36:26 +0000798 _test_generator(N, 'gammavariate(0.5, 1.0)')
799 _test_generator(N, 'gammavariate(0.9, 1.0)')
800 _test_generator(N, 'gammavariate(1.0, 1.0)')
801 _test_generator(N, 'gammavariate(2.0, 1.0)')
802 _test_generator(N, 'gammavariate(20.0, 1.0)')
803 _test_generator(N, 'gammavariate(200.0, 1.0)')
804 _test_generator(N, 'gauss(0.0, 1.0)')
805 _test_generator(N, 'betavariate(3.0, 3.0)')
806 _test_generator(N, 'paretovariate(1.0)')
807 _test_generator(N, 'weibullvariate(1.0, 1.0)')
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000808 _test_generator(N, '_sample_generator(50, 5)') # expected s.d.: 14.4
809 _test_generator(N, '_sample_generator(50, 45)') # expected s.d.: 14.4
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000810 _test_sample(500)
Tim Petersd7b5e882001-01-25 03:36:26 +0000811
Tim Peterscd804102001-01-25 20:25:57 +0000812 # Test jumpahead.
813 s = getstate()
814 jumpahead(N)
815 r1 = random()
816 # now do it the slow way
817 setstate(s)
818 for i in range(N):
819 random()
820 r2 = random()
821 if r1 != r2:
822 raise ValueError("jumpahead test failed " + `(N, r1, r2)`)
823
Tim Peters715c4c42001-01-26 22:56:56 +0000824# Create one instance, seeded from current time, and export its methods
825# as module-level functions. The functions are not threadsafe, and state
826# is shared across all uses (both in the user's code and in the Python
827# libraries), but that's fine for most programs and is easier for the
828# casual user than making them instantiate their own Random() instance.
Tim Petersd7b5e882001-01-25 03:36:26 +0000829_inst = Random()
830seed = _inst.seed
831random = _inst.random
832uniform = _inst.uniform
833randint = _inst.randint
834choice = _inst.choice
835randrange = _inst.randrange
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000836sample = _inst.sample
Tim Petersd7b5e882001-01-25 03:36:26 +0000837shuffle = _inst.shuffle
838normalvariate = _inst.normalvariate
839lognormvariate = _inst.lognormvariate
840cunifvariate = _inst.cunifvariate
841expovariate = _inst.expovariate
842vonmisesvariate = _inst.vonmisesvariate
843gammavariate = _inst.gammavariate
844stdgamma = _inst.stdgamma
845gauss = _inst.gauss
846betavariate = _inst.betavariate
847paretovariate = _inst.paretovariate
848weibullvariate = _inst.weibullvariate
849getstate = _inst.getstate
850setstate = _inst.setstate
Tim Petersd52269b2001-01-25 06:23:18 +0000851jumpahead = _inst.jumpahead
Tim Peters0de88fc2001-02-01 04:59:18 +0000852whseed = _inst.whseed
Tim Petersd7b5e882001-01-25 03:36:26 +0000853
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000854if __name__ == '__main__':
Tim Petersd7b5e882001-01-25 03:36:26 +0000855 _test()