LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
map_count_var.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_COUNT_VAR_H
6#define LINE_API_MAM_MAP_COUNT_VAR_H
7
8/**
9 * @file
10 * @ingroup api_mam
11 * Variance of the counting process of a MAP at resolution t.
12 *
13 * Templated port of matlab/lib/kpctoolbox/map/map_count_var.m, cross-checked
14 * against jar/src/main/java/jline/api/mam/Map_count_var.java. With
15 * D = D0 + D1, theta the stationary phase vector, e the vector of ones and
16 * the deviation matrix tmp = (e theta - D)^-1,
17 *
18 * Var[N(t)] = (lambda - 2 lambda^2 + 2 theta D1 tmp D1 e) t
19 * - 2 theta D1 tmp (I - exp(D t)) tmp D1 e,
20 *
21 * from He and Neuts, "Markov chains with marked transitions" (1998).
22 *
23 * ARITHMETIC: the linear part is rational in the entries, the transient
24 * correction needs exp(D t), so the function requires transcendental
25 * arithmetic. The two terms have opposite signs and nearly cancel for small t,
26 * where Var -> lambda t; that cancellation is the reason the high-precision
27 * backends are useful here.
28 *
29 * map_varcount.m is the same quantity written with (e theta - D)^-2 in the
30 * middle instead of tmp on both sides. The two agree identically, because
31 * D (e theta) = (D e) theta = 0 and (e theta) D = e (theta D) = 0, so e theta
32 * and D commute and hence tmp commutes with exp(D t). Both spellings are
33 * ported (see map_varcount.h) and the tests assert their agreement.
34 */
35
36#include <cstddef>
37#include <vector>
38
40#include "line/num/number.h"
41#include "line/util/error.h"
42#include "line/util/expm.h"
43#include "line/util/linalg.h"
44#include "line/util/matrix.h"
45
46namespace line {
47namespace mam {
48
49namespace detail {
50
51/**
52 * Deviation matrix (e theta - D)^-1 of the phase process, MATLAB's tmp. Shared
53 * by every counting-process descriptor.
54 */
55template <class T>
56Matrix<T> map_count_deviation(const Matrix<T>& D, const std::vector<T>& theta) {
57 const std::size_t n = D.rows();
58 Matrix<T> A(n, n);
59 for (std::size_t i = 0; i < n; ++i)
60 for (std::size_t j = 0; j < n; ++j) A(i, j) = theta[j] - D(i, j);
61 return inverse(A);
62}
63
64} // namespace detail
65
66/**
67 * @brief Variance of the counting process of a MAP at resolution t.
68 *
69 * @param m the MAP (D0, D1)
70 * @param t window lengths
71 * @return Var[N(t)] for each window length, in the order of t
72 */
73template <class T>
74std::vector<T> map_count_var(const Map<T>& m, const std::vector<T>& t) {
76 "map_count_var requires transcendental arithmetic");
77 const std::size_t n = m.order();
78 const Matrix<T> D = map_infgen(m);
79 const std::vector<T> theta = map_prob(m);
80 const Matrix<T> tmp = detail::map_count_deviation(D, theta);
81 const std::vector<T> e = ones<T>(n);
82
83 const std::vector<T> thetaD1 = vecmul(theta, m.D1);
84 T lam = num_traits<T>::from_int(0);
85 for (const T& v : thetaD1) lam += v; // lambda = theta D1 e
86 const std::vector<T> c = vecmul(thetaD1, tmp); // theta D1 tmp
87 const std::vector<T> d = mulvec(tmp, mulvec(m.D1, e)); // tmp D1 e
88
89 const std::vector<T> cD1 = vecmul(c, m.D1);
90 T cD1e = num_traits<T>::from_int(0);
91 for (const T& v : cD1) cD1e += v;
92 const T two = num_traits<T>::from_int(2);
93 const T linear = lam - two * lam * lam + two * cD1e;
94
95 std::vector<T> out;
96 out.reserve(t.size());
97 for (std::size_t k = 0; k < t.size(); ++k) {
98 if (t[k] < num_traits<T>::from_int(0))
99 throw InputError("map_count_var: negative window length");
100 // c (I - exp(D t)) d
101 const Matrix<T> E = expm(D, t[k]);
102 const std::vector<T> cE = vecmul(c, E);
103 T corr = num_traits<T>::from_int(0);
104 for (std::size_t i = 0; i < n; ++i) corr += (c[i] - cE[i]) * d[i];
105 out.push_back(linear * t[k] - two * corr);
106 }
107 return out;
108}
109
110} // namespace mam
111} // namespace line
112
113#endif // LINE_API_MAM_MAP_COUNT_VAR_H
InputError(const std::string &what)
Definition error.h:39
The exception types the port throws.
Matrix exponential by scaling and squaring with a diagonal Pade approximant.
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...
Dense matrix and non-owning view.
Matrix< T > map_infgen(const Map< T > &m)
Generator of the underlying phase process, D0 + D1.
Definition map_moment.h:62
std::vector< T > map_count_var(const Map< T > &m, const std::vector< T > &t)
Variance of the counting process of a MAP at resolution t.
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::vector< T > vecmul(const std::vector< T > &v, const Matrix< T > &A)
Row vector times matrix, v A.
Definition linalg.h:50
Matrix< T > inverse(const Matrix< T > &A)
Inverse by LU with one factorization and n back substitutions.
Definition linalg.h:72
std::vector< T > mulvec(const Matrix< T > &A, const std::vector< T > &v)
Matrix times column vector, A v.
Definition linalg.h:62
std::vector< T > ones(std::size_t n)
Column vector of ones, the ubiquitous e in MAP algebra.
Definition linalg.h:104
Matrix< T > expm(const Matrix< T > &A)
Matrix exponential exp(A).
Definition expm.h:141
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
std::size_t order() const
Definition map_moment.h:57