CSCS530 Winter 2015

Complex Systems 530 - Computer Modeling of Complex Systems (Winter 2015)

View this repository on NBViewer


In [1]:
%matplotlib inline
# Imports
import numpy
import numpy.random
import matplotlib.pyplot as plt

Random number generation and seeds

Basic reading on random number generation:

On Determinism

The second method uses computational algorithms that can produce long sequences of apparently random results, which are in fact completely determined by a shorter initial value, known as a seed or key. The latter type are often called pseudorandom number generators. These types of generators do not typically rely on sources of naturally occurring entropy, though they may be periodically seeded by natural sources, they are non-blocking i.e. not rate-limited by an external event.

A "random number generator" based solely on deterministic computation cannot be regarded as a "true" random number generator in the purest sense of the word, since their output is inherently predictable if all seed values are known. In practice however they are sufficient for most tasks. Carefully designed and implemented pseudo-random number generators can even be certified for security-critical cryptographic purposes, as is the case with the yarrow algorithm and fortuna (PRNG). (The former being the basis of the /dev/random source of entropy on FreeBSD, AIX, Mac OS X, NetBSD and others. OpenBSD also uses a pseudo-random number algorithm based on ChaCha20 known as arc4random.[5])

On distributions

Random numbers uniformly distributed between 0 and 1 can be used to generate random numbers of any desired distribution by passing them through the inverse cumulative distribution function (CDF) of the desired distribution. Inverse CDFs are also called quantile functions. To generate a pair of statistically independent standard normally distributed random numbers (x, y), one may first generate the polar coordinates (r, θ), where r~χ22 and θ~UNIFORM(0,2π) (see Box–Muller transform).

Without a seeded RNG


In [21]:
# Let's make a random draw without seeding/controlling our RNG
for n in range(3):
    print("Draw {0}".format(n))
    X = numpy.random.uniform(size=10)
    print(X)
    print(X.mean())
    print("=" * 16 + "\n")


Draw 0
[ 0.27913612  0.88304944  0.90650699  0.90959833  0.6378356   0.16630971
  0.90582092  0.42943375  0.42724209  0.37184667]
0.591677961493
================

Draw 1
[ 0.60828926  0.68482624  0.88001386  0.84444655  0.66739229  0.53894798
  0.84514952  0.48747753  0.04339293  0.54421089]
0.61441470532
================

Draw 2
[ 0.12898055  0.37412006  0.88815831  0.55001458  0.2399099   0.6827149
  0.16719905  0.76470928  0.25233562  0.42583843]
0.447398068686
================

With a seeded RNG


In [22]:
# Now let's try again with a fixed seed
seed = 0

# Let's make a random draw without seeding/controlling our RNG
for n in range(3):
    print("Draw {0}".format(n))
    rs = numpy.random.RandomState(seed)
    Y = rs.uniform(size=10)
    print(Y)
    print(Y.mean())
    print("=" * 16 + "\n")


Draw 0
[ 0.5488135   0.71518937  0.60276338  0.54488318  0.4236548   0.64589411
  0.43758721  0.891773    0.96366276  0.38344152]
0.615766283315
================

Draw 1
[ 0.5488135   0.71518937  0.60276338  0.54488318  0.4236548   0.64589411
  0.43758721  0.891773    0.96366276  0.38344152]
0.615766283315
================

Draw 2
[ 0.5488135   0.71518937  0.60276338  0.54488318  0.4236548   0.64589411
  0.43758721  0.891773    0.96366276  0.38344152]
0.615766283315
================