5#ifndef LINE_API_MAM_DTIME_H
6#define LINE_API_MAM_DTIME_H
64using DBatch = std::vector<Matrix<T>>;
72 for (std::size_t i = 0; i < A.
rows(); ++i)
73 for (std::size_t j = 0; j < A.
cols(); ++j) {
75 for (std::size_t k = 0; k < B.
rows(); ++k)
76 for (std::size_t l = 0; l < B.
cols(); ++l)
77 C(i * B.
rows() + k, j * B.
cols() + l) = a * B(k, l);
92 for (std::size_t i = 0; i < A.
rows(); ++i)
93 for (std::size_t j = 0; j < A.
cols(); ++j) C(i, j) = C(i, j) + B(i, j);
100 for (std::size_t i = 0; i < A.
rows(); ++i)
101 for (std::size_t j = 0; j < A.
cols(); ++j) C(i, j) = C(i, j) - B(i, j);
108 for (std::size_t i = 0; i < A.
rows(); ++i)
109 for (std::size_t k = 0; k < A.
cols(); ++k) {
110 const T& a = A(i, k);
111 for (std::size_t j = 0; j < B.
cols(); ++j) C(i, j) = C(i, j) + a * B(k, j);
119 std::size_t n = M.
rows();
121 for (std::size_t i = 0; i < n; ++i)
122 for (std::size_t j = 0; j < n; ++j) Mt(i, j) = M(j, i);
124 for (std::size_t r = 0; r < N.
rows(); ++r) {
125 std::vector<T> rhs(n);
126 for (std::size_t j = 0; j < n; ++j) rhs[j] = N(r, j);
127 std::vector<T> sol =
solve(Mt, rhs);
128 for (std::size_t j = 0; j < n; ++j) X(r, j) = sol[j];
136 std::size_t n = M.
rows();
138 for (std::size_t c = 0; c < N.
cols(); ++c) {
139 std::vector<T> rhs(n);
140 for (std::size_t i = 0; i < n; ++i) rhs[i] = N(i, c);
141 std::vector<T> sol =
solve(M, rhs);
142 for (std::size_t i = 0; i < n; ++i) X(i, c) = sol[i];
160 const double tol = 1e-8;
163 T p = one / mean_slots;
165 throw InputError(
"dph_from_dist: Geometric mean is outside the support {1,2,...}");
168 d.
alpha.assign(1, one);
175 long k =
static_cast<long>(m + 0.5);
176 if (std::abs(m -
static_cast<double>(k)) > tol * std::max(1.0, m) || k < 1)
177 throw InputError(
"dph_from_dist: Det is not a positive integral number of slots");
178 std::size_t n =
static_cast<std::size_t
>(k);
180 d.
alpha.assign(n, zero);
183 for (std::size_t i = 0; i + 1 < n; ++i) d.
A(i, i + 1) = one;
190 double width = std::sqrt(std::max(0.0, 12 * v + 1)) - 1;
191 long lo =
static_cast<long>(m - width / 2 + 0.5);
192 long hi =
static_cast<long>(m + width / 2 + 0.5);
193 if (lo < 1 || hi < lo)
194 throw InputError(
"dph_from_dist: DiscreteUniform is outside the support {1,2,...}");
195 std::size_t n =
static_cast<std::size_t
>(hi);
197 d.
alpha.assign(n, zero);
200 for (
long j = 1; j < hi; ++j) {
203 d.
A(
static_cast<std::size_t
>(j - 1),
static_cast<std::size_t
>(j)) = one - h;
209 "dph_from_dist: the process type has no exact discrete phase-type representation. "
210 "The discrete-time path accepts Geometric, Det on the slot lattice, DiscreteUniform "
218 std::size_t m = d.
A.rows();
222 for (std::size_t i = 0; i < m; ++i) {
224 for (std::size_t j = 0; j < m; ++j) rowsum = rowsum + d.
A(i, j);
226 for (std::size_t j = 0; j < m; ++j) out.
D1(i, j) = a * d.
alpha[j];
234 std::size_t m = d.
D0.rows();
235 if (m == 1)
return true;
237 std::size_t pivot = 0;
238 for (std::size_t i = 0; i < m; ++i) {
239 for (std::size_t j = 0; j < m; ++j) row_mass[i] = row_mass[i] + d.
D1(i, j);
244 for (std::size_t i = 0; i < m; ++i)
245 for (std::size_t j = 0; j < m; ++j) {
246 T expected = row_mass[i] * d.
D1(pivot, j) / row_mass[pivot];
256 throw InputError(
"dmap_to_dph: the D-MAP does not renew at events, so it has no DPH form");
257 std::size_t m = d.
D0.rows();
259 std::size_t pivot = 0;
260 for (std::size_t i = 0; i < m; ++i) {
261 for (std::size_t j = 0; j < m; ++j) row_mass[i] = row_mass[i] + d.
D1(i, j);
268 for (std::size_t j = 0; j < m; ++j) out.
alpha[j] = d.
D1(pivot, j) / row_mass[pivot];
278 std::size_t m = A[0].rows();
280 for (std::size_t k = 0; k < A.size(); ++k) P = detail::dt_add(P, A[k]);
283 for (std::size_t k = 1; k < A.size(); ++k)
284 for (std::size_t i = 0; i < m; ++i)
285 for (std::size_t j = 0; j < m; ++j)
301 std::size_t p = A.size() - 1, q = B.size() - 1;
303 E.reserve(p + q + 1);
304 for (std::size_t k = 0; k <= p + q; ++k) {
305 Matrix<T> Ek(A[0].rows() * B[0].rows(), A[0].cols() * B[0].cols(),
307 std::size_t lo = k > q ? k - q : 0;
308 for (std::size_t i = lo; i <= (k < p ? k : p); ++i)
309 Ek = detail::dt_add(Ek, detail::dt_kron(A[i], B[k - i]));
322 if (pd < 0 || pd > 1)
throw InputError(
"dmap_thin: the routing probability must lie in [0,1]");
324 std::size_t n = A.size() - 1;
327 for (std::size_t k = 0; k <= n; ++k) {
329 for (std::size_t j = k; j <= n; ++j) {
331 for (std::size_t i = 0; i < k; ++i)
334 for (std::size_t i = 0; i < k; ++i) w = w * p;
335 for (std::size_t i = 0; i < j - k; ++i) w = w * (one - p);
337 for (std::size_t r = 0; r < Bk.rows(); ++r)
338 for (std::size_t c = 0; c < Bk.cols(); ++c)
339 Bk(r, c) = Bk(r, c) + w * A[j](r, c);
344 while (B.size() > 2) {
346 for (std::size_t r = 0; r < B.back().rows(); ++r)
347 for (std::size_t c = 0; c < B.back().cols(); ++c)
349 if (worst >= 1e-14)
break;
362inline void dph2_moments(
double b,
double p1,
double p2,
double* m1,
double* m2,
double* m3) {
363 const double A1 = 1 / p1, A2 = 1 / p2;
364 const double S1 = (2 - p1) / (p1 * p1), S2 = (2 - p2) / (p2 * p2);
365 const double C1 = (p1 * p1 - 6 * p1 + 6) / (p1 * p1 * p1);
366 const double C2 = (p2 * p2 - 6 * p2 + 6) / (p2 * p2 * p2);
368 *m2 = b * (S1 + 2 * A1 * A2) + S2;
369 *m3 = b * (C1 + 3 * S1 * A2 + 3 * A1 * S2) + C2;
377inline bool dph2_from_3moments(
double m1,
double m2,
double m3,
double* b_out,
double* p1_out,
379 const double starts[4][2] = {{0.5, 0.5}, {0.9, 1 / std::max(1.0, m1)}, {0.2, 0.8}, {0.99, 0.3}};
380 for (
int s = 0; s < 4; ++s) {
381 double p1 = starts[s][0], p2 = starts[s][1];
382 for (
int it = 0; it < 200; ++it) {
383 const double b = (m1 - 1 / p2) * p1;
385 dph2_moments(b, p1, p2, &f1, &f2, &f3);
386 const double r2 = f2 - m2, r3 = f3 - m3;
387 if (std::abs(r2) <= 1e-11 * std::max(1.0, std::abs(m2)) &&
388 std::abs(r3) <= 1e-11 * std::max(1.0, std::abs(m3))) {
389 if (b < -1e-9 || b > 1 + 1e-9 || p1 <= 0 || p1 > 1 || p2 <= 0 || p2 > 1)
break;
390 *b_out = std::min(1.0, std::max(0.0, b));
395 const double h = 1e-7;
396 double a2, a3, c2, c3, d2, d3, dummy;
397 dph2_moments((m1 - 1 / p2) * (p1 + h), p1 + h, p2, &dummy, &a2, &a3);
398 dph2_moments((m1 - 1 / (p2 + h)) * p1, p1, p2 + h, &dummy, &c2, &c3);
399 const double j11 = (a2 - f2) / h, j12 = (c2 - f2) / h;
400 const double j21 = (a3 - f3) / h, j22 = (c3 - f3) / h;
401 const double det = j11 * j22 - j12 * j21;
402 if (std::abs(det) < 1e-18)
break;
403 double dp1 = -(j22 * r2 - j12 * r3) / det;
404 double dp2 = -(-j21 * r2 + j11 * r3) / det;
407 while (step > 1e-6 && (p1 + step * dp1 <= 1e-9 || p1 + step * dp1 > 1 ||
408 p2 + step * dp2 <= 1e-9 || p2 + step * dp2 > 1))
410 if (step <= 1e-6)
break;
439 if (d.
D0.rows() <= max_order)
return d;
441 std::vector<T> moms =
dmap_moment(d, std::vector<unsigned>{1u, 2u, 3u});
446 double b = 0, p1 = 0, p2 = 0;
447 if (detail::dph2_from_3moments(m1, m2, m3, &b, &p1, &p2)) {
462 p = std::min(1.0, std::max(1e-12, p));
481 if (A[0].rows() <= max_order)
return A;
482 const std::size_t nb = A.size() - 1, m = A[0].rows();
485 for (std::size_t k = 1; k < A.size(); ++k) Ptot = detail::dt_add(Ptot, A[k]);
490 for (std::size_t k = 0; k < nb; ++k) {
491 for (std::size_t i = 0; i < m; ++i)
492 for (std::size_t j = 0; j < m; ++j) qraw[k] = qraw[k] + pi_phase[i] * A[k + 1](i, j);
493 mass = mass + qraw[k];
496 throw InputError(
"dmap_compress_batch: the batch stream carries no events");
500 marked.
D1 = detail::dt_sub(Ptot, A[0]);
504 out.push_back(markedC.
D0);
505 for (std::size_t k = 0; k < nb; ++k) {
507 const T w = qraw[k] / mass;
508 for (std::size_t i = 0; i < blk.
rows(); ++i)
509 for (std::size_t j = 0; j < blk.
cols(); ++j) blk(i, j) = blk(i, j) * w;
523 int max_iter = 200) {
524 std::size_t m = A1.
rows();
526 Matrix<T> inv_local = detail::dt_left_solve(detail::dt_sub(I, A1), I);
527 Matrix<T> B0 = detail::dt_mul(inv_local, A0);
528 Matrix<T> B2 = detail::dt_mul(inv_local, A2);
532 for (
int it = 0; it < max_iter; ++it) {
533 Matrix<T> A1n = detail::dt_add(detail::dt_mul(B0, B2), detail::dt_mul(B2, B0));
536 Matrix<T> inv_n = detail::dt_left_solve(detail::dt_sub(I, A1n), I);
537 B0 = detail::dt_mul(inv_n, A0n);
538 B2 = detail::dt_mul(inv_n, A2n);
539 G = detail::dt_add(G, detail::dt_mul(PI, B0));
540 PI = detail::dt_mul(PI, B2);
543 for (std::size_t i = 0; i < m; ++i) {
545 for (std::size_t j = 0; j < m; ++j) rowsum = rowsum + G(i, j);
546 residual = std::max(residual,
549 if (residual < 1e-14)
break;
566 double tol = 1e-14) {
567 std::size_t m = A[0].rows();
569 for (
int it = 0; it < max_iter; ++it) {
572 for (std::size_t k = 1; k < A.size(); ++k) {
573 Gnew = detail::dt_add(Gnew, detail::dt_mul(A[k], Gpow));
574 if (k + 1 < A.size()) Gpow = detail::dt_mul(Gpow, G);
577 for (std::size_t i = 0; i < m; ++i)
578 for (std::size_t j = 0; j < m; ++j)
581 if (delta < tol)
break;
600 std::size_t max_num_comp = 1000) {
603 std::size_t m = A[0].rows();
604 std::size_t dega = A.size() - 1;
605 std::size_t degb = B.size() - 1;
610 std::vector<Matrix<T>> hatA = A;
612 std::vector<T> beta(m, zero);
613 for (std::size_t i = 0; i < m; ++i)
614 for (std::size_t j = 0; j < m; ++j) beta[i] = beta[i] + sumA(i, j);
615 for (std::size_t i = dega; i-- > 1;) {
616 sumA = detail::dt_add(sumA, A[i]);
617 hatA[i] = detail::dt_add(A[i], detail::dt_mul(hatA[i + 1], G));
618 for (std::size_t r = 0; r < m; ++r)
619 for (std::size_t c = 0; c < m; ++c) beta[r] = beta[r] + sumA(r, c);
621 sumA = detail::dt_add(sumA, A[0]);
625 for (std::size_t i = 0; i < m; ++i) drift = drift + theta[i] * beta[i];
627 throw InputError(
"mg1_dt_pi: the chain characterized by A is not positive recurrent");
629 Matrix<T> invBarA1 = detail::dt_left_solve(detail::dt_sub(I, hatA[1]), I);
633 std::vector<Matrix<T>> hatB = B;
635 std::vector<T> Bbeta(m, zero);
636 for (std::size_t i = degb; i-- > 1;) {
637 for (std::size_t r = 0; r < m; ++r)
638 for (std::size_t c = 0; c < m; ++c) Bbeta[r] = Bbeta[r] + sumBB0(r, c);
639 sumBB0 = detail::dt_add(sumBB0, B[i]);
640 hatB[i] = detail::dt_add(B[i], detail::dt_mul(hatB[i + 1], G));
643 Matrix<T> Kmat = detail::dt_add(B[0], detail::dt_mul(hatB[1], G));
649 for (std::size_t r = 0; r < m; ++r)
650 for (std::size_t c = 0; c < m; ++c) W(r, c) = W(r, c) - (one - beta[r]) * g[c];
651 Matrix<T> invW = detail::dt_left_solve(W, I);
652 std::vector<T> temp(m, zero);
653 for (std::size_t r = 0; r < m; ++r)
654 for (std::size_t c = 0; c < m; ++c) temp[r] = temp[r] + invW(r, c);
656 const T inv_slack = one / (one - drift);
657 std::vector<T> psi1(m, zero), psi2(m, one);
658 Matrix<T> M1 = detail::dt_sub(detail::dt_sub(I, A[0]), hatA[1]);
659 Matrix<T> M2 = detail::dt_sub(sumBB0, hatB[1]);
660 for (std::size_t r = 0; r < m; ++r) {
661 T acc1 = zero, acc2 = zero, a0row = zero;
662 for (std::size_t c = 0; c < m; ++c) {
663 acc1 = acc1 + M1(r, c) * temp[c];
664 acc2 = acc2 + M2(r, c) * temp[c];
665 a0row = a0row + A[0](r, c);
667 psi1[r] = acc1 + inv_slack * a0row;
668 psi2[r] = one + acc2 + inv_slack * Bbeta[r];
671 std::vector<T> tmp(m, zero), tilde(m, zero);
672 for (std::size_t r = 0; r < m; ++r)
673 for (std::size_t c = 0; c < m; ++c) tmp[r] = tmp[r] + invBarA1(r, c) * psi1[c];
674 for (std::size_t r = 0; r < m; ++r) {
676 for (std::size_t c = 0; c < m; ++c) acc = acc + hatB[1](r, c) * tmp[c];
677 tilde[r] = psi2[r] + acc;
680 for (std::size_t r = 0; r < m; ++r) denom = denom + kappa[r] * tilde[r];
682 std::vector<std::vector<T>> pi;
683 std::vector<T> pi0(m, zero);
684 for (std::size_t r = 0; r < m; ++r) pi0[r] = kappa[r] / denom;
688 for (std::size_t r = 0; r < m; ++r) sumpi += num_traits<T>::to_double(pi0[r]);
689 std::size_t numit = 1;
690 while (sumpi < 1 - 1e-10 && numit < max_num_comp) {
691 std::vector<T> pin(m, zero);
693 for (std::size_t r = 0; r < m; ++r)
694 for (std::size_t c = 0; c < m; ++c)
695 pin[c] = pin[c] + pi0[r] * hatB[numit](r, c);
696 for (std::size_t j = 1; j <= std::min(numit - 1, dega - 1); ++j)
697 for (std::size_t r = 0; r < m; ++r)
698 for (std::size_t c = 0; c < m; ++c)
699 pin[c] = pin[c] + pi[numit - j][r] * hatA[j + 1](r, c);
700 std::vector<T> row(m, zero);
701 for (std::size_t r = 0; r < m; ++r)
702 for (std::size_t c = 0; c < m; ++c) row[c] = row[c] + pin[r] * invBarA1(r, c);
704 for (std::size_t r = 0; r < m; ++r) sumpi += num_traits<T>::to_double(row[r]);
709 out.reserve(pi.size() * m);
710 for (std::size_t i = 0; i < pi.size(); ++i)
711 for (std::size_t r = 0; r < m; ++r) out.push_back(pi[i][r]);
725 std::size_t max_num_comp = 1000) {
727 std::size_t ma = arv.
D0.rows(), ms = svc.
D0.rows(), mtot = ma * ms;
731 for (std::size_t i = 0; i < ma; ++i)
732 for (std::size_t j = 0; j < ma; ++j) avga = avga + pi_a[i] * arv.
D1(i, j);
735 for (std::size_t i = 0; i < ms; ++i)
736 for (std::size_t j = 0; j < ms; ++j) avgs = avgs + pi_s[i] * svc.
D1(i, j);
738 throw InputError(
"q_dt_map_map_1: the load of the system exceeds one");
742 Matrix<T> A0 = detail::dt_add(detail::dt_kron(arv.
D0, svc.
D0),
743 detail::dt_kron(arv.
D1, svc.
D1));
751 Matrix<T> denom = detail::dt_sub(detail::dt_sub(I, A0), detail::dt_mul(A1, G));
752 Matrix<T> R = detail::dt_right_divide(A1, denom);
756 Matrix<T> lower = detail::dt_add(A0, detail::dt_mul(R, Am1));
758 for (std::size_t i = 0; i < mtot; ++i)
759 for (std::size_t j = 0; j < mtot; ++j) {
760 joint(i, j) = B0(i, j);
761 joint(mtot + i, j) = Am1(i, j);
762 joint(i, mtot + j) = B1(i, j);
763 joint(mtot + i, mtot + j) = lower(i, j);
767 Matrix<T> temp = detail::dt_left_solve(detail::dt_sub(I, R), I);
768 std::vector<T> pi0(pi01.begin(), pi01.begin() + mtot);
769 std::vector<T> pi1(pi01.begin() + mtot, pi01.end());
771 for (std::size_t i = 0; i < mtot; ++i) norm = norm + pi0[i];
772 for (std::size_t i = 0; i < mtot; ++i)
773 for (std::size_t j = 0; j < mtot; ++j) norm = norm + pi1[i] * temp(i, j);
774 for (std::size_t i = 0; i < mtot; ++i) {
775 pi0[i] = pi0[i] / norm;
776 pi1[i] = pi1[i] / norm;
781 for (std::size_t i = 0; i < mtot; ++i) mass0 = mass0 + pi0[i];
783 std::vector<T> cur = pi1;
785 for (std::size_t it = 0; it < max_num_comp; ++it) {
787 for (std::size_t i = 0; i < mtot; ++i) mass = mass + cur[i];
790 if (acc > 1 - 1e-10)
break;
792 for (std::size_t j = 0; j < mtot; ++j)
793 for (std::size_t i = 0; i < mtot; ++i) nxt[j] = nxt[j] + cur[i] * R(i, j);
798 for (std::size_t i = 0; i < ql.size(); ++i) total = total + ql[i];
799 for (std::size_t i = 0; i < ql.size(); ++i) ql[i] = ql[i] / total;
806 std::size_t max_num_comp = 1000) {
836 std::size_t max_num_comp = 1000,
bool want_departure =
false) {
838 std::size_t ms = svc.
D0.rows(), ma = arv[0].rows(), K = arv.size() - 1;
839 std::size_t m = ma * ms;
844 svc_batch.push_back(svc.
D0);
845 svc_batch.push_back(svc.
D1);
848 throw InputError(
"mg1_dt_queue: the discrete-time load of the station is not below one");
852 std::vector<Matrix<T>> Ablocks, Bblocks;
853 Ablocks.push_back(detail::dt_kron(arv[0], svc.
D1));
854 for (std::size_t k = 0; k <= K; ++k) {
856 if (k + 1 <= K) blk = detail::dt_add(blk, detail::dt_kron(arv[k + 1], svc.
D1));
857 Ablocks.push_back(blk);
859 for (std::size_t k = 0; k <= K; ++k) Bblocks.push_back(detail::dt_kron(arv[k], Ims));
861 std::vector<T> pi =
mg1_dt_pi(Bblocks, Ablocks, max_num_comp);
864 std::size_t nlev = pi.size() / m;
866 for (std::size_t i = 0; i < nlev; ++i)
867 for (std::size_t j = 0; j < m; ++j) out.
ql[i] = out.
ql[i] + pi[i * m + j];
869 for (std::size_t i = 0; i < nlev; ++i) total = total + out.
ql[i];
870 for (std::size_t i = 0; i < nlev; ++i) out.
ql[i] = out.
ql[i] / total;
873 for (std::size_t i = 0; i < nlev; ++i)
875 out.
UN = one - out.
ql[0];
878 if (want_departure) {
880 std::size_t L = nlev - 1;
881 for (std::size_t i = 0; i < nlev; ++i) {
883 if (cum > 1 - 1e-10) {
889 std::size_t nstates = (L + 1) * m;
894 for (std::size_t i = 0; i <= L; ++i)
895 for (std::size_t k = 0; k <= K; ++k) {
897 std::size_t tgt = std::min(L, k);
898 Matrix<T> blk = detail::dt_kron(arv[k], Ims);
899 for (std::size_t r = 0; r < m; ++r)
900 for (std::size_t c = 0; c < m; ++c)
901 D0(i * m + r, tgt * m + c) = D0(i * m + r, tgt * m + c) + blk(r, c);
903 std::size_t tno = std::min(L, i + k);
905 for (std::size_t r = 0; r < m; ++r)
906 for (std::size_t c = 0; c < m; ++c)
907 D0(i * m + r, tno * m + c) = D0(i * m + r, tno * m + c) + no(r, c);
908 std::size_t tdep = std::min(L, i - 1 + k);
910 for (std::size_t r = 0; r < m; ++r)
911 for (std::size_t c = 0; c < m; ++c)
912 D1(i * m + r, tdep * m + c) = D1(i * m + r, tdep * m + c) + dp(r, c);
Discrete-time Markovian arrival processes (D-MAPs).
Equilibrium distribution of a discrete-time Markov chain, and stochastic complementation.
The exception types the port throws.
Enumerations and the minimal distribution descriptor shared by the model layer of the C++ port.
LU factorization with partial pivoting, templated on the number type.
Dense matrix and non-owning view.
ProcessType
Distribution kinds, with the values of MATLAB ProcessType.
DBatch< T > dmap_compress_batch(const DBatch< T > &A, std::size_t max_order)
Order reduction of a BATCH stream.
Matrix< T > mg1_dt_g(const std::vector< Matrix< T > > &A, int max_iter=5000, double tol=1e-14)
G matrix of an M/G/1-type chain by functional iteration on G = sum_k A_k G^k, the blocks being stocha...
Dmap< T > dmap_compress(const Dmap< T > &d, std::size_t max_order)
Reduces the order of a D-MAP by matching interevent moments.
bool dmap_isfeasible(const Dmap< T > &d)
True when D0 and D1 are nonnegative and D0 + D1 is stochastic.
std::vector< T > q_dt_map_map_1(const Dmap< T > &arv, const Dmap< T > &svc, std::size_t max_num_comp=1000)
Queue length distribution of a discrete-time D-MAP/D-MAP/1/FCFS queue, the queue-length half of Q_DT_...
std::vector< Matrix< T > > DBatch
A discrete batch arrival stream, entry k carrying the slots with k events.
T dmap_lambda_batch(const DBatch< T > &A)
Mean number of EVENTS per slot, pi sum_k k A_k e.
std::vector< T > q_dt_ph_ph_1(const Dph< T > &arv, const Dph< T > &svc, std::size_t max_num_comp=1000)
Queue length of a discrete-time DPH/DPH/1/FCFS queue, via the D-MAP route.
Matrix< T > qbd_dt_g(const Matrix< T > &A0, const Matrix< T > &A1, const Matrix< T > &A2, int max_iter=200)
G matrix of a discrete-time QBD by logarithmic reduction (Latouche and Ramaswami).
DtQueueResult< T > mg1_dt_queue(const DBatch< T > &arv, const Dmap< T > &svc, std::size_t max_num_comp=1000, bool want_departure=false)
Discrete-time single-server queue with batch D-MAP arrivals, DBMAP/D-MAP/1.
Dph< T > dph_from_dist(lang::ProcessType type, const T &mean_slots, const T &scv)
Exact discrete phase-type representation of a lattice-valued law.
Dmap< T > dph_to_dmap(const Dph< T > &d)
Renewal D-MAP (A, a alpha) of a discrete phase-type law.
std::vector< T > dmap_moment(const Dmap< T > &d, const std::vector< unsigned > &orders)
Raw moments of the interarrival time in slots, for orders 1, 2 and 3 only.
Dph< T > dmap_to_dph(const Dmap< T > &d)
Discrete phase-type law underlying a renewal D-MAP.
DBatch< T > dmap_super(const DBatch< T > &A, const DBatch< T > &B)
Superposition, E_k = sum_{i+j=k} kron(A_i, B_j).
bool dmap_is_renewal(const Dmap< T > &d)
True when D1 has rank one, i.e.
std::vector< T > mg1_dt_pi(const std::vector< Matrix< T > > &B, const std::vector< Matrix< T > > &A, std::size_t max_num_comp=1000)
Stationary vector of an M/G/1-type chain by the stable Ramaswami formula.
DBatch< T > dmap_thin(const DBatch< T > &A, const T &p)
Bernoulli thinning, B_k = sum_{n>=k} C(n,k) p^k (1-p)^(n-k) A_n.
std::vector< T > dtmc_solve(const Matrix< T > &P)
Stationary distribution of a stochastic matrix P.
std::vector< T > solve(const Matrix< T > &A, const std::vector< T > &b)
Convenience: solve Ax = b, leaving A and b untouched.
Number-type abstraction for the templated API port.
A discrete-time MAP: substochastic D0 (no arrival) and D1 (one arrival).
A discrete phase-type law: initial row vector alpha and transient A.
std::size_t order() const
Outcome of a slotted station solve.