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 shapeshape
.>>> 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 onRandomState
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’srandom
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 theseed
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 therandom
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 originalrandom
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 theseed
parameter.