5#ifndef LINE_SOLVERS_NC_SOLVER_NC_RUNNER_H
6#define LINE_SOLVERS_NC_SOLVER_NC_RUNNER_H
93 return {
"default",
"exact",
"rayint",
"spm",
"erlangfp",
"mci",
"imci",
"ls",
"le",
94 "ble",
"aghq",
"mmint2",
"gleint",
"pana",
"panald",
"ca",
"clw",
"kt",
"bkt",
"lekt",
95 "bk",
"bkue",
"lc",
"lc.ue",
96 "sampling",
"is",
"propfair",
"comom",
"cub",
"rgf",
108 "nrl",
"nre",
"gm",
"mem",
"comomld",
"ms",
132 "cftp",
"cftp.approx"};
145 std::vector<std::string> toks;
146 for (
char ch : method) {
147 if (ch ==
'.' || ch ==
'/') {
151 tok +=
static_cast<char>(std::tolower(
static_cast<unsigned char>(ch)));
155 for (
const std::string& t : toks)
156 if (t ==
"mci" || t ==
"imci" || t ==
"ls" || t ==
"sampling" || t ==
"is" ||
179 if (method !=
"default")
return method;
181 for (std::size_t i = 0; i < L.
nstations; ++i)
182 for (std::size_t r = 0; r < L.
nclasses; ++r) {
193 if (std::find(valid.begin(), valid.end(), method) != valid.end())
return;
194 throw UnsupportedError(
"SolverNC: the '" + method +
"' method is unsupported by this solver");
222bool multiserver_to_lld(qn::NetworkStruct<T>& sn) {
224 for (
const qn::JobClass& c : sn.classes) {
225 if (std::isinf(c.population))
return false;
228 const std::size_t n =
static_cast<std::size_t
>(std::llround(Nt));
229 if (n < 1)
return false;
230 for (std::size_t i = 0; i < sn.nstations; ++i) {
231 std::vector<T> lld(n, num_traits<T>::from_int(1));
232 const double c = sn.stations[i].nservers;
233 if (std::isfinite(c) && c > 1.0)
234 for (std::size_t k = 1; k <= n; ++k)
236 num_traits<T>::from_double(std::min<double>(
static_cast<double>(k), c));
237 sn.stations[i].lldscaling = lld;
254inline std::string nc_multiserver_policy(
const std::string& requested,
255 std::string* warning =
nullptr) {
256 if (requested.empty() || requested ==
"default")
return "default";
257 if (requested ==
"seidmann")
return "seidmann";
258 if (requested ==
"lld" || requested ==
"exact" || requested ==
"loaddep" ||
259 requested ==
"load-dependent")
261 if (warning !=
nullptr)
262 *warning =
"SolverNC does not implement config.multiserver='" + requested +
263 "' (it is a SolverMVA approximation); using 'default'. SolverNC accepts "
264 "'default', 'seidmann' and 'lld'.";
273double nc_population_lattice(
const qn::NetworkStruct<T>& sn) {
274 double lattice = 1.0;
275 if (!sn.chains.empty()) {
277 for (std::size_t c = 0; c < sn.chains.size(); ++c) {
279 for (std::size_t r = 0; r < sn.nclasses && r < sn.chains[c].size(); ++r)
280 if (sn.chains[c][r]) {
281 const double v = sn.classes[r].population;
282 if (std::isfinite(v)) popc += v;
284 lattice *= (1.0 + popc);
287 for (
const qn::JobClass& c : sn.classes)
288 if (std::isfinite(c.population)) lattice *= (1.0 + c.population);
317 if (
sn.has_open_classes())
return true;
318 const std::size_t M =
sn.nstations, C =
sn.nchains;
319 const std::vector<double> Nchain = detail::chain_population(
sn);
321 for (std::size_t c = 0; c < C; ++c)
322 if (std::isfinite(Nchain[c])) NtD += Nchain[c];
323 const std::size_t Nt =
static_cast<std::size_t
>(std::llround(NtD));
324 if (Nt < 1)
return true;
328 std::vector<double> Ztot(C, 0.0);
329 for (std::size_t i = 0; i < M; ++i)
330 if (std::isinf(
sn.stations[i].nservers))
331 for (std::size_t c = 0; c < C; ++c)
333 for (std::size_t c = 0; c < C; ++c)
334 if (Nchain[c] > 0.0 && !(Ztot[c] > 0.0))
337 for (std::size_t i = 0; i < M; ++i) {
338 const double nserv =
sn.stations[i].nservers;
339 if (std::isinf(nserv))
continue;
340 const std::vector<T>& lld =
sn.stations[i].lldscaling;
344 else if (nserv > 1.0)
345 muK = std::min(
static_cast<double>(Nt), nserv);
348 if (!(muK > 0.0) || !std::isfinite(muK))
return false;
350 for (std::size_t c = 0; c < C; ++c)
353 if (!(1.0 - lambda / muK > 0.0))
return false;
370 const std::size_t M =
sn.nstations, C =
sn.nchains;
371 const std::vector<double> Nchain = detail::chain_population(
sn);
372 bool any_closed =
false;
373 std::vector<bool> closed(C,
false);
374 for (std::size_t c = 0; c < C; ++c) {
375 closed[c] = std::isfinite(Nchain[c]) && Nchain[c] > 0.0;
376 if (closed[c]) any_closed =
true;
378 if (!any_closed)
return 0;
382 for (std::size_t i = 0; i < M; ++i) {
383 if (std::isinf(
sn.stations[i].nservers))
continue;
384 for (std::size_t c = 0; c < C; ++c)
437 bool slotted =
false,
bool for_report =
true) {
438 const std::string m = method.empty() ? std::string(
"default") : method;
443 if (slotted)
return "";
457 if (m !=
"default" && m !=
"morrison")
458 return "SolverNC: method '" + m +
459 "' cannot represent the DPS weights of a discriminatory processor-sharing "
460 "station; it would return the egalitarian-PS network. Use method 'default' or "
461 "'morrison' (npfqn_dps_morrison), SolverMVA, SolverFLD or SolverCTMC.";
468 return "SolverNC analyzes a discriminatory processor-sharing station only in the shape "
469 "Morrison's expansion is derived for: a CLOSED network of exactly two stations, one "
470 "infinite-server (think) station and one single-server DPS station, exponential "
471 "service, each class visiting the two equally often. Use SolverMVA, SolverFLD or "
472 "SolverCTMC for any other DPS model.";
478 return "SolverNC: method 'morrison' is the heavy-usage expansion of a CLOSED network of "
479 "exactly two stations, one infinite-server (think) station and one single-server DPS "
480 "station with exponential service, which this model is not. Remove the method option "
481 "to let SolverNC choose, or use SolverMVA, SolverFLD or SolverCTMC.";
486 if (!
sn.sdr.branch.empty())
return "";
487 if (m ==
"sdr" || m ==
"sdr.mva")
488 return "SolverNC: method '" + m +
489 "' requires state-dependent routing, which this model does not declare.";
495 for (std::size_t ind = 0; ind <
sn.nodes.size(); ++ind)
497 if (m !=
"default" && m !=
"rec")
498 return "solver_nc: a stochastic Petri net is solved by the MDD-rec route; method '" +
499 m +
"' is a normalizing-constant algorithm for queueing networks. Use 'rec' "
509 if (m !=
"default" && m !=
"exact" && m !=
"is" && m !=
"sampling")
510 return "SolverNC: method '" + m +
511 "' cannot represent the rank rate mu(n) of an order-independent station; use "
512 "method 'default' or 'exact' (pfqn_ncoi), 'is', SolverMVA, or SolverCTMC.";
520 for (std::size_t ind = 0; ind <
sn.nodes.size(); ++ind)
521 if (
sn.nodes[ind].nodetype == qn::NodeType::Cache) {
523 const auto itp =
sn.nodeparam.find(ind + 1);
527 if (itp !=
sn.nodeparam.end() &&
530 return "solver_nc_cache_analyzer: NC does not support the exact solution of "
531 "this cache replacement policy -- only RR and FIFO are exchangeable, "
532 "and a recency-based policy (LRU, h-LRU, q-LRU, CLIMB) would silently "
533 "receive the exchangeable answer. Use the default (approximate) method "
538 if (m ==
"rayint" || m ==
"spm")
539 return "SolverNC: method " + m +
540 " names the SPM saddle point of a cache and, on a retrieval model, the ray/WKB "
541 "delayed-hit expansion; this model declares no Cache node.";
546 return "SolverNC: the Finite Capacity Region holds a single infinite server but does not "
547 "apply DROP to every class; holding an arrival back (WAITQ) or blocking the server "
548 "(BAS/BBS/RSRD) keeps the job in the region while it waits, which the Erlang loss "
549 "model has no state for -- use DROP, or SolverCTMC/SolverJMT";
551 return "SolverNC: the 'erlangfp' Erlang fixed point applies only to a loss network, which "
552 "is an open model whose single Delay sits inside a Finite Capacity Region under a "
553 "DROP rule; this model declares no such region (see nc_is_lossn_model)";
555 return "SolverNC: method 'ms' is admissible only on a loss network (open model, one DROP "
556 "region holding a single Delay).";
558 return "SolverNC: method rec is the MDD-rec route, admissible on a stochastic Petri net or "
559 "on a loss network (open model, one DROP region holding a single Delay); this model "
561 if (!
sn.regions.empty())
562 return "SolverNC: this model applies a Finite Capacity Region to queueing stations, whose "
563 "aggregate population limit no normalizing-constant algorithm here enforces; only "
564 "the loss network -- one region over a single infinite server, DROP on every "
565 "class -- is solvable. Use SolverCTMC or SolverJMT, or setCapacity for a "
566 "single-station limit";
577 for (std::size_t i = 0; i <
sn.nstations; ++i)
578 if (!
sn.stations[i].lldscaling.empty() ||
579 static_cast<bool>(
sn.stations[i].cdscaling) ||
580 static_cast<bool>(
sn.stations[i].jdscaling))
581 return "SolverNC: method 'mem' is the maximum-entropy GE/GE/1/N of "
582 "solver_nc_mem, which reads the first two moments of ONE service law and "
583 "cannot apply a declared load-, class- or joint-dependent rate. Use "
584 "SolverMVA, SolverCTMC or SolverLDES";
597 if (
sn.has_open_classes()) {
598 for (std::size_t i = 0; i <
sn.nstations; ++i)
599 if (
static_cast<bool>(
sn.stations[i].cdscaling) ||
600 static_cast<bool>(
sn.stations[i].jdscaling))
601 return "SolverNC: class- or joint-dependent rates are solved by the convolution "
602 "of solver_nc_conv, Sauer's multichain recursion on the CLOSED population "
603 "lattice, which holds no position for an open chain; this model is open "
604 "or mixed. Use SolverMVA, SolverCTMC or SolverLDES";
613 bool any_cd =
false, any_multi =
false, any_lld =
false;
614 for (std::size_t i = 0; i <
sn.nstations; ++i) {
615 if (
static_cast<bool>(
sn.stations[i].cdscaling) ||
616 static_cast<bool>(
sn.stations[i].jdscaling))
618 const double c =
sn.stations[i].nservers;
619 if (std::isfinite(c) && c > 1.0) any_multi =
true;
620 if (!
sn.stations[i].lldscaling.empty()) any_lld =
true;
622 if (any_cd && (any_multi || any_lld))
623 return "SolverNC: class- or joint-dependent rates are solved by the convolution of "
624 "solver_nc_conv, which reads no server count above one and no load-dependent "
625 "rate lattice; fold the multiserver capacity into the class-dependent handle, "
626 "or use SolverMVA or SolverCTMC";
643 if ((m ==
"pana" || m ==
"panald") && !
sn.has_open_classes()) {
644 bool diverted_to_conv =
false, any_lld =
false;
645 for (std::size_t i = 0; i <
sn.nstations; ++i) {
646 if (
static_cast<bool>(
sn.stations[i].cdscaling) ||
647 static_cast<bool>(
sn.stations[i].jdscaling))
648 diverted_to_conv =
true;
649 if (!
sn.stations[i].lldscaling.empty()) any_lld =
true;
651 const bool reaches_ld_kernel = (m ==
"panald") || any_lld;
653 const std::string why =
654 "the model is not in normal usage, so the 'panald' asymptotic expansion does "
655 "not apply. Use 'exact', 'clw' or an approximate load-dependent method instead.";
657 return "SolverNC: method 'pana' reaches the load-dependent kernel on this "
658 "model, where pfqn_ncld evaluates it as 'panald', and " + why;
659 return "SolverNC: " + why;
679 if (m ==
"comomld" || (for_report && (m ==
"mmint2" || m ==
"gleint"))) {
683 return "SolverNC: method 'comomld' is the load-dependent CoMoM recursion, and "
684 "pfqn_comomrm_ld accepts at most a single queueing station; this model has " +
685 std::to_string(nq) +
".";
686 return "SolverNC: the '" + m +
687 "' method requires a model with a delay and a single queueing station; this "
688 "model has " + std::to_string(nq) +
".";
693 if (m ==
"exact" &&
sn.has_open_classes()) {
694 for (std::size_t i = 0; i <
sn.nstations; ++i)
695 if (std::isfinite(
sn.stations[i].nservers) &&
sn.stations[i].nservers > 1.0)
696 return "solver_nc_analyzer: the NC solver cannot provide exact solutions for open "
697 "or mixed multiserver queueing networks. Remove the 'exact' option";
726 if (opt_in.
method ==
"cftp" || opt_in.
method ==
"cftp.approx") {
734 "SolverNC(cftp): the cftp methods draw random states and form the station "
735 "balance functions in the log domain, neither of which exists in exact rational "
756 const std::string refusal =
803 bool mem_blocking =
false;
804 if (
opt.method ==
"mem") {
808 const bool mm1k_closed_form =
819 std::vector<T> lam(
tr.V.classes.size() + 1,
862 const std::size_t src = mva::detail::station_of_type(L, qn::NodeType::Source);
863 const std::size_t q = mva::detail::station_of_type(L, qn::NodeType::Queue);
865 const T Vq = L.
visits[0](qstateful - 1, 0);
866 const T lambda = T(L.
rates(src - 1, 0) * Vq);
867 const T mu = L.
rates(q - 1, 0);
868 const T rho = T(lambda / mu);
869 const double Kcap = L.
cap[q - 1];
870 const unsigned Kint =
static_cast<unsigned>(std::llround(Kcap));
872 const T Tq = T(lambda * (one - Ploss));
881 Lsys = T(rho / (one - rho) - Kp1 * rKp1 / (one - rKp1));
889 ls.
X.assign(1, zero);
890 ls.
C.assign(1, zero);
894 ls.
R(q - 1, 0) = T(Lsys / Tq);
895 ls.
Q(q - 1, 0) = Lsys;
896 ls.
U(q - 1, 0) = T(Tq / mu);
897 ls.
Tp(q - 1, 0) = Tq;
898 ls.
Tp(src - 1, 0) = lambda;
900 ls.
C[0] = T(ls.
R(q - 1, 0) * Vq);
922 for (std::size_t ind = 0; ind < L.
nodes.size(); ++ind)
926 bool multiserver =
false;
936 std::string ms_warning;
937 const std::string ms_policy =
938 detail::nc_multiserver_policy(
opt.multiserver, &ms_warning);
940 if (
opt.method ==
"default") {
944 if (L.
nstations == 2 && !detail::has_node_type(L, qn::NodeType::Cache) &&
945 detail::has_node_type(L, qn::NodeType::Delay) && multiserver) {
947 if (detail::multiserver_to_lld(L)) anyLld =
true;
949 opt.method =
"comom";
951 }
else if (ms_policy ==
"lld" && multiserver && !anyLld && L.
has_product_form() &&
952 detail::nc_population_lattice(L) <= 6000.0) {
958 if (detail::multiserver_to_lld(L)) anyLld =
true;
960 }
else if (
opt.method ==
"exact" ||
opt.method ==
"is" ||
opt.method ==
"panald") {
981 "SolverNC: the '" +
opt.method +
982 "' method requires the model to have a product-form solution, and this model "
990 if (!anyLld && multiserver && ms_policy !=
"seidmann") {
991 if (detail::multiserver_to_lld(L)) anyLld =
true;
1001 if (detail::has_node_type(L, qn::NodeType::Source)) {
1022 std::vector<T>(), std::vector<T>(),
1035 for (std::size_t ci = 0; ci < res.
cache.caches.size() && ci < cr.
itemprob.size(); ++ci)
1064 if (anyLld || nc::detail::has_scaling(L)) {
1066 }
else if (
opt.method ==
"rd" ||
opt.method ==
"nrp" ||
opt.method ==
"nrl" ||
1067 opt.method ==
"nre" ||
opt.method ==
"comomld" ||
opt.method ==
"panald") {
1075 if (!ms_warning.empty())
1088 const std::string& origmethod);
1102 const std::string& origmethod) {
1108 std::vector<std::vector<bool>> mask(M, std::vector<bool>(K,
false));
1109 for (std::size_t i = 0; i < M; ++i)
1110 for (std::size_t k = 0; k < K; ++k)
1112 std::vector<std::vector<bool>> srcmask(M, std::vector<bool>(K,
false));
1113 for (std::size_t i = 0; i < M; ++i)
1114 if (L.
stations[i].nodetype == qn::NodeType::Source)
1115 for (std::size_t k = 0; k < K; ++k) srcmask[i][k] =
true;
1135 std::string satwarn;
1144 out.
actualmethod = (origmethod ==
"default" && !actualmethod.empty() &&
1145 actualmethod !=
"default")
1146 ?
"default/" + actualmethod
1154 "SolverNC does not handle immediate feedback (immfeed); the solver will treat "
1155 "self-loops as class-switching with re-queueing.";
1161 if (!satwarn.empty())
1174 if (std::isfinite(lg))
What a solver observed about the Cache nodes of a model.
UnsupportedError(const std::string &what)
A network plus its refreshed NetworkStruct.
bool has_immediate_feedback() const
Whether immediate feedback is EFFECTIVE anywhere in the model.
std::size_t stateful_of_station(std::size_t st) const
std::vector< std::vector< bool > > disabled
std::vector< double > cap
sn.cap and sn.classcap: the total and per-class buffers.
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< NodeDef > nodes
every node, in creation order
std::vector< Matrix< T > > visits
(nchains) each (nstateful x nclasses)
bool has_product_form() const
static void step(const char *fmt,...)
Write one progress line.
The exception types the port throws.
The fork-join fixed point that drives one inner MVA solve.
The Heidelberger-Trivedi fork-join transform, options.config.fork_join='ht'.
The fork-join transform SolverMVA applies before solving a layer that contains a Fork.
Running progress log of a LINE solver run (the "solver console").
bool sn_is_mm1k_loss(const qn::NetworkStruct< T > &sn)
sn_is_mm1k_loss: the three-node Source/Queue/Sink model of an M/M/1/K with loss, the shape MVA answer...
NodeType
Node kinds, with the values of MATLAB NodeType.
@ FIFO
first in, first out
Matrix< T > sn_get_residt_from_respt(const qn::NetworkStruct< T > &L, const Matrix< T > &RN)
Port of sn_get_residt_from_respt: the per-JOB residence time.
Matrix< T > filter_metric(const qn::NetworkStruct< T > &L, const Matrix< T > &metric, MetricKind kind, const std::vector< std::vector< bool > > *zero_mask)
Port of filterMetric: what @@NetworkSolver/getAvg does between the analyzer and the caller.
bool cap_unstable_open_stations(const qn::NetworkStruct< T > &L, Matrix< T > &QN, Matrix< T > &UN, Matrix< T > &RN, const Matrix< T > &TN)
The saturated open-station rule of @@NetworkSolver/getAvg.m:221-308.
const char * unstable_open_warning()
The warning getAvg.m raises when cap_unstable_open_stations() fires.
FjMmt< T > fj_fork_join_transform(const qn::NetworkStruct< T > &L, const std::string &method)
options.config.fork_join -> the transform it names.
Matrix< T > sn_get_arvr_from_tput(const qn::NetworkStruct< T > &L, const Matrix< T > &TN)
MvaSolution< T > fj_fixed_point(const qn::NetworkStruct< T > &L, FjMmt< T > &tr, std::vector< T > &lam, const MvaOptions &opt, InnerSolve inner)
Drive the fork-join fixed point of a transformed model to convergence.
ChainDemands< T > sn_get_demands_chain(const qn::NetworkStruct< T > &L)
Port of sn_get_demands_chain.
NcCftpSolution< T > solver_nc_cftp(const qn::NetworkStruct< T > &sn, const NcSolverOptions &opt, const NcCftpOptions &cftpopt)
Solve with the cftp / cftp.approx method.
mva::AvgResult< T > solver_nc_run_analyzer(const qn::NetworkStruct< T > &L_in, const NcSolverOptions &opt_in)
bool nc_is_cacheqn(const qn::NetworkStruct< T > &sn)
True when the model has a Cache node and is not the Source-Cache-Sink shape.
bool nc_is_oi_model(const qn::NetworkStruct< T > &sn)
Port of nc_is_oi_model.m: a closed network with at least one OI station and nothing but BCMP product-...
NcSolution< T > solver_nc_dt(const qn::NetworkStruct< T > &sn, const NcSolverOptions &opt)
Exact discrete-time analysis of sn.
NcSpnSolution< T > solver_nc_spn_analyzer(const qn::NetworkStruct< T > &sn, const NcSolverOptions &opt)
Analyse a product-form stochastic Petri net.
NcSolution< T > solver_nc_dps_analyzer(const qn::NetworkStruct< T > &sn, const NcSolverOptions &opt)
Analyzes the closed think+DPS network.
MemSupport solver_nc_mem_supports(const qn::NetworkStruct< T > &sn)
Port of solver_nc_mem_supports.m.
NcCacheSolution< T > solver_nc_cache_analyzer(const qn::NetworkStruct< T > &sn, const NcSolverOptions &opt)
Port of solver_nc_cache_analyzer.m.
NcSolution< T > solver_nc_cftp_solution(const NcCftpSolution< T > &s)
A cftp solve in the shape every other SolverNC analyzer returns, so the runner's metric filter applie...
bool nc_is_lossn_model(const qn::NetworkStruct< T > &sn)
True when the model is a loss network: the shape above, with EVERY class dropped at the region.
bool nc_is_pas_model(const qn::NetworkStruct< T > &sn)
Port of nc_is_pas_model.m: a closed two-station OI / P&S tandem.
NcSolution< T > solver_nc_oi_analyzer(const qn::NetworkStruct< T > &sn, const NcSolverOptions &opt)
Port of solver_nc_oi_analyzer.m.
double solver_nc_lognormconst(const qn::NetworkStruct< T > &L, const NcSolverOptions &opt)
Port of @@SolverNC/getProbNormConstAggr.m: the log normalizing constant.
NcCacheqnRetrievalSolution< T > solver_nc_cacheqn_retrieval_analyzer(const qn::NetworkStruct< T > &sn, const NcSolverOptions &opt)
Port of solver_nc_cacheqn_retrieval_analyzer.m.
void check_method(const std::string &method)
Port of runAnalyzerChecks' method gate: an unlisted method is refused.
std::vector< std::string > list_valid_methods()
Port of SolverNC.listValidMethods.
std::size_t nc_closed_queueing_stations(const qn::NetworkStruct< T > &sn)
How many queueing (non-infinite-server) stations carry demand from a CLOSED chain?
NcRetrievalSolution< T > solver_nc_retrieval_analyzer(const qn::NetworkStruct< T > &sn, const NcSolverOptions &opt)
Port of solver_nc_retrieval_analyzer.m.
NcSolution< T > solver_nc_analyzer(const qn::NetworkStruct< T > &sn, const NcSolverOptions &opt)
Port of solver_nc_analyzer.m.
bool is_stochastic_method(const std::string &method)
Port of SolverNC.isStochasticMethod.
NcSolution< T > solver_nc_solve(const qn::NetworkStruct< T > &L_in, const NcSolverOptions &opt_in)
The gates, the multiserver conversion and the dispatch of @@SolverNC/runAnalyzer.m,...
bool nc_has_lossn_shape(const qn::NetworkStruct< T > &sn)
True when the model has the SHAPE of a loss network – open, one region, one member station,...
NcCacheqnSolution< T > solver_nc_cacheqn_analyzer(const qn::NetworkStruct< T > &sn, const NcSolverOptions &opt)
Port of solver_nc_cacheqn_analyzer.m.
NcSolution< T > solver_ncld_analyzer(const qn::NetworkStruct< T > &sn, const NcSolverOptions &opt)
Port of solver_ncld_analyzer.m: the load-dependent analyzer, which is solver_ncld plus the same fract...
bool sn_has_dps(const qn::NetworkStruct< T > &sn)
True when any station of the network is scheduled DPS.
bool nc_has_retrieval(const qn::NetworkStruct< T > &sn)
True when the model's Cache carries a delayed-hit retrieval system.
std::string resolve_method(const qn::NetworkStruct< T > &L, const std::string &method)
Port of SolverNC.resolveMethod: the feature-driven resolution of method='default'.
NcLossnSolution< T > solver_nc_lossn_analyzer(const qn::NetworkStruct< T > &sn, const NcSolverOptions &opt)
Port of solver_nc_lossn_analyzer.m.
bool nc_is_normal_usage(const qn::NetworkStruct< T > &sn)
Is the closed model in NORMAL USAGE, the domain of the Mitra-McKenna PANACEA asymptotic expansion (J.
bool nc_is_noreentrant_cache(const qn::NetworkStruct< T > &sn)
True when the model is exactly a Source, a Cache and a Sink.
std::string nc_method_refusal(const qn::NetworkStruct< T > &sn, const std::string &method, bool slotted=false, bool for_report=true)
May method run on this model?
mva::AvgResult< T > solver_nc_avg_table(const qn::NetworkStruct< T > &L_in, const NcSolution< T > &d, const std::string &origmethod)
Port of @@SolverNC/runAnalyzer.m for the lang='matlab' path: solve, then apply the metric filter @@Ne...
std::string solver_nc_cftp_supports(const qn::NetworkStruct< T > &sn)
The cftp model-class gate as a public predicate.
bool nc_is_dps_model(const qn::NetworkStruct< T > &sn)
True when the model is the closed two-station network Morrison's expansion is derived for: one infini...
NcSolution< T > nc_dispatch(const qn::NetworkStruct< T > &sn, const NcSolverOptions &opt)
Port of @@SolverNC/ncDispatch.m: the inner solve of the fork-join fixed point, which is the load-depe...
FeatureSet nc_feature_set(const std::string &method)
SolverNC.getFeatureSet, 48 names, transcribed unchanged.
void check_binding_capacity(const std::string &solver, const NetworkStruct< T > &sn)
void feature_gate(const std::string &solver, const FeatureSet &declared, const NetworkStruct< T > &sn, const std::string &requested_method="", const std::string &resolved_method="")
runAnalyzerChecks: refuse a model the solver does not declare, by name.
Mm1kLossResult< T > qsys_mm1k_loss(const T &lambda, const T &mu, unsigned K)
Blocking probability of the M/M/1/K 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.
T num_pow_int(const T &base, unsigned e)
Integer power, valid in any field (no transcendental requirement).
Port of solver_nc_analyzer.m, solver_ncld_analyzer.m and @@SolverNC/ncDispatch.m: one inner solve,...
Controls and result shape shared by the normalizing-constant analyzers.
A queueing network and its refreshed NetworkStruct.
Blocking probability of the M/M/1/K queue.
Chain aggregation and de-aggregation.
Ports of the sn_has_* / sn_is_* predicate family of matlab/src/api/sn.
The DECLARED side of the gate: one feature set per solver.
The SolverMVA class surface: @@SolverMVA/runAnalyzer.m and the gates around it.
Port of solver_nc_cache_analyzer.m: the NON-REENTRANT cache, a model that is exactly a Source,...
Port of solver_nc_cacheqn_analyzer.m: the INTEGRATED caching-queueing network, where a Cache sits ins...
Port of solver_nc_cacheqn_retrieval_analyzer.m: a CLOSED integrated cache-queueing model whose Cache ...
The cftp and cftp.approx methods of SolverNC: stationary analysis of a closed single-class product-fo...
Heavy-usage asymptotic analysis of the closed two-station network with one think (infinite-server) st...
Port of solver_nc_lossn_analyzer.m: the open LOSS NETWORK, which is a Source, ONE multiclass Delay si...
Port of solver_nc_mem.m and solver_nc_mem_supports.m: the Maximum Entropy Method of Kouvatsos (1994).
Order-independent (OI) and pass-and-swap (P&S) normalizing-constant analysis.
Port of solver_nc_retrieval_analyzer.m: the OPEN delayed-hit (retrieval-system) cache.
Stationary analysis of a PRODUCT-FORM stochastic Petri net by MDD-rec.
The metrics getAvg returns, after filtering.
Matrix< T > RN
response time, per visit
std::string warning
The reference's own warning text, verbatim, empty when it did not warn.
Matrix< T > UN
utilization
std::vector< T > listcost
(h) mean storage cost held by each cache list, K_j = sum_i sigma_i pi_ij, filled only by the NC cache...
std::optional< double > lognormconst
@@SolverNC/getProbNormConstAggr, i.e.
Matrix< T > WN
residence time, per job
std::string method
the method asked for
std::string actualmethod
the algorithm that ran
Matrix< T > QN
queue length
std::vector< T > CN
system response time per class
std::vector< T > XN
system throughput per class
solvers::CacheMetrics< T > cache
What the cache branches observed, EMPTY on a model with no Cache node and on every solver that does n...
Matrix< T > AN
arrival rate
The chain-level view of a layer, as sn_get_demands_chain returns it.
Matrix< T > Lchain
(M x C) demand
The transformed layer and the bookkeeping the fixed point needs to drive it and to merge its results ...
The options SolverMVA reads.
bool base_has_fork
Whether the model this solve came from has a Fork, which the model handed to the analyzer no longer d...
std::string fork_join
options.config.fork_join: which fork-join arm the fixed point takes.
Class-level results, the [Q,U,R,T,C,X] of the MATLAB analyzers.
double lG
log of the normalizing constant, the reference's lG.
static constexpr double FineTol
The verdict of solver_nc_mem_supports.
bool blocking
the model carries a binding finite station buffer
What the cache analyzer returns beyond the usual metric table.
Matrix< T > hitproblist
(u x h) access-weighted per-list hit probability, NaN if not exact
std::vector< T > missprob
(u) per-class miss and hit PROBABILITIES, missrate divided by the read class's arrival rate and its c...
Matrix< T > itemprob
(n x h+1) the same from the EXACT recursion, NaN above 10 items
std::vector< T > listcost
(h) mean storage cost held by each list, EMPTY without item sizes
What the closed delayed-hit analyzer returns.
std::vector< T > delayedprob
(K) zero on this path, by the reference's convention
std::vector< T > missprob
(K) the delayed fraction is folded in here
std::vector< T > hitprob
(K) P(item cached)
std::vector< T > latency
(K) NaN: not computed on this path
Matrix< T > hitproblist
(K x h) NaN: not computed on this path
What the integrated analyzer returns: the metrics plus the converged split.
Matrix< T > hitprob
(ncaches x nclasses) converged hit probability
Matrix< T > missprob
(ncaches x nclasses)
qn::NetworkStruct< T > refreshed
The struct whose cache self-switch carries the CONVERGED split rather than the offered one,...
std::vector< Matrix< T > > itemprob
per cache, (n x h+1); EMPTY = not computed
What the delayed-hit analyzer returns beyond the metric table.
Matrix< T > itemprob
(n x h+1) column 0 = miss, 1.. = per list
std::vector< T > missprob
(K)
std::vector< T > hitprob
(K) TRUE hit fraction, NaN off the read class
Matrix< T > hitproblist
(K x h) per-list hit fraction
std::vector< T > delayedprob
(K) delayed-hit fraction
std::vector< T > latency
(K) NaN: the latency belongs to SolverMVA
The [Q,U,R,T,C,X,lG] of the reference, plus the algorithm that ran.
std::vector< T > listcost
(h) mean storage cost held by each cache list, K_j = sum_i sigma_i pi_ij.
mva::MvaSolution< T > sol
std::string warning
The reference's warning text, verbatim, empty when it did not warn.
std::shared_ptr< qn::NetworkStruct< T > > refreshed_struct
Set only by the integrated cacheqn branch: the converged struct whose routing carries the ACTUAL hit/...
solvers::CacheMetrics< T > cache
What the cache branches observed, EMPTY on a model with no Cache node.
Controls, defaulting to SolverOptions('NC') in the reference.
bool base_has_fork
Whether the model this solve came from has a Fork, which the model handed to the analyzer no longer d...
bool slotted
options.config.slotted.
One station of the network.
double nservers
may be infinite (a Delay, or an inf-scheduled task)
std::vector< T > lldscaling
sn.lldscaling for this station: the multiplier at population 1, 2, ... Empty when the station is not ...