1 """Random variable generators.
10 generate random permutation
12 distributions on the real line:
13 ------------------------------
21 distributions on the circle (angles 0 to 2pi)
22 ---------------------------------------------
26 Translated from anonymously contributed C/C++ source.
28 Multi-threading note: the random number generator used here is not thread-
29 safe; it is possible that two calls return the same random value. However,
30 you can instantiate a different instance of Random() in each thread to get
31 generators that don't share state, then use .setstate() and .jumpahead() to
32 move the generators to disjoint segments of the full period. For example,
34 def create_generators(num, delta, firstseed=None):
35 ""\"Return list of num distinct generators.
36 Each generator has its own unique segment of delta elements from
37 Random.random()'s full period.
38 Seed the first generator with optional arg firstseed (default is
39 None, to seed from current time).
42 from random import Random
45 for i in range(num - 1):
46 laststate = g.getstate()
53 gens = create_generators(10, 1000000)
55 That creates 10 distinct generators, which can be passed out to 10 distinct
56 threads. The generators don't share state so can be called safely in
57 parallel. So long as no thread calls its g.random() more than a million
58 times (the second argument to create_generators), the sequences seen by
59 each thread will not overlap.
61 The period of the underlying Wichmann-Hill generator is 6,953,607,871,644,
62 and that limits how far this technique can be pushed.
64 Just for fun, note that since we know the period, .jumpahead() can also be
65 used to "move backward in time":
67 >>> g = Random(42) # arbitrary
70 >>> g.jumpahead(6953607871644L - 1) # move *back* one
76 _e = 2.7182818284590451
77 from VS
import log
as _log, exp
as _exp
78 from VS
import sqrt
as _sqrt, acos
as _acos, cos
as _cos, sin
as _sin
80 __all__ = [
"Random",
"seed",
"random",
"uniform",
"randint",
"choice",
81 "randrange",
"shuffle",
"normalvariate",
"lognormvariate",
82 "cunifvariate",
"expovariate",
"vonmisesvariate",
"gammavariate",
83 "stdgamma",
"gauss",
"betavariate",
"paretovariate",
"weibullvariate",
84 "getstate",
"setstate",
"jumpahead",
"whseed"]
86 def _verify(name, computed, expected):
87 if abs(computed - expected) > 1e-7:
89 "computed value for %s deviates too much "
90 "(computed %g, expected %g)" % (name, computed, expected))
92 NV_MAGICCONST = 4 * _exp(-0.5)/_sqrt(2.0)
93 _verify(
'NV_MAGICCONST', NV_MAGICCONST, 1.71552776992141)
96 _verify(
'TWOPI', TWOPI, 6.28318530718)
99 _verify(
'LOG4', LOG4, 1.38629436111989)
101 SG_MAGICCONST = 1.0 + _log(4.5)
102 _verify(
'SG_MAGICCONST', SG_MAGICCONST, 2.50407739677627)
114 """Initialize an instance.
116 Optional argument x controls seeding, as for Random.seed().
129 """Initialize internal state from hashable object.
131 None or no argument seeds from current time.
133 If a is not None or an int or long, hash(a) is used instead.
135 If a is an int or long, a is used directly. Distinct values between
136 0 and 27814431486575L inclusive are guaranteed to yield distinct
137 internal states (this guarantee is specific to the default
138 Wichmann-Hill generator).
144 a = long(VS.timeofday() * 256)
146 if type(a)
not in (type(3), type(3L)):
149 a, x = divmod(a, 30268)
150 a, y = divmod(a, 30306)
151 a, z = divmod(a, 30322)
152 self._seed = int(x)+1, int(y)+1, int(z)+1
155 """Get the next random number in the range [0.0, 1.0)."""
175 x = (171 * x) % 30269
176 y = (172 * y) % 30307
177 z = (170 * z) % 30323
183 return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
186 """Return internal state; can be passed to setstate() later."""
187 return self.VERSION, self._seed, self.gauss_next
190 """Restore internal state from object returned by getstate()."""
193 version, self._seed, self.gauss_next = state
195 raise ValueError(
"state with version %s passed to "
196 "Random.setstate() of version %s" %
197 (version, self.VERSION))
200 """Act as if n calls to random() were made, but quickly.
202 n is an int, greater than or equal to 0.
204 Example use: If you have 2 threads and know that each will
205 consume no more than a million random numbers, create two Random
206 objects r1 and r2, then do
207 r2.setstate(r1.getstate())
208 r2.jumpahead(1000000)
209 Then r1 and r2 will use guaranteed-disjoint segments of the full
214 raise ValueError(
"n must be >= 0")
216 x = int(x * pow(171, n, 30269)) % 30269
217 y = int(y * pow(172, n, 30307)) % 30307
218 z = int(z * pow(170, n, 30323)) % 30323
221 def __whseed(self, x=0, y=0, z=0):
222 """Set the Wichmann-Hill seed from (x, y, z).
224 These must be integers in the range [0, 256).
227 if not type(x) == type(y) == type(z) == type(0):
228 raise TypeError(
'seeds must be integers')
229 if not (0 <= x < 256
and 0 <= y < 256
and 0 <= z < 256):
230 raise ValueError(
'seeds must be in range(0, 256)')
234 t = long(VS.timeofday() * 256)
235 t = int((t&0xffffff) ^ (t>>24))
236 t, x = divmod(t, 256)
237 t, y = divmod(t, 256)
238 t, z = divmod(t, 256)
240 self._seed = (x
or 1, y
or 1, z
or 1)
243 """Seed from hashable object's hash code.
245 None or no argument seeds from current time. It is not guaranteed
246 that objects with distinct hash codes lead to distinct internal
249 This is obsolete, provided for compatibility with the seed routine
250 used prior to Python 2.1. Use the .seed() method instead.
257 a, x = divmod(a, 256)
258 a, y = divmod(a, 256)
259 a, z = divmod(a, 256)
260 x = (x + a) % 256
or 1
261 y = (y + a) % 256
or 1
262 z = (z + a) % 256
or 1
263 self.__whseed(x, y, z)
271 return self.getstate()
278 def randrange(self, start, stop=None, step=1, int=int, default=None):
279 """Choose a random item from range(start, stop[, step]).
281 This fixes the problem with randint() which includes the
282 endpoint; in Python this is usually not what you want.
283 Do not supply the 'int' and 'default' arguments.
290 raise ValueError,
"non-integer arg 1 for randrange()"
293 return int(self.random() * istart)
294 raise ValueError,
"empty range for randrange()"
297 raise ValueError,
"non-integer stop for randrange()"
300 return istart + int(self.random() *
302 raise ValueError,
"empty range for randrange()"
305 raise ValueError,
"non-integer step for randrange()"
307 n = (istop - istart + istep - 1) / istep
309 n = (istop - istart + istep + 1) / istep
311 raise ValueError,
"zero step for randrange()"
314 raise ValueError,
"empty range for randrange()"
315 return istart + istep*int(self.random() * n)
318 """Return random integer in range [a, b], including both end points.
320 (Deprecated; use randrange(a, b+1).)
323 return self.randrange(a, b+1)
328 """Choose a random element from a non-empty sequence."""
329 return seq[int(self.random() * len(seq))]
332 """x, random=random.random -> shuffle list x in place; return None.
334 Optional arg random is a 0-argument function returning a random
335 float in [0.0, 1.0); by default, the standard random.random.
337 Note that for even rather small len(x), the total number of
338 permutations of x is larger than the period of most random number
339 generators; this implies that "most" permutations of a long
340 sequence can never be generated.
345 for i
in xrange(len(x)-1, 0, -1):
348 x[i], x[j] = x[j], x[i]
355 """Get a random number in the range [a, b)."""
356 return a + (b-a) * self.random()
372 z = NV_MAGICCONST*(u1-0.5)/u2
381 return _exp(self.normalvariate(mu, sigma))
389 return (mean + arc * (self.random() - 0.5)) % _pi
401 return -_log(u)/lambd
421 a = 1.0 + _sqrt(1.0 + 4.0 * kappa * kappa)
422 b = (a - _sqrt(2.0 * a))/(2.0 * kappa)
423 r = (1.0 + b * b)/(2.0 * b)
429 f = (1.0 + r * z)/(r + z)
434 if not (u2 >= c * (2.0 - c)
and u2 > c * _exp(1.0 - c)):
439 theta = (mu % TWOPI) + _acos(f)
441 theta = (mu % TWOPI) - _acos(f)
449 ainv = _sqrt(2.0 * alpha - 1.0)
450 return beta * self.stdgamma(alpha, ainv, alpha - LOG4, alpha + ainv)
459 raise ValueError,
'stdgamma: alpha must be > 0.0'
470 v = _log(u1/(1.0-u1))/ainv
474 if r + SG_MAGICCONST - 4.5*z >= 0.0
or r >= _log(z):
493 x = pow(p, 1.0/alpha)
496 x = -_log((b-p)/alpha)
498 if not (((p <= 1.0)
and (u1 > _exp(-x)))
or
499 ((p > 1)
and (u1 > pow(x, alpha - 1.0)))):
528 self.gauss_next =
None
531 g2rad = _sqrt(-2.0 * _log(1.0 -
random()))
532 z = _cos(x2pi) * g2rad
533 self.gauss_next = _sin(x2pi) * g2rad
554 y = self.gammavariate(alpha, 1.)
558 return y / (y + self.gammavariate(beta, 1.))
566 return 1.0 / pow(u, 1.0/alpha)
574 return alpha * pow(-_log(u), 1.0/beta)
578 def _test_generator(n, funccall):
580 print n,
'times', funccall
581 code =
compile(funccall, funccall,
'eval')
591 smallest =
min(x, smallest)
592 largest =
max(x, largest)
594 print round(t1-t0, 3),
'sec,',
596 stddev = _sqrt(sqsum/n - avg*avg)
597 print 'avg %g, stddev %g, min %g, max %g' % \
598 (avg, stddev, smallest, largest)
601 print 'TWOPI =', TWOPI
603 print 'NV_MAGICCONST =', NV_MAGICCONST
604 print 'SG_MAGICCONST =', SG_MAGICCONST
605 _test_generator(N,
'random()')
606 _test_generator(N,
'normalvariate(0.0, 1.0)')
607 _test_generator(N,
'lognormvariate(0.0, 1.0)')
608 _test_generator(N,
'cunifvariate(0.0, 1.0)')
609 _test_generator(N,
'expovariate(1.0)')
610 _test_generator(N,
'vonmisesvariate(0.0, 1.0)')
611 _test_generator(N,
'gammavariate(0.5, 1.0)')
612 _test_generator(N,
'gammavariate(0.9, 1.0)')
613 _test_generator(N,
'gammavariate(1.0, 1.0)')
614 _test_generator(N,
'gammavariate(2.0, 1.0)')
615 _test_generator(N,
'gammavariate(20.0, 1.0)')
616 _test_generator(N,
'gammavariate(200.0, 1.0)')
617 _test_generator(N,
'gauss(0.0, 1.0)')
618 _test_generator(N,
'betavariate(3.0, 3.0)')
619 _test_generator(N,
'paretovariate(1.0)')
620 _test_generator(N,
'weibullvariate(1.0, 1.0)')
632 raise ValueError(
"jumpahead test failed " + `(N, r1, r2)`)
641 random = _inst.random
642 uniform = _inst.uniform
643 randint = _inst.randint
644 choice = _inst.choice
645 randrange = _inst.randrange
646 shuffle = _inst.shuffle
647 normalvariate = _inst.normalvariate
648 lognormvariate = _inst.lognormvariate
649 cunifvariate = _inst.cunifvariate
650 expovariate = _inst.expovariate
651 vonmisesvariate = _inst.vonmisesvariate
652 gammavariate = _inst.gammavariate
653 stdgamma = _inst.stdgamma
655 betavariate = _inst.betavariate
656 paretovariate = _inst.paretovariate
657 weibullvariate = _inst.weibullvariate
658 getstate = _inst.getstate
659 setstate = _inst.setstate
660 jumpahead = _inst.jumpahead
661 whseed = _inst.whseed
663 if __name__ ==
'__main__':