5#ifndef LINE_API_QSYS_QSYS_MMAPGK1_H
6#define LINE_API_QSYS_QSYS_MMAPGK1_H
114 std::function<std::complex<double>(std::complex<double>)>
lst;
135namespace mmapgk1detail {
137typedef std::complex<double> cdbl;
140inline double binom(std::size_t n, std::size_t k);
144std::vector<T> stat_left_null(
const Matrix<T>& G) {
146 const std::size_t n = G.
rows();
148 for (std::size_t i = 0; i < n; ++i)
149 for (std::size_t j = 0; j < n; ++j) A(j, i) = G(i, j);
150 for (std::size_t j = 0; j < n; ++j) A(n - 1, j) = one;
151 std::vector<T> b(n, zero);
158void stieltjes_nodes(
const lang::Distrib<T>& law, std::vector<T>& x, std::vector<T>& w,
159 std::size_t quad_nodes = 120) {
161 const std::size_t n_grid = (quad_nodes > 20 ? quad_nodes : 20) * 20;
162 const T zero = num_traits<T>::from_int(0);
164 double hi = mean * 60.0;
166 if (std::isfinite(var) && var > 0.0) hi = std::max(hi, mean + 12.0 * std::sqrt(var));
167 const double step = hi /
static_cast<double>(n_grid);
168 x.assign(n_grid, zero);
169 w.assign(n_grid, zero);
172 for (std::size_t i = 0; i < n_grid; ++i) {
173 const T right = num_traits<T>::from_double((i + 1) * step);
175 x[i] = num_traits<T>::from_double((i + 0.5) * step);
181 for (std::size_t i = 0; i < n_grid; ++i) w[i] = w[i] / mass;
194T raw_moment(
const lang::Distrib<T>& law, std::size_t j) {
197 }
catch (
const NumericError&) {
198 return num_traits<T>::from_double(std::numeric_limits<double>::infinity());
204T raw_moment(
const MmapGk1Service<T>& svc, std::size_t j) {
209 if (j > svc.transform.moments.size())
210 throw InputError(
"qsys_mmapgk1: The service law was given as a transform with " +
211 std::to_string(svc.transform.moments.size()) +
212 " moments, but order " + std::to_string(j) +
213 " is needed. Supply at least numWMoms+1 moments.");
214 return svc.transform.moments[j - 1];
216 return raw_moment(svc.dist, j);
222Matrix<T> gk_kron(
const Matrix<T>& A,
const Matrix<T>& B) {
223 Matrix<T> C(A.rows() * B.rows(), A.cols() * B.cols(), num_traits<T>::from_int(0));
224 for (std::size_t i = 0; i < A.rows(); ++i)
225 for (std::size_t j = 0; j < A.cols(); ++j)
226 for (std::size_t p = 0; p < B.rows(); ++p)
227 for (std::size_t q = 0; q < B.cols(); ++q)
228 C(i * B.rows() + p, j * B.cols() + q) = A(i, j) * B(p, q);
233inline std::vector<cdbl> complex_solve(std::vector<std::vector<cdbl> > A, std::vector<cdbl> b);
241Matrix<T> matrix_lst_map(
const mam::Map<T>& rep,
const Matrix<T>& U) {
242 const T zero = num_traits<T>::from_int(0);
243 const std::size_t n = U.rows();
244 const Matrix<T>& S = rep.D0;
245 const std::size_t ms = S.rows();
247 std::vector<T> s0(ms, zero);
248 for (std::size_t i = 0; i < ms; ++i) {
250 for (std::size_t j = 0; j < ms; ++j) r += S(i, j);
253 Matrix<T> Ims =
eye<T>(ms);
254 Matrix<T> KS = gk_kron(U, Ims);
255 const Matrix<T> In =
eye<T>(n);
256 const Matrix<T> IkS = gk_kron(In, S);
257 for (std::size_t i = 0; i < KS.rows(); ++i)
258 for (std::size_t j = 0; j < KS.cols(); ++j) KS(i, j) += IkS(i, j);
259 Matrix<T> betaM(1, ms, zero);
260 for (std::size_t i = 0; i < ms; ++i) betaM(0, i) = beta[i];
261 Matrix<T> s0M(ms, 1, zero);
262 for (std::size_t i = 0; i < ms; ++i) s0M(i, 0) = s0[i];
263 const Matrix<T> L = gk_kron(In, betaM);
264 Matrix<T> R = gk_kron(In, s0M);
266 for (std::size_t i = 0; i < X.rows(); ++i)
267 for (std::size_t j = 0; j < X.cols(); ++j) X(i, j) = -X(i, j);
279inline void eig_decomp(
const std::vector<std::vector<double> >& U, std::vector<cdbl>& ev,
280 std::vector<std::vector<cdbl> >& V, std::vector<std::vector<cdbl> >& Vinv,
282 const std::size_t n = U.size();
283 ev.assign(n, cdbl(0.0, 0.0));
284 V.assign(n, std::vector<cdbl>(n, cdbl(0.0, 0.0)));
285 Vinv.assign(n, std::vector<cdbl>(n, cdbl(0.0, 0.0)));
289 std::vector<double> c(n + 1, 0.0);
291 std::vector<std::vector<double> > Mk(n, std::vector<double>(n, 0.0));
292 for (std::size_t i = 0; i < n; ++i) Mk[i][i] = 1.0;
293 for (std::size_t k = 1; k <= n; ++k) {
294 std::vector<std::vector<double> > TM(n, std::vector<double>(n, 0.0));
296 for (std::size_t i = 0; i < n; ++i)
297 for (std::size_t j = 0; j < n; ++j) {
299 for (std::size_t l = 0; l < n; ++l) acc += U[i][l] * Mk[l][j];
301 if (i == j) tr += acc;
303 c[k] = -tr /
static_cast<double>(k);
305 for (std::size_t i = 0; i < n; ++i) Mk[i][i] += c[k];
309 const cdbl seed(0.4, 0.9);
311 for (std::size_t i = 0; i < n; ++i) {
316 for (std::size_t i = 0; i < n; ++i)
317 for (std::size_t j = 0; j < n; ++j) scale = std::max(scale, std::fabs(U[i][j]));
319 for (std::size_t i = 0; i < n; ++i) ev[i] *= scale;
320 for (
int it = 0; it < 2000; ++it) {
322 for (std::size_t i = 0; i < n; ++i) {
324 for (std::size_t j = 0; j < n; ++j)
325 if (j != i) den *= (ev[i] - ev[j]);
326 if (std::abs(den) < 1e-300)
continue;
328 for (std::size_t q = 0; q <= n; ++q) pv = pv * ev[i] + c[q];
329 const cdbl step = pv / den;
331 move = std::max(move, std::abs(step));
333 if (move < 1e-15 * std::max(1.0, scale))
break;
338 for (std::size_t i = 0; i < n; ++i) umax = std::max(umax, std::abs(ev[i]));
339 for (std::size_t i = 0; i < n; ++i) {
340 const cdbl shift = ev[i] + cdbl(1e-10 * std::max(1.0, umax), 1e-10 * std::max(1.0, umax));
341 std::vector<cdbl> v(n);
342 for (std::size_t q = 0; q < n; ++q) v[q] = cdbl(1.0 / std::sqrt(
static_cast<double>(n)), 0.0);
343 for (
int it = 0; it < 3; ++it) {
344 std::vector<std::vector<cdbl> > A(n, std::vector<cdbl>(n, cdbl(0.0, 0.0)));
345 for (std::size_t p = 0; p < n; ++p) {
346 for (std::size_t q = 0; q < n; ++q) A[p][q] = cdbl(U[p][q], 0.0);
349 std::vector<cdbl> w = complex_solve(A, v);
351 for (std::size_t q = 0; q < n; ++q) nrm += std::norm(w[q]);
352 nrm = std::sqrt(nrm);
353 if (!(nrm > 0.0) || !std::isfinite(nrm))
break;
354 for (std::size_t q = 0; q < n; ++q) v[q] = w[q] / nrm;
356 for (std::size_t q = 0; q < n; ++q) V[q][i] = v[q];
359 double normV = 0.0, normW = 0.0;
360 for (std::size_t j = 0; j < n; ++j) {
361 std::vector<cdbl> ej(n, cdbl(0.0, 0.0));
362 ej[j] = cdbl(1.0, 0.0);
363 const std::vector<cdbl> col = complex_solve(V, ej);
364 double cs = 0.0, vs = 0.0;
365 for (std::size_t i = 0; i < n; ++i) {
367 cs += std::abs(col[i]);
368 vs += std::abs(V[i][j]);
370 normW = std::max(normW, cs);
371 normV = std::max(normV, vs);
373 if (std::isfinite(normW) && normW > 0.0 && normV > 0.0) rcond = 1.0 / (normV * normW);
378Matrix<T> matrix_lst_eig(std::size_t n,
const std::vector<std::vector<cdbl> >& V,
379 const std::vector<std::vector<cdbl> >& Vinv,
const std::vector<cdbl>& g) {
380 Matrix<T> F(n, n, num_traits<T>::from_int(0));
381 for (std::size_t i = 0; i < n; ++i)
382 for (std::size_t j = 0; j < n; ++j) {
384 for (std::size_t q = 0; q < n; ++q) acc += V[i][q] * g[q] * Vinv[q][j];
385 F(i, j) = num_traits<T>::from_double(acc.real());
392Matrix<T> matrix_lst(
const lang::Distrib<T>& law,
const Matrix<T>& U, std::size_t quad_nodes = 120) {
393 const T zero = num_traits<T>::from_int(0);
394 const std::size_t n = U.rows();
399 for (std::size_t i = 0; i < n; ++i)
400 for (std::size_t j = 0; j < n; ++j) Ud(i, j) = Ud(i, j) * d;
407 std::vector<std::vector<double> > Ud(n, std::vector<double>(n, 0.0));
408 for (std::size_t i = 0; i < n; ++i)
409 for (std::size_t j = 0; j < n; ++j) Ud[i][j] = num_traits<T>::to_double(U(i, j));
410 std::vector<cdbl> ev;
411 std::vector<std::vector<cdbl> > V, Vinv;
413 eig_decomp(Ud, ev, V, Vinv, rcond);
414 bool ok = rcond > 1e-12;
415 std::vector<cdbl> g(n, cdbl(0.0, 0.0));
417 for (std::size_t i = 0; i < n; ++i) {
420 }
catch (
const Error&) {
424 if (!std::isfinite(g[i].real()) || !std::isfinite(g[i].imag())) {
430 if (ok)
return matrix_lst_eig<T>(n, V, Vinv, g);
433 stieltjes_nodes(law, x, w, quad_nodes);
434 Matrix<T> F(n, n, zero);
435 for (std::size_t i = 0; i < x.size(); ++i) {
437 for (std::size_t p = 0; p < n; ++p)
438 for (std::size_t q = 0; q < n; ++q) Ut(p, q) = Ut(p, q) * x[i];
440 for (std::size_t p = 0; p < n; ++p)
441 for (std::size_t q = 0; q < n; ++q) F(p, q) += w[i] * E(p, q);
448Matrix<T> matrix_lst(
const MmapGk1Service<T>& svc,
const Matrix<T>& U, std::size_t quad_nodes) {
451 return matrix_lst_map(svc.map, U);
454 const std::size_t n = U.rows();
455 std::vector<std::vector<double> > Ud(n, std::vector<double>(n, 0.0));
456 for (std::size_t i = 0; i < n; ++i)
457 for (std::size_t j = 0; j < n; ++j) Ud[i][j] = num_traits<T>::to_double(U(i, j));
458 std::vector<cdbl> ev;
459 std::vector<std::vector<cdbl> > V, Vinv;
461 eig_decomp(Ud, ev, V, Vinv, rcond);
462 std::vector<cdbl> g(n);
463 for (std::size_t i = 0; i < n; ++i) g[i] = svc.transform.lst(-ev[i]);
464 return matrix_lst_eig<T>(n, V, Vinv, g);
467 return matrix_lst(svc.dist, U, quad_nodes);
472inline std::vector<cdbl> complex_solve(std::vector<std::vector<cdbl> > A, std::vector<cdbl> b) {
473 const std::size_t n = b.size();
474 for (std::size_t col = 0; col < n; ++col) {
475 std::size_t piv = col;
476 double best = std::abs(A[col][col]);
477 for (std::size_t r = col + 1; r < n; ++r) {
478 if (std::abs(A[r][col]) > best) { best = std::abs(A[r][col]); piv = r; }
480 if (piv != col) { std::swap(A[piv], A[col]); std::swap(b[piv], b[col]); }
481 for (std::size_t r = col + 1; r < n; ++r) {
482 const cdbl f = A[r][col] / A[col][col];
483 for (std::size_t c = col; c < n; ++c) A[r][c] -= f * A[col][c];
487 std::vector<cdbl> x(n);
488 for (std::size_t row = n; row-- > 0;) {
490 for (std::size_t c = row + 1; c < n; ++c) s -= A[row][c] * x[c];
491 x[row] = s / A[row][row];
505cdbl scalar_lst(
const lang::Distrib<T>& law, cdbl s) {
511cdbl scalar_lst(
const MmapGk1Service<T>& svc, cdbl s) {
515 const Matrix<T>& D0s = svc.map.D0;
516 const std::size_t n = D0s.rows();
518 std::vector<std::vector<cdbl> > A(n, std::vector<cdbl>(n, cdbl(0.0, 0.0)));
519 std::vector<cdbl> b(n, cdbl(0.0, 0.0));
520 for (std::size_t i = 0; i < n; ++i) {
522 for (std::size_t j = 0; j < n; ++j) {
523 A[i][j] = cdbl(-num_traits<T>::to_double(D0s(i, j)), 0.0);
524 rs += num_traits<T>::to_double(D0s(i, j));
527 b[i] = cdbl(-rs, 0.0);
529 const std::vector<cdbl> x = complex_solve(A, b);
531 for (std::size_t i = 0; i < n; ++i) g += num_traits<T>::to_double(alpha[i]) * x[i];
535 return svc.transform.lst(s);
544cdbl wait_lst(
const Matrix<T>& D0,
const std::vector<Matrix<T> >& Dk,
545 const std::vector<MmapGk1Service<T> >& svc,
const std::vector<T>& v0,
546 const std::vector<T>& lambdas, std::size_t k, cdbl s) {
547 const std::size_t ma = D0.rows();
548 std::vector<std::vector<cdbl> > M(ma, std::vector<cdbl>(ma, cdbl(0.0, 0.0)));
549 for (std::size_t i = 0; i < ma; ++i)
550 for (std::size_t j = 0; j < ma; ++j) M[i][j] = cdbl(num_traits<T>::to_double(D0(i, j)), 0.0);
551 for (std::size_t i = 0; i < ma; ++i) M[i][i] += s;
552 for (std::size_t q = 0; q < Dk.size(); ++q) {
553 const cdbl g = scalar_lst(svc[q], s);
554 for (std::size_t i = 0; i < ma; ++i)
555 for (std::size_t j = 0; j < ma; ++j)
556 M[i][j] += num_traits<T>::to_double(Dk[q](i, j)) * g;
559 std::vector<std::vector<cdbl> > A(ma, std::vector<cdbl>(ma, cdbl(0.0, 0.0)));
560 std::vector<cdbl> b(ma, cdbl(0.0, 0.0));
561 for (std::size_t i = 0; i < ma; ++i) {
562 for (std::size_t j = 0; j < ma; ++j) A[i][j] = M[j][i];
563 b[i] = s * num_traits<T>::to_double(v0[i]);
565 const std::vector<cdbl> f = complex_solve(A, b);
567 for (std::size_t i = 0; i < ma; ++i) {
569 for (std::size_t j = 0; j < ma; ++j) rowsum += num_traits<T>::to_double(Dk[k](i, j));
570 out += f[i] * rowsum;
572 return out / num_traits<T>::to_double(lambdas[k]);
577double euler_invert(
const Matrix<T>& D0,
const std::vector<Matrix<T> >& Dk,
578 const std::vector<MmapGk1Service<T> >& svc,
const std::vector<T>& v0,
579 const std::vector<T>& lambdas, std::size_t k,
double t) {
580 if (t <= 0.0)
return wait_lst(D0, Dk, svc, v0, lambdas, k, cdbl(1e12, 0.0)).real();
581 const double A = 18.4;
582 const std::size_t nE = 15, mE = 11;
583 const double u = std::exp(A / 2) / t;
584 const double x = A / (2 * t);
585 std::vector<double> terms(nE + mE + 1, 0.0);
586 terms[0] = wait_lst(D0, Dk, svc, v0, lambdas, k, cdbl(x, 0.0)).real() / x / 2.0;
587 for (std::size_t j = 1; j <= nE + mE; ++j) {
588 const cdbl s(x, M_PI *
static_cast<double>(j) / t);
589 terms[j] = ((j % 2 == 0) ? 1.0 : -1.0) * (wait_lst(D0, Dk, svc, v0, lambdas, k, s) / s).real();
591 std::vector<double> partial(terms.size(), 0.0);
593 for (std::size_t j = 0; j < terms.size(); ++j) { run += terms[j]; partial[j] = run; }
595 for (std::size_t j = 0; j <= mE; ++j) F += binom(mE, j) / std::pow(2.0,
static_cast<double>(mE)) * partial[nE + j];
597 return std::min(std::max(F, 0.0), 1.0);
601inline double binom(std::size_t n, std::size_t k) {
603 for (std::size_t i = 1; i <= k; ++i) r = r * static_cast<double>(n - k + i) /
static_cast<double>(i);
604 return std::floor(r + 0.5);
625 const std::vector<T>& w_points, std::size_t num_w_moms,
626 double tol, std::size_t iter_max, std::size_t quad_nodes) {
628 "qsys_mmapgk1 requires transcendental arithmetic");
629 using namespace mmapgk1detail;
631 if (MMAP.size() < 3)
throw InputError(
"qsys_mmapgk1: the MMAP must carry a marked block");
632 const std::size_t K = MMAP.size() - 2;
633 if (svc.size() != K)
throw InputError(
"qsys_mmapgk1: one service law per marked type");
635 const std::size_t ma = D0.
rows();
636 std::vector<Matrix<T> > Dk;
638 for (std::size_t k = 0; k < K; ++k) {
639 Dk.push_back(MMAP[k + 2]);
640 for (std::size_t i = 0; i < ma; ++i)
641 for (std::size_t j = 0; j < ma; ++j) Dsum(i, j) += Dk[k](i, j);
644 const std::vector<T> theta = stat_left_null(Dsum);
645 std::vector<T> lambdas(K, zero), mean_s(K, zero);
647 for (std::size_t k = 0; k < K; ++k) {
649 for (std::size_t i = 0; i < ma; ++i)
650 for (std::size_t j = 0; j < ma; ++j) lam += theta[i] * Dk[k](i, j);
652 mean_s[k] = raw_moment(svc[k], 1);
653 rho += lam * mean_s[k];
655 if (rho >= one)
throw InputError(
"qsys_mmapgk1: load rho must be strictly less than 1");
658 for (std::size_t it = 0; it < iter_max; ++it) {
660 for (std::size_t k = 0; k < K; ++k) {
661 const Matrix<T> Fk = matrix_lst(svc[k], U, quad_nodes);
663 for (std::size_t i = 0; i < ma; ++i)
664 for (std::size_t j = 0; j < ma; ++j) Unew(i, j) += P(i, j);
667 for (std::size_t i = 0; i < ma; ++i)
668 for (std::size_t j = 0; j < ma; ++j)
671 if (diff <= tol)
break;
675 for (std::size_t i = 0; i < ma; ++i) {
677 for (std::size_t j = 0; j < ma; ++j) rowsum += U(i, j);
680 std::vector<T> v0 = stat_left_null(U);
681 for (std::size_t i = 0; i < ma; ++i) v0[i] = v0[i] * (one - rho);
684 std::vector<Matrix<T> > Mder;
685 for (std::size_t j = 0; j <= num_w_moms + 1; ++j) {
689 for (std::size_t k = 0; k < K; ++k)
690 for (std::size_t i = 0; i < ma; ++i)
691 for (std::size_t q = 0; q < ma; ++q) Mj(i, q) += Dk[k](i, q);
693 for (std::size_t k = 0; k < K; ++k) {
694 const T mom = raw_moment(svc[k], j);
695 const double sign = (j % 2 == 0) ? 1.0 : -1.0;
696 for (std::size_t i = 0; i < ma; ++i)
697 for (std::size_t q = 0; q < ma; ++q)
701 for (std::size_t i = 0; i < ma; ++i) Mj(i, i) += one;
705 const std::vector<T> e(ma, one);
708 const std::vector<T> v =
mulvec(Mder[1], e);
709 for (std::size_t i = 0; i < ma; ++i) denom += theta[i] * v[i];
711 std::vector<std::vector<T> > fder;
712 fder.push_back(theta);
716 for (std::size_t i = 0; i < ma; ++i)
717 for (std::size_t j = 0; j < ma; ++j) Abase(j, i) = Mder[0](i, j);
718 for (std::size_t i = 0; i < ma; ++i) Abase(ma, i) = one;
720 for (std::size_t i = 0; i < ma; ++i)
721 for (std::size_t j = 0; j < ma; ++j) {
723 for (std::size_t q = 0; q < ma + 1; ++q) s += Abase(q, i) * Abase(q, j);
727 for (std::size_t j = 1; j <= num_w_moms; ++j) {
728 std::vector<T> rhs(ma, zero);
729 if (j == 1)
for (std::size_t i = 0; i < ma; ++i) rhs[i] = v0[i];
730 for (std::size_t i = 0; i < j; ++i) {
731 const double c = binom(j, i);
732 for (std::size_t q = 0; q < ma; ++q) {
734 for (std::size_t p = 0; p < ma; ++p) acc += fder[i][p] * Mder[j - i](p, q);
738 std::vector<T> rhsAug(ma + 1, zero);
739 for (std::size_t q = 0; q < ma; ++q) rhsAug[q] = rhs[q];
740 std::vector<T> Atb(ma, zero);
741 for (std::size_t i = 0; i < ma; ++i) {
743 for (std::size_t q = 0; q < ma + 1; ++q) s += Abase(q, i) * rhsAug[q];
746 const std::vector<T> fp =
mulvec(AtAinv, Atb);
748 for (std::size_t i = 0; i < j; ++i) {
749 const std::vector<T> v =
mulvec(Mder[j + 1 - i], e);
751 for (std::size_t p = 0; p < ma; ++p) inner += fder[i][p] * v[p];
756 const std::vector<T> v =
mulvec(Mder[1], e);
757 for (std::size_t p = 0; p < ma; ++p) fpM1e += fp[p] * v[p];
760 std::vector<T>
fj(ma, zero);
761 for (std::size_t p = 0; p < ma; ++p)
fj[p] = fp[p] + cfree * theta[p];
768 for (std::size_t k = 0; k < K; ++k) r.
arrivalRate += lambdas[k];
771 r.
waitMoments.assign(K, std::vector<T>(num_w_moms, zero));
775 for (std::size_t k = 0; k < K; ++k) {
776 for (std::size_t j = 1; j <= num_w_moms; ++j) {
777 const std::vector<T> v =
mulvec(Dk[k], e);
779 for (std::size_t p = 0; p < ma; ++p) inner += fder[j][p] * v[p];
780 const double sign = (j % 2 == 0) ? 1.0 : -1.0;
789 if (!w_points.empty()) {
790 r.
waitCDF.assign(K, std::vector<T>(w_points.size(), zero));
791 for (std::size_t k = 0; k < K; ++k) {
792 for (std::size_t it = 0; it < w_points.size(); ++it) {
795 euler_invert(D0, Dk, svc, v0, lambdas, k, t));
807 const std::vector<T>& w_points, std::size_t num_w_moms,
808 double tol, std::size_t iter_max) {
809 return qsys_mmapgk1(MMAP, svc, w_points, num_w_moms, tol, iter_max,
810 static_cast<std::size_t
>(120));
817 const std::vector<T>& w_points, std::size_t num_w_moms,
818 double tol, std::size_t iter_max) {
819 std::vector<MmapGk1Service<T> > laws;
820 laws.reserve(svc.size());
821 for (std::size_t k = 0; k < svc.size(); ++k) laws.push_back(
MmapGk1Service<T>(svc[k]));
822 return qsys_mmapgk1(MMAP, laws, w_points, num_w_moms, tol, iter_max,
823 static_cast<std::size_t
>(120));
830 return qsys_mmapgk1(MMAP, svc, std::vector<T>(),
static_cast<std::size_t
>(3), 1e-12,
831 static_cast<std::size_t
>(10000));
838 return qsys_mmapgk1(MMAP, svc, std::vector<T>(),
static_cast<std::size_t
>(3), 1e-12,
839 static_cast<std::size_t
>(10000),
static_cast<std::size_t
>(120));
What refreshProcessRepresentations and refreshLST compute FROM a distribution: the (D0,...
The exception types the port throws.
Matrix exponential by scaling and squaring with a diagonal Pade approximant.
Enumerations and the minimal distribution descriptor shared by the model layer of the C++ port.
Dense linear algebra over the templated number type: products, identity, inverse, and powers.
LU factorization with partial pivoting, templated on the number type.
Markovian arrival process descriptors: stationary vectors, rate, moments, autocorrelation and the ind...
Dense matrix and non-owning view.
mam::Map< T > dist_to_map(const Distrib< T > &d)
The (D0,D1) pair that reaches sn.proc.
T dist_lst(const Distrib< T > &d, const T &s)
sn.lst: the Laplace-Stieltjes transform E[exp(-sX)].
T dist_cdf(const Distrib< T > &d, const T &x)
F(x) = P{X <= x}, MATLAB's Distribution.evalCDF.
bool process_is_markovian(ProcessType p)
ProcessType.isMarkovian: true when sn.proc carries an exact matrix representation of the law,...
T dist_moment(const Distrib< T > &d, unsigned k)
The k-th raw moment.
std::vector< T > map_pie(const Map< T > &m)
Phase distribution seen by an arriving job, pie = pi D1 / (pi D1 e).
T map_moment(const Map< T > &m, unsigned k)
Raw moment of order k of the inter-arrival time: k!
MmapGk1Result< T > qsys_mmapgk1(const std::vector< Matrix< T > > &MMAP, const std::vector< MmapGk1Service< T > > &svc, const std::vector< T > &w_points, std::size_t num_w_moms, double tol, std::size_t iter_max, std::size_t quad_nodes)
MMAP[K]/G[K]/1 FCFS, per type.
Conservation laws of a layered queueing network, enumerated from its structure.
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.
std::vector< T > mulvec(const Matrix< T > &A, const std::vector< T > &v)
Matrix times column vector, A v.
std::vector< T > solve(const Matrix< T > &A, const std::vector< T > &b)
Convenience: solve Ax = b, leaving A and b untouched.
Matrix< T > eye(std::size_t n)
Identity of order n.
Matrix< T > expm(const Matrix< T > &A)
Matrix exponential exp(A).
Number-type abstraction for the templated API port.
A MAP as the pair of matrices (D0, D1).
Return value of qsys_mmapgk1, mirroring the MATLAB struct.
T utilization
rho = sum_k lambda_k E[S_k]
std::vector< T > lambdas
per-type arrival rates
std::vector< T > waitPoints
the requested points
std::vector< T > meanWaitingTime
per-type E[Wq]
std::vector< T > meanSojournTime
per-type E[Wq] + E[S]
std::vector< std::vector< T > > waitCDF
[type][point], P(Wk <= t)
T arrivalRate
sum of the per-type rates
std::vector< T > idleVector
v0, summing to 1 - rho
T meanQueueLength
E[N] by Little over all types.
std::vector< std::vector< T > > waitMoments
[type][order], E[Wk^j]
One marked type's service law, in any of the three forms the reference accepts: a Distribution object...
MmapGk1Service(const MmapGk1Transform< T > &t)
MmapGk1Service(const mam::Map< T > &m)
MmapGk1Transform< T > transform
MmapGk1Service(const lang::Distrib< T > &d)