5#ifndef LINE_SOLVERS_AG_SOLVER_AG_RUNNER_H
6#define LINE_SOLVERS_AG_SOLVER_AG_RUNNER_H
39namespace runner_detail {
42inline std::vector<std::string> list_valid_methods() {
43 return {
"default",
"inap",
"inapplus",
"inapinf",
"exact"};
47inline void check_method(
const std::string& method) {
48 const std::vector<std::string> valid = list_valid_methods();
49 if (std::find(valid.begin(), valid.end(), method) == valid.end()) {
51 for (std::size_t i = 0; i < valid.size(); ++i) {
52 names += (i ?
", " :
"") + valid[i];
54 throw InputError(
"SolverAG: unknown method '" + method +
"'; valid methods are "
76std::string method_refusal(
const qn::NetworkStruct<T>& L,
const std::string& method) {
78 for (std::size_t i = 0; i < L.nstations; ++i) {
79 for (std::size_t r = 0; r < L.nclasses; ++r) {
82 if (!L.has_service_law(i, r) || !(L.rates(i, r) > num_traits<T>::from_int(0)))
84 const bool is_signal = r < L.issignal.size() && L.issignal[r];
85 const bool is_source = L.stations[i].nodetype == qn::NodeType::Source;
86 if (is_signal && !is_source)
continue;
88 if (L.service[i][r].type == ProcessType::EXP)
continue;
90 "SolverAG: the " + method +
91 " method needs an exponential signal arrival process (a removal signal "
92 "is folded into the agent as a scalar rate), but station '" +
93 L.stations[i].name +
"' class '" + L.classes[r].name +
"' is " +
95 ". Use SolverMAM (-s mam, method 'dec.source') for such models");
99 "SolverAG: the " + method +
100 " method supports processes with a Markovian (D0,D1) representation only "
101 "(RCAT builds a phase dimension per agent out of it), but station '" +
102 L.stations[i].name +
"' class '" + L.classes[r].name +
"' is " +
104 ". Use SolverMAM (-s mam, method 'dec.source') for such models");
121 for (std::size_t nd = 0; nd < L.nodes.size(); ++nd) {
122 for (std::size_t r = 0; r < L.nodes[nd].routing.size(); ++r) {
128 return std::string(
"SolverAG: the ") + method +
" method needs state-independent "
129 "routing (RCAT folds the split into a fixed action probability), but node '" +
130 L.nodes[nd].name +
"' routes class '" + L.classes[r].name +
"' by " +
132 ", whose share depends on the network state. Use SolverCTMC, SolverSSA or "
133 "SolverLDES, which re-evaluate the split per state";
139 for (std::size_t i = 0; i < L.nstations; ++i) {
140 if (std::isfinite(L.stations[i].nservers) && L.stations[i].nservers > 1.0) {
142 "SolverAG: the " + method +
143 " method supports single-server stations only (RCAT does not model "
144 "sn.nservers), but station '" + L.stations[i].name +
"' has " +
145 std::to_string(
static_cast<long long>(L.stations[i].nservers)) +
146 " servers. Use SolverMAM (-s mam, method 'dec.source') for multiserver "
166void check_model_method(
const qn::NetworkStruct<T>& L,
const std::string& method) {
167 const std::string why = method_refusal(L, method);
181 return runner_detail::list_valid_methods();
194 runner_detail::check_method(
opt.method);
195 runner_detail::check_model_method(L,
opt.method);
Options of the agent-based (RCAT) solver.
UnsupportedError(const std::string &what)
A network plus its refreshed NetworkStruct.
The exception types the port throws.
The language-feature gate: what a MODEL uses against what a SOLVER declares.
AgResult< T > solver_ag_solve(const qn::NetworkStruct< T > &L, const AgOptions &opt)
The gates and the dispatch of SolverAG's runAnalyzer.
std::vector< std::string > list_valid_methods()
Every method SolverAG serves, as the other families expose theirs.
AgResult< T > solver_ag(const qn::NetworkStruct< T > &L, const AgOptions &opt, std::size_t max_states=0)
Port of solver_ag.m.
bool rcat_supports_process(lang::ProcessType t)
The process types the RCAT construction can give a phase dimension to.
bool sn_has_nonmarkov(const qn::NetworkStruct< T > &sn, bool preserve_det=false)
Whether any law in the struct would be replaced, so a caller can skip copying the struct when there i...
@ Ph
Bernstein density fit: a genuine phase-type, shape-carrying.
void sn_nonmarkov_toph(qn::NetworkStruct< T > &sn, const NonmarkovOptions &opts=NonmarkovOptions())
Replace every non-Markovian service and firing law by a Markovian surrogate.
RoutingStrategy
Routing strategies, with the values of MATLAB RoutingStrategy.
ProcessType
Distribution kinds, with the values of MATLAB ProcessType.
const char * process_to_text(ProcessType p)
The MATLAB ProcessType name, as sn.procid prints it.
const char * routing_to_text(RoutingStrategy r)
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.
FeatureSet ag_feature_set(const std::string &)
SolverAG.getFeatureSet: what the RCAT decomposition can represent.
std::string binding_capacity_reason(const std::string &solver, const NetworkStruct< T > &sn)
The refusal check_binding_capacity raises, as a string, or empty when no buffer binds.
A queueing network and its refreshed NetworkStruct.
Replace every non-Markovian service and firing law by a Markovian surrogate.
Port of solver_ag.m: the RCAT (Reversed Compound Agent Theorem) analyzers, reached by methods 'inap',...
The DECLARED side of the gate: one feature set per solver.
What the RCAT analyzer returns beyond the metrics.
options.config.nonmkv and friends.
std::size_t order
nonmkvorder, the phase budget
PhFit phfit
which surrogate family
bool preserve_det
Leave Det alone for the exact MAP/D/c branch, options.config.preserveDet.