blob: 1ae25532d3f41514e04d0f2b1eac2f255163197f [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:
Tim Peters76ca1d42003-06-19 03:46:46 +0000151 # Note that
152 # int(istart + self.random()*(istop - istart))
153 # instead would be incorrect. For example, consider istart
154 # = -2 and istop = 0. Then the guts would be in
155 # -2.0 to 0.0 exclusive on both ends (ignoring that random()
156 # might return 0.0), and because int() truncates toward 0, the
157 # final result would be -1 or 0 (instead of -2 or -1).
158 # istart + int(self.random()*(istop - istart))
159 # would also be incorrect, for a subtler reason: the RHS
160 # can return a long, and then randrange() would also return
161 # a long, but we're supposed to return an int (for backward
162 # compatibility).
163 return int(istart + int(self.random()*(istop - istart)))
Tim Petersd7b5e882001-01-25 03:36:26 +0000164 if step == 1:
Tim Petersd7b5e882001-01-25 03:36:26 +0000165 raise ValueError, "empty range for randrange()"
Tim Peters9146f272002-08-16 03:41:39 +0000166
167 # Non-unit step argument supplied.
Tim Petersd7b5e882001-01-25 03:36:26 +0000168 istep = int(step)
169 if istep != step:
170 raise ValueError, "non-integer step for randrange()"
171 if istep > 0:
172 n = (istop - istart + istep - 1) / istep
173 elif istep < 0:
174 n = (istop - istart + istep + 1) / istep
175 else:
176 raise ValueError, "zero step for randrange()"
177
178 if n <= 0:
179 raise ValueError, "empty range for randrange()"
180 return istart + istep*int(self.random() * n)
181
182 def randint(self, a, b):
Tim Peterscd804102001-01-25 20:25:57 +0000183 """Return random integer in range [a, b], including both end points.
Tim Petersd7b5e882001-01-25 03:36:26 +0000184 """
185
186 return self.randrange(a, b+1)
187
Tim Peterscd804102001-01-25 20:25:57 +0000188## -------------------- sequence methods -------------------
189
Tim Petersd7b5e882001-01-25 03:36:26 +0000190 def choice(self, seq):
191 """Choose a random element from a non-empty sequence."""
192 return seq[int(self.random() * len(seq))]
193
194 def shuffle(self, x, random=None, int=int):
195 """x, random=random.random -> shuffle list x in place; return None.
196
197 Optional arg random is a 0-argument function returning a random
198 float in [0.0, 1.0); by default, the standard random.random.
199
200 Note that for even rather small len(x), the total number of
201 permutations of x is larger than the period of most random number
202 generators; this implies that "most" permutations of a long
203 sequence can never be generated.
204 """
205
206 if random is None:
207 random = self.random
208 for i in xrange(len(x)-1, 0, -1):
Tim Peterscd804102001-01-25 20:25:57 +0000209 # pick an element in x[:i+1] with which to exchange x[i]
Tim Petersd7b5e882001-01-25 03:36:26 +0000210 j = int(random() * (i+1))
211 x[i], x[j] = x[j], x[i]
212
Raymond Hettingerfdbe5222003-06-13 07:01:51 +0000213 def sample(self, population, k):
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000214 """Chooses k unique random elements from a population sequence.
215
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000216 Returns a new list containing elements from the population while
217 leaving the original population unchanged. The resulting list is
218 in selection order so that all sub-slices will also be valid random
219 samples. This allows raffle winners (the sample) to be partitioned
220 into grand prize and second place winners (the subslices).
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000221
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000222 Members of the population need not be hashable or unique. If the
223 population contains repeats, then each occurrence is a possible
224 selection in the sample.
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000225
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000226 To choose a sample in a range of integers, use xrange as an argument.
227 This is especially fast and space efficient for sampling from a
228 large population: sample(xrange(10000000), 60)
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000229 """
230
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000231 # Sampling without replacement entails tracking either potential
Raymond Hettinger8b9aa8d2003-01-04 05:20:33 +0000232 # selections (the pool) in a list or previous selections in a
233 # dictionary.
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000234
Raymond Hettinger8b9aa8d2003-01-04 05:20:33 +0000235 # When the number of selections is small compared to the population,
236 # then tracking selections is efficient, requiring only a small
237 # dictionary and an occasional reselection. For a larger number of
238 # selections, the pool tracking method is preferred since the list takes
239 # less space than the dictionary and it doesn't suffer from frequent
240 # reselections.
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000241
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000242 n = len(population)
243 if not 0 <= k <= n:
244 raise ValueError, "sample larger than population"
Raymond Hettinger8b9aa8d2003-01-04 05:20:33 +0000245 random = self.random
Raymond Hettingerfdbe5222003-06-13 07:01:51 +0000246 _int = int
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000247 result = [None] * k
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000248 if n < 6 * k: # if n len list takes less space than a k len dict
Raymond Hettinger311f4192002-11-18 09:01:24 +0000249 pool = list(population)
250 for i in xrange(k): # invariant: non-selected at [0,n-i)
Raymond Hettingerfdbe5222003-06-13 07:01:51 +0000251 j = _int(random() * (n-i))
Raymond Hettinger311f4192002-11-18 09:01:24 +0000252 result[i] = pool[j]
Raymond Hettinger8b9aa8d2003-01-04 05:20:33 +0000253 pool[j] = pool[n-i-1] # move non-selected item into vacancy
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000254 else:
Raymond Hettinger311f4192002-11-18 09:01:24 +0000255 selected = {}
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000256 for i in xrange(k):
Raymond Hettingerfdbe5222003-06-13 07:01:51 +0000257 j = _int(random() * n)
Raymond Hettinger311f4192002-11-18 09:01:24 +0000258 while j in selected:
Raymond Hettingerfdbe5222003-06-13 07:01:51 +0000259 j = _int(random() * n)
Raymond Hettingerc0b40342002-11-13 15:26:37 +0000260 result[i] = selected[j] = population[j]
Raymond Hettinger311f4192002-11-18 09:01:24 +0000261 return result
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000262
Tim Peterscd804102001-01-25 20:25:57 +0000263## -------------------- real-valued distributions -------------------
264
265## -------------------- uniform distribution -------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000266
267 def uniform(self, a, b):
268 """Get a random number in the range [a, b)."""
269 return a + (b-a) * self.random()
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000270
Tim Peterscd804102001-01-25 20:25:57 +0000271## -------------------- normal distribution --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000272
Tim Petersd7b5e882001-01-25 03:36:26 +0000273 def normalvariate(self, mu, sigma):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000274 """Normal distribution.
275
276 mu is the mean, and sigma is the standard deviation.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000277
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000278 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000279 # mu = mean, sigma = standard deviation
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000280
Tim Petersd7b5e882001-01-25 03:36:26 +0000281 # Uses Kinderman and Monahan method. Reference: Kinderman,
282 # A.J. and Monahan, J.F., "Computer generation of random
283 # variables using the ratio of uniform deviates", ACM Trans
284 # Math Software, 3, (1977), pp257-260.
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000285
Tim Petersd7b5e882001-01-25 03:36:26 +0000286 random = self.random
Raymond Hettinger311f4192002-11-18 09:01:24 +0000287 while True:
Tim Peters0c9886d2001-01-15 01:18:21 +0000288 u1 = random()
Raymond Hettinger73ced7e2003-01-04 09:26:32 +0000289 u2 = 1.0 - random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000290 z = NV_MAGICCONST*(u1-0.5)/u2
291 zz = z*z/4.0
292 if zz <= -_log(u2):
293 break
294 return mu + z*sigma
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000295
Tim Peterscd804102001-01-25 20:25:57 +0000296## -------------------- lognormal distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000297
298 def lognormvariate(self, mu, sigma):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000299 """Log normal distribution.
300
301 If you take the natural logarithm of this distribution, you'll get a
302 normal distribution with mean mu and standard deviation sigma.
303 mu can have any value, and sigma must be greater than zero.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000304
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000305 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000306 return _exp(self.normalvariate(mu, sigma))
307
Tim Peterscd804102001-01-25 20:25:57 +0000308## -------------------- circular uniform --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000309
310 def cunifvariate(self, mean, arc):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000311 """Circular uniform distribution.
312
313 mean is the mean angle, and arc is the range of the distribution,
314 centered around the mean angle. Both values must be expressed in
315 radians. Returned values range between mean - arc/2 and
316 mean + arc/2 and are normalized to between 0 and pi.
317
318 Deprecated in version 2.3. Use:
319 (mean + arc * (Random.random() - 0.5)) % Math.pi
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000320
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000321 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000322 # mean: mean angle (in radians between 0 and pi)
323 # arc: range of distribution (in radians between 0 and pi)
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000324 import warnings
325 warnings.warn("The cunifvariate function is deprecated; Use (mean "
326 "+ arc * (Random.random() - 0.5)) % Math.pi instead",
327 DeprecationWarning)
Tim Petersd7b5e882001-01-25 03:36:26 +0000328
329 return (mean + arc * (self.random() - 0.5)) % _pi
330
Tim Peterscd804102001-01-25 20:25:57 +0000331## -------------------- exponential distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000332
333 def expovariate(self, lambd):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000334 """Exponential distribution.
335
336 lambd is 1.0 divided by the desired mean. (The parameter would be
337 called "lambda", but that is a reserved word in Python.) Returned
338 values range from 0 to positive infinity.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000339
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000340 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000341 # lambd: rate lambd = 1/mean
342 # ('lambda' is a Python reserved word)
343
344 random = self.random
Tim Peters0c9886d2001-01-15 01:18:21 +0000345 u = random()
346 while u <= 1e-7:
347 u = random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000348 return -_log(u)/lambd
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000349
Tim Peterscd804102001-01-25 20:25:57 +0000350## -------------------- von Mises distribution --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000351
Tim Petersd7b5e882001-01-25 03:36:26 +0000352 def vonmisesvariate(self, mu, kappa):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000353 """Circular data distribution.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000354
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000355 mu is the mean angle, expressed in radians between 0 and 2*pi, and
356 kappa is the concentration parameter, which must be greater than or
357 equal to zero. If kappa is equal to zero, this distribution reduces
358 to a uniform random angle over the range 0 to 2*pi.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000359
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000360 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000361 # mu: mean angle (in radians between 0 and 2*pi)
362 # kappa: concentration parameter kappa (>= 0)
363 # if kappa = 0 generate uniform random angle
364
365 # Based upon an algorithm published in: Fisher, N.I.,
366 # "Statistical Analysis of Circular Data", Cambridge
367 # University Press, 1993.
368
369 # Thanks to Magnus Kessler for a correction to the
370 # implementation of step 4.
371
372 random = self.random
373 if kappa <= 1e-6:
374 return TWOPI * random()
375
376 a = 1.0 + _sqrt(1.0 + 4.0 * kappa * kappa)
377 b = (a - _sqrt(2.0 * a))/(2.0 * kappa)
378 r = (1.0 + b * b)/(2.0 * b)
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000379
Raymond Hettinger311f4192002-11-18 09:01:24 +0000380 while True:
Tim Peters0c9886d2001-01-15 01:18:21 +0000381 u1 = random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000382
383 z = _cos(_pi * u1)
384 f = (1.0 + r * z)/(r + z)
385 c = kappa * (r - f)
386
387 u2 = random()
388
389 if not (u2 >= c * (2.0 - c) and u2 > c * _exp(1.0 - c)):
Tim Peters0c9886d2001-01-15 01:18:21 +0000390 break
Tim Petersd7b5e882001-01-25 03:36:26 +0000391
392 u3 = random()
393 if u3 > 0.5:
394 theta = (mu % TWOPI) + _acos(f)
395 else:
396 theta = (mu % TWOPI) - _acos(f)
397
398 return theta
399
Tim Peterscd804102001-01-25 20:25:57 +0000400## -------------------- gamma distribution --------------------
Tim Petersd7b5e882001-01-25 03:36:26 +0000401
402 def gammavariate(self, alpha, beta):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000403 """Gamma distribution. Not the gamma function!
404
405 Conditions on the parameters are alpha > 0 and beta > 0.
406
407 """
Tim Peters8ac14952002-05-23 15:15:30 +0000408
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000409 # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2
Tim Peters8ac14952002-05-23 15:15:30 +0000410
Guido van Rossum570764d2002-05-14 14:08:12 +0000411 # Warning: a few older sources define the gamma distribution in terms
412 # of alpha > -1.0
413 if alpha <= 0.0 or beta <= 0.0:
414 raise ValueError, 'gammavariate: alpha and beta must be > 0.0'
Tim Peters8ac14952002-05-23 15:15:30 +0000415
Tim Petersd7b5e882001-01-25 03:36:26 +0000416 random = self.random
Tim Petersd7b5e882001-01-25 03:36:26 +0000417 if alpha > 1.0:
418
419 # Uses R.C.H. Cheng, "The generation of Gamma
420 # variables with non-integral shape parameters",
421 # Applied Statistics, (1977), 26, No. 1, p71-74
422
Raymond Hettingerca6cdc22002-05-13 23:40:14 +0000423 ainv = _sqrt(2.0 * alpha - 1.0)
424 bbb = alpha - LOG4
425 ccc = alpha + ainv
Tim Peters8ac14952002-05-23 15:15:30 +0000426
Raymond Hettinger311f4192002-11-18 09:01:24 +0000427 while True:
Tim Petersd7b5e882001-01-25 03:36:26 +0000428 u1 = random()
Raymond Hettinger73ced7e2003-01-04 09:26:32 +0000429 if not 1e-7 < u1 < .9999999:
430 continue
431 u2 = 1.0 - random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000432 v = _log(u1/(1.0-u1))/ainv
433 x = alpha*_exp(v)
434 z = u1*u1*u2
435 r = bbb+ccc*v-x
436 if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z):
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000437 return x * beta
Tim Petersd7b5e882001-01-25 03:36:26 +0000438
439 elif alpha == 1.0:
440 # expovariate(1)
441 u = random()
442 while u <= 1e-7:
443 u = random()
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000444 return -_log(u) * beta
Tim Petersd7b5e882001-01-25 03:36:26 +0000445
446 else: # alpha is between 0 and 1 (exclusive)
447
448 # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
449
Raymond Hettinger311f4192002-11-18 09:01:24 +0000450 while True:
Tim Petersd7b5e882001-01-25 03:36:26 +0000451 u = random()
452 b = (_e + alpha)/_e
453 p = b*u
454 if p <= 1.0:
455 x = pow(p, 1.0/alpha)
456 else:
457 # p > 1
458 x = -_log((b-p)/alpha)
459 u1 = random()
460 if not (((p <= 1.0) and (u1 > _exp(-x))) or
461 ((p > 1) and (u1 > pow(x, alpha - 1.0)))):
462 break
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000463 return x * beta
464
465
466 def stdgamma(self, alpha, ainv, bbb, ccc):
467 # This method was (and shall remain) undocumented.
468 # This method is deprecated
469 # for the following reasons:
470 # 1. Returns same as .gammavariate(alpha, 1.0)
471 # 2. Requires caller to provide 3 extra arguments
472 # that are functions of alpha anyway
473 # 3. Can't be used for alpha < 0.5
474
475 # ainv = sqrt(2 * alpha - 1)
476 # bbb = alpha - log(4)
477 # ccc = alpha + ainv
478 import warnings
479 warnings.warn("The stdgamma function is deprecated; "
480 "use gammavariate() instead",
481 DeprecationWarning)
482 return self.gammavariate(alpha, 1.0)
483
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000484
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000485
Tim Peterscd804102001-01-25 20:25:57 +0000486## -------------------- Gauss (faster alternative) --------------------
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000487
Tim Petersd7b5e882001-01-25 03:36:26 +0000488 def gauss(self, mu, sigma):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000489 """Gaussian distribution.
490
491 mu is the mean, and sigma is the standard deviation. This is
492 slightly faster than the normalvariate() function.
493
494 Not thread-safe without a lock around calls.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000495
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000496 """
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000497
Tim Petersd7b5e882001-01-25 03:36:26 +0000498 # When x and y are two variables from [0, 1), uniformly
499 # distributed, then
500 #
501 # cos(2*pi*x)*sqrt(-2*log(1-y))
502 # sin(2*pi*x)*sqrt(-2*log(1-y))
503 #
504 # are two *independent* variables with normal distribution
505 # (mu = 0, sigma = 1).
506 # (Lambert Meertens)
507 # (corrected version; bug discovered by Mike Miller, fixed by LM)
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000508
Tim Petersd7b5e882001-01-25 03:36:26 +0000509 # Multithreading note: When two threads call this function
510 # simultaneously, it is possible that they will receive the
511 # same return value. The window is very small though. To
512 # avoid this, you have to use a lock around all calls. (I
513 # didn't want to slow this down in the serial case by using a
514 # lock here.)
Guido van Rossumd03e1191998-05-29 17:51:31 +0000515
Tim Petersd7b5e882001-01-25 03:36:26 +0000516 random = self.random
517 z = self.gauss_next
518 self.gauss_next = None
519 if z is None:
520 x2pi = random() * TWOPI
521 g2rad = _sqrt(-2.0 * _log(1.0 - random()))
522 z = _cos(x2pi) * g2rad
523 self.gauss_next = _sin(x2pi) * g2rad
Guido van Rossumcc32ac91994-03-15 16:10:24 +0000524
Tim Petersd7b5e882001-01-25 03:36:26 +0000525 return mu + z*sigma
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000526
Tim Peterscd804102001-01-25 20:25:57 +0000527## -------------------- beta --------------------
Tim Peters85e2e472001-01-26 06:49:56 +0000528## See
529## http://sourceforge.net/bugs/?func=detailbug&bug_id=130030&group_id=5470
530## for Ivan Frohne's insightful analysis of why the original implementation:
531##
532## def betavariate(self, alpha, beta):
533## # Discrete Event Simulation in C, pp 87-88.
534##
535## y = self.expovariate(alpha)
536## z = self.expovariate(1.0/beta)
537## return z/(y+z)
538##
539## was dead wrong, and how it probably got that way.
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000540
Tim Petersd7b5e882001-01-25 03:36:26 +0000541 def betavariate(self, alpha, beta):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000542 """Beta distribution.
543
544 Conditions on the parameters are alpha > -1 and beta} > -1.
545 Returned values range between 0 and 1.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000546
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000547 """
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000548
Tim Peters85e2e472001-01-26 06:49:56 +0000549 # This version due to Janne Sinkkonen, and matches all the std
550 # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution").
551 y = self.gammavariate(alpha, 1.)
552 if y == 0:
553 return 0.0
554 else:
555 return y / (y + self.gammavariate(beta, 1.))
Guido van Rossum95bfcda1994-03-09 14:21:05 +0000556
Tim Peterscd804102001-01-25 20:25:57 +0000557## -------------------- Pareto --------------------
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000558
Tim Petersd7b5e882001-01-25 03:36:26 +0000559 def paretovariate(self, alpha):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000560 """Pareto distribution. alpha is the shape parameter."""
Tim Petersd7b5e882001-01-25 03:36:26 +0000561 # Jain, pg. 495
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000562
Raymond Hettinger73ced7e2003-01-04 09:26:32 +0000563 u = 1.0 - self.random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000564 return 1.0 / pow(u, 1.0/alpha)
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000565
Tim Peterscd804102001-01-25 20:25:57 +0000566## -------------------- Weibull --------------------
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000567
Tim Petersd7b5e882001-01-25 03:36:26 +0000568 def weibullvariate(self, alpha, beta):
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000569 """Weibull distribution.
570
571 alpha is the scale parameter and beta is the shape parameter.
Raymond Hettingeref4d4bd2002-05-23 23:58:17 +0000572
Raymond Hettingerc32f0332002-05-23 19:44:49 +0000573 """
Tim Petersd7b5e882001-01-25 03:36:26 +0000574 # Jain, pg. 499; bug fix courtesy Bill Arms
Guido van Rossumcf4559a1997-12-02 02:47:39 +0000575
Raymond Hettinger73ced7e2003-01-04 09:26:32 +0000576 u = 1.0 - self.random()
Tim Petersd7b5e882001-01-25 03:36:26 +0000577 return alpha * pow(-_log(u), 1.0/beta)
Guido van Rossum6c395ba1999-08-18 13:53:28 +0000578
Raymond Hettinger40f62172002-12-29 23:03:38 +0000579## -------------------- Wichmann-Hill -------------------
580
581class WichmannHill(Random):
582
583 VERSION = 1 # used by getstate/setstate
584
585 def seed(self, a=None):
586 """Initialize internal state from hashable object.
587
588 None or no argument seeds from current time.
589
590 If a is not None or an int or long, hash(a) is used instead.
591
592 If a is an int or long, a is used directly. Distinct values between
593 0 and 27814431486575L inclusive are guaranteed to yield distinct
594 internal states (this guarantee is specific to the default
595 Wichmann-Hill generator).
596 """
597
598 if a is None:
599 # Initialize from current time
600 import time
601 a = long(time.time() * 256)
602
603 if not isinstance(a, (int, long)):
604 a = hash(a)
605
606 a, x = divmod(a, 30268)
607 a, y = divmod(a, 30306)
608 a, z = divmod(a, 30322)
609 self._seed = int(x)+1, int(y)+1, int(z)+1
610
611 self.gauss_next = None
612
613 def random(self):
614 """Get the next random number in the range [0.0, 1.0)."""
615
616 # Wichman-Hill random number generator.
617 #
618 # Wichmann, B. A. & Hill, I. D. (1982)
619 # Algorithm AS 183:
620 # An efficient and portable pseudo-random number generator
621 # Applied Statistics 31 (1982) 188-190
622 #
623 # see also:
624 # Correction to Algorithm AS 183
625 # Applied Statistics 33 (1984) 123
626 #
627 # McLeod, A. I. (1985)
628 # A remark on Algorithm AS 183
629 # Applied Statistics 34 (1985),198-200
630
631 # This part is thread-unsafe:
632 # BEGIN CRITICAL SECTION
633 x, y, z = self._seed
634 x = (171 * x) % 30269
635 y = (172 * y) % 30307
636 z = (170 * z) % 30323
637 self._seed = x, y, z
638 # END CRITICAL SECTION
639
640 # Note: on a platform using IEEE-754 double arithmetic, this can
641 # never return 0.0 (asserted by Tim; proof too long for a comment).
642 return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
643
644 def getstate(self):
645 """Return internal state; can be passed to setstate() later."""
646 return self.VERSION, self._seed, self.gauss_next
647
648 def setstate(self, state):
649 """Restore internal state from object returned by getstate()."""
650 version = state[0]
651 if version == 1:
652 version, self._seed, self.gauss_next = state
653 else:
654 raise ValueError("state with version %s passed to "
655 "Random.setstate() of version %s" %
656 (version, self.VERSION))
657
658 def jumpahead(self, n):
659 """Act as if n calls to random() were made, but quickly.
660
661 n is an int, greater than or equal to 0.
662
663 Example use: If you have 2 threads and know that each will
664 consume no more than a million random numbers, create two Random
665 objects r1 and r2, then do
666 r2.setstate(r1.getstate())
667 r2.jumpahead(1000000)
668 Then r1 and r2 will use guaranteed-disjoint segments of the full
669 period.
670 """
671
672 if not n >= 0:
673 raise ValueError("n must be >= 0")
674 x, y, z = self._seed
675 x = int(x * pow(171, n, 30269)) % 30269
676 y = int(y * pow(172, n, 30307)) % 30307
677 z = int(z * pow(170, n, 30323)) % 30323
678 self._seed = x, y, z
679
680 def __whseed(self, x=0, y=0, z=0):
681 """Set the Wichmann-Hill seed from (x, y, z).
682
683 These must be integers in the range [0, 256).
684 """
685
686 if not type(x) == type(y) == type(z) == int:
687 raise TypeError('seeds must be integers')
688 if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256):
689 raise ValueError('seeds must be in range(0, 256)')
690 if 0 == x == y == z:
691 # Initialize from current time
692 import time
693 t = long(time.time() * 256)
694 t = int((t&0xffffff) ^ (t>>24))
695 t, x = divmod(t, 256)
696 t, y = divmod(t, 256)
697 t, z = divmod(t, 256)
698 # Zero is a poor seed, so substitute 1
699 self._seed = (x or 1, y or 1, z or 1)
700
701 self.gauss_next = None
702
703 def whseed(self, a=None):
704 """Seed from hashable object's hash code.
705
706 None or no argument seeds from current time. It is not guaranteed
707 that objects with distinct hash codes lead to distinct internal
708 states.
709
710 This is obsolete, provided for compatibility with the seed routine
711 used prior to Python 2.1. Use the .seed() method instead.
712 """
713
714 if a is None:
715 self.__whseed()
716 return
717 a = hash(a)
718 a, x = divmod(a, 256)
719 a, y = divmod(a, 256)
720 a, z = divmod(a, 256)
721 x = (x + a) % 256 or 1
722 y = (y + a) % 256 or 1
723 z = (z + a) % 256 or 1
724 self.__whseed(x, y, z)
725
Tim Peterscd804102001-01-25 20:25:57 +0000726## -------------------- test program --------------------
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000727
Tim Petersd7b5e882001-01-25 03:36:26 +0000728def _test_generator(n, funccall):
Tim Peters0c9886d2001-01-15 01:18:21 +0000729 import time
730 print n, 'times', funccall
731 code = compile(funccall, funccall, 'eval')
Raymond Hettingerb98154e2003-05-24 17:26:02 +0000732 total = 0.0
Tim Peters0c9886d2001-01-15 01:18:21 +0000733 sqsum = 0.0
734 smallest = 1e10
735 largest = -1e10
736 t0 = time.time()
737 for i in range(n):
738 x = eval(code)
Raymond Hettingerb98154e2003-05-24 17:26:02 +0000739 total += x
Tim Peters0c9886d2001-01-15 01:18:21 +0000740 sqsum = sqsum + x*x
741 smallest = min(x, smallest)
742 largest = max(x, largest)
743 t1 = time.time()
744 print round(t1-t0, 3), 'sec,',
Raymond Hettingerb98154e2003-05-24 17:26:02 +0000745 avg = total/n
Tim Petersd7b5e882001-01-25 03:36:26 +0000746 stddev = _sqrt(sqsum/n - avg*avg)
Tim Peters0c9886d2001-01-15 01:18:21 +0000747 print 'avg %g, stddev %g, min %g, max %g' % \
748 (avg, stddev, smallest, largest)
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000749
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000750
751def _test(N=2000):
Tim Petersd7b5e882001-01-25 03:36:26 +0000752 _test_generator(N, 'random()')
753 _test_generator(N, 'normalvariate(0.0, 1.0)')
754 _test_generator(N, 'lognormvariate(0.0, 1.0)')
755 _test_generator(N, 'cunifvariate(0.0, 1.0)')
Tim Petersd7b5e882001-01-25 03:36:26 +0000756 _test_generator(N, 'vonmisesvariate(0.0, 1.0)')
Raymond Hettingerb760efb2002-05-14 06:40:34 +0000757 _test_generator(N, 'gammavariate(0.01, 1.0)')
758 _test_generator(N, 'gammavariate(0.1, 1.0)')
Tim Peters8ac14952002-05-23 15:15:30 +0000759 _test_generator(N, 'gammavariate(0.1, 2.0)')
Tim Petersd7b5e882001-01-25 03:36:26 +0000760 _test_generator(N, 'gammavariate(0.5, 1.0)')
761 _test_generator(N, 'gammavariate(0.9, 1.0)')
762 _test_generator(N, 'gammavariate(1.0, 1.0)')
763 _test_generator(N, 'gammavariate(2.0, 1.0)')
764 _test_generator(N, 'gammavariate(20.0, 1.0)')
765 _test_generator(N, 'gammavariate(200.0, 1.0)')
766 _test_generator(N, 'gauss(0.0, 1.0)')
767 _test_generator(N, 'betavariate(3.0, 3.0)')
Tim Peterscd804102001-01-25 20:25:57 +0000768
Tim Peters715c4c42001-01-26 22:56:56 +0000769# Create one instance, seeded from current time, and export its methods
Raymond Hettinger40f62172002-12-29 23:03:38 +0000770# as module-level functions. The functions share state across all uses
771#(both in the user's code and in the Python libraries), but that's fine
772# for most programs and is easier for the casual user than making them
773# instantiate their own Random() instance.
774
Tim Petersd7b5e882001-01-25 03:36:26 +0000775_inst = Random()
776seed = _inst.seed
777random = _inst.random
778uniform = _inst.uniform
779randint = _inst.randint
780choice = _inst.choice
781randrange = _inst.randrange
Raymond Hettingerf24eb352002-11-12 17:41:57 +0000782sample = _inst.sample
Tim Petersd7b5e882001-01-25 03:36:26 +0000783shuffle = _inst.shuffle
784normalvariate = _inst.normalvariate
785lognormvariate = _inst.lognormvariate
786cunifvariate = _inst.cunifvariate
787expovariate = _inst.expovariate
788vonmisesvariate = _inst.vonmisesvariate
789gammavariate = _inst.gammavariate
790stdgamma = _inst.stdgamma
791gauss = _inst.gauss
792betavariate = _inst.betavariate
793paretovariate = _inst.paretovariate
794weibullvariate = _inst.weibullvariate
795getstate = _inst.getstate
796setstate = _inst.setstate
Tim Petersd52269b2001-01-25 06:23:18 +0000797jumpahead = _inst.jumpahead
Tim Petersd7b5e882001-01-25 03:36:26 +0000798
Guido van Rossumff03b1a1994-03-09 12:55:02 +0000799if __name__ == '__main__':
Tim Petersd7b5e882001-01-25 03:36:26 +0000800 _test()