Skip to content

Commit 4943394

Browse files
author
rhettinger
committed
SF patch 658251: Install a C implementation of the Mersenne Twister as the
core generator for random.py. git-svn-id: http://svn.python.org/projects/python/trunk@30307 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent c648155 commit 4943394

6 files changed

Lines changed: 983 additions & 322 deletions

File tree

Doc/lib/librandom.tex

Lines changed: 55 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -8,89 +8,46 @@ \section{\module{random} ---
88

99
This module implements pseudo-random number generators for various
1010
distributions.
11+
1112
For integers, uniform selection from a range.
12-
For sequences, uniform selection of a random element, and a function to
13-
generate a random permutation of a list in-place.
13+
For sequences, uniform selection of a random element, a function to
14+
generate a random permutation of a list in-place, and a function for
15+
random sampling without replacement.
16+
1417
On the real line, there are functions to compute uniform, normal (Gaussian),
1518
lognormal, negative exponential, gamma, and beta distributions.
16-
For generating distribution of angles, the circular uniform and
17-
von Mises distributions are available.
19+
For generating distributions of angles, the von Mises distribution
20+
is available.
1821

1922
Almost all module functions depend on the basic function
2023
\function{random()}, which generates a random float uniformly in
21-
the semi-open range [0.0, 1.0). Python uses the standard Wichmann-Hill
22-
generator, combining three pure multiplicative congruential
23-
generators of modulus 30269, 30307 and 30323. Its period (how many
24-
numbers it generates before repeating the sequence exactly) is
25-
6,953,607,871,644. While of much higher quality than the \function{rand()}
26-
function supplied by most C libraries, the theoretical properties
27-
are much the same as for a single linear congruential generator of
28-
large modulus. It is not suitable for all purposes, and is completely
29-
unsuitable for cryptographic purposes.
30-
31-
The functions in this module are not threadsafe: if you want to call these
32-
functions from multiple threads, you should explicitly serialize the calls.
33-
Else, because no critical sections are implemented internally, calls
34-
from different threads may see the same return values.
24+
the semi-open range [0.0, 1.0). Python uses the Mersenne Twister as
25+
the core generator. It produces 53-bit precision floats and has a
26+
period of 2**19937-1. The underlying implementation in C
27+
is both fast and threadsafe. The Mersenne Twister is one of the most
28+
extensively tested random number generators in existence. However, being
29+
completely deterministic, it is not suitable for all purposes, and is
30+
completely unsuitable for cryptographic purposes.
3531

3632
The functions supplied by this module are actually bound methods of a
3733
hidden instance of the \class{random.Random} class. You can
3834
instantiate your own instances of \class{Random} to get generators
3935
that don't share state. This is especially useful for multi-threaded
4036
programs, creating a different instance of \class{Random} for each
4137
thread, and using the \method{jumpahead()} method to ensure that the
42-
generated sequences seen by each thread don't overlap (see example
43-
below).
38+
generated sequences seen by each thread don't overlap.
4439

4540
Class \class{Random} can also be subclassed if you want to use a
4641
different basic generator of your own devising: in that case, override
4742
the \method{random()}, \method{seed()}, \method{getstate()},
4843
\method{setstate()} and \method{jumpahead()} methods.
4944

