LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
ctmc_accumulated.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_ACCUMULATED_H
6
#define LINE_API_MC_CTMC_ACCUMULATED_H
7
8
/**
9
* @file
10
* @ingroup api_mc
11
* Accumulated state probabilities L(t) = int_0^t pi(s) ds of a CTMC by
12
* uniformisation (Reibman and Trivedi 1989; Haverkort 1998, section 15.2.4).
13
*
14
* Templated port of matlab/src/api/mc/ctmc_accumulated.m, twin of
15
* jline.api.mc.Ctmc_accumulated and line_solver.api.mc.ctmc.ctmc_accumulated.
16
* With P = I + Q/q, q = 1.1 max|q_ii| and Poisson weights w_j at q h,
17
*
18
* int_0^h pi0 exp(Q s) ds = (1/q) sum_j (1 - W_j) pi0 P^j, W_j = sum_{i<=j} w_i
19
*
20
* so L(t) r is the expected reward accumulated over [0, t] for a rate reward
21
* r, and L(t) r / t its time average. Successive time points are marched
22
* interval by interval, so a grid costs one series per gap. The series is
23
* truncated at the first K whose Poisson tail 1 - W_K is below tol and whose
24
* neglected integral mass q h - sum_{j<=K}(1 - W_j) is below tol q h. An
25
* interval with q h > 500 is split into equal segments, as in
26
* ctmc_uniformization.h, and each segment end is rescaled to the mass of its
27
* start so the truncation loss does not compound across segments.
28
*
29
* The weights involve exp(-q h): no exact instantiation.
30
*/
31
32
#include <algorithm>
33
#include <cmath>
34
#include <cstddef>
35
#include <vector>
36
37
#include "
line/api/mc/ctmc_uniformization.h
"
38
#include "
line/num/number.h
"
39
#include "
line/util/error.h
"
40
#include "
line/util/matrix.h
"
41
42
namespace
line
{
43
namespace
mc
{
44
45
template
<
class
T>
46
struct
AccumulatedResult
{
47
Matrix<T>
L
;
///< row k is int_0^{t_k} pi(s) ds
48
Matrix<T>
piT
;
///< row k is pi(t_k)
49
std::size_t
kmax
;
///< largest number of Poisson terms used by any interval
50
};
51
52
namespace
detail {
53
54
template
<
class
T>
55
void
accumulate_interval(std::vector<T>& v,
const
Matrix<T>
& P,
const
T& q,
const
T& h,
double
tol,
56
long
maxiter, std::vector<T>& Lh, std::size_t& kmax) {
57
using
std::exp;
58
using
std::expm1;
59
const
std::size_t n = v.size();
60
const
T zero =
num_traits<T>::from_int
(0);
61
Lh.assign(n, zero);
62
kmax = 0;
63
if
(h == zero)
return
;
64
if
(q == zero) {
65
for
(std::size_t i = 0; i < n; ++i) Lh[i] = h * v[i];
66
return
;
67
}
68
const
T qt = q * h;
69
const
double
qtd =
num_traits<T>::to_double
(qt);
70
const
double
MAXQT = 500.0;
71
if
(qtd > MAXQT) {
72
const
long
nSeg =
static_cast<
long
>
(std::ceil(qtd / MAXQT));
73
const
T hs = h /
num_traits<T>::from_int
(nSeg);
74
std::vector<T> dL;
75
for
(
long
s = 0; s < nSeg; ++s) {
76
std::size_t K = 0;
77
accumulate_interval(v, P, q, hs, tol, maxiter, dL, K);
78
for
(std::size_t i = 0; i < n; ++i) Lh[i] += dL[i];
79
kmax = std::max(kmax, K);
80
}
81
return
;
82
}
83
if
(maxiter <= 0)
84
maxiter =
static_cast<
long
>
(std::max(100.0, std::ceil(qtd + 10.0 * std::sqrt(qtd) + 20.0)));
85
const
T tolT =
num_traits<T>::from_double
(tol);
86
87
// Truncation point.
88
T w = exp(-qt);
89
T tail = -expm1(-qt);
// 1 - W_0
90
T S = tail;
// sum_{j<=K} (1 - W_j)
91
long
K = 0;
92
while
(K < maxiter && !(tail <= tolT && T(qt - S) <= T(tolT * qt))) {
93
++K;
94
w = w * qt /
num_traits<T>::from_int
(K);
95
tail = tail - w;
96
if
(tail < zero) tail = zero;
97
S += tail;
98
}
99
kmax =
static_cast<
std::size_t
>
(K);
100
101
// Series.
102
w = exp(-qt);
103
tail = -expm1(-qt);
104
std::vector<T> Pk = v, vEnd(n), Lsum(n);
105
for
(std::size_t i = 0; i < n; ++i) {
106
vEnd[i] = w * Pk[i];
107
Lsum[i] = tail * Pk[i];
108
}
109
for
(
long
j = 1; j <= K; ++j) {
110
Pk = vecmat(Pk, P);
111
w = w * qt /
num_traits<T>::from_int
(j);
112
tail = tail - w;
113
if
(tail < zero) tail = zero;
114
for
(std::size_t i = 0; i < n; ++i) {
115
vEnd[i] += w * Pk[i];
116
Lsum[i] += tail * Pk[i];
117
}
118
}
119
T sv = zero, se = zero;
120
for
(std::size_t i = 0; i < n; ++i) {
121
sv += v[i];
122
se += vEnd[i];
123
}
124
if
(se != zero && sv != zero)
125
for
(T& e : vEnd) e = e * (sv / se);
126
for
(std::size_t i = 0; i < n; ++i) Lh[i] = Lsum[i] / q;
127
v = vEnd;
128
}
129
130
}
// namespace detail
131
132
/**
133
* @brief Accumulated state probabilities int_0^t pi(s) ds at each time point.
134
*
135
* @param pi0 initial distribution (row vector of length n)
136
* @param Q generator
137
* @param t nonempty, finite, nonnegative, nondecreasing time points
138
* @param tol truncation tolerance (MATLAB default 1e-12)
139
* @param maxiter Poisson term cap per interval, <= 0 for the MATLAB heuristic
140
*/
141
template
<
class
T>
142
AccumulatedResult<T>
ctmc_accumulated
(
const
std::vector<T>& pi0,
const
Matrix<T>
& Q,
const
std::vector<T>& t,
143
double
tol = 1e-12,
long
maxiter = -1) {
144
static_assert
(
num_traits<T>::has_transcendental
,
145
"ctmc_accumulated requires transcendental arithmetic: the Poisson weights involve "
146
"exp(-q t)"
);
147
const
std::size_t n = Q.
rows
();
148
if
(Q.
cols
() != n)
throw
InputError
(
"ctmc_accumulated: generator is not square"
);
149
if
(pi0.size() != n)
throw
InputError
(
"ctmc_accumulated: pi0 has the wrong length"
);
150
const
T zero =
num_traits<T>::from_int
(0);
151
if
(t.empty())
throw
InputError
(
"ctmc_accumulated: t must be nonempty"
);
152
for
(std::size_t k = 0; k < t.size(); ++k) {
153
const
double
tk =
num_traits<T>::to_double
(t[k]);
154
if
(!std::isfinite(tk) || t[k] < zero || (k > 0 && t[k] < t[k - 1]))
155
throw
InputError
(
"ctmc_accumulated: t must hold finite, nonnegative, nondecreasing time points"
);
156
}
157
const
T q = detail::uniformization_rate(Q);
158
const
Matrix<T>
P = (q == zero) ?
Matrix<T>
(n, n) : detail::uniformized_matrix(Q, q);
159
160
AccumulatedResult<T>
res{
Matrix<T>
(t.size(), n),
Matrix<T>
(t.size(), n), 0};
161
std::vector<T> v = pi0, acc(n, zero), dL;
162
T tprev = zero;
163
for
(std::size_t k = 0; k < t.size(); ++k) {
164
std::size_t K = 0;
165
detail::accumulate_interval(v, P, q, T(t[k] - tprev), tol, maxiter, dL, K);
166
res.
kmax
= std::max(res.
kmax
, K);
167
for
(std::size_t i = 0; i < n; ++i) {
168
acc[i] += dL[i];
169
res.
L
(k, i) = acc[i];
170
res.
piT
(k, i) = v[i];
171
}
172
tprev = t[k];
173
}
174
return
res;
175
}
176
177
/** Single time point overload. */
178
template
<
class
T>
179
AccumulatedResult<T>
ctmc_accumulated
(
const
std::vector<T>& pi0,
const
Matrix<T>
& Q,
const
T& t,
180
double
tol = 1e-12,
long
maxiter = -1) {
181
return
ctmc_accumulated
(pi0, Q, std::vector<T>{t}, tol, maxiter);
182
}
183
184
}
// namespace mc
185
}
// namespace line
186
187
#endif
// LINE_API_MC_CTMC_ACCUMULATED_H
line::InputError::InputError
InputError(const std::string &what)
Definition
error.h:105
line::Matrix
Definition
matrix.h:56
line::Matrix::cols
std::size_t cols() const
Definition
matrix.h:90
line::Matrix::Matrix
Matrix()
Definition
matrix.h:58
line::Matrix::rows
std::size_t rows() const
Definition
matrix.h:89
ctmc_uniformization.h
Transient distribution of a CTMC by uniformization (Jensen's method), and the time-averaged distribut...
error.h
The exception types the port throws.
matrix.h
Dense matrix and non-owning view.
line::mc
Definition
ctmc_accumulated.h:43
line::mc::ctmc_accumulated
AccumulatedResult< T > ctmc_accumulated(const std::vector< T > &pi0, const Matrix< T > &Q, const std::vector< T > &t, double tol=1e-12, long maxiter=-1)
Accumulated state probabilities int_0^t pi(s) ds at each time point.
Definition
ctmc_accumulated.h:142
line
Conservation laws of a layered queueing network, enumerated from its structure.
Definition
aoi_dist2ph.h:52
number.h
Number-type abstraction for the templated API port.
line::mc::AccumulatedResult
Definition
ctmc_accumulated.h:46
line::mc::AccumulatedResult::L
Matrix< T > L
row k is int_0^{t_k} pi(s) ds
Definition
ctmc_accumulated.h:47
line::mc::AccumulatedResult::piT
Matrix< T > piT
row k is pi(t_k)
Definition
ctmc_accumulated.h:48
line::mc::AccumulatedResult::kmax
std::size_t kmax
largest number of Poisson terms used by any interval
Definition
ctmc_accumulated.h:49
line::num_traits
Definition
number.h:123
include
line
api
mc
ctmc_accumulated.h
Generated by
1.18.0