LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
dtmc_transient.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_DTMC_TRANSIENT_H
6
#define LINE_API_MC_DTMC_TRANSIENT_H
7
8
/**
9
* @file
10
* @ingroup api_mc
11
* Discrete-time transient distributions, hitting times and uniformization.
12
*
13
* Templated port of matlab/src/api/mc/dtmc_transient.m,
14
* matlab/src/api/mc/dtmc_hitting_time.m and
15
* matlab/lib/kpctoolbox/mc/dtmc_uniformization.m.
16
*
17
* dtmc_transient returns the WHOLE trajectory, steps+1 rows with row 0 the
18
* initial law, not just the distribution at the last step.
19
*
20
* dtmc_hitting_time solves (I - P_TT) h = 1 on the non-target states only. A
21
* state that cannot reach the target set makes that system singular, and the
22
* right answer there is an INFINITE hitting time, not the least-squares
23
* solution of the singular system: the code detects the singularity and reports
24
* infinity for the unreachable block rather than a finite fabricated number.
25
*/
26
27
#include <cmath>
28
#include <cstddef>
29
#include <limits>
30
#include <set>
31
#include <vector>
32
33
#include "
line/api/mc/ctmc_solve.h
"
34
#include "
line/api/mc/ctmc_uniformization.h
"
35
#include "
line/num/number.h
"
36
#include "
line/util/error.h
"
37
#include "
line/util/lu.h
"
38
#include "
line/util/matrix.h
"
39
40
namespace
line
{
41
namespace
mc
{
42
43
/** Trajectory of the law over steps transitions, row k holding pi0 P^k. */
44
template
<
class
T>
45
Matrix<T>
dtmc_transient
(
const
Matrix<T>
& P,
const
std::vector<T>& pi0, std::size_t steps) {
46
const
std::size_t n = P.
rows
();
47
if
(P.
cols
() != n)
throw
InputError
(
"dtmc_transient: P is not square"
);
48
std::vector<T> pik = pi0;
49
if
(pik.empty())
50
pik.assign(n,
num_traits<T>::from_int
(1) /
num_traits<T>::from_int
(
static_cast<
int
>
(n)));
51
if
(pik.size() != n)
throw
InputError
(
"dtmc_transient: pi0 has the wrong length"
);
52
Matrix<T>
out(steps + 1, n,
num_traits<T>::from_int
(0));
53
for
(std::size_t j = 0; j < n; ++j) out(0, j) = pik[j];
54
for
(std::size_t k = 1; k <= steps; ++k) {
55
std::vector<T> next(n,
num_traits<T>::from_int
(0));
56
for
(std::size_t i = 0; i < n; ++i)
57
for
(std::size_t j = 0; j < n; ++j) next[j] += pik[i] * P(i, j);
58
pik = next;
59
for
(std::size_t j = 0; j < n; ++j) out(k, j) = pik[j];
60
}
61
return
out;
62
}
63
64
/** Uniform initial law and one step, matching the one-argument MATLAB call. */
65
template
<
class
T>
66
Matrix<T>
dtmc_transient
(
const
Matrix<T>
& P) {
67
return
dtmc_transient
(P, std::vector<T>(), 1);
68
}
69
70
/** Expected number of steps to reach the target set, zero on the target set itself. */
71
template
<
class
T>
72
std::vector<T>
dtmc_hitting_time
(
const
Matrix<T>
& P,
const
std::vector<std::size_t>& target) {
73
static_assert
(
num_traits<T>::has_transcendental
,
74
"dtmc_hitting_time requires a backend with an infinity, since a state that "
75
"cannot reach the target set has an infinite hitting time"
);
76
const
std::size_t n = P.
rows
();
77
if
(P.
cols
() != n)
throw
InputError
(
"dtmc_hitting_time: P is not square"
);
78
std::vector<bool> is_target(n,
false
);
79
for
(std::size_t k = 0; k < target.size(); ++k) {
80
if
(target[k] >= n)
throw
InputError
(
"dtmc_hitting_time: target index out of range"
);
81
is_target[target[k]] =
true
;
82
}
83
std::vector<std::size_t> nt;
84
for
(std::size_t i = 0; i < n; ++i)
85
if
(!is_target[i]) nt.push_back(i);
86
std::vector<T> h(n,
num_traits<T>::from_int
(0));
87
if
(nt.empty())
return
h;
88
const
std::size_t m = nt.size();
89
Matrix<T>
A(m, m,
num_traits<T>::from_int
(0));
90
for
(std::size_t a = 0; a < m; ++a)
91
for
(std::size_t b = 0; b < m; ++b)
92
A(a, b) = (a == b ?
num_traits<T>::from_int
(1) :
num_traits<T>::from_int
(0)) -
93
P(nt[a], nt[b]);
94
std::vector<T> b(m,
num_traits<T>::from_int
(1));
95
// A state from which the target set is unreachable makes I - P_TT singular
96
// there, and its hitting time is infinite rather than any finite solution.
97
std::vector<bool> reaches(m,
false
);
98
bool
changed =
true
;
99
while
(changed) {
100
changed =
false
;
101
for
(std::size_t a = 0; a < m; ++a) {
102
if
(reaches[a])
continue
;
103
for
(std::size_t j = 0; j < n; ++j) {
104
if
(P(nt[a], j) ==
num_traits<T>::from_int
(0))
continue
;
105
bool
ok = is_target[j];
106
if
(!ok)
107
for
(std::size_t c = 0; c < m; ++c)
108
if
(nt[c] == j && reaches[c]) ok =
true
;
109
if
(ok) {
110
reaches[a] =
true
;
111
changed =
true
;
112
break
;
113
}
114
}
115
}
116
}
117
std::vector<std::size_t> keep;
118
for
(std::size_t a = 0; a < m; ++a) {
119
if
(reaches[a])
120
keep.push_back(a);
121
else
122
h[nt[a]] =
num_traits<T>::from_double
(std::numeric_limits<double>::infinity());
123
}
124
if
(keep.empty())
return
h;
125
Matrix<T>
Ak(keep.size(), keep.size(),
num_traits<T>::from_int
(0));
126
std::vector<T> bk(keep.size(),
num_traits<T>::from_int
(1));
127
for
(std::size_t a = 0; a < keep.size(); ++a)
128
for
(std::size_t c = 0; c < keep.size(); ++c) Ak(a, c) = A(keep[a], keep[c]);
129
const
std::vector<T> hk =
solve
(Ak, bk);
130
for
(std::size_t a = 0; a < keep.size(); ++a) h[nt[keep[a]]] = hk[a];
131
return
h;
132
}
133
134
/** Transient law of a DTMC through the uniformized generator of P. */
135
template
<
class
T>
136
UniformizationResult<T>
dtmc_uniformization
(
const
std::vector<T>& pi0,
const
Matrix<T>
& P,
137
const
T& t,
double
tol = 1e-12,
long
maxiter = -1) {
138
return
ctmc_uniformization
(pi0,
ctmc_makeinfgen
(P), t, tol, maxiter);
139
}
140
141
}
// namespace mc
142
}
// namespace line
143
144
#endif
line::InputError::InputError
InputError(const std::string &what)
Definition
error.h:39
line::Matrix
Definition
matrix.h:56
line::Matrix::cols
std::size_t cols() const
Definition
matrix.h:90
line::Matrix::rows
std::size_t rows() const
Definition
matrix.h:89
ctmc_solve.h
Steady-state distribution of a continuous-time Markov chain.
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.
lu.h
LU factorization with partial pivoting, templated on the number type.
matrix.h
Dense matrix and non-owning view.
line::mc
Definition
ctmc_bicgstab.h:59
line::mc::ctmc_makeinfgen
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
line::mc::ctmc_uniformization
UniformizationResult< T > ctmc_uniformization(const std::vector< T > &pi0, const Matrix< T > &Q, const T &t, double tol=1e-12, long maxiter=-1)
Transient distribution of a CTMC by uniformization (Jensen's method), and the time-averaged distribut...
Definition
ctmc_uniformization.h:124
line::mc::dtmc_hitting_time
std::vector< T > dtmc_hitting_time(const Matrix< T > &P, const std::vector< std::size_t > &target)
Expected number of steps to reach the target set, zero on the target set itself.
Definition
dtmc_transient.h:72
line::mc::dtmc_uniformization
UniformizationResult< T > dtmc_uniformization(const std::vector< T > &pi0, const Matrix< T > &P, const T &t, double tol=1e-12, long maxiter=-1)
Transient law of a DTMC through the uniformized generator of P.
Definition
dtmc_transient.h:136
line::mc::dtmc_transient
Matrix< T > dtmc_transient(const Matrix< T > &P, const std::vector< T > &pi0, std::size_t steps)
Trajectory of the law over steps transitions, row k holding pi0 P^k.
Definition
dtmc_transient.h:45
line
Definition
aoi_dist2ph.h:52
line::solve
std::vector< T > solve(const Matrix< T > &A, const std::vector< T > &b)
Convenience: solve Ax = b, leaving A and b untouched.
Definition
lu.h:158
number.h
Number-type abstraction for the templated API port.
line::mc::UniformizationResult
Definition
ctmc_uniformization.h:45
line::num_traits
Definition
number.h:111
include
line
api
mc
dtmc_transient.h
Generated by
1.18.0