50-
Here's one way to create threadsafe distinct and non-overlapping generators:
51-
52-
\begin{verbatim}
53-
def create_generators(num, delta, firstseed=None):
54-
"""Return list of num distinct generators.
55-
Each generator has its own unique segment of delta elements
56-
from Random.random()'s full period.
57-
Seed the first generator with optional arg firstseed (default
58-
is None, to seed from current time).
59-
"""
60-
61-
from random import Random
62-
g = Random(firstseed)
63-
result = [g]
64-
for i in range(num - 1):
65-
laststate = g.getstate()
66-
g = Random()
67-
g.setstate(laststate)
68-
g.jumpahead(delta)
69-
result.append(g)
70-
return result
71-
72-
gens = create_generators(10, 1000000)
73-
\end{verbatim}
74-
75-
That creates 10 distinct generators, which can be passed out to 10
76-
distinct threads. The generators don't share state so can be called
77-
safely in parallel. So long as no thread calls its \code{g.random()}
78-
more than a million times (the second argument to
79-
\function{create_generators()}, the sequences seen by each thread will
80-
not overlap. The period of the underlying Wichmann-Hill generator
81-
limits how far this technique can be pushed.
82-
83-
Just for fun, note that since we know the period, \method{jumpahead()}
84-
can also be used to ``move backward in time:''
85-
86-
\begin{verbatim}
87-
>>> g = Random(42) # arbitrary
88-
>>> g.random()
89-
0.25420336316883324
90-
>>> g.jumpahead(6953607871644L - 1) # move *back* one
91-
>>> g.random()
92-
0.25420336316883324
93-
\end{verbatim}
45+
As an example of subclassing, the \module{random} module provides
46+
the \class{WichmannHill} class which implements an alternative generator
47+
in pure Python. The class provides a backward compatible way to
48+
reproduce results from earlier versions of Python which used the
49+
Wichmann-Hill algorithm as the core generator.
50+
\versionchanged[Substituted MersenneTwister for Wichmann-Hill]{2.3}
9451

9552

9653
Bookkeeping functions:
@@ -104,18 +61,6 @@ \section{\module{random} ---
10461
If \var{x} is not \code{None} or an int or long,
10562
\code{hash(\var{x})} is used instead.
10663
If \var{x} is an int or long, \var{x} is used directly.
107-
Distinct values between 0 and 27814431486575L inclusive are guaranteed
108-
to yield distinct internal states (this guarantee is specific to the
109-
default Wichmann-Hill generator, and may not apply to subclasses
110-
supplying their own basic generator).
111-
\end{funcdesc}
112-
113-
\begin{funcdesc}{whseed}{\optional{x}}
114-
This is obsolete, supplied for bit-level compatibility with versions
115-
of Python prior to 2.1.
116-
See \function{seed} for details. \function{whseed} does not guarantee
117-
that distinct integer arguments yield distinct internal states, and can
118-
yield no more than about 2**24 distinct internal states in all.
11964
\end{funcdesc}
12065

12166
\begin{funcdesc}{getstate}{}
@@ -134,17 +79,20 @@ \section{\module{random} ---
13479
\end{funcdesc}
13580

13681
\begin{funcdesc}{jumpahead}{n}
137-
Change the internal state to what it would be if \function{random()}
138-
were called \var{n} times, but do so quickly. \var{n} is a
139-
non-negative integer. This is most useful in multi-threaded
82+
Change the internal state to one different from and likely far away from
83+
the current state. \var{n} is a non-negative integer which is used to
84+
scramble the current state vector. This is most useful in multi-threaded
14085
programs, in conjuction with multiple instances of the \class{Random}
141-
class: \method{setstate()} or \method{seed()} can be used to force
142-
all instances into the same internal state, and then
143-
\method{jumpahead()} can be used to force the instances' states as
144-
far apart as you like (up to the period of the generator).
86+
class: \method{setstate()} or \method{seed()} can be used to force all
87+
instances into the same internal state, and then \method{jumpahead()}
88+
can be used to force the instances' states far apart.
14589
\versionadded{2.1}
90+
\versionchanged[Instead of jumping to a specific state, \var{n} steps
91+
ahead, \method{jumpahead(\var{n})} jumps to another state likely to be
92+
separated by many steps.]{2.3}
14693
\end{funcdesc}
14794

95+
14896
Functions for integers:
14997

15098
\begin{funcdesc}{randrange}{\optional{start,} stop\optional{, step}}
@@ -279,8 +227,32 @@ \section{\module{random} ---
279227
\var{beta} is the shape parameter.
280228
\end{funcdesc}
281229

230+
Alternative Generator
231+
232+
\begin{classdesc}{WichmannHill}{\optional{seed}}
233+
Class that implements the Wichmann-Hill algorithm as the core generator.
234+
Has all of the same methods as \class{Random} plus the \method{whseed}
235+
method described below. Because this class is implemented in pure
236+
Python, it is not threadsafe and may require locks between calls. The
237+
period of the generator is 6,953,607,871,644 which is small enough to
238+
require care that two independent random sequences do not overlap.
239+
\end{classdesc}
240+
241+
\begin{funcdesc}{whseed}{\optional{x}}
242+
This is obsolete, supplied for bit-level compatibility with versions
243+
of Python prior to 2.1.
244+
See \function{seed} for details. \function{whseed} does not guarantee
245+
that distinct integer arguments yield distinct internal states, and can
246+
yield no more than about 2**24 distinct internal states in all.
247+
\end{funcdesc}
282248

283249
\begin{seealso}
250+
\seetext{M. Matsumoto and T. Nishimura, ``Mersenne Twister: A
251+
623-dimensionally equidistributed uniform pseudorandom
252+
number generator'',
253+
\citetitle{ACM Transactions on Modeling and Computer Simulation}
254+
Vol. 8, No. 1, January pp.3-30 1998.}
255+
284256
\seetext{Wichmann, B. A. \& Hill, I. D., ``Algorithm AS 183:
285257
An efficient and portable pseudo-random number generator'',
286258
\citetitle{Applied Statistics} 31 (1982) 188-190.}

0 commit comments

Comments
 (0)