Random Number Generator

The module random.py contains the random generator classes which can be used to generate random numbers and control the random behavior of your code. This module also provides the global random object which is an instance of the RanGen class.

The random object

The random object by default is initialized as a Permuted Congruential Generator based on Numpy’s PCG64 class. It can be used to generate random numbers using the methods defined for Numpy’s Generator class such as choice or shuffle.

>>> from neoradium import random
>>> random.choice(5, 3)
array([1, 1, 4])

>>> a = np.arange(10)
>>> random.shuffle(a)
>>> a
array([5, 8, 0, 1, 6, 9, 7, 2, 3, 4])

In addition to the methods defined for the Generator class, NeoRadium’s random object also supports the following additional methods:

bits(size):

This method create a bitstream of size random bits.

>>> from neoradium import random
>>> random.bits(8)
array([0, 1, 1, 0, 1, 1, 0, 1], dtype=int8)
awgn(shape, noiseStd):

This method creates Additive White Gaussian Noise with standard deviation specified by noiseStd. The result will be a complex numpy array of shape shape.

>>> from neoradium import random
>>> random.awgn((2,2),0.5)
array([[-0.38382838+0.35261486j,  0.10004801-0.5325556j ],
       [-0.20456608+0.58387099j, -0.85796067-0.15164351j]])

Supported Random Generators

Using the random object’s getGenerator() method you can create all types of random generators supported by Numpy. Here is a list of supported generators:

Default Random Generator:

This is based on the numpy class default_rng. which internally uses the default bit generator (PCG64). You can make this random generator predictable by providing a seed value.

>>> from neoradium import random
>>> # Creating a predictable random generator based on "default_rng"
>>> myGen = random.getGenerator(np.random.default_rng(123))
>>> myGen.integers(0,10,5)
array([0, 6, 5, 0, 9])

>>> # The same as above since both using "PCG64" internally
>>> myGen = random.getGenerator(123)
>>> myGen.integers(0,10,5)
array([0, 6, 5, 0, 9])
PCG64:

Permuted Congruential Generator (64-bit, PCG64). This is currently NeoRadium’s (and python’s) default bit generator object. It is based on Numpy’s PCG64 class. As you can see the results of the following example matches the above results as all of them use the same bit generator with the same seed.

>>> from neoradium import random
>>> # Creating a predictable random generator based on "default_rng"
>>> myGen = random.getGenerator(np.random.PCG64(123))
>>> myGen.integers(0,10,5)
array([0, 6, 5, 0, 9])
MT19937:

Mersenne Twister. This is based on Numpy’s MT19937 class. You can make this random generator predictable by providing a seed value.

>>> from neoradium import random
>>> # Creating an unpredictable random generator based on "MT19937"
>>> myGen = random.getGenerator(np.random.MT19937()) # No seed specified -> Unpredictable
>>> myGen.integers(0,10,5)
array([1, 8, 6, 8, 9])
PCG64DXSM:

Permuted Congruential Generator (64-bit, PCG64 DXSM). This is based on Numpy’s PCG64DXSM class. You can make this random generator predictable by providing a seed value.

>>> from neoradium import random
>>> # Creating a predictable random generator based on "PCG64DXSM"
>>> myGen = random.getGenerator(np.random.PCG64DXSM(123))
>>> myGen.integers(0,10,5)
array([9, 7, 0, 9, 7])
Philox:

Philox Counter-based RNG. This is based on Numpy’s Philox class. You can make this random generator predictable by providing a seed value.

>>> from neoradium import random
>>> # Creating an unpredictable random generator based on "Philox"
>>> myGen = random.getGenerator(np.random.Philox()) # No seed specified -> Unpredictable
>>> myGen.integers(0,10,5)
array([4, 0, 1, 6, 4])
SFC64:

SFC64 Small Fast Chaotic PRNG. This is based on Numpy’s SFC64 class. You can make this random generator predictable by providing a seed value.

>>> from neoradium import random
>>> # Creating an unpredictable random generator based on "SFC64"
>>> myGen = random.getGenerator(np.random.SFC64()) # No seed specified -> Unpredictable
>>> myGen.integers(0,10,5)
array([0, 7, 8, 1, 8])
RandomState:

Python’s Legacy Random Generation. This is based on Numpy’s RandomState class. You can make this random generator predictable by providing a seed value.

>>> from neoradium import random
>>> # Creating an unpredictable random generator based on "RandomState"
>>> myGen = random.getGenerator(np.random.RandomState(123))
>>> myGen.randint(0,10,5)
array([2, 2, 6, 1, 3])

Important

The RandomState can be used to create a random generator that matches Matlab’s default random generator. This is for example used by NeoRadium when comparing the simulation results with Matlab’s implementation.

predictable random generator based on RandomState in NeoRadium
>>> from neoradium import random
>>> # Creating a predictable random generator based on "RandomState"
>>> myGen = random.getGenerator(np.random.RandomState(123))
>>> myGen.random(size=5)
array([0.69646919, 0.28613933, 0.22685145, 0.55131477, 0.71946897])
predictable random generator in Matlab
>> rng(123);
>> rand(1,5)

ans =

    0.6965    0.2861    0.2269    0.5513    0.7195
class neoradium.random.RanGen

This is NeoRadium’s random number generator class. This class is used internally to create NeoRadium’s random object. It is strongly recommended to only use NeoRadium’s random object for all random operations.

getGenerator(seed=None)

This function creates a new random generator object that can be used to create new random values. See Supported Random Generators for examples of how to use this function.

Parameters:

seed (int, BitGenerator, Generator, RandomState, or None) –

This parameter specifies how the new random generator should be created. It can be one of the following:

int:

If seed is an integer, it is used as the seed to generate a PCG64 random number generator. The returned random number generator is predictable.

BitGenerator:

If seed is one of the Supported BitGenerators the returned random generator is based on specified bit generator.

Generator:

If seed is a Generator object, the returned random generator is based on default_rng. Note that internally, default_rng uses the PCG64 bit generator.

RandomState:

If seed is a RandomState object, the returned random generator is based on RandomState.

None:

If seed is None (default), a default PCG64 bit generator is used without specifying the seed which results in an unpredictable random generator.

Returns:

The returned random generator object is based on a NeoRadium internal class which is derived from Numpy’s Generator or RandomState class.

Return type:

Generator or RandomState

setSeed(seed)

This function changes the random generator used by this RanGen object.

Important

It is recommended to avoid using this method on NeoRadium’s global random object. Since the random object is a single instance used globally by all of codebase using NeoRadium, changing it affects other parts of your code which may depend on the original random object.

A better approach is to create a new random generator using the getGenerator() method and use that for the part of code the needs a specific random generator.

However, for smaller programs where you want to control the random behavior of your code, this function provides a quick and easy way to make your results reproducible by passing a constant integer value to this function.

from neoradium import random

# Changing the "random" object to be predictable with "MT19937" bit generator
# This is not recommended because it changes the "random" object which is
# used globally in NeoRadium.
random.setSeed(np.random.MT19937(123))
myRandInts = random.integers(0,10,5)

# Creating a new predictable random generator with "MT19937" bit generator
# This is the preferred approach as the original "random" object remains unchanged
# The results is the same as the above code.
myGen = random.getGenerator(np.random.MT19937(123))
myRandInts = myGen.integers(0,10,5)
Parameters:

seed (int, BitGenerator, Generator, RandomState, or None) – Please refer to getGenerator() method for details about the seed parameter.