LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
ctmc_rand.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012-2026, QORE Lab, Imperial College London
3 * All rights reserved.
4 */
5#ifndef LINE_API_MC_CTMC_RAND_H
6#define LINE_API_MC_CTMC_RAND_H
7
8/**
9 * @file
10 * @ingroup api_mc
11 * Random infinitesimal generator of a CTMC.
12 *
13 * Templated port of matlab/src/api/mc/ctmc_rand.m (identical to the kpctoolbox
14 * copy) and jar/src/main/java/jline/api/mc/Ctmc_rand.java: an n x n matrix of
15 * uniform [0,1) rates whose diagonal is then set by ctmc_makeinfgen.
16 *
17 * The MATLAB and Java versions draw from a global stream (rand / randMatrix),
18 * so the caller has no way to reproduce a generator except by seeding that
19 * stream. Here the source of randomness is an explicit parameter: any callable
20 * returning a double in [0,1) with no global state. COMPARABILITY ACROSS
21 * IMPLEMENTATIONS THEREFORE REQUIRES THE SAME GENERATOR, and a matrix built
22 * here will not match one MATLAB built unless the same stream of variates is
23 * fed in; what is guaranteed is that two calls with equal generator states
24 * return the same matrix.
25 *
26 * The variates are consumed in row-major order, one per off-diagonal and
27 * diagonal position alike (n*n draws), matching MATLAB's rand(n) column count
28 * only in total, not in order: MATLAB fills column-major. Pass the transpose of
29 * a MATLAB-filled stream if that ordering matters.
30 *
31 * Only the diagonal is arithmetic, so this is exact at Rational whenever the
32 * generator's variates are (LcgUniform yields dyadic rationals, which are).
33 */
34
35#include <cstddef>
36#include <cstdint>
37
39#include "line/num/number.h"
40#include "line/util/error.h"
41#include "line/util/matrix.h"
42
43namespace line {
44namespace mc {
45
46/**
47 * Deterministic uniform [0,1) source, so that a caller who does not have one
48 * still has no reason to reach for a global stream. Numerical Recipes' 64-bit
49 * linear congruential recurrence, whose high bits are the ones used.
50 */
52public:
53 explicit LcgUniform(std::uint64_t seed = 20260721ull) : s_(seed ? seed : 1ull) {}
54 double operator()() {
55 s_ = s_ * 6364136223846793005ull + 1442695040888963407ull;
56 // Top 53 bits scaled into [0,1), so the value is an exact dyadic.
57 return static_cast<double>(s_ >> 11) / 9007199254740992.0;
58 }
59
60private:
61 std::uint64_t s_;
62};
63
64/**
65 * @brief Random infinitesimal generator of a CTMC.
66 *
67 * @param n order of the generator
68 * @param gen callable returning a uniform variate in [0,1); n*n draws are made
69 */
70template <class T, class Gen>
71Matrix<T> ctmc_rand(std::size_t n, Gen& gen) {
72 if (n == 0) throw InputError("ctmc_rand: order must be positive");
73 Matrix<T> R(n, n);
74 for (std::size_t i = 0; i < n; ++i)
75 for (std::size_t j = 0; j < n; ++j) R(i, j) = num_traits<T>::from_double(gen());
76 return ctmc_makeinfgen(R);
77}
78
79} // namespace mc
80} // namespace line
81
82#endif // LINE_API_MC_CTMC_RAND_H
InputError(const std::string &what)
Definition error.h:39
LcgUniform(std::uint64_t seed=20260721ull)
Definition ctmc_rand.h:53
Steady-state distribution of a continuous-time Markov chain.
The exception types the port throws.
Dense matrix and non-owning view.
Matrix< T > ctmc_makeinfgen(const Matrix< T > &Q)
Set the diagonal so that every row sums to zero (ctmc_makeinfgen).
Definition ctmc_solve.h:58
Matrix< T > ctmc_rand(std::size_t n, Gen &gen)
Random infinitesimal generator of a CTMC.
Definition ctmc_rand.h:71
Number-type abstraction for the templated API port.