Skip to content

Random Stream Generators

esseff edited this page Jun 10, 2025 · 19 revisions

Home > Model Development Topics > Random Stream Generators

Describes the available random number generators and how to select one.

Related topics

Topic contents

Introduction

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 with lcg41 can produce identical results to the same model built with Modgen. The lcg41 generators are very fast and very memory efficient.

  • lcg200 The same mathematical family as lcg41, 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 the lcg41 family, so it’s probably best to use the lcg200 family if x-compatibility is not required. The lcg200 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 the lcg41 and lcg200 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 than mt19937, but slower than lcg41 and lcg200. Can be useful to probe that the lcg41 and lcg200 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.

[back to topic contents]

Stream generators

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";

[back to topic contents]

Case seed generators

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.

[back to topic contents]

Historical background

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.

[back to topic contents]

Home

Getting Started

Model development in OpenM++

Using OpenM++

Model Development Topics

OpenM++ web-service: API and cloud setup

Using OpenM++ from Python and R

Docker

OpenM++ Development

OpenM++ Design, Roadmap and Status

OpenM++ web-service API

GET Model Metadata

GET Model Extras

GET Model Run results metadata

GET Model Workset metadata: set of input parameters

Read Parameters, Output Tables or Microdata values

GET Parameters, Output Tables or Microdata values

GET Parameters, Output Tables or Microdata as CSV

GET Modeling Task metadata and task run history

Update Model Profile: set of key-value options

Update Model Workset: set of input parameters

Update Model Runs

Update Modeling Tasks

Run Models: run models and monitor progress

Download model, model run results or input parameters

Upload model runs or worksets (input scenarios)

Download and upload user files

User: manage user settings

Model run jobs and service state

Administrative: manage web-service state

Clone this wiki locally