LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
map_algebra.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_MAM_MAP_ALGEBRA_H
6#define LINE_API_MAM_MAP_ALGEBRA_H
7
8/**
9 * @file
10 * @ingroup api_mam
11 * MAP algebra missing from the moment and transform headers: time reversal, the
12 * Kronecker product composition, the subdominant eigenvalue of the embedded
13 * chain and the large-order threshold.
14 *
15 * Templated port of matlab/lib/kpctoolbox/map/map_timereverse.m, map_kpc.m,
16 * map_gamma2.m and map_largemap.m.
17 *
18 * map_kpc composes two MAPs into one of order na*nb whose autocorrelation
19 * decays with the PRODUCT of the two decay rates; note the sign, D0 of the
20 * composition is MINUS the Kronecker product of the two D0 blocks, because
21 * kron of two matrices with negative diagonals has a positive one.
22 *
23 * map_gamma2 is the second largest eigenvalue in modulus of the embedded
24 * chain, which is the geometric decay rate of the autocorrelation of a
25 * second-order MAP and its leading term in general. It is genuinely COMPLEX for
26 * a MAP with oscillating correlation, so it is returned as such rather than as
27 * its modulus.
28 */
29
30#include <algorithm>
31#include <complex>
32#include <cstddef>
33#include <vector>
34
38#include "line/num/number.h"
39#include "line/util/eig.h"
40#include "line/util/error.h"
41#include "line/util/linalg.h"
42#include "line/util/matrix.h"
43
44namespace line {
45namespace mam {
46
47/** Order above which a MAP counts as large for the fitting heuristics. */
48inline std::size_t map_largemap() { return 100; }
49
50/** Time-reversed MAP, diag(pi)^-1 M' diag(pi) applied to D0 and D1. */
51template <class T>
53 const std::size_t n = m.D0.rows();
54 const std::vector<T> piq = map_prob(m);
55 Map<T> out;
56 out.D0 = Matrix<T>(n, n, num_traits<T>::from_int(0));
57 out.D1 = Matrix<T>(n, n, num_traits<T>::from_int(0));
58 for (std::size_t i = 0; i < n; ++i)
59 for (std::size_t j = 0; j < n; ++j) {
60 out.D0(i, j) = m.D0(j, i) * piq[j] / piq[i];
61 out.D1(i, j) = m.D1(j, i) * piq[j] / piq[i];
62 }
63 return out;
64}
65
66/** Kronecker product composition of two MAPs. */
67template <class T>
68Map<T> map_kpc(const Map<T>& a, const Map<T>& b) {
69 Matrix<T> D0 = kron(a.D0, b.D0);
70 for (std::size_t i = 0; i < D0.rows(); ++i)
71 for (std::size_t j = 0; j < D0.cols(); ++j) D0(i, j) = -D0(i, j);
72 return Map<T>{D0, kron(a.D1, b.D1)};
73}
74
75/** Left-folded composition of a whole list of MAPs. */
76template <class T>
77Map<T> map_kpc(const std::vector<Map<T>>& maps) {
78 if (maps.size() < 2) throw InputError("map_kpc: at least two MAPs are required");
79 Map<T> out = map_kpc(maps[0], maps[1]);
80 for (std::size_t k = 2; k < maps.size(); ++k) out = map_kpc(out, maps[k]);
81 return out;
82}
83
84/** Subdominant eigenvalue of the embedded chain, the leading ACF decay rate. */
85inline std::complex<double> map_gamma2(const Map<double>& m) {
86 const Matrix<double> P = map_embedded(m);
87 std::vector<std::complex<double>> ev = eig_values(P);
88 if (ev.size() < 2) throw InputError("map_gamma2: the MAP must have order at least 2");
89 std::sort(ev.begin(), ev.end(),
90 [](const std::complex<double>& x, const std::complex<double>& y) {
91 return std::abs(x) > std::abs(y);
92 });
93 return ev[1];
94}
95
96} // namespace mam
97} // namespace line
98
99#endif
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
Eigenvalues and singular values, backed by LAPACK.
The exception types the port throws.
Dense linear algebra over the templated number type: products, identity, inverse, and powers.
Markovian arrival process descriptors: stationary vectors, rate, moments, autocorrelation and the ind...
MAP constructors and structural transformations.
Dense matrix and non-owning view.
Marked MAP (MMAP) algebra: per-class rates, class probabilities, superposition, normalization and sca...
Map< T > map_timereverse(const Map< T > &m)
Time-reversed MAP, diag(pi)^-1 M' diag(pi) applied to D0 and D1.
Definition map_algebra.h:52
std::complex< double > map_gamma2(const Map< double > &m)
Subdominant eigenvalue of the embedded chain, the leading ACF decay rate.
Definition map_algebra.h:85
Matrix< T > kron(const Matrix< T > &A, const Matrix< T > &B)
Kronecker product.
Definition mmap_lambda.h:57
std::vector< T > map_prob(const Map< T > &m)
Stationary distribution of the phase process, pi (D0 + D1) = 0.
Definition map_moment.h:73
std::size_t map_largemap()
Order above which a MAP counts as large for the fitting heuristics.
Definition map_algebra.h:48
Map< T > map_kpc(const Map< T > &a, const Map< T > &b)
Kronecker product composition of two MAPs.
Definition map_algebra.h:68
Matrix< T > map_embedded(const Map< T > &m)
Embedded DTMC at arrival epochs, P = (-D0)^-1 D1.
Definition map_moment.h:109
std::vector< std::complex< double > > eig_values(const Matrix< double > &A)
Eigenvalues of a general real square matrix, in LAPACK's order.
Definition eig.h:59
Number-type abstraction for the templated API port.
A MAP as the pair of matrices (D0, D1).
Definition map_moment.h:53
Matrix< T > D1
Definition map_moment.h:55
Matrix< T > D0
Definition map_moment.h:54