5#ifndef LINE_API_MAM_QBD_DEPPROC_H
6#define LINE_API_MAM_QBD_DEPPROC_H
88namespace depproc_detail {
92void put_block(Matrix<T>& dest, std::size_t br, std::size_t bc,
const Matrix<T>& src) {
93 const std::size_t r0 = br * src.rows(), c0 = bc * src.cols();
94 if (r0 + src.rows() > dest.rows() || c0 + src.cols() > dest.cols())
95 throw InputError(
"qbd_depproc: block write out of range");
96 for (std::size_t i = 0; i < src.rows(); ++i)
97 for (std::size_t j = 0; j < src.cols(); ++j) dest(r0 + i, c0 + j) = src(i, j);
102void add_block(Matrix<T>& dest, std::size_t br, std::size_t bc,
const Matrix<T>& src) {
103 const std::size_t r0 = br * src.rows(), c0 = bc * src.cols();
104 if (r0 + src.rows() > dest.rows() || c0 + src.cols() > dest.cols())
105 throw InputError(
"qbd_depproc: block write out of range");
106 for (std::size_t i = 0; i < src.rows(); ++i)
107 for (std::size_t j = 0; j < src.cols(); ++j) dest(r0 + i, c0 + j) += src(i, j);
113 Matrix<T> F, L, B, L0;
122EtaqaPieces<T> etaqa_pieces(
const Map<T>& arrival,
const Map<T>& service) {
123 using namespace qbd_detail;
130 p.lvlsz = blk.L.
rows();
131 const QbdFundMat<T> fm =
qbd_fundmat(p.B, p.L, p.F);
134 p.G =
matmul(
inverse(msub(mscale(p.L, T(num_traits<T>::from_int(-1))),
matmul(p.R, p.B))), p.B);
135 p.Lhat = madd(p.F, p.L);
136 p.Bbar = madd(p.B,
matmul(p.F, p.G));
137 p.Bhat =
matmul(p.F, p.G);
155 "qbd_depproc_etaqa requires transcendental arithmetic");
156 if (n < 2)
throw InputError(
"qbd_depproc_etaqa: the truncation level must be at least 2");
157 using namespace depproc_detail;
158 const EtaqaPieces<T> p = etaqa_pieces(arrival, service);
159 const std::size_t m = p.lvlsz;
160 const std::size_t dim = (n + 1) * m;
166 for (std::size_t r = 1; r <= n; ++r) put_block(D0, r, r, p.L);
167 for (std::size_t r = 1; r + 1 <= n; ++r) put_block(D0, r, r + 1, p.F);
169 put_block(D0, 0, 0, p.L0);
170 put_block(D0, 0, 1, p.F);
172 put_block(D0, n - 1, n - 1, p.Lhat);
175 put_block(D1, n, n - 1, p.Bbar);
176 put_block(D1, n, n, p.Bhat);
179 for (std::size_t r = 1; r + 1 <= n; ++r) put_block(D1, r, r - 1, p.B);
198 "qbd_depproc_etaqa_ps requires transcendental arithmetic");
199 if (n < 2)
throw InputError(
"qbd_depproc_etaqa_ps: the truncation level must be at least 2");
200 using namespace depproc_detail;
201 using namespace qbd_detail;
202 const EtaqaPieces<T> p = etaqa_pieces(arrival, service);
203 const std::size_t m = p.lvlsz;
204 const std::size_t dim = (n + 1) * m;
210 for (std::size_t r = 1; r <= n; ++r) put_block(D0, r, r, p.L);
211 for (std::size_t r = 1; r + 1 <= n; ++r) put_block(D0, r, r + 1, p.F);
212 put_block(D0, 0, 0, p.L0);
213 put_block(D0, 0, 1, p.F);
214 put_block(D0, n - 1, n - 1, p.Lhat);
216 add_block(D0, n, n - 1, p.Bbar);
217 add_block(D0, n, n, mscale(p.Bhat, T((nT - one) / nT)));
220 put_block(D1, n, n - 1, p.Bbar);
221 put_block(D1, n, n, mscale(p.Bhat, T(one / nT)));
223 for (std::size_t j = 1; j + 1 <= n; ++j) {
225 put_block(D0, j, j - 1, mscale(p.B, T(one - one / jT)));
226 put_block(D1, j, j - 1, mscale(p.B, T(one / jT)));
241 const std::size_t n = m.
D0.rows();
243 for (std::size_t i = 0; i < n; ++i) {
245 for (std::size_t j = 0; j < m.
D0.cols(); ++j) s += m.
D0(i, j) + m.
D1(i, j);
247 if (a > worst) worst = a;
274 const std::vector<std::pair<unsigned, unsigned>>& iset) {
276 "qbd_depproc_jointmom requires transcendental arithmetic");
277 using namespace depproc_detail;
278 using namespace qbd_detail;
279 const EtaqaPieces<T> p = etaqa_pieces(arrival, service);
280 const std::size_t m = p.lvlsz;
284 std::vector<T> v0(m);
285 for (std::size_t j = 0; j < m; ++j) v0[j] = pi(0, j);
288 if (lambdaS == zero)
throw NumericError(
"qbd_depproc_jointmom: zero service rate");
291 const std::vector<T> v0R =
vecmul(v0, p.R);
292 const std::vector<T> v0R2 =
vecmul(v0R, p.R);
293 const std::vector<T> v0R3 =
vecmul(v0R2, p.R);
298 const std::vector<T> v0D =
vecmul(v0R, p.B);
299 const std::vector<T> v1D =
vecmul(v0R2, p.B);
300 const std::vector<T> v2Dp =
vecmul(
vecmul(v0R3, ImRinv), p.B);
302 std::vector<T> z(3 * m);
303 for (std::size_t j = 0; j < m; ++j) {
305 z[m + j] = inv * v1D[j];
306 z[2 * m + j] = inv * v2Dp[j];
309 for (
const T& v : z) zs += v;
310 if (zs == zero)
throw NumericError(
"qbd_depproc_jointmom: degenerate initial vector");
311 for (T& v : z) v /= zs;
313 Matrix<T> M0(3 * m, 3 * m, zero), M1(3 * m, 3 * m, zero);
314 put_block(M0, 0, 0, p.L0);
315 put_block(M0, 0, 1, p.F);
316 put_block(M0, 1, 1, p.L);
317 put_block(M0, 1, 2, p.F);
318 put_block(M0, 2, 2, p.Lhat);
319 put_block(M1, 1, 0, p.B);
320 put_block(M1, 2, 1, p.B);
323 const std::vector<T> e =
ones<T>(3 * m);
326 out.reserve(iset.size());
327 for (std::size_t k = 0; k < iset.size(); ++k) {
328 const unsigned i = iset[k].first, j = iset[k].second;
329 std::vector<T> row =
vecmul(z,
matpow(negM0inv, i + 1));
335 for (std::size_t q = 0; q < row.size(); ++q) s += row[q] * e[q];
NumericError(const std::string &what)
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...
Dense matrix and non-owning view.
Marked MAP (MMAP) algebra: per-class rates, class probabilities, superposition, normalization and sca...
QbdMapMap1Blocks< T > qbd_mapmap1_blocks(const Map< T > &arrival, const Map< T > &service)
Level blocks of the MAP/MAP/1 QBD from the arrival and service MAPs.
T qbd_depproc_residual(const Map< T > &m)
||(D0 + D1) e||_inf, zero for a genuine MAP.
Map< T > qbd_depproc_etaqa(const Map< T > &arrival, const Map< T > &service, std::size_t n)
MAP descriptor of the departure process of a MAP/MAP/1-FCFS queue, ETAQA-truncated at level n (qbd_de...
Map< T > qbd_depproc_etaqa_ps(const Map< T > &arrival, const Map< T > &service, std::size_t n)
MAP descriptor of the departure process of a MAP/MAP/1-PS queue, ETAQA-truncated at level n (qbd_depp...
QbdFundMat< T > qbd_fundmat(const Matrix< T > &B, const Matrix< T > &L, const Matrix< T > &F, unsigned iter_max, const T &tol)
G and R by cyclic reduction (qbd_fundmat.m, the Bini-Meini logarithmic reduction on the raw level blo...
Matrix< T > qbd_pi(const Matrix< T > &B, const Matrix< T > &Lbar, const Matrix< T > &R, std::size_t max_levels, const T &mass_tol)
Stationary distribution of a QBD given R (QBD_pi.m, continuous-time branch, default boundary).
T map_lambda(const Map< T > &m)
Stationary arrival rate, lambda = pi D1 e.
std::vector< T > qbd_depproc_jointmom(const Map< T > &arrival, const Map< T > &service, const std::vector< std::pair< unsigned, unsigned > > &iset)
Joint moments E[X_0^i X_1^j] of consecutive inter-departure times of a MAP/MAP/1-FCFS queue (qbd_depp...
T num_factorial(unsigned n)
Factorial as a value of T.
std::vector< T > vecmul(const std::vector< T > &v, const Matrix< T > &A)
Row vector times matrix, v A.
Matrix< T > inverse(const Matrix< T > &A)
Inverse by LU with one factorization and n back substitutions.
Matrix< T > matmul(const Matrix< T > &A, const Matrix< T > &B)
Matrix product A B.
Matrix< T > matpow(const Matrix< T > &A, unsigned k)
Integer matrix power, by repeated squaring.
std::vector< T > ones(std::size_t n)
Column vector of ones, the ubiquitous e in MAP algebra.
Matrix< T > eye(std::size_t n)
Identity of order n.
Number-type abstraction for the templated API port.
The MAP/MAP/1 queue solved as a quasi-birth-death process.
Quasi-birth-death processes: the rate matrix R, the fundamental matrix G, the caudal characteristic,...
A MAP as the pair of matrices (D0, D1).