5#ifndef LINE_SOLVERS_MVA_MVA_DISPATCH_H
6#define LINE_SOLVERS_MVA_MVA_DISPATCH_H
153 int src = 0, q = 0, snk = 0;
155 if (nd.
nodetype == qn::NodeType::Source) ++src;
156 else if (nd.
nodetype == qn::NodeType::Queue) ++q;
157 else if (nd.
nodetype == qn::NodeType::Sink) ++snk;
159 return src == 1 && q == 1 && snk == 1 && L.
nclosedjobs() == 0.0;
182inline bool qsys_serves_method(
const std::string& method) {
183 static const char*
const kServed[] = {
184 "default",
"exact",
"erlanga",
"mgisrgi",
"gigk.diffusion",
185 "mm1",
"mmk",
"mg1",
"mgi1",
"gigk",
186 "gigk.kingman_approx",
"gigk.whitt",
"gig1",
"gig1.allen",
187 "gig1.kingman",
"gig1.heyman",
"gig1.kobayashi",
"gig1.klb",
"gig1.marchal",
188 "gig1.gelenbe",
"gig1.kimura",
"gig1.extremal",
"qed",
"rqna",
189 "rqt",
"gm1",
"gim1"};
190 for (std::size_t i = 0; i <
sizeof(kServed) /
sizeof(*kServed); ++i)
191 if (method == kServed[i])
return true;
197bool is_open_scs(
const qn::NetworkStruct<T>& L) {
198 if (L.nof_nodes() != 3)
return false;
199 int src = 0, ca = 0, snk = 0;
200 for (
const qn::NodeDef& nd : L.nodes) {
201 if (nd.nodetype == qn::NodeType::Source) ++src;
202 else if (nd.nodetype == qn::NodeType::Cache) ++ca;
203 else if (nd.nodetype == qn::NodeType::Sink) ++snk;
205 return src == 1 && ca == 1 && snk == 1 && L.nclosedjobs() == 0.0;
210 return s == qn::SchedStrategy::SRPT || s == qn::SchedStrategy::PSJF ||
211 s == qn::SchedStrategy::FB || s == qn::SchedStrategy::LRPT ||
212 s == qn::SchedStrategy::SETF;
217std::size_t station_of_type(
const qn::NetworkStruct<T>& L,
qn::NodeType ty) {
218 for (std::size_t i = 0; i < L.nof_nodes(); ++i)
219 if (L.nodes[i].nodetype == ty)
return L.nodes[i].station;
225bool row_is_exponential(
const qn::NetworkStruct<T>& L, std::size_t ist) {
226 for (std::size_t r = 0; r < L.nclasses; ++r) {
227 if (L.disabled[ist - 1][r])
continue;
228 const double v = num_traits<T>::to_double(L.scv(ist - 1, r));
229 if (!std::isfinite(v))
continue;
230 if (std::fabs(v - 1.0) >= 1e-6)
return false;
254 "solver_mva_qsys_analyzer: the open queueing-system closed forms need transcendental "
255 "arithmetic; rerun this model with --arith double or --arith real");
259 const std::size_t src = detail::station_of_type(L, qn::NodeType::Source);
260 const std::size_t q = detail::station_of_type(L, qn::NodeType::Queue);
261 if (src == 0 || q == 0)
throw InputError(
"solver_mva_qsys_analyzer: no Source-Queue pair");
266 const T Vq = L.
visits[0](qstateful - 1, 0);
267 const T srcRate = L.
rates(src - 1, 0);
268 const T lambda = T(srcRate * Vq);
269 const T mu = L.
rates(q - 1, 0);
270 const double k = L.
stations[q - 1].nservers;
271 const unsigned ku = std::isfinite(k) ?
static_cast<unsigned>(std::llround(k)) : 1u;
284 if (
opt.method ==
"exact")
286 "solver_mva_qsys_analyzer: M/M/1/K tail-drop is solved by the approximate "
287 "'mg1k.mgs' method (MacGregor Smith); it is not available under method='exact'. "
288 "Use the default method, or SolverCTMC/SolverNC for an exact result");
289 const double Kcap = L.
cap[q - 1];
290 const T rho = T(lambda / mu);
294 const T Tq = T(lambda * (one - Ploss));
297 if (std::fabs(rhod - 1.0) < 1e-10) {
301 const T rKp1 = qsys::detail::num_pow(rho, Kp1);
302 Lsys = T(rho / (one - rho) - Kp1 * rKp1 / (one - rKp1));
310 ls.
X.assign(1, zero);
311 ls.
C.assign(1, zero);
314 ls.
R(q - 1, 0) = T(Lsys / Tq);
315 ls.
Q(q - 1, 0) = Lsys;
316 ls.
U(q - 1, 0) = T(Tq / mu);
317 ls.
Tp(q - 1, 0) = Tq;
318 ls.
Tp(src - 1, 0) = lambda;
320 ls.
C[0] = T(ls.
R(q - 1, 0) * Vq);
329 if (method ==
"exact") {
330 if (ca1 && cs1 && ku == 1) method =
"mm1";
331 else if (ca1 && cs1 && ku > 1) method =
"mmk";
332 else if (ca1 && ku == 1) method =
"mg1";
333 else if (cs1 && ku == 1) method =
"gm1";
336 "solver_mva_qsys_analyzer: no exact closed form for this queueing system "
337 "(neither arrivals nor service are exponential, or it has several servers)");
338 }
else if (method ==
"default") {
343 else if (ca1 && cs1 && ku == 1) method =
"mm1";
344 else if (ca1 && cs1 && ku > 1) method =
"mmk";
345 else if (ca1 && ku == 1) method =
"mg1";
346 else if (cs1 && ku == 1) method =
"gm1";
347 else if (ku > 1) method =
"gigk";
348 else method =
"gig1.klb";
355 if (method ==
"erlanga" || method ==
"mgisrgi" || method ==
"gigk.diffusion") {
356 const double cap = L.
cap[q - 1];
358 const double room = std::isfinite(cap)
359 ? std::max(0.0, cap -
static_cast<double>(ku))
360 : std::numeric_limits<double>::infinity();
361 T Lsys = zero, Tq = zero, Uq = zero;
362 if (method ==
"gigk.diffusion") {
370 "' needs a reneging patience law on the queue");
387 as.
X.assign(1, zero);
388 as.
C.assign(1, zero);
393 as.
R(q - 1, 0) = Tq > zero ? T(Lsys / Tq) : zero;
394 as.
Q(q - 1, 0) = Lsys;
396 as.
Tp(q - 1, 0) = Tq;
397 as.
Tp(src - 1, 0) = srcRate;
399 as.
C[0] = T(as.
R(q - 1, 0) * Vq);
407 else if (method ==
"mg1" || method ==
"mgi1") R =
qsys::qsys_mg1(lambda, mu, cs).W;
409 else if (method ==
"gigk.kingman_approx")
413 else if (method ==
"gig1" || method ==
"gig1.allen")
427 else if (method ==
"rqna") {
430 const T rho1 = lambda / mu;
433 }
else if (method ==
"rqt") {
436 const T Gamma_a = ca / lambda;
442 else if (method ==
"qed") R = T(
qsys::qsys_mmk_qed(lambda, mu, ku).meanWait + one / mu);
444 else if (method ==
"gig1.extremal")
446 else if (method ==
"gm1" || method ==
"gim1") {
452 const bool markovian = arv.
has_map();
475 auto f = [&](
const T& x) {
return T(
lang::dist_lst(arv, T(mu - mu * x)) - x); };
477 bool straddles =
false;
478 for (
int i = 0; i < 8; ++i) {
483 hi = 1.0 - (1.0 - hi) / 10.0;
498 "' is not available for a model with one station and one class");
517 s.
Tp(src - 1, 0) = srcRate;
518 s.
Tp(q - 1, 0) = lambda;
519 s.
Q(q - 1, 0) = T(lambda * R);
537 const std::size_t src = detail::station_of_type(L, qn::NodeType::Source);
538 const std::size_t q = detail::station_of_type(L, qn::NodeType::Queue);
540 std::vector<std::size_t> order(K);
541 for (std::size_t r = 0; r < K; ++r) order[r] = r;
542 std::stable_sort(order.begin(), order.end(), [&](std::size_t a, std::size_t b) {
543 return L.classes[a].prio < L.classes[b].prio;
546 std::vector<T> lam(K, zero), mu(K, zero), cs(K, one);
547 for (std::size_t j = 0; j < K; ++j) {
548 const std::size_t r = order[j];
549 lam[j] = L.
rates(src - 1, r);
550 mu[j] = L.
rates(q - 1, r);
566 for (std::size_t j = 0; j < K; ++j) {
567 const std::size_t r = order[j];
569 s.
R(q - 1, r) = W[j];
572 s.
U(q - 1, r) = T(lam[j] / mu[j]);
573 s.
Tp(q - 1, r) = lam[j];
574 s.
Tp(src - 1, r) = lam[j];
575 s.
Q(q - 1, r) = T(lam[j] * W[j]);
592 "solver_mva_dps_exact: the exact DPS closed form needs transcendental arithmetic; "
593 "rerun this model with --arith double or --arith real");
597 const std::size_t src = detail::station_of_type(L, qn::NodeType::Source);
598 const std::size_t q = detail::station_of_type(L, qn::NodeType::Queue);
600 std::vector<T> lam(K, zero), mu(K, zero), w(K, one);
601 for (std::size_t r = 0; r < K; ++r) {
602 lam[r] = L.
rates(src - 1, r);
603 mu[r] = L.
rates(q - 1, r);
604 const std::vector<T>& sp = L.
stations[q - 1].schedparam;
605 if (sp.size() > r && sp[r] > zero) w[r] = sp[r];
619 for (std::size_t r = 0; r < K; ++r) {
620 s.
R(q - 1, r) = Wd[r];
623 if (mu[r] > zero) s.
U(q - 1, r) = T(lam[r] / mu[r]);
624 s.
Tp(q - 1, r) = lam[r];
625 s.
Tp(src - 1, r) = lam[r];
626 s.
Q(q - 1, r) = T(lam[r] * Wd[r]);
645 const bool has_cd = [&] {
647 if (st.cdscaling)
return true;
651 if (method ==
"exact" || method ==
"mva") {
654 "solver_mvald_analyzer: there is no exact class-dependent solver in MVA");
660 if (!(method ==
"default" || method ==
"amva" || method ==
"qd" || method ==
"lin" ||
663 "' method is not supported by the load-dependent MVA solver");
665 if (method ==
"default" && !has_cd) {
667 bool integral =
true, finite =
true;
669 if (!std::isfinite(c.
population)) finite =
false;
682 bool converged =
true;
690 out.
sol.converged = converged;
719 "solver_mva_qsys_sizebased_analyzer: the M/G/1 size-based closed forms need "
720 "transcendental arithmetic; rerun this model with --arith double or --arith real");
724 const std::size_t src = detail::station_of_type(L, qn::NodeType::Source);
725 const std::size_t q = detail::station_of_type(L, qn::NodeType::Queue);
733 std::vector<std::size_t> chain_of(K, 0);
734 for (std::size_t c = 0; c < L.
nchains; ++c)
735 for (std::size_t r : L.
inchain[c]) chain_of[r - 1] = c;
737 std::vector<T> lambda(K, zero), mu(K, zero), cs(K, one), vis(K, one);
738 for (std::size_t r = 0; r < K; ++r) {
739 vis[r] = L.
visits[chain_of[r]](qstateful - 1, r);
740 lambda[r] = T(L.
rates(src - 1, r) * vis[r]);
741 mu[r] = L.
rates(q - 1, r);
744 if (!(lambda[r] > zero) || !(mu[r] > zero))
746 "solver_mva_qsys_sizebased_analyzer: the arrival and service rates must be "
754 case qn::SchedStrategy::SRPT:
758 case qn::SchedStrategy::PSJF:
762 case qn::SchedStrategy::FB:
766 case qn::SchedStrategy::LRPT:
770 case qn::SchedStrategy::SETF:
775 throw UnsupportedError(std::string(
"solver_mva_qsys_sizebased_analyzer: ") +
789 for (std::size_t r = 0; r < K; ++r) {
790 s.
R(q - 1, r) = T(W[r] * vis[r]);
791 s.
C[r] = s.
R(q - 1, r);
793 s.
U(q - 1, r) = T(lambda[r] / mu[r]);
794 s.
Tp(q - 1, r) = lambda[r];
795 s.
Tp(src - 1, r) = lambda[r];
796 s.
Q(q - 1, r) = T(lambda[r] * W[r]);
821 "solver_mva_marie_analyzer: Marie's aggregation-decomposition needs transcendental "
822 "arithmetic; rerun this model with --arith double or --arith real");
828 for (std::size_t c = 0; c < C; ++c)
829 if (!std::isfinite(d.
Nchain[c]))
831 "solver_mva_marie_analyzer: the 'marie' method supports closed models only; this "
832 "model has open classes");
833 for (
const auto& nd : L.
nodes)
834 if (nd.nodetype == qn::NodeType::Source)
836 "solver_mva_marie_analyzer: the 'marie' method supports closed models only; this "
837 "model has a Source");
839 std::vector<std::size_t> qrows, drows;
840 for (std::size_t i = 0; i < M; ++i) {
842 const bool delay = std::isinf(L.
stations[i].nservers) || sc == qn::SchedStrategy::INF;
847 if (!(sc == qn::SchedStrategy::FCFS || sc == qn::SchedStrategy::PS ||
848 sc == qn::SchedStrategy::LCFSPR))
849 throw UnsupportedError(std::string(
"solver_mva_marie_analyzer: the 'marie' method "
850 "supports FCFS, PS, LCFSPR and Delay stations "
856 std::vector<T> Z(C, zero);
857 for (std::size_t c = 0; c < C; ++c)
858 for (std::size_t i : drows) Z[c] += d.
Lchain(i, c);
860 const std::size_t Mq = qrows.size();
861 Matrix<T> Lq(Mq, C, zero), SCV(Mq, C, one);
862 std::vector<int> ns(Mq, 1);
863 bool multiserver =
false;
864 for (std::size_t a = 0; a < Mq; ++a) {
865 const std::size_t i = qrows[a];
866 const double srv = L.
stations[i].nservers;
867 ns[a] = std::isfinite(srv) ?
static_cast<int>(std::llround(srv)) : 1;
868 if (ns[a] > 1) multiserver =
true;
869 for (std::size_t c = 0; c < C; ++c) {
870 Lq(a, c) = d.
Lchain(i, c);
871 if (L.
stations[i].sched != qn::SchedStrategy::FCFS)
continue;
876 if (C > 1 && multiserver)
878 "solver_mva_marie_analyzer: the 'marie' method supports multiserver stations for "
879 "single-chain models only");
881 std::vector<int> N(C, 0);
882 for (std::size_t c = 0; c < C; ++c) N[c] = static_cast<int>(std::llround(d.
Nchain[c]));
888 mr.
X.assign(C, zero);
892 for (std::size_t c = 0; c < C; ++c)
899 Matrix<T> Qchain(M, C, zero), Uchain(M, C, zero), Rchain(M, C, zero), Tchain(M, C, zero);
900 for (std::size_t a = 0; a < Mq; ++a)
901 for (std::size_t c = 0; c < C; ++c) {
902 Qchain(qrows[a], c) = mr.
Q(a, c);
903 Uchain(qrows[a], c) = mr.
U(a, c);
905 for (std::size_t i = 0; i < M; ++i)
906 for (std::size_t c = 0; c < C; ++c) Tchain(i, c) = T(mr.
X[c] * d.
Vchain(i, c));
907 for (std::size_t i = 0; i < M; ++i)
908 for (std::size_t c = 0; c < C; ++c)
909 if (Tchain(i, c) > zero) Rchain(i, c) = T(Qchain(i, c) / Tchain(i, c));
911 for (std::size_t i : drows)
912 for (std::size_t c = 0; c < C; ++c) {
913 Qchain(i, c) = T(Tchain(i, c) * d.
STchain(i, c));
914 Uchain(i, c) = Qchain(i, c);
915 Rchain(i, c) = d.
STchain(i, c);
927 out.
sol.method =
opt.method;
928 out.
sol.iter = mr.
it;
955 for (
const auto& c : L.
classes)
956 if (std::isinf(c.population)) open =
true;
959 "SolverMVA supports shortest-job-next (SJF) scheduling only in closed models, the "
960 "conditional waiting time equation being a population recursion. Use SolverLDES, "
961 "or SolverMVA with SRPT or PSJF for the preemptive size-based open queue");
984 const bool has_oi_station = std::any_of(
986 return st.sched == SchedStrategy::OI || st.sched == SchedStrategy::PAS;
988 const bool exact_method = (
opt.method ==
"default" ||
opt.method ==
"exact");
997 "SolverMVA supports order-independent (OI) and pass-and-swap (PAS) stations only "
998 "through its exact order-independent analyzer, which requires method 'default' or "
999 "'exact' (got '" +
opt.method +
1000 "'), an empty/zero swap graph at every OI/PAS station, a closed model, and every "
1001 "other station to be product-form (INF, PS, LCFS-PR, SIRO, or "
1002 "class-independent-rate FCFS). Use SolverCTMC or SolverLDES for this model");
1015 if (kv.second.retrieval_capacity <= 0)
continue;
1017 if (detail::station_of_type(L, NodeType::Source) == 0) {
1034 const bool sqs = detail::is_open_sqs(L);
1035 const std::size_t qst = detail::station_of_type(L, NodeType::Queue);
1037 const std::size_t srcst = detail::station_of_type(L, NodeType::Source);
1040 if (detail::is_open_scs(L)) {
1063 for (std::size_t ci = 0; ci < qout.
cache.caches.size() && ci < co.
itemprob.size(); ++ci)
1090 if (sqs && L.
nclasses > 1 && qsched == SchedStrategy::POLLING) {
1098 if (sqs && L.
nclasses > 1 && qsched == SchedStrategy::HOL &&
1099 L.
stations[qst - 1].nservers == 1.0 && detail::row_is_exponential(L, srcst))
1103 if (sqs && L.
nclasses > 1 && L.
nclasses <= 3 && qsched == SchedStrategy::DPS &&
1104 L.
stations[qst - 1].nservers == 1.0 && detail::row_is_exponential(L, srcst) &&
1105 detail::row_is_exponential(L, qst))
1109 static const char* kBounds[] = {
"aba.upper",
"aba.lower",
"bjb.upper",
"bjb.lower",
1110 "pb.upper",
"pb.lower",
"gb.upper",
"gb.lower",
1111 "sb.upper",
"sb.lower",
"mwba.upper",
"mwba.lower"};
1112 for (
const char* b : kBounds)
1114 throw UnsupportedError(
"SolverMVA: bound methods have moved to SolverBA; use "
1115 "SolverBA with method '" +
1122 bool has_scaling =
false;
1124 if (!st.lldscaling.empty() || st.cdscaling) has_scaling =
true;
1131 if (method ==
"mvac") {
1141 if (method ==
"qna") {
1150 if (method ==
"rqna") {
1158 if (method ==
"rqt") {
1166 if (method ==
"amva.mapqn" || method ==
"mapqn") {
1180 bool all_open =
true;
1181 for (std::size_t r = 0; r < L.
nclasses; ++r)
1182 if (std::isfinite(L.
classes[r].population)) all_open =
false;
1192 if ((
opt.base_has_fork || L.
has_fork()) && method ==
"default") {
What a solver observed about the Cache nodes of a model.
UnsupportedError(const std::string &what)
A network plus its refreshed NetworkStruct.
std::size_t stateful_of_station(std::size_t st) const
std::size_t nof_nodes() const
std::vector< std::vector< Distrib< T > > > service
service[i][r], 0-based station and class; a disabled entry marks a pair never visited.
std::map< std::size_t, CacheParam< T > > nodeparam
Cache parameters by 1-based NODE index; only Cache nodes have an entry.
std::vector< double > cap
sn.cap and sn.classcap: the total and per-class buffers.
std::vector< JobClass > classes
std::vector< Station< T > > stations
stations[k-1] is the k-th station
Matrix< T > rates
(nstations x nclasses) service rates and SCVs, with a PARALLEL disabled flag instead of MATLAB's NaN ...
std::vector< std::vector< std::size_t > > inchain
1-based class indices per chain
std::vector< NodeDef > nodes
every node, in creation order
std::vector< Matrix< T > > visits
(nchains) each (nstateful x nclasses)
double nclosedjobs() const
sn.nclosedjobs: the total population of the closed classes.
bool has_product_form() const
What refreshProcessRepresentations and refreshLST compute FROM a distribution: the (D0,...
Index of dispersion for counts (IDC) of a MAP at resolution t.
PatienceHandles< T > sn_patience_handles(const qn::NetworkStruct< T > &sn, std::size_t ist, std::size_t r)
Build the patience handles of station ist (0-based), class r.
bool sn_has_bursty_arrival(const qn::NetworkStruct< T > &sn)
mam::Map< T > dist_to_map(const Distrib< T > &d)
SchedStrategy
Scheduling disciplines, with the values of MATLAB SchedStrategy.
T dist_lst(const Distrib< T > &d, const T &s)
sn.lst: the Laplace-Stieltjes transform E[exp(-sX)].
const char * sched_to_text(SchedStrategy s)
NodeType
Node kinds, with the values of MATLAB NodeType.
std::vector< T > map_count_idc(const Map< T > &m, const std::vector< T > &t)
Index of dispersion for counts (IDC) of a MAP at resolution t.
std::vector< T > map_pie(const Map< T > &m)
Phase distribution seen by an arriving job, pie = pi D1 / (pi D1 e).
DispatchResult< T > solver_mva_qsys_prio_analyzer(const qn::NetworkStruct< T > &L, const MvaOptions &opt)
Port of solver_mva_qsys_prio_analyzer.m: the exact Cobham formula for a single open M/G/1 queue with ...
DispatchResult< T > solver_mva_qsys_sizebased_analyzer(const qn::NetworkStruct< T > &L, const MvaOptions &opt)
Port of solver_mva_qsys_sizebased_analyzer.m: the M/G/1 formulas for the size-based disciplines (Wier...
MvaSolution< T > solver_mva_polling_analyzer(const qn::NetworkStruct< T > &L, const MvaOptions &opt)
Port of solver_mva_polling_analyzer.m.
MvaSolution< T > solver_mva_cacheqn_analyzer(const qn::NetworkStruct< T > &L, const MvaOptions &opt, qn::NetworkStruct< T > *refreshed_out=nullptr, MvaCacheqnCacheOutputs< T > *cache_out=nullptr)
bool sn_has_sjn(const qn::NetworkStruct< T > &L)
True when the layer has an SJF station, the reference's any(sn.sched == SchedStrategy....
std::vector< std::size_t > find_oi_stations(const qn::NetworkStruct< T > &L)
The OI stations of a model, 1-based station indices.
bool sn_is_mm1k_loss(const qn::NetworkStruct< T > &L)
Port of matlab/src/api/sn/sn_is_mm1k_loss.m: a single-class open Source-Queue-Sink system whose queue...
MvaSolution< T > solver_rqna(const qn::NetworkStruct< T > &L, const MvaOptions &opt)
SjnAnalyzerResult< T > solver_mva_sjn_analyzer(const qn::NetworkStruct< T > &L, const MvaOptions &opt)
Port of solver_mva_sjn_analyzer.m.
std::string amva_method_alias(const std::string &m)
The amva.
DispatchResult< T > solver_mva_marie_analyzer(const qn::NetworkStruct< T > &L, const MvaOptions &opt)
Port of solver_mva_marie_analyzer.m: Marie's iterative aggregation-decomposition for a CLOSED network...
CacheResult< T > solver_mva_cache_analyzer(const qn::NetworkStruct< T > &L, const MvaOptions &opt)
Port of solver_mva_cache_analyzer.m for a Source-Cache-Sink model.
MvaSolution< T > solver_mvac_analyzer(const qn::NetworkStruct< T > &L, const MvaOptions &opt)
Port of solver_mvac.m.
MvaSolution< T > solver_mapqn(const qn::NetworkStruct< T > &L, const MvaOptions &opt)
MvaSolution< T > solver_qna(const qn::NetworkStruct< T > &L, const MvaOptions &opt)
Port of solver_qna.m.
DispatchResult< T > solver_mvald_analyzer(const qn::NetworkStruct< T > &L, const MvaOptions &opt, const Matrix< T > &init_sol)
Port of solver_mvald_analyzer.m: the load-dependent branch.
ClassResults< T > sn_deaggregate_chain_results(const qn::NetworkStruct< T > &L, const ChainDemands< T > &d, const Matrix< T > &Qchain, const Matrix< T > &Uchain, const Matrix< T > &Rchain, const Matrix< T > &Tchain, const std::vector< T > &Xchain)
Port of sn_deaggregate_chain_results.
MvaSolution< T > solver_mvald(const qn::NetworkStruct< T > &L, const MvaOptions &opt)
Port of solver_mvald.m: exact MVA on a load-dependent model, through pfqn_mvaldmx.
MvaCacheqnRetrievalSolution< T > solver_mva_cacheqn_retrieval_analyzer(const qn::NetworkStruct< T > &L, const MvaOptions &opt)
Port of solver_mva_cacheqn_retrieval_analyzer.m.
MvaSolution< T > solver_mva_oi_analyzer(const qn::NetworkStruct< T > &L, const MvaOptions &opt)
Port of solver_mva_oi_analyzer.m.
MvaSolution< T > solver_rqt(const qn::NetworkStruct< T > &L, const MvaOptions &opt)
DispatchResult< T > solver_mva_qsys_analyzer(const qn::NetworkStruct< T > &L, const MvaOptions &opt)
Port of solver_mva_qsys_analyzer.m: the closed forms for a single-class open Source-Queue-Sink model.
DispatchResult< T > solver_mva_dps_exact(const qn::NetworkStruct< T > &L, const MvaOptions &opt)
The exact multiclass M/M/1-DPS solve the reference inlines in mvaDispatch: the truncated multiclass c...
MvaSolution< T > solver_amva(const qn::NetworkStruct< T > &L, const ChainDemands< T > &d, MvaOptions opt, const Matrix< T > &init_sol, bool &converged)
bool nc_is_oi_model(const qn::NetworkStruct< T > &L)
Port of nc_is_oi_model: whether the model as a WHOLE is order-independent, which is a strictly strong...
MvaSolution< T > solver_mva_retrieval_analyzer(const qn::NetworkStruct< T > &L, const MvaOptions &opt, MvaRetrievalCacheOutputs< T > *cache_out=nullptr)
MvaSolution< T > solver_mva_analyzer(const qn::NetworkStruct< T > &L, const MvaOptions &opt, const Matrix< T > &init_sol)
Port of solver_mva_analyzer.m, default and the explicit method names.
DispatchResult< T > mva_dispatch(const qn::NetworkStruct< T > &L, const MvaOptions &opt, const Matrix< T > &init_sol)
The ladder itself.
ChainDemands< T > sn_get_demands_chain(const qn::NetworkStruct< T > &L)
Port of sn_get_demands_chain.
MarieResult< T > pfqn_marie(const Matrix< T > &L, const std::vector< int > &N, const std::vector< T > &Z, const Matrix< T > &scv, double tol, int maxiter, const std::vector< int > &nservers)
Marie's method for a closed network with FCFS Coxian service.
GigkRqtResult< T > qsys_gigk_rqt(const T &lambda, const T &mu, const T &Gamma_a, const T &Gamma_s, std::size_t k, const T &alpha_a, const T &alpha_s)
Robust Queueing Theory (RQT) worst-case system time of a G/G/k FCFS queue.
QsysQedResult< T > qsys_mmk_qed(const T &lambda, const T &mu, unsigned s)
Halfin-Whitt QED approximation for the M/M/s queue, and the square-root staffing rule that inverts it...
QsysResult< T > qsys_gigk_approx_kingman(const T &lambda, const T &mu, const T &ca, const T &cs, unsigned k)
Kingman (Lee-Longton) scaling of the exact M/M/k waiting time.
QsysResult< T > qsys_mm1(const T &lambda, const T &mu)
Exact mean response time of the M/M/1 queue.
Gig1ExtremalResult< T > qsys_gig1_bnds_extremal(const T &lambda, const T &mu, const T &ca, const T &cs, std::size_t K=4000, std::size_t N=2000, bool skipTight=false)
Extremal two-moment bounds for the GI/GI/1 queue.
QsysResult< T > qsys_gigk_approx(const T &lambda, const T &mu, const T &ca, const T &cs, unsigned k)
Default G/I/G/k approximation of the mean response time.
QsysGgnmResult< T > qsys_ggnm_diffusion(const T &lambda, const T &mu, unsigned n, double m, const T &ca, const T &cs, const std::function< T(const T &)> &serviceCcdf=std::function< T(const T &)>(), double tol=1e-12, std::size_t panels=4000)
Diffusion approximation for the G/GI/n/m queue.
Mg1DisciplineResult< T > qsys_mg1_srpt(const std::vector< T > &lambda, const std::vector< T > &mu, const std::vector< T > &cs)
M/G/1 under SRPT (shortest remaining processing time), by the Schrage-Miller formula.
QsysAbandonResult< T > qsys_erlanga(const T &lambda, const T &mu, const T &theta, unsigned s, double r=std::numeric_limits< double >::infinity(), const MgisrgiOptions &opts=MgisrgiOptions())
Exact analysis of the Erlang A model M/M/s/r+M.
T qsys_gm1(const T &sigma, const T &mu)
Exact mean response time of the G/M/1 queue.
QsysResult< T > qsys_gig1_approx_gelenbe(const T &lambda, const T &mu, const T &ca, const T &cs)
Gelenbe diffusion approximation with instantaneous-return boundary.
QsysResult< T > qsys_gig1_approx_marchal(const T &lambda, const T &mu, const T &ca, const T &cs)
Marchal approximation of the mean response time of a G/I/G/1 queue.
Mg1DisciplineResult< T > qsys_mg1_fb(const std::vector< T > &lambda, const std::vector< T > &mu, const std::vector< T > &cs)
M/G/1 under FB (feedback), also called LAS (least attained service).
QsysAbandonResult< T > qsys_mgisrgi_whitt(const T &lambda, const T &mu, unsigned s, double r, const Patience< T > &patience, const MgisrgiOptions &opts=MgisrgiOptions())
Engineering solution of the call-center model M/GI/s/r+GI.
QsysResult< T > qsys_gigk_approx_whitt(const T &lambda, const T &mu, const T &ca, const T &cs, unsigned k)
Whitt (1993) approximation for the GI/G/k queue, eqs.
Mg1DisciplineResult< T > qsys_mg1_lrpt(const std::vector< T > &lambda, const std::vector< T > &mu, const std::vector< T > &cs)
M/G/1 under LRPT (longest remaining processing time).
PhM1Result< T > qsys_phm1(const std::vector< T > &alpha, const Matrix< T > &Tm, const T &mu, const T &tol)
Exact PH/M/1, the GI/M/1 queue with phase-type interarrival times.
Mm1DpsResult< T > qsys_mm1_dps(const std::vector< T > &lambda, const std::vector< T > &mu, const std::vector< T > &w, const T &tol, unsigned maxCutoff)
Multiclass M/M/1 under DPS (discriminatory processor sharing), solved numerically on the truncated po...
QsysResult< T > qsys_mg1(const T &lambda, const T &mu, const T &cs)
Exact mean response time of the M/G/1 queue (Pollaczek-Khinchine).
QsysResult< T > qsys_gig1_approx_kobayashi(const T &lambda, const T &mu, const T &ca, const T &cs)
Kobayashi diffusion approximation for the G/I/G/1 queue.
Mg1kLossMgsResult< T > qsys_mg1k_loss_mgs(const T &lambda, const T &mu, const T &mu_scv, unsigned K)
MacGregor Smith's closed-form approximation of the M/G/1/K loss probability.
T qsys_gigk_rqt_gamma(const T &rho, const T &mu, const T &Gamma_a, const T &sigma_s, std::size_t k, const T &alpha_a, const std::string ®ime="independent")
Service variability parameter of the Robust Queueing Theory (RQT) framework.
QsysResult< T > qsys_gig1_approx_allencunneen(const T &lambda, const T &mu, const T &ca, const T &cs)
Allen-Cunneen approximation of the mean response time of a G/I/G/1 queue.
QsysResult< T > qsys_mmk(const T &lambda, const T &mu, unsigned k)
Exact mean response time of the M/M/k queue (Erlang-C).
QsysResult< T > qsys_gig1_approx_heyman(const T &lambda, const T &mu, const T &ca, const T &cs)
Heyman approximation of the mean response time of a G/I/G/1 queue.
QsysResult< T > qsys_gg1(const T &lambda, const T &mu, const T &ca2, const T &cs2)
G/G/1 dispatcher: exact where a two-moment description determines the answer, Allen-Cunneen otherwise...
QsysResult< T > qsys_gig1_approx_klb(const T &lambda, const T &mu, const T &ca, const T &cs)
Kraemer and Langenbach-Belz approximation for the G/I/G/1 queue.
Mg1PrioResult< T > qsys_mg1_prio(const std::vector< T > &lambda, const std::vector< T > &mu, const std::vector< T > &cs)
M/G/1 with non-preemptive head-of-line priorities: per-class mean response times from the Cobham/Klei...
Mg1DisciplineResult< T > qsys_mg1_psjf(const std::vector< T > &lambda, const std::vector< T > &mu, const std::vector< T > &cs)
M/G/1 under PSJF (preemptive shortest job first).
QsysResult< T > qsys_gig1_ubnd_kingman(const T &lambda, const T &mu, const T &ca, const T &cs)
Kingman upper bound on the mean waiting time of a G/G/1 queue.
Mg1DisciplineResult< T > qsys_mg1_setf(const std::vector< T > &lambda, const std::vector< T > &mu, const std::vector< T > &cs)
M/G/1 under SETF (shortest elapsed time first), the non-preemptive counterpart of FB/LAS.
Gig1RqResult< T > qsys_gig1_rq(const T &rho, const T &mu, const T &cs2, IaFun &&IaFun_)
Robust Queueing (RQ) approximation of a G/GI/1 queue characterized by its arrival index of dispersion...
QsysResult< T > qsys_gig1_approx_kimura(const T &lambda, const T &mu, const T &ca, const T &cs)
Kimura diffusion-interpolation approximation for the G/I/G/1 queue.
CacheMetrics< T > cache_metrics_of(const qn::NetworkStruct< T > &sn, const std::vector< T > &hitprob, const std::vector< T > &missprob, const std::vector< T > &delayedprob, const std::vector< T > &latency, const Matrix< T > &hitproblist, const Matrix< T > &itemprob, const std::vector< T > &listcost)
Assemble CacheMetrics from what a cache analyzer returned.
CacheMetrics< T > cache_metrics_of_matrix(const qn::NetworkStruct< T > &sn, const Matrix< T > &hitprob, const Matrix< T > &missprob)
The same, for the integrated caching-queueing branch, whose hit and miss probabilities are (ncaches x...
RootResult< T > root_brent(F f, const T &a0, const T &b0, const T &tol, unsigned maxiter=200)
Brent's method on a bracket with a sign change.
A queueing network and its refreshed NetworkStruct.
Marie's iterative aggregation-decomposition for closed networks with FCFS general (Coxian) service.
G/G/1 dispatcher: exact where a two-moment description determines the answer, Allen-Cunneen otherwise...
Diffusion approximation for the G/GI/n/m queue.
Allen-Cunneen approximation of the mean response time of a G/I/G/1 queue.
Gelenbe diffusion approximation with instantaneous-return boundary.
Heyman approximation of the mean response time of a G/I/G/1 queue.
Kimura diffusion-interpolation approximation for the G/I/G/1 queue.
Kraemer and Langenbach-Belz approximation for the G/I/G/1 queue.
Kobayashi diffusion approximation for the G/I/G/1 queue.
Marchal approximation of the mean response time of a G/I/G/1 queue.
Extremal two-moment bounds for the GI/GI/1 queue.
Robust Queueing (RQ) approximation of a G/GI/1 queue characterized by its arrival index of dispersion...
Kingman upper bound on the mean waiting time of a G/G/1 queue.
Default G/I/G/k approximation of the mean response time.
Kingman (Lee-Longton) scaling of the exact M/M/k waiting time.
Whitt (1993) approximation for the GI/G/k queue, eqs.
Robust Queueing Theory (RQT) worst-case system time of a G/G/k FCFS queue.
Service variability parameter of the Robust Queueing Theory (RQT) framework.
Exact mean response time of the G/M/1 queue.
Exact mean response time of the M/G/1 queue (Pollaczek-Khinchine).
M/G/1 under FB (feedback), also called LAS (least attained service).
M/G/1 under LRPT (longest remaining processing time).
M/G/1 with non-preemptive head-of-line priorities: per-class mean response times from the Cobham/Klei...
M/G/1 under PSJF (preemptive shortest job first).
M/G/1 under SETF (shortest elapsed time first), the non-preemptive counterpart of FB/LAS.
M/G/1 under SRPT (shortest remaining processing time), by the Schrage-Miller formula.
MacGregor Smith's closed-form approximation of the M/G/1/K loss probability.
Engineering solution of the call-center model M/GI/s/r+GI.
Exact mean response time of the M/M/1 queue.
Multiclass M/M/1 under DPS (discriminatory processor sharing), solved numerically on the truncated po...
Exact mean response time of the M/M/k queue (Erlang-C).
Halfin-Whitt QED approximation for the M/M/s queue, and the square-root staffing rule that inverts it...
Exact PH/M/1, the GI/M/1 queue with phase-type interarrival times.
Deterministic scalar root finding.
Port of matlab/src/api/sn/sn_has_bursty_arrival.m.
Port of matlab/src/api/sn/sn_patience_handles.m.
SolverMVA method 'amva.mapqn': the horizontal-cut mean value analysis (mapqn_amva) of a closed multic...
SolverMVA over a SolverLN layer.
The non-reentrant cache analyzer: a Source-Cache-Sink model.
Integrated caching-queueing analyzer, a port of matlab/src/solvers/MVA/solver_mva_cacheqn_analyzer....
Port of solver_mva_cacheqn_retrieval_analyzer.m: a CLOSED integrated cache-queueing model whose Cache...
Exact mean-value analysis for networks with order-independent stations.
The multiclass open polling analyzer (ladder branch 5).
Delayed-hit (retrieval-system) cache analyzer, a port of matlab/src/solvers/MVA/solver_mva_retrieval_...
Closed networks with shortest-job-next (SJF) stations, ladder branch 0.
MVAC, exact mean value analysis BY CHAIN (Conway, de Souza e Silva and Lavenberg, IEEE Trans.
QNA, the two-moment open-network decomposition analyzer.
Robust Queueing Network Analyzer (RQNA), a port of matlab/src/solvers/MVA/solver_rqna....
Robust Queueing Network Analyzer (RQNA) of Robust Queueing Theory, a port of matlab/src/solvers/MVA/s...
Outcome of a scalar solve.
bool converged
tolerance was met before the iteration cap
T root
best estimate of the root
The patience law of one station-class pair, in the forms the solvers consume.
qsys::Patience< T > as_patience() const
This law as the Patience argument of the abandonment solvers.
bool present
Whether the pair declares reneging at all; everything below is unset when false.
bool isExponential
Whether the law is exponential, in which case the analysis is exact.
T rate
The abandonment rate 1/mean.
bool has_map() const
True when the type carries a (D0,D1) pair of its own.
A MAP as the pair of matrices (D0, D1).
What the cache analyzer reports beyond the [Q,U,R,T] block.
std::vector< T > hitprob
per class, NaN where the class does not read
std::vector< T > missprob
Matrix< T > itemprob
(n x h+1) per-item occupancy, column 0 = miss.
Matrix< T > hitproblist
(R x h) per-list hit fractions, access-weighted over items.
The chain-level view of a layer, as sn_get_demands_chain returns it.
std::vector< double > Nchain
(C) population, infinite for an open chain
Matrix< T > STchain
(M x C) mean service time
Matrix< T > Lchain
(M x C) demand
Matrix< T > Vchain
(M x C) visits
Matrix< T > SCVchain
(M x C)
Class-level results, as sn_deaggregate_chain_results returns them.
What the dispatch returns: the metrics plus the algorithm that produced them.
std::string actualmethod
The concrete algorithm, as the reference's actualmethod.
std::string warning
Non-empty when the analyzer that ran would have raised a reference line_warning and still returned a ...
solvers::CacheMetrics< T > cache
What a cache branch measured, EMPTY on every model without a Cache.
std::shared_ptr< qn::NetworkStruct< T > > refreshed_struct
Set only by the integrated cacheqn branch: the converged struct whose routing carries the actual hit/...
The cache half of the reference's return list: the (ncaches x nclasses) hit and miss split,...
Matrix< T > missprob
(ncaches x nclasses)
Matrix< T > hitprob
(ncaches x nclasses)
std::vector< Matrix< T > > itemprob
per cache, (n x h+1); EMPTY = not computed
What the closed delayed-hit analyzer returns.
std::vector< T > delayedprob
(K) zero on this path, by the reference's convention
Matrix< T > hitproblist
(K x h) NaN: not computed on this path
std::vector< T > missprob
(K) the delayed fraction is folded in here
std::vector< T > latency
(K) NaN: not computed on this path
std::vector< T > hitprob
(K) P(item cached), read class only
The options SolverMVA reads.
The cache half of the reference's return list: hitprob, missprob, delayedprob, latency,...
std::vector< T > missprob
Matrix< T > itemprob
(n x h+1), column 0 = miss
Matrix< T > hitproblist
(K x h)
std::vector< T > delayedprob
Class-level results, the [Q,U,R,T,C,X] of the MATLAB analyzers.
What the analyzer returns, the reference's metrics plus its actualmethod.
std::string warning
Non-empty when the reference would have called line_warning AND RETURNED, carrying its text.
Result of pfqn_marie, mirroring the six MATLAB outputs.
int it
iterations performed
Matrix< T > Q
(M x R) mean queue length
std::vector< T > X
(R) per-class throughput
Matrix< T > U
(M x R) utilization
One job class of the network.
double population
infinite for an open class
One station of the network.
Steady-state measures of a multiserver queue with customer abandonment.
T utilization
E[min(N,s)]/s.
T throughput
lambda(1-P_loss)P(S)
Steady-state measures of the G/GI/n/m diffusion approximation.
T throughput
lambda(1-P(block))
T meanNumber
mean number in system
Every Cache node of the model, in node order; empty on a model with none.