![]() |
LINE Solver (C++)
Templated C++ port of the LINE queueing solver
|
The two random number generators the Java LDES engine draws from, reproduced exactly: SSJ's MRG32k3a and java.util.Random. More...
Go to the source code of this file.
Classes | |
| class | line::rng::Mrg32k3a |
| SSJ's umontreal.ssj.rng.MRG32k3a, state and all. More... | |
| class | line::rng::JavaRandom |
| java.util.Random, the 48-bit LCG of the Java Language Specification. More... | |
Namespaces | |
| namespace | line |
| namespace | line::rng |
The two random number generators the Java LDES engine draws from, reproduced exactly: SSJ's MRG32k3a and java.util.Random.
WHY THIS EXISTS. common/ldes is to become the C++ engine compiled, in place of a GraalVM image of the Java one, and a simulator that answers with a different sample path at the same seed is not a replacement – every seeded golden in MATLAB, Python and the parity harness would re-baseline, and "LDES agrees across the codebases at a given seed", which CLAUDE.md states as an invariant, would weaken to "agrees in distribution". The C++ engine previously drew from std::mt19937_64; this header is the first half of closing that gap, and ldes_sampler.h is the second (the variate algorithms must consume the same uniforms in the same order).
WHAT MADE IT TRACTABLE. Solver_ssj never relies on SSJ's package-level stream sequence: every stream is created and then given an EXPLICIT six-long seed derived from the run seed and a per-(node, class) offset, e.g.
long offset = ((long) (numSources + svcIdx) * numClasses + k) * 10 + 1000;
stream.setSeed(new long[] { seed + offset, ..., seed + offset + 5 });
so none of SSJ's 2^127 jump-ahead machinery is on the path. Matching the engine means matching the recurrence, nextValue/nextDouble, and those offsets – not the stream hierarchy.
MRG32k3a is L'Ecuyer's combined multiple recursive generator (Operations Research 47(1), 1999): two order-three recurrences modulo m1 = 2^32 - 209 and m2 = 2^32 - 22853, combined by subtraction. SSJ computes it in DOUBLES with the multipliers split so every intermediate stays exactly representable, and that arithmetic is reproduced here rather than an integer rewrite: the double form is what the reference runs, and the two agree only if the rounding does.
java.util.Random is the specified 48-bit LCG of the Java Language Specification: seed scrambling by 0x5DEECE66D, next(bits) taking the high bits, nextDouble from a 26-bit and a 27-bit draw, and nextInt(bound) with its rejection loop for non-power-of-two bounds. All of it is normative, so a faithful transcription is exact by construction.
Definition in file rng_ssj.h.