5#ifndef LINE_SOLVERS_FLUID_FLUID_RUNNER_H
6#define LINE_SOLVERS_FLUID_FLUID_RUNNER_H
78 return ::line::method_registry::methods(
"FLD");
84 if (std::find(valid.begin(), valid.end(), method) != valid.end())
return;
95 if (nd.
nodetype == qn::NodeType::Cache)
return true;
101bool fluid_has_dps(
const qn::NetworkStruct<T>& sn) {
102 for (
const auto& st : sn.stations)
115inline std::string fluid_unqualify(
const std::string& method) {
116 std::string m = method;
117 if (m.size() > 4 && m.compare(0, 4,
"fld.") == 0) m = m.substr(4);
118 if (m ==
"aoi")
return "mfq";
141bool fluid_minnormal_applicable(
const qn::NetworkStruct<T>& sn,
const FluidOptions& opt,
142 std::string& reason) {
143 const std::size_t M = sn.nstations, K = sn.nclasses;
149 for (std::size_t i = 0; i < M; ++i) {
151 for (std::size_t r = 0; r < K; ++r)
152 if (L.kic[i][r] > 1) {
153 reason =
"class " + std::to_string(r + 1) +
" has a " +
154 std::to_string(L.kic[i][r]) +
"-phase (non-Poisson) arrival process";
164 for (std::size_t nd = 0; nd < sn.nodes.size(); ++nd) {
165 if (sn.nodes[nd].nodetype != qn::NodeType::Cache)
continue;
166 const std::size_t key = nd + 1;
167 if (sn.nodeparam.count(key) == 0) {
168 reason =
"a cache uses a replacement strategy with no drift-based fluid model";
174 reason =
"a cache uses a replacement strategy with no drift-based fluid model";
180 for (std::size_t i = 0; i < M; ++i) {
187 ", which has no fluid drift branch";
194 if (L.nstates > opt.moment_maxstate) {
195 reason =
"the phase-resolved state has " + std::to_string(L.nstates) +
196 " coordinates, above the moment_maxstate limit of " +
197 std::to_string(opt.moment_maxstate);
204 if (fluid_has_time_varying_rates(opt)) {
205 reason =
"a rate schedule (nhpp_sched / rate_traj / rate_sched) makes the drift "
237bool fluid_dae_applicable(
const qn::NetworkStruct<T>& sn,
const FluidOptions& opt,
239 const FluidDaeOptions& dopt_in = FluidDaeOptions()) {
241 const std::size_t M = sn.nstations;
249 if (fluid_has_cache(sn)) {
250 reason =
"a cache model is answered by the decomposition analyzer, which has no dae route";
257 for (std::size_t i = 0; i < M; ++i) {
261 ", whose share closes on the covariance between its class coordinates "
262 "rather than on the station variance";
270 if (L.nstates > dopt.maxstate) {
271 reason =
"the phase-resolved state has " + std::to_string(L.nstates) +
272 " coordinates, above the dae_maxstate limit of " +
273 std::to_string(dopt.maxstate);
298std::string fluid_resolve_method(
const qn::NetworkStruct<T>& sn,
const std::string& method,
299 const FluidOptions& opt, std::string& reason) {
300 const std::string m = fluid_unqualify(method);
305 if (m ==
"rmf" || m ==
"refined") {
306 if (fluid_has_cache(sn)) {
307 reason =
"the model has cache nodes";
310 reason =
"the model has no cache nodes";
325 if (m !=
"default")
return m;
326 if (fluid_has_cache(sn)) {
327 reason =
"the model has cache nodes";
342 if (fluid_dae_applicable(sn, opt, dae_why)) {
343 reason = sn.regions.empty() ?
"the model has a binding finite buffer"
344 :
"the model has a finite capacity region";
348 if (fluid_minnormal_applicable(sn, opt, reason))
return "minnormal";
349 return fluid_has_dps(sn) ?
"closing" :
"matrix";
354std::string fluid_resolve_method(
const qn::NetworkStruct<T>& sn,
const std::string& method,
355 const FluidOptions& opt = FluidOptions()) {
357 return fluid_resolve_method(sn, method, opt, reason);
370void fluid_check_load_dependence(
const qn::NetworkStruct<T>& sn,
const std::string& m) {
371 if (m ==
"closing" || m ==
"minnormal" || m ==
"refined" || m ==
"dae")
return;
372 for (std::size_t i = 0; i < sn.stations.size(); ++i)
373 for (std::size_t k = 0; k < sn.stations[i].lldscaling.size(); ++k)
374 if (std::fabs(num_traits<T>::to_double(sn.stations[i].lldscaling[k]) - 1.0) >
377 "solver_fluid_run_analyzer: this model uses load dependence (setLoadDependence), which "
380 "' method does not evaluate. Use method 'closing' for the mean-field answer, or "
381 "'minnormal'/'refined' for the moment-closure correction");
408std::string fluid_forkjoin_supports(
const qn::NetworkStruct<T>& sn,
const std::string& m) {
409 if (m !=
"dae" && m !=
"fld.dae")
return std::string();
410 if (!sn.has_fork())
return std::string();
411 bool any_open =
false;
412 for (std::size_t r = 0; r < sn.classes.size(); ++r)
413 if (!std::isfinite(sn.classes[r].population)) any_open =
true;
414 if (!any_open)
return std::string();
415 return "solver_fluid_run_analyzer: the dae method has no route through the fork-join fixed "
416 "point on an OPEN model: the transform hands the inner solve a mixed network whose "
417 "auxiliary open classes the DAE form carries no unknowns for. Use method 'minnormal', "
418 "which is the same closure and does run that fixed point";
439void fluid_check_dae(
const qn::NetworkStruct<T>& sn,
const std::string& m) {
440 if (m !=
"dae")
return;
441 if (fluid_has_cache(sn))
443 "solver_fluid_run_analyzer: the dae method does not support caching stations: a cache model is "
444 "solved by decomposition, so it has no single drift to constrain. Use "
445 "method 'minnormal' for the same closure, or 'rmf'");
446 const std::string fj = fluid_forkjoin_supports(sn, m);
466void fluid_check_finite_capacity(
const qn::NetworkStruct<T>& sn,
const std::string& m) {
467 if (m ==
"dae" || m ==
"fld.dae" || m ==
"mol" || m ==
"fld.mol")
return;
469 if ((m ==
"mfq" || m ==
"fld.mfq" || m ==
"aoi" || m ==
"fld.aoi") &&
aoi_is_aoi(sn).ok)
return;
505 qn::NetworkStruct<T>* sn_out =
nullptr,
506 qn::NetworkStruct<T>* refreshed_out =
nullptr,
507 solvers::CacheMetrics<T>* cache_out =
nullptr);
522mva::MvaSolution<T> fluid_as_mva_solution(
const FluidSolution& f) {
523 mva::MvaSolution<T> s;
524 const std::size_t M = f.QN.rows(), K = f.QN.cols();
525 const T zero = num_traits<T>::from_int(0);
530 for (std::size_t i = 0; i < M; ++i)
531 for (std::size_t k = 0; k < K; ++k) {
532 s.Q(i, k) = num_traits<T>::from_double(f.QN(i, k));
533 s.U(i, k) = num_traits<T>::from_double(f.UN(i, k));
534 s.R(i, k) = num_traits<T>::from_double(f.RN(i, k));
535 s.Tp(i, k) = num_traits<T>::from_double(f.TN(i, k));
537 s.C.reserve(f.CN.size());
538 for (
double v : f.CN) s.C.push_back(num_traits<T>::from_double(v));
539 s.X.reserve(f.XN.size());
540 for (
double v : f.XN) s.X.push_back(num_traits<T>::from_double(v));
542 s.iter =
static_cast<int>(f.iters);
551FluidSolution fluid_from_mva_solution(
const mva::MvaSolution<T>& s,
const std::string& method) {
553 const std::size_t M = s.Q.rows(), K = s.Q.cols();
554 f.QN = Matrix<double>(M, K, 0.0);
555 f.UN = Matrix<double>(M, K, 0.0);
556 f.RN = Matrix<double>(M, K, 0.0);
557 f.TN = Matrix<double>(M, K, 0.0);
558 for (std::size_t i = 0; i < M; ++i)
559 for (std::size_t k = 0; k < K; ++k) {
560 f.QN(i, k) = num_traits<T>::to_double(s.Q(i, k));
561 f.UN(i, k) = num_traits<T>::to_double(s.U(i, k));
562 f.RN(i, k) = num_traits<T>::to_double(s.R(i, k));
563 f.TN(i, k) = num_traits<T>::to_double(s.Tp(i, k));
565 f.CN.reserve(s.C.size());
566 for (
const T& v : s.C) f.CN.push_back(num_traits<T>::to_double(v));
567 f.XN.reserve(s.X.size());
568 for (
const T& v : s.X) f.XN.push_back(num_traits<T>::to_double(v));
569 f.iters =
static_cast<std::size_t
>(s.iter < 0 ? 0 : s.iter);
575inline Matrix<double> fluid_leading_rows(
const Matrix<double>& m, std::size_t M) {
576 if (m.rows() <= M)
return m;
577 Matrix<double> out(M, m.cols(), 0.0);
578 for (std::size_t i = 0; i < M; ++i)
579 for (std::size_t k = 0; k < m.cols(); ++k) out(i, k) = m(i, k);
594FluidSolution fluid_fork_join_run(
const qn::NetworkStruct<T>& sn,
const FluidOptions& opt) {
596 std::vector<T> lam(tr.V.classes.size() + 1,
598 mva::MvaOptions mopt;
599 mopt.method = opt.method;
605 mopt.iter_tol = opt.iter_tol > 0.0 ? opt.iter_tol : 1e-4;
606 mopt.iter_max = opt.iter_max;
607 mopt.fork_join = opt.fork_join;
608 mopt.base_has_fork =
true;
609 FluidOptions inner = opt;
611 const mva::MvaSolution<T> merged =
615 FluidSolution out = fluid_from_mva_solution<T>(merged, opt.method);
623 out.QN = detail::fluid_leading_rows(out.QN, sn.nstations);
624 out.UN = detail::fluid_leading_rows(out.UN, sn.nstations);
625 out.RN = detail::fluid_leading_rows(out.RN, sn.nstations);
626 out.TN = detail::fluid_leading_rows(out.TN, sn.nstations);
631 for (std::size_t i = 0; i < sn.nstations && i < out.UN.rows(); ++i)
632 if (sn.stations[i].nodetype == qn::NodeType::Join)
633 for (std::size_t k = 0; k < out.UN.cols(); ++k) out.UN(i, k) = 0.0;
643inline bool fluid_is_petri_net(
const qn::NetworkStruct<T>& sn) {
644 for (std::size_t i = 0; i < sn.nodes.size(); ++i)
659inline FluidSolution fluid_petri_run(
const qn::NetworkStruct<T>& sn,
const FluidOptions& opt) {
660 const std::string m = (opt.method.rfind(
"fld.", 0) == 0) ? opt.method.substr(4) : opt.method;
661 if (!(m ==
"default" || m ==
"dae"))
663 "SolverFluid: method '" + opt.method +
664 "' cannot solve a Petri net: its conserved quantities are P-invariants rather than "
665 "chain populations, an immediate transition is an algebraic FLOW rather than an "
666 "event with a rate, and a bounded place is a linear inequality on the marking. Only "
667 "'dae' states those as equations; every other fluid method builds its drift from the "
668 "station/class/phase encoding, where a Place contributes no coordinate at all, and "
669 "would integrate the net as an empty model and report zeros without a warning");
670 petri::PetriOptions po;
671 if (opt.dae_maxstate > 0) po.dae_maxstate = opt.dae_maxstate;
672 po.fluid_boundary = opt.fluid_boundary;
680 out.iters = ps.iters;
682 const std::size_t M = ps.QN.rows(), K = ps.QN.cols();
683 out.CN.assign(K, 0.0);
684 out.XN.assign(K, 0.0);
685 for (std::size_t k = 0; k < K; ++k) {
686 double q = 0.0, x = 0.0;
687 for (std::size_t i = 0; i < M; ++i) {
689 x = std::max(x, ps.TN(i, k));
692 out.CN[k] = (x > 1e-14) ? q / x : 0.0;
696 out.has_moments =
true;
697 out.moments.Sigma = ps.Sigma;
698 out.moments.QVar = ps.QVar;
699 out.moments.QStd = ps.QStd;
711inline std::vector<FluidTranPoint> fluid_petri_transient(
const qn::NetworkStruct<T>& sn,
const FluidOptions& opt,
712 std::size_t points) {
713 const std::string m = (opt.method.rfind(
"fld.", 0) == 0) ? opt.method.substr(4) : opt.method;
716 "SolverFluid: getTranAvg integrates the first-order 'closing' drift for method '" + opt.method +
717 "', which has no coordinate for a Place, so a Petri net has no transient under it. Use method "
718 "'dae', which integrates the net's own differential-algebraic system");
719 petri::PetriOptions po;
720 if (opt.dae_maxstate > 0) po.dae_maxstate = opt.dae_maxstate;
721 if (opt.dae_maxcov > 0) po.dae_maxcov = opt.dae_maxcov;
722 po.fluid_boundary = opt.fluid_boundary;
724 const std::size_t np = std::max<std::size_t>(points, 2);
725 for (std::size_t j = 1; j < np; ++j)
726 po.tranpoints.push_back(po.timespan_end *
static_cast<double>(j) /
static_cast<double>(np - 1));
729 const std::size_t M = ps.QN.rows(), K = ps.QN.cols(), nt = ps.t.size();
730 const bool withvar = ps.Sigmat.size() == nt && nt > 0;
731 std::vector<FluidTranPoint> traj(nt);
732 for (std::size_t a = 0; a < nt; ++a) {
733 FluidTranPoint& p = traj[a];
736 p.QN = Matrix<double>(M, K, 0.0);
737 p.UN = Matrix<double>(M, K, 0.0);
738 p.TN = Matrix<double>(M, K, 0.0);
739 for (std::size_t i = 0; i < M; ++i)
740 for (std::size_t k = 0; k < K; ++k) {
741 p.QN(i, k) = ps.QNt[i][k][a];
742 p.UN(i, k) = ps.UNt[i][k][a];
743 p.TN(i, k) = ps.TNt[i][k][a];
745 if (!withvar)
continue;
747 p.QVar = Matrix<double>(M, K, 0.0);
748 for (std::size_t ci = 0; ci < terms.cov_idx.size(); ++ci) {
749 const std::size_t s = terms.cov_idx[ci];
750 const double v = std::max(0.0, ps.Sigmat[a](ci, ci));
751 if (s < terms.nm && terms.coord_station[s] >= 0 &&
static_cast<std::size_t
>(terms.coord_station[s]) < M)
752 p.QVar(
static_cast<std::size_t
>(terms.coord_station[s]), terms.coord_class[s]) = v;
753 for (std::size_t q = 0; q < terms.nf; ++q)
754 if (terms.fluid_slot[q] == s && terms.fluid_station[q] >= 0 && K > 0)
755 p.QVar(
static_cast<std::size_t
>(terms.fluid_station[q]), 0) = v;
769 if (sn_out) *sn_out =
sn;
782 if (detail::fluid_is_petri_net(
sn))
return detail::fluid_petri_run(
sn,
opt);
787 const std::string m = detail::fluid_resolve_method(
sn,
opt.method,
opt, why);
792 detail::fluid_check_load_dependence(
sn, m);
793 detail::fluid_check_dae(
sn, m);
794 detail::fluid_check_finite_capacity(
sn, m);
801 return detail::fluid_fork_join_run(
sn, fo);
822 if (m ==
"rmf" || (m ==
"minnormal" && detail::fluid_has_cache(
sn))) {
830 if (refreshed_out) *refreshed_out = cq.
refreshed;
832 }
else if (m ==
"closing" || m ==
"statedep" || m ==
"softmin" || m ==
"tbi") {
835 }
else if (m ==
"minnormal" || m ==
"refined") {
863 moments_solve, sn_out);
865 std::string dae_reason;
867 if (detail::fluid_dae_applicable(
sn, o, dae_reason)) {
880 o.
method = detail::fluid_has_dps(
sn) ?
"closing" :
"matrix";
882 detail::fluid_check_load_dependence(
sn, o.
method);
888 closing_solve, sn_out);
889 detail::fluid_analyzer_correct(
sn, out.
QN, out.
UN, out.
RN, out.
TN);
890 detail::fluid_snap_all(out.
QN, out.
UN, out.
RN, out.
TN);
894 }
else if (m ==
"dae") {
907 }
else if (m ==
"kp") {
909 }
else if (detail::fluid_qsys_handles(m)) {
920 detail::fluid_analyzer_correct(
sn, out.
QN, out.
UN, out.
RN, out.
TN);
921 detail::fluid_snap_all(out.
QN, out.
UN, out.
RN, out.
TN);
943 std::size_t points = 101) {
945 if (detail::fluid_is_petri_net(
sn))
return detail::fluid_petri_transient(
sn,
opt, points);
950 if (detail::fluid_qsys_handles(detail::fluid_unqualify(
opt.method))) {
952 o.
method = detail::fluid_unqualify(
opt.method);
954 std::vector<FluidTranPoint> traj;
958 if (detail::fluid_unqualify(
opt.method) !=
"dae")
961 detail::fluid_check_dae(
sn, std::string(
"dae"));
985 std::size_t points = 201) {
990 "solver_fluid_cdf_respt: the '" + r.
method +
991 "' method reports no fluid state vector to mark a job in, so it has no passage time; "
992 "use 'closing', 'matrix' or a moment closure");
993 std::vector<std::vector<FluidPassage> > RD(
995 for (std::size_t i = 0; i < snr.
nstations; ++i) {
996 if (snr.
stations[i].nodetype == qn::NodeType::Source)
continue;
997 for (std::size_t c = 0; c < snr.
nclasses; ++c) {
1018 const std::string& notation =
"scalar",
1019 const std::string& model_name =
"model") {
1020 const std::string m = detail::fluid_resolve_method(
sn,
opt.method);
1023 "solver_fluid_export_odes: a Cache model is solved by alternating a cache drift with a "
1024 "queueing drift whose routing is rewritten at every sweep, so it has no one ODE system "
1025 "to export; export the model without its Cache node, or read the sweeps through "
1026 "solver_fld_cacheqn_tran");
What a solver observed about the Cache nodes of a model.
UnsupportedError(const std::string &what)
Raised when the moment closure cannot serve this model: the linearization at the fixed point is not h...
A network plus its refreshed NetworkStruct.
std::vector< std::vector< bool > > disabled
std::vector< Station< T > > stations
stations[k-1] is the k-th station
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 INTEGRATED caching-queueing network under the fluid solver: ports of solver_fld_cacheqn_analyzer....
Port of solver_fluid_initsol.m, and of the entry point of solver_fluid_closing.m that consumes it.
The min-normal closure as a DIFFERENTIAL-ALGEBRAIC system: solver_fluid_dae.m.
@@SolverFLD/exportODEs.m: the fluid ODE system as a standalone LaTeX document, in a form meant to be ...
Port of solver_fluid_kp.m: the fluid AND diffusion limits of the (MAP_t/Ph_t/inf)^N network of Y.
The second-order fluid methods: fluid_moment_terms.m, fluid_lyapunov.m, fluid_drift_jacobian....
The one exception the fluid fallback ladder catches.
Response-time distribution by tagged fluid: a port of solver_fluid_passage_time.m,...
Fluid analysis of a stochastic Petri net: one simultaneous algebraic solve per active set.
Port of matlab/src/solvers/FLD/solver_fluid_qsys_analyzer.m: the single-station fluid limits.
Port of ode_eliminate_immediate.m, eliminate_immediate_matrix.m and ode_solve_stiff....
The method names of each solver, in listing order.
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...
PetriTerms petri_build_terms(const qn::NetworkStruct< T > &sn)
Assemble the drift terms of a net.
double petri_fine_tol()
GlobalConstants.FineTol, the reference's own "effectively zero".
PetriSolution solver_fluid_petri(const qn::NetworkStruct< T > &sn, const PetriOptions &opt=PetriOptions())
Fluid analysis of a stochastic Petri net.
FluidCacheqnSolution< T > solver_fld_cacheqn_analyzer(const qn::NetworkStruct< T > &sn, const FluidOptions &opt)
Port of solver_fld_cacheqn_analyzer.m.
void fluid_check_method(const std::string &method)
Port of runAnalyzerChecks' method gate: an unlisted method is refused.
double fluid_default_horizon(const qn::NetworkStruct< T > &sn, const FluidOptions &opt)
The horizon a transient runs to when the caller gives none.
FluidMfqAdmits fluid_mfq_admits(const qn::NetworkStruct< T > &sn)
Port of fluid_mfq_admits.m.
FluidSolution solver_fluid_kp(const qn::NetworkStruct< T > &sn, const FluidOptions &opt)
Port of solver_fluid_kp.m: the steady table at the horizon.
FluidLayout fluid_layout(const qn::NetworkStruct< T > &sn)
Port of the layout half of solver_fluid_odes.m.
FluidSolution solver_fluid_dae(const qn::NetworkStruct< T > &sn, const FluidOptions &opt, const FluidDaeOptions &dopt_in=FluidDaeOptions())
solver_fluid_dae.m: the min-normal closure solved as one system.
FluidSolution solver_fluid_closing(const qn::NetworkStruct< T > &sn, const FluidOptions &opt)
Port of solver_fluid_closing.m: the closing family's entry point.
std::vector< std::string > fluid_list_valid_methods()
Port of SolverFLD.listValidMethods.
AoiTopology aoi_is_aoi(const qn::NetworkStruct< T > &sn)
Port of aoi_is_aoi.m.
std::string solver_fluid_export_odes(const qn::NetworkStruct< T > &sn, const FluidOptions &opt, const std::string ¬ation="scalar", const std::string &model_name="model")
Port of @@SolverFLD/exportODEs.m, which hands options.method to solver_fluid_symodes UNRESOLVED: defa...
FluidDaeOptions fluid_dae_options(const FluidOptions &opt, const FluidDaeOptions &dopt)
The controls the DAE route actually reads: the struct a caller pinned, with whatever options....
FluidSolution solver_fluid(const qn::NetworkStruct< T > &sn_in, const FluidOptions &opt, qn::NetworkStruct< T > *sn_out=nullptr)
Port of solver_fluid_analyzer.m: dispatch on the method, refit the non-exponential FCFS stations the ...
FluidSolution solver_fluid_qsys(const qn::NetworkStruct< T > &sn, const FluidOptions &opt, std::vector< FluidTranPoint > *traj=nullptr)
Solve a single-station model with one of the closed-form fluid limits.
std::vector< FluidTranPoint > solver_fluid_tran_avg(const qn::NetworkStruct< T > &sn, const FluidOptions &opt, std::size_t points=101)
getTranAvg on the first-order closing drift, over that horizon.
FluidPassage fluid_passage_time(const qn::NetworkStruct< T > &sn, const std::vector< double > &x_steady, std::size_t ist, std::size_t cls, double tol=1e-4, std::size_t points=201, const FluidClosure &closure=FluidClosure())
Response-time CDF at station ist for class cls, both 1-based.
FluidSolution solver_fluid_moments(const qn::NetworkStruct< T > &sn, const FluidOptions &opt)
Port of solver_fluid_moments.m: the second-order fluid analysis backing minnormal and refined.
FluidSolution solver_fluid_run_analyzer(const qn::NetworkStruct< T > &sn, const FluidOptions &opt, qn::NetworkStruct< T > *sn_out=nullptr, qn::NetworkStruct< T > *refreshed_out=nullptr, solvers::CacheMetrics< T > *cache_out=nullptr)
Port of @@SolverFLD/runAnalyzer.m: resolve the method, route to the function the reference routes to,...
std::vector< std::vector< FluidPassage > > solver_fluid_cdf_respt(const qn::NetworkStruct< T > &sn, const FluidOptions &opt, std::size_t points=201)
Port of @@SolverFLD/getCdfRespT: the response-time law of every (station, class) pair,...
std::string fluid_export_odes(const qn::NetworkStruct< T > &sn, const FluidOptions &opt, const std::string ¬ation="scalar", const std::string &model_name="model")
Render the fluid ODE system of sn as a LaTeX document.
std::vector< FluidTranPoint > solver_fluid_run_transient(const qn::NetworkStruct< T > &sn, const FluidOptions &opt, std::size_t points=101)
-a tran / @@SolverFLD/getTranAvg with the method HONOURED, which is the one place the reference does ...
std::vector< FluidTranPoint > solver_fluid_dae_transient(const qn::NetworkStruct< T > &sn, const FluidOptions &opt, double t_end, std::size_t points=101, const std::vector< double > &out_grid=std::vector< double >(), const FluidDaeOptions &dopt_in=FluidDaeOptions())
@@SolverFLD/getTranAvg for the DAE route: the metrics ALONG the trajectory.
SchedStrategy
Scheduling disciplines, with the values of MATLAB SchedStrategy.
const char * sched_to_text(SchedStrategy s)
ReplacementStrategy
Cache replacement policies, with the values of MATLAB ReplacementStrategy.
@ FIFO
first in, first out
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.
FeatureSet fluid_feature_set(const std::string &method)
void check_binding_capacity(const std::string &solver, const NetworkStruct< T > &sn)
NetworkSolver.checkBindingCapacity (NetworkSolver.m:1172-1228): the shared structural gate for finite...
bool has_binding_capacity(const NetworkStruct< T > &sn)
getUsedLangFeatures: the features the MODEL uses.
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.
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...
FjMetrics< double > fj_metrics_to_double(const FjMetrics< T > &in)
The same metrics in double precision, for the facade and the CLI.
Conservation laws of a layered queueing network, enumerated from its structure.
A queueing network and its refreshed NetworkStruct.
Port of matlab/src/api/sn/sn_patience_handles.m.
The DECLARED side of the gate: one feature set per solver.
SolverFluid: the closing method, a port of solver_fluid.m, solver_fluid_iteration....
The <kind> part of a LINE:<category>:<kind> identifier (see _kb/17-error-vocabulary....
What the steady analyzer returns: the fluid metrics plus the converged split.
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,...
Matrix< T > hitprob
(ncaches x nclasses), cache order as the node scan
Controls, defaulting to SolverOptions('Fluid') in the reference.
What the analyzer returns, in the same shape as the MVA solver's result.
std::vector< double > xvec
the converged fluid state
static constexpr double FineTol
static constexpr double Zero
Every Cache node of the model, in node order; empty on a model with none.