Random Number Generator
The module random.py
contains the random generator classes that 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 methods:
- bits(size):
This method creates 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). The generator can be made deterministic 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 use "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 match those above because all use the same bit generator with the same seed.
>>> from neoradium import random >>> # Creating a predictable random generator based on "PCG64" >>> 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. The generator can be made deterministic 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. The generator can be made deterministic 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. The generator can be made deterministic 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. The generator can be made deterministic 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 generator. This is based on Numpy’s RandomState class. The generator can be made deterministic 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. For example, this is 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 use only 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 the specified bit generator.- Generator:
If
seed
is a Generator object, the returned random generator is based ondefault_rng
. Note that internally,default_rng
uses the PCG64 bit generator.- RandomState:
If
seed
is a RandomState object, the returned random generator is based onRandomState
.- None:
If
seed
isNone
(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 the 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 your code that 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 are 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.