5#ifndef LINE_SOLVERS_MVA_SOLVER_MVA_RUNNER_H
6#define LINE_SOLVERS_MVA_SOLVER_MVA_RUNNER_H
156 std::set<std::string> drop;
159 drop.insert({
"aql",
"amva.aql",
"qsa",
"amva.qsa",
"tay",
"amva.tay",
"sqni"});
162 bool open =
true, closed =
false;
170 bool has_bas =
false;
174 if (!(L.
nclasses == 1 && !open && has_bas)) drop.insert(
"sqd");
177 bool any_open_class =
false;
179 if (std::isinf(c.
population)) any_open_class =
true;
180 if (any_open_class) drop.insert(
"mvac");
183 drop.insert({
"sjn.mva",
"sjn.amva"});
186 bool classdep_routing =
false;
188 drop.insert({
"marie",
"amva.marie"});
190 drop.insert({
"qna",
"rqna",
"rqt"});
191 for (std::size_t r = 0; r + 1 < L.
nclasses; ++r)
192 for (std::size_t i = 1; i <= L.
nof_nodes() && !classdep_routing; ++i)
193 for (std::size_t j = 1; j <= L.
nof_nodes(); ++j)
195 classdep_routing =
true;
198 if (classdep_routing) drop.insert({
"marie",
"amva.marie"});
200 bool has_prio =
false;
202 if (st.
sched == qn::SchedStrategy::FCFSPRPRIO) has_prio =
true;
203 if (!has_prio) drop.insert({
"priomva",
"amva.priomva"});
206 const std::set<std::string>
qsys = {
"mm1",
"mmk",
"mg1",
"mgi1",
"gm1",
"gig1",
"gim1",
207 "gig1.kingman",
"gigk",
"gigk.kingman_approx",
208 "gig1.gelenbe",
"gig1.heyman",
"gig1.kimura",
"gig1.allen",
209 "gig1.kobayashi",
"gig1.klb",
"gig1.marchal",
210 "gigk.whitt",
"qed",
"gig1.extremal",
"gigk.diffusion"};
212 drop.insert(
qsys.begin(),
qsys.end());
213 drop.insert({
"erlanga",
"mgisrgi"});
215 const std::size_t qi = detail::station_of_type(L, qn::NodeType::Queue);
217 drop.insert({
"erlanga",
"mgisrgi"});
219 drop.insert(
"erlanga");
223 std::vector<std::string> kept;
224 kept.reserve(m.size());
225 for (
const std::string& name : m)
226 if (drop.count(name) == 0) kept.push_back(name);
230 std::size_t n_inf = 0;
232 if (st.
sched == qn::SchedStrategy::INF) ++n_inf;
237 std::vector<double> sx_n;
238 std::vector<bool> sx_fcfs;
239 bool sx_ready =
false;
240 std::vector<std::string> keep;
241 keep.reserve(m.size());
242 for (
const std::string& name : m) {
250 for (std::size_t c = 0; c < L.
nchains; ++c) sx_n.push_back(cd.
Nchain[c]);
252 if (st.
sched != qn::SchedStrategy::INF && st.
sched != qn::SchedStrategy::EXT)
253 sx_fcfs.push_back(st.
sched == qn::SchedStrategy::FCFS);
261 keep.push_back(name);
274 if (method ==
"mvablo") {
279 if (method ==
"erlanga") {
284 if (std::find(valid.begin(), valid.end(), method) != valid.end())
return;
287 if (std::find(all.begin(), all.end(), method) != all.end())
289 "' method does not apply to this model. list_valid_methods names the methods that do.");
305 if (method !=
"default" || L.
nclasses != 1)
return method;
308 for (std::size_t r = 0; r < L.
nclasses; ++r)
309 if (std::isfinite(L.
classes[r].population))
return method;
316 const std::size_t qi = detail::station_of_type(L, qn::NodeType::Queue);
338 for (std::size_t c = 0; c < L.
nchains; ++c)
339 for (std::size_t i = 0; i < L.
nstations; ++i) {
341 for (std::size_t k = 0; k < L.
nclasses; ++k)
342 V(i, k) = T(V(i, k) + L.
visits[c](sf - 1, k));
362 const Matrix<T> V = detail::station_visits(L);
364 for (std::size_t i = 0; i < M; ++i)
365 for (std::size_t k = 0; k < K; ++k) {
374 const bool is_place = L.
stations[i].nodetype == qn::NodeType::Place;
375 if ((L.
disabled[i][k] && !is_place) || !(RN(i, k) > zero))
continue;
381 for (std::size_t cc = 0; cc < L.
nchains; ++cc)
382 if (L.
chains[cc][k]) c = cc;
384 const std::size_t rs = L.
classes[k].refstat;
389 for (std::size_t r : L.
inchain[c]) den += V(rs - 1, r - 1);
391 if (den > zero) WN(i, k) = T(RN(i, k) * V(i, k) / den);
393 for (std::size_t i = 0; i < M; ++i)
394 for (std::size_t k = 0; k < K; ++k)
418 for (std::size_t nd = 0; nd < L.
nodes.size(); ++nd) {
419 if (L.
nodes[nd].nodetype != qn::NodeType::Join)
continue;
420 const std::size_t ist = L.
nodes[nd].station;
421 if (ist == 0 || ist > RN.
rows())
continue;
422 for (std::size_t r = 0; r < RN.
cols(); ++r)
423 if (AN(ist - 1, r) > zero) RN(ist - 1, r) = QN(ist - 1, r) / AN(ist - 1, r);
459 if (L.
rt.rows() != S * R)
return AN;
463 if (TN.
rows() == 0)
return AN;
468 for (std::size_t sf = 0; sf < S; ++sf) {
470 const std::size_t ist = L.
nodes[nd - 1].station;
471 if (ist == 0)
continue;
472 for (std::size_t r = 0; r < R; ++r) TS(sf, r) = TN(ist - 1, r);
477 std::vector<std::size_t> ucols;
478 std::vector<bool> is_u(S * R,
false);
479 for (std::size_t sf = 0; sf < S; ++sf) {
481 for (std::size_t k = 0; k < R; ++k) {
482 ucols.push_back(sf * R + k);
483 is_u[sf * R + k] =
true;
486 if (!ucols.empty()) {
487 const std::size_t nU = ucols.size();
489 std::vector<T> b(nU, zero);
490 for (std::size_t j = 0; j < nU; ++j) {
492 for (std::size_t col = 0; col < S * R; ++col)
493 if (!is_u[col]) acc += T(TS(col / R, col % R) * L.
rt(col, ucols[j]));
495 for (std::size_t i = 0; i < nU; ++i)
499 for (std::size_t j = 0; j < nU; ++j) TS(ucols[j] / R, ucols[j] % R) = xu[j];
501 for (std::size_t ist = 0; ist < M; ++ist) {
503 if (L.
stations[ist].nodetype == qn::NodeType::Source)
continue;
505 for (std::size_t k = 0; k < R; ++k) {
507 for (std::size_t sf2 = 0; sf2 < S; ++sf2)
508 for (std::size_t r = 0; r < R; ++r)
509 acc += T(TS(sf2, r) * L.
rt(sf2 * R + r, sf_i * R + k));
518 for (std::size_t ist = 0; ist < M; ++ist) {
520 if (ind == 0 || ind > ANn.
rows())
continue;
521 for (std::size_t k = 0; k < R; ++k) AN(ist, k) = ANn(ind - 1, k);
527 bool any_place =
false;
528 for (std::size_t a = 0; a < L.
nodes.size() && !any_place; ++a)
529 any_place = L.
nodes[a].nodetype == qn::NodeType::Place;
533 for (std::size_t pp = 0; pp < fr.
place_nodes.size(); ++pp) {
535 if (ist == 0)
continue;
536 for (std::size_t k = 0; k < R; ++k) {
538 for (std::size_t mm = 0; mm < fr.
x.size(); ++mm) {
539 const std::size_t col = pp * fr.
nclasses + k;
559 for (std::size_t i = 0; i < AN.
rows(); ++i)
560 for (std::size_t k = 0; k < AN.
cols(); ++k)
572 if (TH.
rows() == 0 || TN.
rows() == 0) {
577 if (ANn.
rows() > 0) {
579 for (std::size_t ist = 0; ist < M; ++ist) {
581 if (ind == 0 || ind > ANn.
rows())
continue;
582 for (std::size_t k = 0; k < R; ++k) AN(ist, k) = ANn(ind - 1, k);
604enum class MetricKind { QLen, Util, RespT, ResidT, Tput, ArvR };
615 const std::vector<std::vector<bool>>* zero_mask) {
630 bool has_fj =
false, has_cache =
false, has_spn =
false;
632 if (nd.
nodetype == qn::NodeType::Fork || nd.
nodetype == qn::NodeType::Join) has_fj =
true;
633 if (nd.
nodetype == qn::NodeType::Cache) has_cache =
true;
634 if (nd.
nodetype == qn::NodeType::Transition) has_spn =
true;
640 std::vector<bool> is_cache_class(K,
false);
643 for (std::size_t r = 0; r < cp.
hitclass.size(); ++r) {
646 is_cache_class[cp.
missclass[r] - 1] =
true;
651 for (std::size_t i = 0; i < M; ++i) {
653 const bool src_or_sink = (nt == qn::NodeType::Source || nt == qn::NodeType::Sink);
654 bool kind_disabled =
false;
659 kind_disabled = src_or_sink;
662 kind_disabled = src_or_sink || nt == qn::NodeType::Fork || nt == qn::NodeType::Join;
666 kind_disabled =
false;
669 if (kind_disabled)
continue;
692 bool service_tunnel = (nt == qn::NodeType::Source || nt == qn::NodeType::Fork ||
693 nt == qn::NodeType::Join);
694 if (nt == qn::NodeType::Place) {
695 service_tunnel =
true;
696 for (std::size_t k = 0; k < K && k < L.
service[i].size(); ++k)
697 if (!L.
service[i][k].disabled) { service_tunnel =
false;
break; }
699 for (std::size_t k = 0; k < K; ++k) {
700 if (!L.
disabled[i][k] || service_tunnel) {
701 out(i, k) = metric(i, k);
702 }
else if (is_cache_class[k] &&
707 out(i, k) = metric(i, k);
712 for (std::size_t i = 0; i < M; ++i)
713 for (std::size_t k = 0; k < K; ++k)
714 if ((*zero_mask)[i][k]) out(i, k) = zero;
715 for (std::size_t i = 0; i < M; ++i)
716 for (std::size_t k = 0; k < K; ++k)
719 for (std::size_t k = 0; k < K; ++k) {
721 for (std::size_t cc = 0; cc < L.
nchains; ++cc)
722 if (L.
chains[cc][k]) c = cc;
724 for (std::size_t i = 0; i < M; ++i) {
726 if ((has_fj || has_cache || has_spn) &&
771 (void)L; (void)QN; (void)UN; (void)RN; (void)TN;
775 bool any_open =
false;
776 for (std::size_t r = 0; r < K; ++r)
777 if (std::isinf(L.
classes[r].population)) any_open =
true;
778 if (!any_open)
return false;
780 const double dinf = std::numeric_limits<double>::infinity();
781 bool any_unstable =
false;
782 for (std::size_t i = 0; i < M; ++i) {
786 if (!std::isfinite(c) || c <= 0.0)
continue;
787 if (nt == qn::NodeType::Source || nt == qn::NodeType::Sink)
continue;
788 if (sch == qn::SchedStrategy::INF || sch == qn::SchedStrategy::EXT)
continue;
790 bool bounded = (i < L.
cap.size() && std::isfinite(L.
cap[i]));
791 if (!bounded && i < L.
classcap.size())
793 if (std::isfinite(cc)) { bounded =
true;
break; }
795 for (
const auto& rg : L.
regions)
796 if (i < rg.members.size() && rg.members[i]) { bounded =
true;
break; }
797 if (bounded)
continue;
799 bool reneges =
false;
802 if (reneges)
continue;
804 double lldpeak = 1.0;
805 for (
const T& v : L.
stations[i].lldscaling) {
807 if (std::isfinite(d) && d > 0.0 && d > lldpeak) lldpeak = d;
810 std::vector<double> rho(K, 0.0);
811 double rho_open = 0.0, rho_tot = 0.0;
812 for (std::size_t r = 0; r < K; ++r) {
815 if (rate > 0.0 && tp > 0.0) rho[r] = tp / (c * lldpeak * rate);
817 if (std::isinf(L.
classes[r].population)) rho_open += rho[r];
819 if (rho_open < 1.0 || rho_tot <= 0.0)
continue;
821 for (std::size_t r = 0; r < K; ++r) {
823 if (std::isinf(L.
classes[r].population) && rho[r] > 0.0) {
835 return "The model has unstable queues (utilization >= 1); station utilization is "
836 "reported capped at 1.0, queue length and response time as Inf.";
897 "SolverMVA: this model uses a Finite Capacity Region (addRegion), which is not "
898 "supported by SolverMVA. Use SolverCTMC, SolverSSA, SolverLDES or SolverJMT, or setCapacity for a single-station limit.");
923 std::string actualmethod, warning;
927 std::shared_ptr<qn::NetworkStruct<T>> refreshed;
936 if (st.
sched == qn::SchedStrategy::OI || st.
sched == qn::SchedStrategy::PAS) oi =
true;
939 "SolverMVA: method 'exact' requires a product-form solution; use 'mva' for the "
940 "approximation based on the exact MVA algorithm");
949 std::vector<T> lam(
tr.V.classes.size() + 1,
953 std::string am, wn, fjw;
963 if (!fjw.empty()) warning = warning.empty() ? fjw : warning +
" " + fjw;
978 std::vector<std::vector<bool>> mask(M, std::vector<bool>(K,
false));
979 for (std::size_t i = 0; i < M; ++i)
980 for (std::size_t k = 0; k < K; ++k)
986 std::vector<std::vector<bool>> srcmask(M, std::vector<bool>(K,
false));
987 for (std::size_t i = 0; i < M; ++i)
988 if (L.
stations[i].nodetype == qn::NodeType::Source)
989 for (std::size_t k = 0; k < K; ++k) srcmask[i][k] =
true;
1013 if (!warning.empty()) warning +=
" ";
1028 if (!warning.empty()) warning +=
" ";
1030 "SolverMVA does not handle immediate feedback (immfeed); the solver will treat "
1031 "self-loops as class-switching with re-queueing.";
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::size_t nof_nodes() const
std::size_t nof_stateful() const
std::vector< std::size_t > stateful_nodes
1-based node indices, ascending
std::vector< std::vector< Distrib< T > > > service
service[i][r], 0-based station and class; a disabled entry marks a pair never visited.
std::vector< std::vector< bool > > chains
(nchains x nclasses)
std::vector< std::size_t > refclass
(nchains) 1-based class, 0 = none
std::vector< std::vector< bool > > disabled
Matrix< T > rt
sn.rt and sn.rtnodes: the class-expanded routing.
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 ...
T route_eff(std::size_t r, std::size_t s, std::size_t i, std::size_t j) const
The routing actually in force: the expansion when there is one, else P.
std::vector< std::vector< std::size_t > > inchain
1-based class indices per chain
bool has_multi_server() const
std::vector< NodeDef > nodes
every node, in creation order
std::vector< std::vector< double > > classcap
std::vector< Matrix< T > > visits
(nchains) each (nstateful x nclasses)
std::vector< std::pair< std::size_t, std::size_t > > fj
fj(f,j): the Join node j that closes the Fork node f, 1-based.
bool has_product_form() const
sn_has_product_form, conjunct for conjunct.
std::vector< std::size_t > station_to_node
(nstations) 1-based node index
std::vector< Region > regions
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.
LU factorization with partial pivoting, templated on the number type.
The method names of each solver, in listing order.
Port of @@SolverMVA/mvaDispatch.m: one inner solve, choosing the analyzer that fits the model.
The option and result types every MVA analyzer shares.
SnPnFiringRates sn_pn_firing_rates(const qn::NetworkStruct< T > &sn, const Matrix< T > &TN, bool tput_is_tokens)
Ports of matlab/src/api/sn/sn_pn_firing_rates.m and sn_pn_avg_rates.m.
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)
std::string sn_patience_refusal(const qn::NetworkStruct< T > &sn, std::size_t ist, std::size_t r)
Port of sn_patience_refusal.m: the by-name refusal of a reneging patience that is not a Markovian law...
Matrix< T > sn_get_node_arvr_from_tput(const qn::NetworkStruct< T > &sn, const Matrix< T > &TN, const Matrix< T > &AN)
Port of sn_get_node_arvr_from_tput.
SchedStrategy
Scheduling disciplines, with the values of MATLAB SchedStrategy.
NodeType
Node kinds, with the values of MATLAB NodeType.
ImpatienceType
Impatience kinds, with the values of MATLAB ImpatienceType.
std::vector< std::string > methods(const std::string &solver)
Every method name the solver can be asked for, in listing order.
std::pair< std::string, std::string > mvablo_scope_reason(const qn::NetworkStruct< T > &L)
Port of mvablo_scope_reason.m: why method 'mvablo' cannot solve L, as {reason, kind}...
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 sn_has_sjn(const qn::NetworkStruct< T > &L)
True when the layer has an SJF station, the reference's any(sn.sched == SchedStrategy....
std::string mva_single_class_open_reason(const qn::NetworkStruct< T > &L, const std::string &method)
RQNA and RQT decompose an open network into GI/G/1 queues and build one uncertainty set per flow out ...
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.
std::string mva_schmidt_ext_reason(const std::vector< double > &njobs, const std::vector< bool > &fcfs, const std::string &method)
The extended Schmidt method needs a customer of every class to tag.
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...
MetricKind
Which metric is being filtered.
std::string resolve_method(const qn::NetworkStruct< T > &L, const std::string &method)
Port of SolverMVA.resolveMethod: the feature-driven default -> rqna upgrade for a bursty single-class...
std::vector< std::string > list_valid_methods(const qn::NetworkStruct< T > &L)
Port of SolverMVA.listValidMethods.
std::string mva_erlanga_patience_reason(const qn::NetworkStruct< T > &L)
Why method 'erlanga' cannot answer this model's patience, or "".
bool sn_is_bas_model(const qn::NetworkStruct< T > &L)
Port of matlab/src/api/sn/sn_is_bas_model.m: a closed single-CLASS model with a BAS drop rule.
std::string mva_mvac_reason(const qn::NetworkStruct< T > &L, const std::string &method)
MVAC is the exact chain recursion over single-server fixed-rate (SSFR) queues and infinite-server cen...
void apply_analyzer_arvr(Matrix< T > &AN, const Matrix< T > &supplied)
Overwrite the routing-derived arrival rates with those an analyzer supplied (MvaSolution::AN,...
const char * unstable_open_warning()
The warning getAvg.m raises when cap_unstable_open_stations() fires.
void mva_check_finite_capacity(const qn::NetworkStruct< T > &L, const std::string &method)
Port of SolverMVA.supportsFiniteCapacity (SolverMVA.m:158-186), the structural capacity gate SolverMV...
std::string mva_mapqn_reason(const qn::NetworkStruct< T > &L, const std::string &method)
The reason 'amva.mapqn' cannot solve L, or "" when it can (and "" for any other method).
FjMmt< T > fj_fork_join_transform(const qn::NetworkStruct< T > &L, const std::string &method)
options.config.fork_join -> the transform it names.
MvaSolution< T > fj_fixed_point(const qn::NetworkStruct< T > &L, FjMmt< T > &tr, std::vector< T > &lam, const MvaOptions &opt, InnerSolve inner, std::string *warning=nullptr)
Drive the fork-join fixed point of a transformed model to convergence.
void sn_apply_join_respt(const qn::NetworkStruct< T > &L, const Matrix< T > &QN, const Matrix< T > &AN, Matrix< T > &RN)
A Join reports the PER-SIBLING waiting time, QLen over the SIBLING ARRIVAL RATE, and not QLen over it...
std::string mva_closed_population_reason(const qn::NetworkStruct< T > &L, const std::string &method)
The closed-population AMVA family: an open chain, or a network outside strict product form,...
Matrix< T > sn_get_arvr_from_tput(const qn::NetworkStruct< T > &L, const Matrix< T > &TN)
Port of sn_get_arvr_from_tput: the arrival rate each station sees, from the throughputs and the class...
void check_method(const qn::NetworkStruct< T > &L, const std::string &method)
Port of runAnalyzerChecks' method gate: a method the solver does not list is refused before any analy...
AvgResult< T > solver_mva_run_analyzer(const qn::NetworkStruct< T > &L, const MvaOptions &opt_in, const Matrix< T > &init_sol)
Port of @@SolverMVA/runAnalyzer.m for the lang='matlab' path: gate, solve, convert,...
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.
void check_binding_capacity(const std::string &solver, const NetworkStruct< T > &sn)
NetworkSolver.checkBindingCapacity (NetworkSolver.m:1172-1228): the shared structural gate for finite...
FeatureSet mva_feature_set(const std::string &raw_method)
SolverMVA.getFeatureSet, plus getMethodFeatureSet's per-method deltas.
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.
std::string mva_base_method(const std::string &method)
The method name with any leading "amva." alias stripped.
Conservation laws of a layered queueing network, enumerated from its structure.
std::vector< T > solve(const Matrix< T > &A, const std::vector< T > &b)
Convenience: solve Ax = b, leaving A and b untouched.
A queueing network and its refreshed NetworkStruct.
Chain aggregation and de-aggregation.
Port of matlab/src/api/sn/sn_has_bursty_arrival.m.
Ports of matlab/src/api/sn/sn_get_node_arvr_from_tput.m and sn_get_node_tput_from_tput....
Port of matlab/src/api/sn/sn_patience_handles.m.
Ports of matlab/src/api/sn/sn_pn_firing_rates.m and sn_pn_avg_rates.m.
The DECLARED side of the gate: one feature set per solver.
Closed networks with shortest-job-next (SJF) stations, ladder branch 0.
The <kind> part of a LINE:<category>:<kind> identifier (see _kb/17-error-vocabulary....
The patience law of one station-class pair, in the forms the solvers consume.
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.
What sn_pn_firing_rates returns; x empty means "no answer", as in the reference.
std::vector< std::vector< double > > produced
produced[mode][place * nclasses + class], the reference's (mm, pp, k).
std::vector< double > x
firing rate per mode
std::vector< std::size_t > place_nodes
1-based Place node indices
std::size_t nclasses
the stride of the two tables above
The metrics getAvg returns, after filtering.
std::shared_ptr< qn::NetworkStruct< T > > refreshed_struct
The struct whose cache self-switch carries the CONVERGED hit/miss split, filled by the cacheqn branch...
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
solvers::FjMetrics< T > fj
self.result.FJ: the fork-join section metrics FJQLen, FJRespT and FJTput, filled by the solvers the f...
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.
std::optional< bool > converged
Whether the fixed point met its tolerance, empty when the handler reports none.
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.
std::vector< double > Nchain
(C) population, infinite for an open chain
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 transformed layer and the bookkeeping the fixed point needs to drive it and to merge its results ...
static constexpr double FineTol
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...
Class-level results, the [Q,U,R,T,C,X] of the MATLAB analyzers.
Matrix< T > AN
Analyzer-supplied station arrival rates (M x K), NaN where the runner derives them from the routing; ...
std::optional< bool > converged
Whether the fixed point met its tolerance, or empty when the handler reports none.
solvers::FjMetrics< T > fj
Fork-join section metrics set by the fork-join fixed point (fj_driver.h); empty otherwise.
The parameters of a Cache node, MATLAB's sn.nodeparam{ind} for a Cache.
std::vector< std::size_t > missclass
std::vector< std::size_t > hitclass
One job class of the network.
double population
infinite for an open class
One station of the network.
std::vector< int > droprule
Per-class blocking rule as an INT, with 0 meaning "not set".
Every Cache node of the model, in node order; empty on a model with none.
self.result.FJ: one row per Fork/Join pair, one column per class.