5#ifndef LINE_SOLVERS_MVA_MVA_DISPATCH_H
6#define LINE_SOLVERS_MVA_MVA_DISPATCH_H
154 int src = 0, q = 0, snk = 0;
156 if (nd.
nodetype == qn::NodeType::Source) ++src;
157 else if (nd.
nodetype == qn::NodeType::Queue) ++q;
158 else if (nd.
nodetype == qn::NodeType::Sink) ++snk;
160 return src == 1 && q == 1 && snk == 1 && L.
nclosedjobs() == 0.0;
187inline bool qsys_serves_method(
const std::string& method) {
202bool has_state_dependent_rates(
const qn::NetworkStruct<T>& L) {
203 for (
const auto& st : L.stations)
204 if (!st.lldscaling.empty() || st.cdscaling || st.jdscaling)
return true;
210bool is_open_scs(
const qn::NetworkStruct<T>& L) {
211 if (L.nof_nodes() != 3)
return false;
212 int src = 0, ca = 0, snk = 0;
213 for (
const qn::NodeDef& nd : L.nodes) {
214 if (nd.nodetype == qn::NodeType::Source) ++src;
215 else if (nd.nodetype == qn::NodeType::Cache) ++ca;
216 else if (nd.nodetype == qn::NodeType::Sink) ++snk;
218 return src == 1 && ca == 1 && snk == 1 && L.nclosedjobs() == 0.0;
223 return s == qn::SchedStrategy::SRPT || s == qn::SchedStrategy::PSJF ||
224 s == qn::SchedStrategy::FB || s == qn::SchedStrategy::LRPT ||
225 s == qn::SchedStrategy::SETF;
230std::size_t station_of_type(
const qn::NetworkStruct<T>& L,
qn::NodeType ty) {
231 for (std::size_t i = 0; i < L.nof_nodes(); ++i)
232 if (L.nodes[i].nodetype == ty)
return L.nodes[i].station;
238bool row_is_exponential(
const qn::NetworkStruct<T>& L, std::size_t ist) {
239 for (std::size_t r = 0; r < L.nclasses; ++r) {
240 if (L.disabled[ist - 1][r])
continue;
241 const double v = num_traits<T>::to_double(L.scv(ist - 1, r));
242 if (!std::isfinite(v))
continue;
243 if (std::fabs(v - 1.0) >= 1e-6)
return false;
267 "solver_mva_qsys_analyzer: the open queueing-system closed forms need transcendental "
268 "arithmetic; rerun this model with --arith double or --arith real");
272 const std::size_t src = detail::station_of_type(L, qn::NodeType::Source);
273 const std::size_t q = detail::station_of_type(L, qn::NodeType::Queue);
274 if (src == 0 || q == 0)
throw InputError(
"solver_mva_qsys_analyzer: no Source-Queue pair");
279 const T Vq = L.
visits[0](qstateful - 1, 0);
280 const T srcRate = L.
rates(src - 1, 0);
281 const T lambda = T(srcRate * Vq);
282 const T mu = L.
rates(q - 1, 0);
283 const double k = L.
stations[q - 1].nservers;
284 const unsigned ku = std::isfinite(k) ?
static_cast<unsigned>(std::llround(k)) : 1u;
297 if (
opt.method ==
"exact")
299 "solver_mva_qsys_analyzer: M/M/1/K tail-drop is solved by the approximate "
300 "'mg1k.mgs' method (MacGregor Smith); it is not available under method='exact'. "
301 "Use the default method, or SolverCTMC/SolverNC for an exact result");
302 const double Kcap = L.
cap[q - 1];
303 const T rho = T(lambda / mu);
307 const T Tq = T(lambda * (one - Ploss));
310 if (std::fabs(rhod - 1.0) < 1e-10) {
314 const T rKp1 = qsys::detail::num_pow(rho, Kp1);
315 Lsys = T(rho / (one - rho) - Kp1 * rKp1 / (one - rKp1));
323 ls.
X.assign(1, zero);
324 ls.
C.assign(1, zero);
327 ls.
R(q - 1, 0) = T(Lsys / Tq);
328 ls.
Q(q - 1, 0) = Lsys;
329 ls.
U(q - 1, 0) = T(Tq / mu);
330 ls.
Tp(q - 1, 0) = Tq;
331 ls.
Tp(src - 1, 0) = lambda;
333 ls.
C[0] = T(ls.
R(q - 1, 0) * Vq);
342 if (method ==
"exact") {
343 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";
349 "solver_mva_qsys_analyzer: no exact closed form for this queueing system "
350 "(neither arrivals nor service are exponential, or it has several servers)");
351 }
else if (method ==
"default") {
356 else if (ca1 && cs1 && ku == 1) method =
"mm1";
357 else if (ca1 && cs1 && ku > 1) method =
"mmk";
358 else if (ca1 && ku == 1) method =
"mg1";
359 else if (cs1 && ku == 1) method =
"gm1";
360 else if (ku > 1) method =
"gigk";
361 else method =
"gig1.klb";
368 if (method ==
"erlanga" || method ==
"mgisrgi" || method ==
"gigk.diffusion") {
369 const double cap = L.
cap[q - 1];
371 const double room = std::isfinite(cap)
372 ? std::max(0.0, cap -
static_cast<double>(ku))
373 : std::numeric_limits<double>::infinity();
374 T Lsys = zero, Tq = zero, Uq = zero;
375 if (method ==
"gigk.diffusion") {
383 "' needs a reneging patience law on the queue");
400 as.
X.assign(1, zero);
401 as.
C.assign(1, zero);
406 as.
R(q - 1, 0) = Tq > zero ? T(Lsys / Tq) : zero;
407 as.
Q(q - 1, 0) = Lsys;
409 as.
Tp(q - 1, 0) = Tq;
410 as.
Tp(src - 1, 0) = srcRate;
412 as.
C[0] = T(as.
R(q - 1, 0) * Vq);
420 else if (method ==
"mg1" || method ==
"mgi1") R =
qsys::qsys_mg1(lambda, mu, cs).W;
422 else if (method ==
"gigk.kingman_approx")
426 else if (method ==
"gig1" || method ==
"gig1.allen")
440 else if (method ==
"rqna") {
443 const T rho1 = lambda / mu;
446 }
else if (method ==
"rqt") {
449 const T Gamma_a = ca / lambda;
455 else if (method ==
"qed") R = T(
qsys::qsys_mmk_qed(lambda, mu, ku).meanWait + one / mu);
457 else if (method ==
"gig1.extremal")
459 else if (method ==
"gm1" || method ==
"gim1") {
465 const bool markovian = arv.
has_map();
488 auto f = [&](
const T& x) {
return T(
lang::dist_lst(arv, T(mu - mu * x)) - x); };
490 bool straddles =
false;
491 for (
int i = 0; i < 8; ++i) {
496 hi = 1.0 - (1.0 - hi) / 10.0;
511 "' is not available for a model with one station and one class");
530 s.
Tp(src - 1, 0) = srcRate;
531 s.
Tp(q - 1, 0) = lambda;
532 s.
Q(q - 1, 0) = T(lambda * R);
550 const std::size_t src = detail::station_of_type(L, qn::NodeType::Source);
551 const std::size_t q = detail::station_of_type(L, qn::NodeType::Queue);
553 std::vector<std::size_t> order(K);
554 for (std::size_t r = 0; r < K; ++r) order[r] = r;
555 std::stable_sort(order.begin(), order.end(), [&](std::size_t a, std::size_t b) {
556 return L.classes[a].prio < L.classes[b].prio;
559 std::vector<T> lam(K, zero), mu(K, zero), cs(K, one);
560 for (std::size_t j = 0; j < K; ++j) {
561 const std::size_t r = order[j];
562 lam[j] = L.
rates(src - 1, r);
563 mu[j] = L.
rates(q - 1, r);
579 for (std::size_t j = 0; j < K; ++j) {
580 const std::size_t r = order[j];
582 s.
R(q - 1, r) = W[j];
585 s.
U(q - 1, r) = T(lam[j] / mu[j]);
586 s.
Tp(q - 1, r) = lam[j];
587 s.
Tp(src - 1, r) = lam[j];
588 s.
Q(q - 1, r) = T(lam[j] * W[j]);
605 "solver_mva_dps_exact: the exact DPS closed form needs transcendental arithmetic; "
606 "rerun this model with --arith double or --arith real");
610 const std::size_t src = detail::station_of_type(L, qn::NodeType::Source);
611 const std::size_t q = detail::station_of_type(L, qn::NodeType::Queue);
613 std::vector<T> lam(K, zero), mu(K, zero), w(K, one);
614 for (std::size_t r = 0; r < K; ++r) {
615 lam[r] = L.
rates(src - 1, r);
616 mu[r] = L.
rates(q - 1, r);
617 const std::vector<T>& sp = L.
stations[q - 1].schedparam;
618 if (sp.size() > r && sp[r] > zero) w[r] = sp[r];
632 for (std::size_t r = 0; r < K; ++r) {
633 s.
R(q - 1, r) = Wd[r];
636 if (mu[r] > zero) s.
U(q - 1, r) = T(lam[r] / mu[r]);
637 s.
Tp(q - 1, r) = lam[r];
638 s.
Tp(src - 1, r) = lam[r];
639 s.
Q(q - 1, r) = T(lam[r] * Wd[r]);
663 const bool has_cd_or_jd = [&] {
665 if (st.cdscaling || st.jdscaling)
return true;
669 if (method ==
"exact" || method ==
"mva") {
672 "solver_mvald_analyzer: there is no exact class-/joint-dependent solver in MVA");
678 if (!(method ==
"default" || method ==
"amva" || method ==
"qd" || method ==
"lin" ||
681 "' method is not supported by the load-dependent MVA solver");
683 if (method ==
"default" && !has_cd_or_jd) {
685 bool integral =
true, finite =
true;
687 if (!std::isfinite(c.
population)) finite =
false;
700 bool converged =
true;
708 out.
sol.converged = converged;
737 "solver_mva_qsys_sizebased_analyzer: the M/G/1 size-based closed forms need "
738 "transcendental arithmetic; rerun this model with --arith double or --arith real");
742 const std::size_t src = detail::station_of_type(L, qn::NodeType::Source);
743 const std::size_t q = detail::station_of_type(L, qn::NodeType::Queue);
751 std::vector<std::size_t> chain_of(K, 0);
752 for (std::size_t c = 0; c < L.
nchains; ++c)
753 for (std::size_t r : L.
inchain[c]) chain_of[r - 1] = c;
755 std::vector<T> lambda(K, zero), mu(K, zero), cs(K, one), vis(K, one);
756 for (std::size_t r = 0; r < K; ++r) {
757 vis[r] = L.
visits[chain_of[r]](qstateful - 1, r);
758 lambda[r] = T(L.
rates(src - 1, r) * vis[r]);
759 mu[r] = L.
rates(q - 1, r);
762 if (!(lambda[r] > zero) || !(mu[r] > zero))
764 "solver_mva_qsys_sizebased_analyzer: the arrival and service rates must be "
772 case qn::SchedStrategy::SRPT:
776 case qn::SchedStrategy::PSJF:
780 case qn::SchedStrategy::FB:
784 case qn::SchedStrategy::LRPT:
788 case qn::SchedStrategy::SETF:
793 throw UnsupportedError(std::string(
"solver_mva_qsys_sizebased_analyzer: ") +
807 for (std::size_t r = 0; r < K; ++r) {
808 s.
R(q - 1, r) = T(W[r] * vis[r]);
809 s.
C[r] = s.
R(q - 1, r);
811 s.
U(q - 1, r) = T(lambda[r] / mu[r]);
812 s.
Tp(q - 1, r) = lambda[r];
813 s.
Tp(src - 1, r) = lambda[r];
814 s.
Q(q - 1, r) = T(lambda[r] * W[r]);
839 "solver_mva_marie_analyzer: Marie's aggregation-decomposition needs transcendental "
840 "arithmetic; rerun this model with --arith double or --arith real");
846 for (std::size_t c = 0; c < C; ++c)
847 if (!std::isfinite(d.
Nchain[c]))
849 "solver_mva_marie_analyzer: the 'marie' method supports closed models only; this "
850 "model has open classes");
851 for (
const auto& nd : L.
nodes)
852 if (nd.nodetype == qn::NodeType::Source)
854 "solver_mva_marie_analyzer: the 'marie' method supports closed models only; this "
855 "model has a Source");
857 std::vector<std::size_t> qrows, drows;
858 for (std::size_t i = 0; i < M; ++i) {
860 const bool delay = std::isinf(L.
stations[i].nservers) || sc == qn::SchedStrategy::INF;
865 if (!(sc == qn::SchedStrategy::FCFS || sc == qn::SchedStrategy::PS ||
866 sc == qn::SchedStrategy::LCFSPR))
867 throw UnsupportedError(std::string(
"solver_mva_marie_analyzer: the 'marie' method "
868 "supports FCFS, PS, LCFSPR and Delay stations "
874 std::vector<T> Z(C, zero);
875 for (std::size_t c = 0; c < C; ++c)
876 for (std::size_t i : drows) Z[c] += d.
Lchain(i, c);
878 const std::size_t Mq = qrows.size();
879 Matrix<T> Lq(Mq, C, zero), SCV(Mq, C, one);
880 std::vector<int> ns(Mq, 1);
881 bool multiserver =
false;
882 for (std::size_t a = 0; a < Mq; ++a) {
883 const std::size_t i = qrows[a];
884 const double srv = L.
stations[i].nservers;
885 ns[a] = std::isfinite(srv) ?
static_cast<int>(std::llround(srv)) : 1;
886 if (ns[a] > 1) multiserver =
true;
887 for (std::size_t c = 0; c < C; ++c) {
888 Lq(a, c) = d.
Lchain(i, c);
889 if (L.
stations[i].sched != qn::SchedStrategy::FCFS)
continue;
894 if (C > 1 && multiserver)
896 "solver_mva_marie_analyzer: the 'marie' method supports multiserver stations for "
897 "single-chain models only");
899 std::vector<int> N(C, 0);
900 for (std::size_t c = 0; c < C; ++c) N[c] = static_cast<int>(std::llround(d.
Nchain[c]));
906 mr.
X.assign(C, zero);
910 for (std::size_t c = 0; c < C; ++c)
917 Matrix<T> Qchain(M, C, zero), Uchain(M, C, zero), Rchain(M, C, zero), Tchain(M, C, zero);
918 for (std::size_t a = 0; a < Mq; ++a)
919 for (std::size_t c = 0; c < C; ++c) {
920 Qchain(qrows[a], c) = mr.
Q(a, c);
921 Uchain(qrows[a], c) = mr.
U(a, c);
923 for (std::size_t i = 0; i < M; ++i)
924 for (std::size_t c = 0; c < C; ++c) Tchain(i, c) = T(mr.
X[c] * d.
Vchain(i, c));
925 for (std::size_t i = 0; i < M; ++i)
926 for (std::size_t c = 0; c < C; ++c)
927 if (Tchain(i, c) > zero) Rchain(i, c) = T(Qchain(i, c) / Tchain(i, c));
929 for (std::size_t i : drows)
930 for (std::size_t c = 0; c < C; ++c) {
931 Qchain(i, c) = T(Tchain(i, c) * d.
STchain(i, c));
932 Uchain(i, c) = Qchain(i, c);
933 Rchain(i, c) = d.
STchain(i, c);
945 out.
sol.method =
opt.method;
946 out.
sol.iter = mr.
it;
973 for (
const auto& c : L.
classes)
974 if (std::isinf(c.population)) open =
true;
977 "SolverMVA supports shortest-job-next (SJF) scheduling only in closed models, the "
978 "conditional waiting time equation being a population recursion. Use SolverLDES, "
979 "or SolverMVA with SRPT or PSJF for the preemptive size-based open queue");
1002 const bool has_oi_station = std::any_of(
1004 return st.sched == SchedStrategy::OI || st.sched == SchedStrategy::PAS;
1006 const bool exact_method = (
opt.method ==
"default" ||
opt.method ==
"exact");
1015 "SolverMVA supports order-independent (OI) and pass-and-swap (PAS) stations only "
1016 "through its exact order-independent analyzer, which requires method 'default' or "
1017 "'exact' (got '" +
opt.method +
1018 "'), an empty/zero swap graph at every OI/PAS station, a closed model, and every "
1019 "other station to be product-form (INF, PS, LCFS-PR, SIRO, or "
1020 "class-independent-rate FCFS). Use SolverCTMC or SolverLDES for this model");
1033 if (kv.second.retrieval_capacity <= 0)
continue;
1035 if (detail::station_of_type(L, NodeType::Source) == 0) {
1052 const bool sqs = detail::is_open_sqs(L);
1053 const std::size_t qst = detail::station_of_type(L, NodeType::Queue);
1055 const std::size_t srcst = detail::station_of_type(L, NodeType::Source);
1058 if (detail::is_open_scs(L)) {
1081 for (std::size_t ci = 0; ci < qout.
cache.caches.size() && ci < co.
itemprob.size(); ++ci)
1108 ((detail::qsys_serves_method(method) && !detail::has_state_dependent_rates(L)) ||
1113 if (sqs && L.
nclasses > 1 && qsched == SchedStrategy::POLLING) {
1121 if (sqs && L.
nclasses > 1 && qsched == SchedStrategy::HOL &&
1122 L.
stations[qst - 1].nservers == 1.0 && detail::row_is_exponential(L, srcst))
1126 if (sqs && L.
nclasses > 1 && L.
nclasses <= 3 && qsched == SchedStrategy::DPS &&
1127 L.
stations[qst - 1].nservers == 1.0 && detail::row_is_exponential(L, srcst) &&
1128 detail::row_is_exponential(L, qst))
1132 static const char* kBounds[] = {
"aba.upper",
"aba.lower",
"bjb.upper",
"bjb.lower",
1133 "pb.upper",
"pb.lower",
"gb.upper",
"gb.lower",
1134 "sb.upper",
"sb.lower",
"mw.upper",
"mw.lower"};
1135 for (
const char* b : kBounds)
1137 throw UnsupportedError(
"SolverMVA: bound methods have moved to SolverBA; use "
1138 "SolverBA with method '" +
1155 if (method ==
"mvac") {
1165 if (method ==
"qna") {
1174 if (method ==
"rqna") {
1182 if (method ==
"rqt") {
1190 if (method ==
"amva.mapqn" || method ==
"mapqn") {
1204 bool all_open =
true;
1205 for (std::size_t r = 0; r < L.
nclasses; ++r)
1206 if (std::isfinite(L.
classes[r].population)) all_open =
false;
1216 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.
bool mva_qsys_serves_method(const std::string &method)
The method names solver_mva_qsys_analyzer has an arm for.
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...
Conservation laws of a layered queueing network, enumerated from its structure.
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.
The DECLARED side of the gate: one feature set per solver.
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.