blob: defddbede9850d5b859a92c0394e84ec7ac481b9 [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
Raymond Hettinger40f62172002-12-29 23:03:38 +000021 pareto
22 Weibull
Guido van Rossumff03b1a1994-03-09 12:55:02 +000023
Guido van Rossume7b146f2000-02-04 15:28:42 +000024 distributions on the circle (angles 0 to 2pi)
25 ---------------------------------------------
26 circular uniform
27 von Mises
28
Raymond Hettinger40f62172002-12-29 23:03:38 +000029General notes on the underlying Mersenne Twister core generator:
Guido van Rossume7b146f2000-02-04 15:28:42 +000030
Raymond Hettinger40f62172002-12-29 23:03:38 +000031* The period is 2**19937-1.
32* It is one of the most extensively tested generators in existence
33* Without a direct way to compute N steps forward, the
34 semantics of jumpahead(n) are weakened to simply jump
35 to another distant state and rely on the large period
36 to avoid overlapping sequences.
37* The random() method is implemented in C, executes in
38 a single Python step, and is, therefore, threadsafe.
Tim Peterse360d952001-01-26 10:00:39 +000039
Guido van Rossume7b146f2000-02-04 15:28:42 +000040"""
Guido van Rossumd03e1191998-05-29 17:51:31 +000041
Tim Petersd7b5e882001-01-25 03:36:26 +000042from math import log as _log, exp as _exp, pi as _pi, e as _e
43from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin
Tim Peters9146f272002-08-16 03:41:39 +000044from math import floor as _floor
Guido van Rossumff03b1a1994-03-09 12:55:02 +000045
Raymond Hettingerf24eb352002-11-12 17:41:57 +000046__all__ = ["Random","seed","random","uniform","randint","choice","sample",
Skip Montanaro0de65802001-02-15 22:15:14 +000047 "randrange","shuffle","normalvariate","lognormvariate",
48 "cunifvariate","expovariate","vonmisesvariate","gammavariate",
49 "stdgamma","gauss","betavariate","paretovariate","weibullvariate",
Raymond Hettinger40f62172002-12-29 23:03:38 +000050 "getstate","setstate","jumpahead"]
Tim Petersd7b5e882001-01-25 03:36:26 +000051
52NV_MAGICCONST = 4 * _exp(-0.5)/_sqrt(2.0)
Tim Petersd7b5e882001-01-25 03:36:26 +000053TWOPI = 2.0*_pi
Tim Petersd7b5e882001-01-25 03:36:26 +000054LOG4 = _log(4.0)
Tim Petersd7b5e882001-01-25 03:36:26 +000055SG_MAGICCONST = 1.0 + _log(4.5)
Tim Petersd7b5e882001-01-25 03:36:26 +000056
57# Translated by Guido van Rossum from C source provided by
Raymond Hettinger40f62172002-12-29 23:03:38 +000058# Adrian Baddeley. Adapted by Raymond Hettinger for use with
59# the Mersenne Twister core generator.
Tim Petersd7b5e882001-01-25 03:36:26 +000060
Raymond Hettinger145a4a02003-01-07 10:25:55 +000061import _random
Raymond Hettinger40f62172002-12-29 23:03:38 +000062
Raymond Hettinger145a4a02003-01-07 10:25:55 +000063class Random(_random.Random):
Raymond Hettingerc32f0332002-05-23 19:44:49 +000064 """Random number generator base class used by bound module functions.
65
66 Used to instantiate instances of Random to get generators that don't
67 share state. Especially useful for multi-threaded programs, creating
68 a different instance of Random for each thread, and using the jumpahead()
69 method to ensure that the generated sequences seen by each thread don't
70 overlap.
71
72 Class Random can also be subclassed if you want to use a different basic
73 generator of your own devising: in that case, override the following
74 methods: random(), seed(), getstate(), setstate() and jumpahead().
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +000075
Raymond Hettingerc32f0332002-05-23 19:44:49 +000076 """
Tim Petersd7b5e882001-01-25 03:36:26 +000077
Raymond Hettinger40f62172002-12-29 23:03:38 +000078 VERSION = 2 # used by getstate/setstate
Tim Petersd7b5e882001-01-25 03:36:26 +000079
80 def __init__(self, x=None):
81 """Initialize an instance.
82
83 Optional argument x controls seeding, as for Random.seed().
84 """
85
86 self.seed(x)
Raymond Hettinger40f62172002-12-29 23:03:38 +000087 self.gauss_next = None
Tim Petersd7b5e882001-01-25 03:36:26 +000088
Tim Peters0de88fc2001-02-01 04:59:18 +000089 def seed(self, a=None):
90 """Initialize internal state from hashable object.
Tim Petersd7b5e882001-01-25 03:36:26 +000091
Tim Peters0de88fc2001-02-01 04:59:18 +000092 None or no argument seeds from current time.
93
Tim Petersbcd725f2001-02-01 10:06:53 +000094 If a is not None or an int or long, hash(a) is used instead.
Tim Petersd7b5e882001-01-25 03:36:26 +000095 """
96
Raymond Hettinger145a4a02003-01-07 10:25:55 +000097 super(Random, self).seed(a)
Tim Peters46c04e12002-05-05 20:40:00 +000098 self.gauss_next = None
99
Tim Peterscd804102001-01-25 20:25:57 +0000100 def getstate(self):
101 """Return internal state; can be passed to setstate() later."""
Raymond Hettinger145a4a02003-01-07 10:25:55 +0000102 return self.VERSION, super(Random, self).getstate(), self.gauss_next
Tim Peterscd804102001-01-25 20:25:57 +0000103
104 def setstate(self, state):
105 """Restore internal state from object returned by getstate()."""
106 version = state[0]
Raymond Hettinger40f62172002-12-29 23:03:38 +0000107 if version == 2:
108 version, internalstate, self.gauss_next = state
Raymond Hettinger145a4a02003-01-07 10:25:55 +0000109 super(Random, self).setstate(internalstate)
Tim Peterscd804102001-01-25 20:25:57 +0000110 else:
111 raise ValueError("state with version %s passed to "
112 "Random.setstate() of version %s" %
113 (version, self.VERSION))
114
Tim Peterscd804102001-01-25 20:25:57 +0000115## ---- Methods below this point do not need to be overridden when
116## ---- subclassing for the purpose of using a different core generator.
117
118## -------------------- pickle support -------------------
119
120 def __getstate__(self): # for pickle
121 return self.getstate()
122
123 def __setstate__(self, state): # for pickle
124 self.setstate(state)
125
126## -------------------- integer methods -------------------
127
Tim Petersd7b5e882001-01-25 03:36:26 +0000128 def randrange(self, start, stop=None, step=1, int=int, default=None):
129 """Choose a random item from range(start, stop[, step]).
130
131 This fixes the problem with randint() which includes the
132 endpoint; in Python this is usually not what you want.
133 Do not supply the 'int' and 'default' arguments.
134 """
135
136 # This code is a bit messy to make it fast for the
Tim Peters9146f272002-08-16 03:41:39 +0000137 # common case while still doing adequate error checking.
Tim Petersd7b5e882001-01-25 03:36:26 +0000138 istart = int(start)
139 if istart != start:
140 raise ValueError, "non-integer arg 1 for randrange()"
141 if stop is default:
142 if istart > 0:
143 return int(self.random() * istart)
144 raise ValueError, "empty range for randrange()"
Tim Peters9146f272002-08-16 03:41:39 +0000145
146 # stop argument supplied.
Tim Petersd7b5e882001-01-25 03:36:26 +0000147 istop = int(stop)
148 if istop != stop:
149 raise ValueError, "non-integer stop for randrange()"
Tim Peters9146f272002-08-16 03:41:39 +0000150 if step == 1 and istart < istop:
151 try:
152 return istart + int(self.random()*(istop - istart))
153 except OverflowError:
154 # This can happen if istop-istart > sys.maxint + 1, and
155 # multiplying by random() doesn't reduce it to something
156 # <= sys.maxint. We know that the overall result fits
157 # in an int, and can still do it correctly via math.floor().
158 # But that adds another function call, so for speed we
159 # avoided that whenever possible.
160 return int(istart + _floor(self.random()*(istop - istart)))
Tim Petersd7b5e882001-01-25 03:36:26 +0000161 if step == 1:
Tim Petersd7b5e882001-01-25 03:36:26 +0000162 raise ValueError, "empty range for randrange()"
Tim Peters9146f272002-08-16 03:41:39 +0000163
164 # Non-unit step argument supplied.
Tim Petersd7b5e882001-01-25 03:36:26 +0000165 istep = int(step)
166 if istep != step:
167 raise ValueError, "non-integer step for randrange()"
168 if istep > 0:
169 n = (istop - istart + istep - 1) / istep
170 elif istep < 0:
171 n = (istop - istart + istep + 1) / istep
172 else:
173 raise ValueError, "zero step for randrange()"
174
175 if n <= 0:
176 raise ValueError, "empty range for randrange()"
177 return istart + istep*int(self.random() * n)
178
179 def randint(self, a, b):
Tim Peterscd804102001-01-25 20:25:57 +0000180 """Return random integer in range [a, b], including both end points.
Tim Petersd7b5e882001-01-25 03:36:26 +0000181 """
182
183 return self.randrange(a, b+1)
184
Tim Peterscd804102001-01-25 20:25:57 +0000185## -------------------- sequence methods -------------------
186
Tim Petersd7b5e882001-01-25 03:36:26 +0000187 def choice(self, seq):
188 """Choose a random element from a non-empty sequence."""
189 return seq[int(self.random() * len(seq))]
190
191 def shuffle(self, x, random=None, int=int):
192 """x, random=random.random -> shuffle list x in place; return None.
193
194 Optional arg random is a 0-argument function returning a random
195 float in [0.0, 1.0); by default, the standard random.random.
196
197 Note that for even rather small len(x), the total number of
198 permutations of x is larger than the period of most random number
199 generators; this implies that "most" permutations of a long
200 sequence can never be generated.
201 """
202
203 if random is None:
204 random = self.random
205 for i in xrange(len(x)-1, 0, -1):
Tim Peterscd804102001-01-25 20:25:57 +0000206 # pick an element in x[:i+1] with which to exchange x[i]
Tim Petersd7b5e882001-01-25 03:36:26 +0000207 j = int(random() * (i+1))
208 x[i], x[j] = x[j], x[i]
209
Raymond Hettingerfdbe5222003-06-13 07:01:51 +0000210 def sample(self, population, k):
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000211 """Chooses k unique random elements from a population sequence.
212
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000213 Returns a new list containing elements from the population while
214 leaving the original population unchanged. The resulting list is
215 in selection order so that all sub-slices will also be valid random
216 samples. This allows raffle winners (the sample) to be partitioned
217 into grand prize and second place winners (the subslices).
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000218
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000219 Members of the population need not be hashable or unique. If the
220 population contains repeats, then each occurrence is a possible
221 selection in the sample.
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000222
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000223 To choose a sample in a range of integers, use xrange as an argument.
224 This is especially fast and space efficient for sampling from a
225 large population: sample(xrange(10000000), 60)
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000226 """
227
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000228 # Sampling without replacement entails tracking either potential
Raymond Hettinger8b9aa8d2003-01-04 05:20:33 +0000229 # selections (the pool) in a list or previous selections in a
230 # dictionary.
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000231
Raymond Hettinger8b9aa8d2003-01-04 05:20:33 +0000232 # When the number of selections is small compared to the population,
233 # then tracking selections is efficient, requiring only a small
234 # dictionary and an occasional reselection. For a larger number of
235 # selections, the pool tracking method is preferred since the list takes
236 # less space than the dictionary and it doesn't suffer from frequent
237 # reselections.
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000238
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000239 n = len(population)
240 if not 0 <= k <= n:
241 raise ValueError, "sample larger than population"
Raymond Hettinger8b9aa8d2003-01-04 05:20:33 +0000242 random = self.random
Raymond Hettingerfdbe5222003-06-13 07:01:51 +0000243 _int = int
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000244 result = [None] * k
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000245 if n < 6 * k: # if n len list takes less space than a k len dict
Raymond Hettinger311f4192002-11-18 09:01:24 +0000246 pool = list(population)
247 for i in xrange(k): # invariant: non-selected at [0,n-i)
Raymond Hettingerfdbe5222003-06-13 07:01:51 +0000248 j = _int(random() * (n-i))
Raymond Hettinger311f4192002-11-18 09:01:24 +0000249 result[i] = pool[j]
Raymond Hettinger8b9aa8d2003-01-04 05:20:33 +0000250 pool[j] = pool[n-i-1] # move non-selected item into vacancy
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000251 else:
Raymond Hettinger311f4192002-11-18 09:01:24 +0000252 selected = {}
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000253 for i in xrange(k):
Raymond Hettingerfdbe5222003-06-13 07:01:51 +0000254 j = _int(random() * n)
Raymond Hettinger311f4192002-11-18 09:01:24 +0000255 while j in selected:
Raymond Hettingerfdbe5222003-06-13 07:01:51 +0000256 j = _int(random() * n)
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000257 result[i] = selected[j] = population[j]
Raymond Hettinger311f4192002-11-18 09:01:24 +0000258 return result
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000259
Tim Peterscd804102001-01-25 20:25:57 +0000260## -------------------- real-valued distributions -------------------
261
262## -------------------- uniform distribution -------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000263
264 def uniform(self, a, b):
265 """Get a random number in the range [a, b)."""
266 return a + (b-a) * self.random()
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000267
Tim Peterscd804102001-01-25 20:25:57 +0000268## -------------------- normal distribution --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000269
Tim Petersd7b5e882001-01-25 03:36:26 +0000270 def normalvariate(self, mu, sigma):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000271 """Normal distribution.
272
273 mu is the mean, and sigma is the standard deviation.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000274
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000275 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000276 # mu = mean, sigma = standard deviation
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000277
Tim Petersd7b5e882001-01-25 03:36:26 +0000278 # Uses Kinderman and Monahan method. Reference: Kinderman,
279 # A.J. and Monahan, J.F., "Computer generation of random
280 # variables using the ratio of uniform deviates", ACM Trans
281 # Math Software, 3, (1977), pp257-260.
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000282
Tim Petersd7b5e882001-01-25 03:36:26 +0000283 random = self.random
Raymond Hettinger311f4192002-11-18 09:01:24 +0000284 while True:
Tim Peters0c9886d2001-01-15 01:18:21 +0000285 u1 = random()
Raymond Hettinger73ced7e2003-01-04 09:26:32 +0000286 u2 = 1.0 - random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000287 z = NV_MAGICCONST*(u1-0.5)/u2
288 zz = z*z/4.0
289 if zz <= -_log(u2):
290 break
291 return mu + z*sigma
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000292
Tim Peterscd804102001-01-25 20:25:57 +0000293## -------------------- lognormal distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000294
295 def lognormvariate(self, mu, sigma):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000296 """Log normal distribution.
297
298 If you take the natural logarithm of this distribution, you'll get a
299 normal distribution with mean mu and standard deviation sigma.
300 mu can have any value, and sigma must be greater than zero.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000301
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000302 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000303 return _exp(self.normalvariate(mu, sigma))
304
Tim Peterscd804102001-01-25 20:25:57 +0000305## -------------------- circular uniform --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000306
307 def cunifvariate(self, mean, arc):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000308 """Circular uniform distribution.
309
310 mean is the mean angle, and arc is the range of the distribution,
311 centered around the mean angle. Both values must be expressed in
312 radians. Returned values range between mean - arc/2 and
313 mean + arc/2 and are normalized to between 0 and pi.
314
315 Deprecated in version 2.3. Use:
316 (mean + arc * (Random.random() - 0.5)) % Math.pi
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000317
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000318 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000319 # mean: mean angle (in radians between 0 and pi)
320 # arc: range of distribution (in radians between 0 and pi)
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000321 import warnings
322 warnings.warn("The cunifvariate function is deprecated; Use (mean "
323 "+ arc * (Random.random() - 0.5)) % Math.pi instead",
324 DeprecationWarning)
Tim Petersd7b5e882001-01-25 03:36:26 +0000325
326 return (mean + arc * (self.random() - 0.5)) % _pi
327
Tim Peterscd804102001-01-25 20:25:57 +0000328## -------------------- exponential distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000329
330 def expovariate(self, lambd):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000331 """Exponential distribution.
332
333 lambd is 1.0 divided by the desired mean. (The parameter would be
334 called "lambda", but that is a reserved word in Python.) Returned
335 values range from 0 to positive infinity.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000336
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000337 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000338 # lambd: rate lambd = 1/mean
339 # ('lambda' is a Python reserved word)
340
341 random = self.random
Tim Peters0c9886d2001-01-15 01:18:21 +0000342 u = random()
343 while u <= 1e-7:
344 u = random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000345 return -_log(u)/lambd
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000346
Tim Peterscd804102001-01-25 20:25:57 +0000347## -------------------- von Mises distribution --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000348
Tim Petersd7b5e882001-01-25 03:36:26 +0000349 def vonmisesvariate(self, mu, kappa):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000350 """Circular data distribution.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000351
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000352 mu is the mean angle, expressed in radians between 0 and 2*pi, and
353 kappa is the concentration parameter, which must be greater than or
354 equal to zero. If kappa is equal to zero, this distribution reduces
355 to a uniform random angle over the range 0 to 2*pi.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000356
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000357 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000358 # mu: mean angle (in radians between 0 and 2*pi)
359 # kappa: concentration parameter kappa (>= 0)
360 # if kappa = 0 generate uniform random angle
361
362 # Based upon an algorithm published in: Fisher, N.I.,
363 # "Statistical Analysis of Circular Data", Cambridge
364 # University Press, 1993.
365
366 # Thanks to Magnus Kessler for a correction to the
367 # implementation of step 4.
368
369 random = self.random
370 if kappa <= 1e-6:
371 return TWOPI * random()
372
373 a = 1.0 + _sqrt(1.0 + 4.0 * kappa * kappa)
374 b = (a - _sqrt(2.0 * a))/(2.0 * kappa)
375 r = (1.0 + b * b)/(2.0 * b)
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000376
Raymond Hettinger311f4192002-11-18 09:01:24 +0000377 while True:
Tim Peters0c9886d2001-01-15 01:18:21 +0000378 u1 = random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000379
380 z = _cos(_pi * u1)
381 f = (1.0 + r * z)/(r + z)
382 c = kappa * (r - f)
383
384 u2 = random()
385
386 if not (u2 >= c * (2.0 - c) and u2 > c * _exp(1.0 - c)):
Tim Peters0c9886d2001-01-15 01:18:21 +0000387 break
Tim Petersd7b5e882001-01-25 03:36:26 +0000388
389 u3 = random()
390 if u3 > 0.5:
391 theta = (mu % TWOPI) + _acos(f)
392 else:
393 theta = (mu % TWOPI) - _acos(f)
394
395 return theta
396
Tim Peterscd804102001-01-25 20:25:57 +0000397## -------------------- gamma distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000398
399 def gammavariate(self, alpha, beta):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000400 """Gamma distribution. Not the gamma function!
401
402 Conditions on the parameters are alpha > 0 and beta > 0.
403
404 """
Tim Peters8ac14952002-05-23 15:15:30 +0000405
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000406 # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2
Tim Peters8ac14952002-05-23 15:15:30 +0000407
Guido van Rossum570764d2002-05-14 14:08:12 +0000408 # Warning: a few older sources define the gamma distribution in terms
409 # of alpha > -1.0
410 if alpha <= 0.0 or beta <= 0.0:
411 raise ValueError, 'gammavariate: alpha and beta must be > 0.0'
Tim Peters8ac14952002-05-23 15:15:30 +0000412
Tim Petersd7b5e882001-01-25 03:36:26 +0000413 random = self.random
Tim Petersd7b5e882001-01-25 03:36:26 +0000414 if alpha > 1.0:
415
416 # Uses R.C.H. Cheng, "The generation of Gamma
417 # variables with non-integral shape parameters",
418 # Applied Statistics, (1977), 26, No. 1, p71-74
419
Raymond Hettingerca6cdc22002-05-13 23:40:14 +0000420 ainv = _sqrt(2.0 * alpha - 1.0)
421 bbb = alpha - LOG4
422 ccc = alpha + ainv
Tim Peters8ac14952002-05-23 15:15:30 +0000423
Raymond Hettinger311f4192002-11-18 09:01:24 +0000424 while True:
Tim Petersd7b5e882001-01-25 03:36:26 +0000425 u1 = random()
Raymond Hettinger73ced7e2003-01-04 09:26:32 +0000426 if not 1e-7 < u1 < .9999999:
427 continue
428 u2 = 1.0 - random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000429 v = _log(u1/(1.0-u1))/ainv
430 x = alpha*_exp(v)
431 z = u1*u1*u2
432 r = bbb+ccc*v-x
433 if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z):
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000434 return x * beta
Tim Petersd7b5e882001-01-25 03:36:26 +0000435
436 elif alpha == 1.0:
437 # expovariate(1)
438 u = random()
439 while u <= 1e-7:
440 u = random()
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000441 return -_log(u) * beta
Tim Petersd7b5e882001-01-25 03:36:26 +0000442
443 else: # alpha is between 0 and 1 (exclusive)
444
445 # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
446
Raymond Hettinger311f4192002-11-18 09:01:24 +0000447 while True:
Tim Petersd7b5e882001-01-25 03:36:26 +0000448 u = random()
449 b = (_e + alpha)/_e
450 p = b*u
451 if p <= 1.0:
452 x = pow(p, 1.0/alpha)
453 else:
454 # p > 1
455 x = -_log((b-p)/alpha)
456 u1 = random()
457 if not (((p <= 1.0) and (u1 > _exp(-x))) or
458 ((p > 1) and (u1 > pow(x, alpha - 1.0)))):
459 break
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000460 return x * beta
461
462
463 def stdgamma(self, alpha, ainv, bbb, ccc):
464 # This method was (and shall remain) undocumented.
465 # This method is deprecated
466 # for the following reasons:
467 # 1. Returns same as .gammavariate(alpha, 1.0)
468 # 2. Requires caller to provide 3 extra arguments
469 # that are functions of alpha anyway
470 # 3. Can't be used for alpha < 0.5
471
472 # ainv = sqrt(2 * alpha - 1)
473 # bbb = alpha - log(4)
474 # ccc = alpha + ainv
475 import warnings
476 warnings.warn("The stdgamma function is deprecated; "
477 "use gammavariate() instead",
478 DeprecationWarning)
479 return self.gammavariate(alpha, 1.0)
480
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000481
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000482
Tim Peterscd804102001-01-25 20:25:57 +0000483## -------------------- Gauss (faster alternative) --------------------
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000484
Tim Petersd7b5e882001-01-25 03:36:26 +0000485 def gauss(self, mu, sigma):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000486 """Gaussian distribution.
487
488 mu is the mean, and sigma is the standard deviation. This is
489 slightly faster than the normalvariate() function.
490
491 Not thread-safe without a lock around calls.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000492
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000493 """
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000494
Tim Petersd7b5e882001-01-25 03:36:26 +0000495 # When x and y are two variables from [0, 1), uniformly
496 # distributed, then
497 #
498 # cos(2*pi*x)*sqrt(-2*log(1-y))
499 # sin(2*pi*x)*sqrt(-2*log(1-y))
500 #
501 # are two *independent* variables with normal distribution
502 # (mu = 0, sigma = 1).
503 # (Lambert Meertens)
504 # (corrected version; bug discovered by Mike Miller, fixed by LM)
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000505
Tim Petersd7b5e882001-01-25 03:36:26 +0000506 # Multithreading note: When two threads call this function
507 # simultaneously, it is possible that they will receive the
508 # same return value. The window is very small though. To
509 # avoid this, you have to use a lock around all calls. (I
510 # didn't want to slow this down in the serial case by using a
511 # lock here.)
Guido van Rossumd03e1191998-05-29 17:51:31 +0000512
Tim Petersd7b5e882001-01-25 03:36:26 +0000513 random = self.random
514 z = self.gauss_next
515 self.gauss_next = None
516 if z is None:
517 x2pi = random() * TWOPI
518 g2rad = _sqrt(-2.0 * _log(1.0 - random()))
519 z = _cos(x2pi) * g2rad
520 self.gauss_next = _sin(x2pi) * g2rad
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000521
Tim Petersd7b5e882001-01-25 03:36:26 +0000522 return mu + z*sigma
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000523
Tim Peterscd804102001-01-25 20:25:57 +0000524## -------------------- beta --------------------
Tim Peters85e2e472001-01-26 06:49:56 +0000525## See
526## http://sourceforge.net/bugs/?func=detailbug&bug_id=130030&group_id=5470
527## for Ivan Frohne's insightful analysis of why the original implementation:
528##
529## def betavariate(self, alpha, beta):
530## # Discrete Event Simulation in C, pp 87-88.
531##
532## y = self.expovariate(alpha)
533## z = self.expovariate(1.0/beta)
534## return z/(y+z)
535##
536## was dead wrong, and how it probably got that way.
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000537
Tim Petersd7b5e882001-01-25 03:36:26 +0000538 def betavariate(self, alpha, beta):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000539 """Beta distribution.
540
541 Conditions on the parameters are alpha > -1 and beta} > -1.
542 Returned values range between 0 and 1.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000543
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000544 """
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000545
Tim Peters85e2e472001-01-26 06:49:56 +0000546 # This version due to Janne Sinkkonen, and matches all the std
547 # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution").
548 y = self.gammavariate(alpha, 1.)
549 if y == 0:
550 return 0.0
551 else:
552 return y / (y + self.gammavariate(beta, 1.))
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000553
Tim Peterscd804102001-01-25 20:25:57 +0000554## -------------------- Pareto --------------------
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000555
Tim Petersd7b5e882001-01-25 03:36:26 +0000556 def paretovariate(self, alpha):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000557 """Pareto distribution. alpha is the shape parameter."""
Tim Petersd7b5e882001-01-25 03:36:26 +0000558 # Jain, pg. 495
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000559
Raymond Hettinger73ced7e2003-01-04 09:26:32 +0000560 u = 1.0 - self.random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000561 return 1.0 / pow(u, 1.0/alpha)
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000562
Tim Peterscd804102001-01-25 20:25:57 +0000563## -------------------- Weibull --------------------
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000564
Tim Petersd7b5e882001-01-25 03:36:26 +0000565 def weibullvariate(self, alpha, beta):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000566 """Weibull distribution.
567
568 alpha is the scale parameter and beta is the shape parameter.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000569
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000570 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000571 # Jain, pg. 499; bug fix courtesy Bill Arms
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000572
Raymond Hettinger73ced7e2003-01-04 09:26:32 +0000573 u = 1.0 - self.random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000574 return alpha * pow(-_log(u), 1.0/beta)
Guido van Rossum6c395ba1999-08-18 13:53:28 +0000575
Raymond Hettinger40f62172002-12-29 23:03:38 +0000576## -------------------- Wichmann-Hill -------------------
577
578class WichmannHill(Random):
579
580 VERSION = 1 # used by getstate/setstate
581
582 def seed(self, a=None):
583 """Initialize internal state from hashable object.
584
585 None or no argument seeds from current time.
586
587 If a is not None or an int or long, hash(a) is used instead.
588
589 If a is an int or long, a is used directly. Distinct values between
590 0 and 27814431486575L inclusive are guaranteed to yield distinct
591 internal states (this guarantee is specific to the default
592 Wichmann-Hill generator).
593 """
594
595 if a is None:
596 # Initialize from current time
597 import time
598 a = long(time.time() * 256)
599
600 if not isinstance(a, (int, long)):
601 a = hash(a)
602
603 a, x = divmod(a, 30268)
604 a, y = divmod(a, 30306)
605 a, z = divmod(a, 30322)
606 self._seed = int(x)+1, int(y)+1, int(z)+1
607
608 self.gauss_next = None
609
610 def random(self):
611 """Get the next random number in the range [0.0, 1.0)."""
612
613 # Wichman-Hill random number generator.
614 #
615 # Wichmann, B. A. & Hill, I. D. (1982)
616 # Algorithm AS 183:
617 # An efficient and portable pseudo-random number generator
618 # Applied Statistics 31 (1982) 188-190
619 #
620 # see also:
621 # Correction to Algorithm AS 183
622 # Applied Statistics 33 (1984) 123
623 #
624 # McLeod, A. I. (1985)
625 # A remark on Algorithm AS 183
626 # Applied Statistics 34 (1985),198-200
627
628 # This part is thread-unsafe:
629 # BEGIN CRITICAL SECTION
630 x, y, z = self._seed
631 x = (171 * x) % 30269
632 y = (172 * y) % 30307
633 z = (170 * z) % 30323
634 self._seed = x, y, z
635 # END CRITICAL SECTION
636
637 # Note: on a platform using IEEE-754 double arithmetic, this can
638 # never return 0.0 (asserted by Tim; proof too long for a comment).
639 return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
640
641 def getstate(self):
642 """Return internal state; can be passed to setstate() later."""
643 return self.VERSION, self._seed, self.gauss_next
644
645 def setstate(self, state):
646 """Restore internal state from object returned by getstate()."""
647 version = state[0]
648 if version == 1:
649 version, self._seed, self.gauss_next = state
650 else:
651 raise ValueError("state with version %s passed to "
652 "Random.setstate() of version %s" %
653 (version, self.VERSION))
654
655 def jumpahead(self, n):
656 """Act as if n calls to random() were made, but quickly.
657
658 n is an int, greater than or equal to 0.
659
660 Example use: If you have 2 threads and know that each will
661 consume no more than a million random numbers, create two Random
662 objects r1 and r2, then do
663 r2.setstate(r1.getstate())
664 r2.jumpahead(1000000)
665 Then r1 and r2 will use guaranteed-disjoint segments of the full
666 period.
667 """
668
669 if not n >= 0:
670 raise ValueError("n must be >= 0")
671 x, y, z = self._seed
672 x = int(x * pow(171, n, 30269)) % 30269
673 y = int(y * pow(172, n, 30307)) % 30307
674 z = int(z * pow(170, n, 30323)) % 30323
675 self._seed = x, y, z
676
677 def __whseed(self, x=0, y=0, z=0):
678 """Set the Wichmann-Hill seed from (x, y, z).
679
680 These must be integers in the range [0, 256).
681 """
682
683 if not type(x) == type(y) == type(z) == int:
684 raise TypeError('seeds must be integers')
685 if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256):
686 raise ValueError('seeds must be in range(0, 256)')
687 if 0 == x == y == z:
688 # Initialize from current time
689 import time
690 t = long(time.time() * 256)
691 t = int((t&0xffffff) ^ (t>>24))
692 t, x = divmod(t, 256)
693 t, y = divmod(t, 256)
694 t, z = divmod(t, 256)
695 # Zero is a poor seed, so substitute 1
696 self._seed = (x or 1, y or 1, z or 1)
697
698 self.gauss_next = None
699
700 def whseed(self, a=None):
701 """Seed from hashable object's hash code.
702
703 None or no argument seeds from current time. It is not guaranteed
704 that objects with distinct hash codes lead to distinct internal
705 states.
706
707 This is obsolete, provided for compatibility with the seed routine
708 used prior to Python 2.1. Use the .seed() method instead.
709 """
710
711 if a is None:
712 self.__whseed()
713 return
714 a = hash(a)
715 a, x = divmod(a, 256)
716 a, y = divmod(a, 256)
717 a, z = divmod(a, 256)
718 x = (x + a) % 256 or 1
719 y = (y + a) % 256 or 1
720 z = (z + a) % 256 or 1
721 self.__whseed(x, y, z)
722
Tim Peterscd804102001-01-25 20:25:57 +0000723## -------------------- test program --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000724
Tim Petersd7b5e882001-01-25 03:36:26 +0000725def _test_generator(n, funccall):
Tim Peters0c9886d2001-01-15 01:18:21 +0000726 import time
727 print n, 'times', funccall
728 code = compile(funccall, funccall, 'eval')
Raymond Hettingerb98154e2003-05-24 17:26:02 +0000729 total = 0.0
Tim Peters0c9886d2001-01-15 01:18:21 +0000730 sqsum = 0.0
731 smallest = 1e10
732 largest = -1e10
733 t0 = time.time()
734 for i in range(n):
735 x = eval(code)
Raymond Hettingerb98154e2003-05-24 17:26:02 +0000736 total += x
Tim Peters0c9886d2001-01-15 01:18:21 +0000737 sqsum = sqsum + x*x
738 smallest = min(x, smallest)
739 largest = max(x, largest)
740 t1 = time.time()
741 print round(t1-t0, 3), 'sec,',
Raymond Hettingerb98154e2003-05-24 17:26:02 +0000742 avg = total/n
Tim Petersd7b5e882001-01-25 03:36:26 +0000743 stddev = _sqrt(sqsum/n - avg*avg)
Tim Peters0c9886d2001-01-15 01:18:21 +0000744 print 'avg %g, stddev %g, min %g, max %g' % \
745 (avg, stddev, smallest, largest)
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000746
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000747
748def _test(N=2000):
Tim Petersd7b5e882001-01-25 03:36:26 +0000749 _test_generator(N, 'random()')
750 _test_generator(N, 'normalvariate(0.0, 1.0)')
751 _test_generator(N, 'lognormvariate(0.0, 1.0)')
752 _test_generator(N, 'cunifvariate(0.0, 1.0)')
Tim Petersd7b5e882001-01-25 03:36:26 +0000753 _test_generator(N, 'vonmisesvariate(0.0, 1.0)')
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000754 _test_generator(N, 'gammavariate(0.01, 1.0)')
755 _test_generator(N, 'gammavariate(0.1, 1.0)')
Tim Peters8ac14952002-05-23 15:15:30 +0000756 _test_generator(N, 'gammavariate(0.1, 2.0)')
Tim Petersd7b5e882001-01-25 03:36:26 +0000757 _test_generator(N, 'gammavariate(0.5, 1.0)')
758 _test_generator(N, 'gammavariate(0.9, 1.0)')
759 _test_generator(N, 'gammavariate(1.0, 1.0)')
760 _test_generator(N, 'gammavariate(2.0, 1.0)')
761 _test_generator(N, 'gammavariate(20.0, 1.0)')
762 _test_generator(N, 'gammavariate(200.0, 1.0)')
763 _test_generator(N, 'gauss(0.0, 1.0)')
764 _test_generator(N, 'betavariate(3.0, 3.0)')
Tim Peterscd804102001-01-25 20:25:57 +0000765
Tim Peters715c4c42001-01-26 22:56:56 +0000766# Create one instance, seeded from current time, and export its methods
Raymond Hettinger40f62172002-12-29 23:03:38 +0000767# as module-level functions. The functions share state across all uses
768#(both in the user's code and in the Python libraries), but that's fine
769# for most programs and is easier for the casual user than making them
770# instantiate their own Random() instance.
771
Tim Petersd7b5e882001-01-25 03:36:26 +0000772_inst = Random()
773seed = _inst.seed
774random = _inst.random
775uniform = _inst.uniform
776randint = _inst.randint
777choice = _inst.choice
778randrange = _inst.randrange
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000779sample = _inst.sample
Tim Petersd7b5e882001-01-25 03:36:26 +0000780shuffle = _inst.shuffle
781normalvariate = _inst.normalvariate
782lognormvariate = _inst.lognormvariate
783cunifvariate = _inst.cunifvariate
784expovariate = _inst.expovariate
785vonmisesvariate = _inst.vonmisesvariate
786gammavariate = _inst.gammavariate
787stdgamma = _inst.stdgamma
788gauss = _inst.gauss
789betavariate = _inst.betavariate
790paretovariate = _inst.paretovariate
791weibullvariate = _inst.weibullvariate
792getstate = _inst.getstate
793setstate = _inst.setstate
Tim Petersd52269b2001-01-25 06:23:18 +0000794jumpahead = _inst.jumpahead
Tim Petersd7b5e882001-01-25 03:36:26 +0000795
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000796if __name__ == '__main__':
Tim Petersd7b5e882001-01-25 03:36:26 +0000797 _test()