LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
ctmc_multi.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_MULTI_H
6#define LINE_API_MC_CTMC_MULTI_H
7
8/**
9 * @file
10 * @ingroup api_mc
11 * Two-level multigrid aggregation-disaggregation for a nearly completely
12 * decomposable CTMC.
13 *
14 * Templated port of matlab/src/api/mc/ctmc_multi.m and
15 * jar/src/main/java/jline/api/mc/Ctmc_multi.java. The construction is exactly
16 * Courtois's: permute into macro-state order, decouple, solve each diagonal
17 * block for its conditional distribution, and assemble the macro-state chain G.
18 * The one difference, and the whole point of the method, is that G is not
19 * solved directly but decomposed AGAIN, by a second Courtois step over the
20 * macro-macro-states MSS, so the coarse problem is itself solved by aggregation.
21 * This is the one-step, two-level instance of multigrid; a full multi-level
22 * implementation is repeated coarsening with the same base method.
23 *
24 * The fine level is shared verbatim with ctmc_courtois rather than duplicated,
25 * so the two cannot drift apart.
26 *
27 * GATED ON TRANSCENDENTAL ARITHMETIC: both levels are Courtois steps, and
28 * epsMAX is an eigenvalue modulus.
29 */
30
31#include <cstddef>
32#include <vector>
33
35#include "line/num/number.h"
36#include "line/util/error.h"
37#include "line/util/matrix.h"
38
39namespace line {
40namespace mc {
41
42template <class T>
44 std::vector<T> p; ///< approximate stationary vector, ORIGINAL ordering
45 std::vector<T> pcourt; ///< the plain Courtois estimate, for comparison
46 Matrix<T> Qperm; ///< Q reordered by macro-state
47 T eps; ///< NCD index of the fine level
48 T epsMAX; ///< maximum admissible NCD index of the fine level
49};
50
51/**
52 * @brief Two-level multigrid aggregation-disaggregation for a nearly
53 * completely decomposable CTMC.
54 *
55 * @param Q generator
56 * @param MS macro-states partitioning 0..n-1
57 * @param MSS macro-macro-states partitioning 0..|MS|-1, the coarse partition
58 * @param q uniformization rate for the fine level
59 */
60template <class T>
61MultiResult<T> ctmc_multi(const Matrix<T>& Q, const std::vector<std::vector<std::size_t>>& MS,
62 const std::vector<std::vector<std::size_t>>& MSS, const T& q) {
64 "ctmc_multi requires transcendental arithmetic: both levels are Courtois "
65 "decompositions, whose epsMAX is an iteratively computed eigenvalue modulus");
66 const std::size_t n = Q.rows();
67 if (Q.cols() != n) throw InputError("ctmc_multi: generator is not square");
68 if (MSS.empty()) throw InputError("ctmc_multi: no macro-macro-states given");
69
70 const detail::CourtoisCore<T> c = detail::courtois_core(Q, MS, q);
71 // The coarse solve: a second Courtois decomposition of the macro chain, in
72 // place of the direct dtmc_solve that ctmc_courtois performs.
73 const std::vector<T> pMacro = ctmc_courtois(c.G, MSS).p;
74
75 std::vector<T> pperm(n, num_traits<T>::from_int(0));
76 std::size_t proc = 0;
77 for (std::size_t i = 0; i < MS.size(); ++i) {
78 for (std::size_t a = 0; a < MS[i].size(); ++a) pperm[proc + a] = pMacro[i] * c.pmicro[proc + a];
79 proc += MS[i].size();
80 }
81
83 r.p = detail::unpermute_states(pperm, c.v);
84 r.Qperm = c.Qperm;
85 r.eps = c.eps;
86 r.epsMAX = c.epsMAX;
87 r.pcourt = ctmc_courtois(Q, MS, q).p;
88 return r;
89}
90
91/** Overload deriving the rate as MATLAB does, q = (21/20) max|Qperm|. */
92template <class T>
93MultiResult<T> ctmc_multi(const Matrix<T>& Q, const std::vector<std::vector<std::size_t>>& MS,
94 const std::vector<std::vector<std::size_t>>& MSS) {
95 return ctmc_multi(Q, MS, MSS, detail::courtois_default_rate(Q, MS));
96}
97
98} // namespace mc
99} // namespace line
100
101#endif // LINE_API_MC_CTMC_MULTI_H
InputError(const std::string &what)
Definition error.h:39
std::size_t cols() const
Definition matrix.h:90
std::size_t rows() const
Definition matrix.h:89
Courtois decomposition of a nearly completely decomposable (NCD) CTMC.
The exception types the port throws.
Dense matrix and non-owning view.
MultiResult< T > ctmc_multi(const Matrix< T > &Q, const std::vector< std::vector< std::size_t > > &MS, const std::vector< std::vector< std::size_t > > &MSS, const T &q)
Two-level multigrid aggregation-disaggregation for a nearly completely decomposable CTMC.
Definition ctmc_multi.h:61
CourtoisResult< T > ctmc_courtois(const Matrix< T > &Q, const std::vector< std::vector< std::size_t > > &MS, const T &q)
Courtois decomposition of a nearly completely decomposable (NCD) CTMC.
Number-type abstraction for the templated API port.
Matrix< T > Qperm
Q reordered by macro-state.
Definition ctmc_multi.h:46
std::vector< T > p
approximate stationary vector, ORIGINAL ordering
Definition ctmc_multi.h:44
std::vector< T > pcourt
the plain Courtois estimate, for comparison
Definition ctmc_multi.h:45
T eps
NCD index of the fine level.
Definition ctmc_multi.h:47
T epsMAX
maximum admissible NCD index of the fine level
Definition ctmc_multi.h:48