Random Stream Generators - openmpp/openmpp.github.io GitHub Wiki
Home > Model Development Topics > Random Stream Generators
Describes the available random number generators and how to select one.
OpenM++ includes several drop-in choices of random number generator (RNG) which can be used by models with no changes to substantive model code.
-
lcg41
Identical to the Linear Congruential Generator (LCG) family used in Modgen.
A model built withlcg41
can produce identical results to the same model built with Modgen. Thelcg41
generators are very fast and very memory efficient. -
lcg200
The same mathematical family aslcg41
, but more distinct generators and better random properties.
Includes 200 optimal generators rather than Modgen’s 41 generators. These 200 generators have the best statistical properties in the family of ~500M similar generators, and all are superior to the 41 Modgen RNG’s. There are known issues with some members of thelcg41
family, so it’s probably best to use thelcg200
family if x-compatibility is not required. Thelcg200
generators are very fast and very memory efficient. -
mt19937
An implementation of the Mersenne Twister RNG.
This modern RNG has very good properties, but is slow and memory intensive. Can be useful to probe that thelcg41
andlcg200
generators are performing reasonably well for a given model. -
ranlux48
An implementation of a popular 'subtract with carry' RNG.
This RNG has good randomness properties. It is faster and less memory intensive thanmt19937
, but slower thanlcg41
andlcg200
. Can be useful to probe that thelcg41
andlcg200
generators are performing reasonably well for a given model.
The use
source code modules which implement mt19937
and ranlux48
can be copied and adapted mechanically by changing several lines of C++ code to implement other
RNG families in the C++ standard library.
Each of the random number generators is implemented in a shared use
model code module, specified conventionally in a model source file named ompp_framework.ompp
. Here’s a line from that file for a x-compatible model which replicates Modgen outputs:
use "random/random_lcg41.ompp";
This line instructs the Openm++ compiler omc
to read that file and compile it to become part of the model. To specify a different RNG family, change the name of the file to one of the code modules in the OM_ROOT/use/random
folder, e.g.
use "random/random_lcg200.ompp";
or
use "random/random_mt19937.ompp";
Case-based models (but not time-based models) use RNG’s not only in model code which calls RandUniform
, RandNormal
, etc., but also to generate the starting seed of each case. To ensure independence of simulation members (aka subsample, replicate), a distinct RNG is used for each simulation member to generate the starting seeds for each case. Modgen reserves 41
RNG’s for this purpose, so that each simulation member has its own RNG to generate case seeds and its own RNG to implement the random number streams in each simulation member. OpenM++ follows the same approach.
The code module which implements the RNG’s to generate case seeds in case-based models is also specified in ompp_framework.ompp
. Case-based models can specify either
use "case_based/case_based_lcg41.ompp";
or
use "case_based/case_based_lcg200.ompp";
The module case_based/case_based_lcg200.ompp
uses 200
RNG’s in the same family but distinct from the 200
RNG’s in random/random_lcg200.ompp
.
Other RNG’s are not supported for case seed generation at this time.
The ~85 generators used in Modgen came from a journal article published in the early 1980’s.
The article evaluated the randomness properties of the ~85 generators using several criteria. Some were good and some were not so good. Also included was the very widely-used generator with multiplier 16807
which has known defects. Modgen used most, maybe all, of the generators in the article, including the not-so-good ones, because it needed many independent generators. A single purpose probe model was designed and run to 'reverse engineer' the Modgen generators and their order to implement the equivalent in OpenM++, because the Modgen source code was not available.
The 400
generators in random_lcg200.ompp
and case_based_lcg200.ompp
come from a 1986 SIAM article “An Exhaustive Analysis of Multiplicative Congruential Random Number Generators with Modulus 2^31 – 1”. The authors did an exhaustive search of all possible RNG’s in the family (over 500M) and identified those with good lattice properties in {2,3,4,5,6} dimensions.
For more information, including the C++ code to find the complementary generators using the primitive roots, see comments in the module use/random/random_lcg200.ompp
.