5#ifndef LINE_LANG_QN_ENVIRONMENT_H
6#define LINE_LANG_QN_ENVIRONMENT_H
114 low.reserve(name.size());
115 for (std::size_t i = 0; i < name.size(); ++i)
116 low.push_back(
static_cast<char>(std::tolower(
static_cast<unsigned char>(name[i]))));
120 throw InputError(
"Environment: unknown reset policy '" + name +
121 "'. The serializable policies are 'keep' (carry the queue lengths across "
122 "the switch) and 'clear' (empty the queues); a custom policy is a function "
123 "and is installed through add_transition, not by name");
214 const std::string& node_name,
217 std::size_t node = 0;
218 for (std::size_t i = 0; i <
sn.nodes.size(); ++i)
219 if (
sn.nodes[i].name == node_name) {
224 throw InputError(
"Environment: node '" + node_name +
225 "' is not in the base model, so it has no service to degrade");
226 const std::size_t ist =
sn.nodes[node - 1].station;
228 throw InputError(
"Environment: node '" + node_name +
229 "' is not a station and carries no service distribution, so it cannot "
230 "break down into a degraded service");
236 for (std::size_t r = 1; r <=
sn.classes.size(); ++r)
sn.set_service(ist, r, d);
246 kernel_prob_(
nstages,
nstages, std::numeric_limits<double>::quiet_NaN()) {
247 if (
nstages == 0)
throw InputError(
"Environment: a random environment needs a stage");
250 std::size_t
nstages()
const {
return stages_.size(); }
251 const std::string&
name()
const {
return name_; }
254 void set_stage(std::size_t e,
const std::string& nm,
const std::string& type,
257 stages_[e].name = nm;
258 stages_[e].type = type;
259 stages_[e].model = model;
260 stages_[e].has_model =
true;
261 stages_[e].has_lqn =
false;
278 void set_lqn_stage(std::size_t e,
const std::string& nm,
const std::string& type,
283 for (std::size_t h = 0; h < stages_.size(); ++h)
284 if (h != e && stages_[h].has_lqn &&
285 (stages_[h].lqn_model.nidx != model.
nidx || stages_[h].lqn_model.tshift != model.
tshift))
287 "Unsupported feature. Random environment stages must map to layered networks "
288 "with the same hosts, tasks, entries and activities.");
289 stages_[e].name = nm;
290 stages_[e].type = type;
291 stages_[e].lqn_model = model;
292 stages_[e].has_lqn =
true;
293 stages_[e].has_model =
false;
300 return stages_[e].has_lqn;
305 for (std::size_t e = 0; e < stages_.size(); ++e)
306 if (stages_[e].has_lqn)
return true;
321 for (std::size_t e = 0; e < stages_.size(); ++e)
322 if (stages_[e].has_lqn)
324 who +
": stage " + std::to_string(e + 1) +
" ('" + stages_[e].name +
325 "') holds a LayeredNetwork, and " + why +
326 ". The mean-field coupling (method 'default' / 'meanfield') is the one that "
327 "solves a layered stage, through SolverLN");
342 arcs_[e][h].enabled =
true;
343 arcs_[e][h].dist = d;
344 arcs_[e][h].reset = reset;
345 kernel_prob_(e, h) = std::numeric_limits<double>::quiet_NaN();
361 if (!(prob > 0.0 && prob <= 1.0))
362 throw InputError(
"Environment: the probability of a kernel transition must be a "
365 kernel_prob_(e, h) = prob;
372 return kernel_prob_(e, h);
378 for (std::size_t h = 0; h < stages_.size(); ++h)
379 if (!std::isnan(kernel_prob_(e, h)))
return true;
390 for (std::size_t h = 0; h < stages_.size(); ++h) {
392 if (a.
enabled && !a.
dist.disabled && !arc_is_markovian(a.
dist))
return true;
405 for (std::size_t h = 0; h < stages_.size(); ++h)
406 if (h != e && arcs_[e][h].enabled && !arcs_[e][h].dist.disabled)
return false;
415 for (std::size_t e = 0; e < stages_.size(); ++e)
416 if (!stages_[e].declared())
417 throw InputError(
"Environment: stage " + std::to_string(e + 1) +
" has no model");
422 for (std::size_t e = 0; e < stages_.size(); ++e)
432 for (std::size_t e = 0; e < stages_.size(); ++e)
435 "Stage " + std::to_string(e + 1) +
" ('" + stages_[e].
name +
436 "') has no outgoing transition, so the environment is absorbing and has no "
437 "single steady state: its limit depends on the initial stage. Method '" +
438 method +
"' reads the stationary stage probabilities; use method "
439 "'occupation', with options.config.env_init naming the initial stage law.");
444 for (std::size_t e = 0; e < stages_.size(); ++e)
456 std::vector<double>& probs)
const {
458 const std::size_t E = stages_.size();
460 for (std::size_t h = 0; h < E; ++h)
461 if (h != e && arcs_[e][h].enabled && !arcs_[e][h].dist.disabled)
462 arcs[h] = arcs_[e][h].dist;
465 probs.assign(E, 0.0);
467 for (std::size_t h = 0; h < E; ++h) {
468 if (!arcs[h].disabled) {
469 if (std::isnan(kernel_prob_(e, h)))
470 throw InputError(
"Environment: stage " + std::to_string(e + 1) +
471 " mixes kernel and competing transitions (the one to stage " +
472 std::to_string(h + 1) +
473 " was added by addTransition). Declare all of a stage's "
474 "transitions with addKernelTransition, or none.");
475 probs[h] = kernel_prob_(e, h);
477 }
else if (!std::isnan(kernel_prob_(e, h))) {
478 throw InputError(
"Environment: the kernel transition " + std::to_string(e + 1) +
479 "->" + std::to_string(h + 1) +
" has no law.");
482 if (std::fabs(tot - 1.0) > 1e-8) {
484 std::snprintf(buf,
sizeof buf,
"%.12g", tot);
485 throw InputError(
"Environment: the kernel probabilities out of stage " +
486 std::to_string(e + 1) +
" sum to " + buf +
", not 1.");
497 if (method ==
"smp")
return;
498 const std::size_t E = stages_.size();
499 for (std::size_t e = 0; e < E; ++e) {
502 "Stage " + std::to_string(e + 1) +
503 " has kernel transitions (addKernelTransition), which only method 'smp' of "
504 "SolverENV solves: the other couplings read each stage's holding time as a "
505 "Markovian (D0,D1) race of its transitions.");
506 for (std::size_t h = 0; h < E; ++h) {
508 if (!a.
enabled || a.
dist.disabled || arc_is_markovian(a.
dist))
continue;
510 "The distribution of the environment transition from stage " +
511 std::to_string(e + 1) +
" to " + std::to_string(h + 1) +
" is a " +
514 "' reads every arc as a (D0,D1) process to build the holding-time laws. Use "
515 "method 'smp', which solves the semi-Markov environment, or fit the arc to a "
516 "phase-type law, e.g. APH.fitMeanAndSCV.");
538 if (!arcs_[e][h].enabled)
539 throw InputError(
"Environment: no transition " + stages_[e].
name +
" -> " +
541 " is declared, so its rate cannot be made state dependent");
542 arcs_[e][h].reset_rates = f;
556 if (!arcs_[e][h].enabled)
557 throw InputError(
"Environment: no transition " + stages_[e].
name +
" -> " +
558 stages_[h].
name +
" is declared, so its distribution cannot be set");
559 arcs_[e][h].dist = d;
564 for (std::size_t e = 0; e < stages_.size(); ++e)
565 if (stages_[e].has_model && stages_[e].
name == nm)
return e;
566 return stages_.size();
580 if (!arcs_[e][h].enabled)
581 throw InputError(
"Environment: no transition " + stages_[e].
name +
" -> " +
583 " is declared, so it cannot be given a reset policy");
584 arcs_[e][h].reset = reset;
590 const std::vector<NodeFailure<T>>&
node_failures()
const {
return node_failures_; }
594 for (std::size_t i = 0; i < node_failures_.size(); ++i)
595 if (node_failures_[i].node == nm)
return i;
596 return node_failures_.size();
616 const std::string& reset_policy =
"keep") {
620 throw InputError(
"Environment: the UP and DOWN stages of node '" + node_name +
621 "' must be different stages");
622 if (!stages_[up].has_model)
set_stage(up,
"UP",
"operational", base);
632 record_node_failure(nf);
637 const std::string& reset_policy =
"keep") {
640 if (down == stages_.size())
642 "' is not defined; declare the breakdown of node '" + node_name +
643 "' before its repair");
644 if (up == stages_.size())
645 throw InputError(
"Environment: no UP stage is defined, so node '" + node_name +
646 "' has nothing to be repaired into");
650 if (idx == node_failures_.size())
651 throw InputError(
"Environment: no breakdown is recorded for node '" + node_name +
652 "', so its repair would describe a failure that was never declared");
653 node_failures_[idx].repair = repair;
654 node_failures_[idx].has_repair =
true;
655 node_failures_[idx].repair_reset = reset_policy;
663 const std::string& breakdown_reset =
"keep",
664 const std::string& repair_reset =
"keep") {
665 add_node_breakdown(up, down, base, node_name, breakdown, down_service, breakdown_reset);
681 const std::string& breakdown_reset,
682 const std::string& repair_reset) {
685 if (up == stages_.size())
686 throw InputError(
"Environment: cannot register a node failure on '" + node_name +
687 "': no UP stage is defined in this environment");
688 if (down == stages_.size())
689 throw InputError(
"Environment: cannot register a node failure on '" + node_name +
691 "' stage is defined in this environment");
705 record_node_failure(nf);
723 const std::size_t E = stages_.size();
728 sm_stage_.assign(E, 0);
730 sm_probs_.assign(E, std::vector<double>());
733 for (std::size_t e = 0; e < E; ++e)
734 for (std::size_t h = 0; h < E; ++h)
735 proc[e][h] = sm_stage_[e] ? disabled_mmap(E) : arc_mmap(e, h, E);
740 std::vector<double> lambda(E, 0.0);
741 for (std::size_t e = 0; e < E; ++e) {
746 hold_mean[e] = std::numeric_limits<double>::infinity();
754 for (std::size_t h = 0; h < E; ++h) Pemb(e, h) = q.
P[h];
757 lambda[e] = (q.
m > 0.0) ? 1.0 / q.
m : 0.0;
763 for (std::size_t h = 0; h < E; ++h) {
764 if (h == e)
continue;
765 ht = superpose_collapsed(ht,
proc[e][h]);
770 for (
double v : cl) tot += v;
772 for (std::size_t h = 0; h < E; ++h) Pemb(e, h) = cl[h] / tot;
775 lambda[e] = (m > 0.0) ? 1.0 / m : 0.0;
780 bool all_positive =
true;
781 for (
double v : lambda)
782 if (!(v > 0.0)) all_positive =
false;
795 for (std::size_t e = 0; e < E; ++e)
796 for (std::size_t h = 0; h < E; ++h)
797 A(e, h) = -lambda[e] * ((e == h ? 1.0 : 0.0) - Pemb(e, h));
801 for (std::size_t e = 0; e < E; ++e) {
802 for (std::size_t h = 0; h < E; ++h)
806 for (std::size_t h = 0; h < E; ++h) s +=
prob_orig(h, e);
808 for (std::size_t h = 0; h < E; ++h)
prob_orig(h, e) /= s;
839 "Environment: reliability metrics are read from probEnv; call init() first");
840 const std::size_t E = stages_.size();
844 "Environment: no UP stage, so there is nothing for a breakdown to leave; "
845 "reliability metrics apply to an environment built with add_node_breakdown");
846 std::vector<std::size_t> down;
847 for (std::size_t e = 0; e < E; ++e)
848 if (stages_[e].
name.compare(0, 5,
"DOWN_") == 0) down.push_back(e);
851 "Environment: no DOWN_<node> stage, so no node breaks down; reliability metrics "
852 "apply to an environment built with add_node_breakdown");
854 double lambda_total = 0.0;
855 for (std::size_t h : down)
856 if (arcs_[up][h].enabled) lambda_total += arc_rate(up, h);
857 if (!(lambda_total > 0.0))
859 "Environment: no UP -> DOWN transition, so the system never fails and its mean "
860 "time to failure is not a number");
862 std::vector<double> mu, p;
863 for (std::size_t e : down)
864 if (arcs_[e][up].enabled) {
870 "Environment: no DOWN -> UP transition, so the system is never repaired and its "
871 "mean time to repair is not a number");
874 r.
mttf = 1.0 / lambda_total;
878 for (
double v : p) ptot += v;
880 for (std::size_t i = 0; i < mu.size(); ++i)
881 r.
mttr += (ptot > 0.0 ? p[i] / ptot : 1.0 /
static_cast<double>(mu.size())) / mu[i];
883 double pup =
prob_env[up], pdown = 0.0;
884 for (std::size_t e : down) pdown +=
prob_env[e];
885 r.
availability = (pup + pdown > 0.0) ? pup / (pup + pdown) : 0.0;
905 throw InputError(
"Environment: the stage table reads probEnv; call init() first");
906 std::vector<StageRow> rows(stages_.size());
907 for (std::size_t e = 0; e < stages_.size(); ++e) {
908 rows[e].stage = e + 1;
909 rows[e].name = stages_[e].name;
910 rows[e].type = stages_[e].type;
925 std::string s =
"Stage Table:\n============\n";
927 for (std::size_t e = 0; e < stages_.size(); ++e) {
929 std::snprintf(buf,
sizeof buf,
"Stage %zu: %s (Type: %s)\n", e + 1, st.
name.c_str(), st.
type.c_str());
932 std::snprintf(buf,
sizeof buf,
" - Network: %s\n - Nodes: %zu\n - Classes: %zu\n",
936 std::snprintf(buf,
sizeof buf,
" - Layered network: %zu tasks, %zu entries\n",
942 for (std::size_t e = 0; e < stages_.size(); ++e)
943 for (std::size_t h = 0; h < stages_.size(); ++h) {
948 std::snprintf(buf,
sizeof buf,
" %s -> %s: prob = %.4f, sojourn %s, mean = %.4f\n",
949 stages_[e].
name.c_str(), stages_[h].name.c_str(), kernel_prob_(e, h),
952 std::snprintf(buf,
sizeof buf,
" %s -> %s: rate = %.4f\n", stages_[e].
name.c_str(),
953 stages_[h].name.c_str(), 1.0 / m);
956 if (!
tr.empty()) s +=
"\nTransitions:\n" +
tr;
970 std::vector<double>
hold_time_cdf(std::size_t e,
const std::vector<double>& t)
const {
972 if (e >= sm_stage_.size())
973 throw InputError(
"Environment: the holding-time law is built by init(); call it first");
982 throw InputError(
"Environment: the holding-time law is built by init(); call it first");
989 return e < sm_stage_.size() && sm_stage_[e];
993 std::vector<std::vector<mam::Mmap<double>>>
proc;
1016 void check(std::size_t e)
const {
1017 if (e >= stages_.size())
throw InputError(
"Environment: stage index out of range");
1021 double arc_rate(std::size_t e, std::size_t h)
const {
1022 const double m = num_traits<T>::to_double(arcs_[e][h].dist.mean);
1024 throw InputError(
"Environment: the transition " + stages_[e].
name +
" -> " +
1026 " has no positive mean, so it carries no rate to report");
1031 void record_node_failure(
const NodeFailure<T>& nf) {
1033 if (idx < node_failures_.size())
1034 node_failures_[idx] = nf;
1036 node_failures_.push_back(nf);
1043 mam::Mmap<double> arc_mmap(std::size_t e, std::size_t h, std::size_t E)
const {
1044 mam::Mmap<double> m;
1045 if (!arcs_[e][h].enabled) {
1046 m.D0 = Matrix<double>(1, 1, 0.0);
1047 m.D1 = Matrix<double>(1, 1, 0.0);
1048 m.Dc.assign(E, Matrix<double>(1, 1, 0.0));
1051 const lang::Distrib<T>& d = arcs_[e][h].dist;
1052 const std::size_t n = d.
D0.rows();
1054 throw InputError(
"Environment: the transition distribution has no representation");
1055 m.D0 = Matrix<double>(n, n, 0.0);
1056 m.D1 = Matrix<double>(n, n, 0.0);
1057 for (std::size_t a = 0; a < n; ++a)
1058 for (std::size_t b = 0; b < n; ++b) {
1059 m.D0(a, b) = num_traits<T>::to_double(d.D0(a, b));
1060 m.D1(a, b) = num_traits<T>::to_double(d.D1(a, b));
1062 m.Dc.assign(E, Matrix<double>(n, n, 0.0));
1076 static mam::Mmap<double> superpose_collapsed(
const mam::Mmap<double>& a,
1077 const mam::Mmap<double>& b) {
1078 mam::Mmap<double> s;
1081 s.Dc.reserve(a.Dc.size());
1082 for (std::size_t c = 0; c < a.Dc.size(); ++c)
1083 s.Dc.push_back(collapse(
mam::krons(a.Dc[c], b.Dc[c])));
1088 static Matrix<double> collapse(
const Matrix<double>& X) {
1089 Matrix<double> Y(X.rows(), X.cols(), 0.0);
1090 for (std::size_t i = 0; i < X.rows(); ++i) {
1092 for (std::size_t j = 0; j < X.cols(); ++j) s += X(i, j);
1099 std::vector<EnvStage<T>> stages_;
1100 std::vector<std::vector<EnvArc<T>>> arcs_;
1101 std::vector<NodeFailure<T>> node_failures_;
1102 Matrix<double> kernel_prob_;
1103 std::vector<char> sm_stage_;
1104 std::vector<std::vector<lang::Distrib<T>>> sm_arcs_;
1105 std::vector<std::vector<double>> sm_probs_;
UnsupportedError(const std::string &what)
const std::string & name() const
void set_env_rate_reset(std::size_t e, std::size_t h, const ResetEnvRates< T > &f)
resetEnvRatesFun{e,h}: make the e -> h transition depend on the state the stage is left in.
void register_node_failure(const std::string &node_name, const lang::Distrib< T > &breakdown, const lang::Distrib< T > &down_service, bool has_repair, const lang::Distrib< T > &repair, const std::string &breakdown_reset, const std::string &repair_reset)
Port of registerNodeFailure: attach a breakdown descriptor, and its reset policies,...
const std::vector< NodeFailure< T > > & node_failures() const
nodeFailures, the declarative record of the breakdowns declared here.
void init()
Port of Environment.init().
std::vector< double > rate
1/E[holding time]
void require_declared() const
Refuse a stage with no model.
Environment(const std::string &nm, std::size_t nstages)
void print_stage_table(std::FILE *out=stdout) const
printStageTable: writes stage_table_text() to out.
void add_node_breakdown(std::size_t up, std::size_t down, const qn::NetworkStruct< T > &base, const std::string &node_name, const lang::Distrib< T > &breakdown, const lang::Distrib< T > &down_service, const std::string &reset_policy="keep")
Port of addNodeBreakdown, on a FIXED stage count.
std::vector< double > hold_time_cdf(std::size_t e, const std::vector< double > &t) const
Environment.holdTimeCdf(holdTime{e}, t): the holding-time CDF of stage e at the instants t,...
bool is_semi_markov_stage(std::size_t e) const
isSemiMarkovStage: true if stage e's holding time has no Markovian (MAP) form, i.e.
bool hold_time_is_semi_markov(std::size_t e) const
True when init() built stage e as a semi-Markov stage (no MAP holding time).
void refuse_absorbing(const std::string &method) const
Refuse an absorbing environment for a coupling that reads probEnv: its limit depends on the initial s...
const EnvStage< T > & stage(std::size_t e) const
double kernel_prob(std::size_t e, std::size_t h) const
kernelProb(e,h): the kernel arc's probability, NaN for a competing arc or none.
Matrix< double > prob_orig
probOrig(h, e)
bool is_semi_markov() const
isSemiMarkov: true if any stage is semi-Markov.
std::vector< std::vector< mam::Mmap< double > > > proc
proc[e][h]; disabled for a semi-Markov stage
void add_node_failure_repair(std::size_t up, std::size_t down, const qn::NetworkStruct< T > &base, const std::string &node_name, const lang::Distrib< T > &breakdown, const lang::Distrib< T > &repair, const lang::Distrib< T > &down_service, const std::string &breakdown_reset="keep", const std::string &repair_reset="keep")
addNodeFailureRepair: the two calls above, in order.
void stage_arcs(std::size_t e, std::vector< lang::Distrib< T > > &arcs, std::vector< double > &probs) const
getStageArcs: the transitions out of stage e in the form mc::smp_stage_cif takes.
std::vector< StageRow > stage_table() const
void set_transition_dist(std::size_t e, std::size_t h, const lang::Distrib< T > &d)
Replace the distribution of an arc that is already declared.
void set_lqn_stage(std::size_t e, const std::string &nm, const std::string &type, const lqn::LqnStruct< T > &model)
addStage with a LayeredNetwork: the stage holds a LAYERED model.
bool is_absorbing_stage(std::size_t e) const
isAbsorbingStage: true if stage e has no outgoing transition, so once entered the environment stays t...
std::size_t find_stage(const std::string &nm) const
The index of the stage called nm, or nstages() when there is none.
Reliability reliability() const
std::size_t nstages() const
static std::string down_stage_name(const std::string &nm)
The name addNodeBreakdown gives the stage in which nm is down.
std::vector< mam::Mmap< double > > hold_time
holdTime[e]; disabled for a semi-Markov stage
void add_kernel_transition(std::size_t e, std::size_t h, double prob, const lang::Distrib< T > &d, const ResetMarginal &reset=ResetMarginal())
addKernelTransition: a KERNEL arc of Q(e,h,t) = prob * F(t).
bool is_kernel_stage(std::size_t e) const
isKernelStage: true if stage e's arcs are kernel arcs.
void set_reset(std::size_t e, std::size_t h, const ResetMarginal &reset)
Install a reset policy on an arc that is already declared.
std::string stage_table_text() const
printStageTable, as text: the stages with their networks, then every enabled arc in (from,...
std::size_t find_node_failure(const std::string &nm) const
findNodeFailure: the descriptor for nm, or node_failures().size().
void reject_lqn_stages(const std::string &who, const std::string &why) const
Refuse an environment carrying a LayeredNetwork stage, by name.
bool is_absorbing() const
True if some stage is absorbing, i.e.
double hold_time_mean(std::size_t e) const
Environment.holdTimeMean(holdTime{e}): the mean holding time of stage e.
void set_stage(std::size_t e, const std::string &nm, const std::string &type, const qn::NetworkStruct< T > &model)
addStage: name the stage and give it its network.
bool has_lqn_stages() const
True when ANY stage holds a LayeredNetwork.
Matrix< double > pemb
probEmb, the embedded jump chain
std::vector< double > hold_mean
holdMean
const EnvArc< T > & arc(std::size_t e, std::size_t h) const
void refuse_semi_markov(const std::string &method) const
The methodRefusal rule for every coupling but smp: refuse a kernel stage, or a competing arc that is ...
bool is_lqn(std::size_t e) const
True when stage e holds a LayeredNetwork rather than a flat network.
void add_node_repair(const std::string &node_name, const lang::Distrib< T > &repair, const std::string &reset_policy="keep")
Port of addNodeRepair: the DOWN_<node> -> UP arc and its policy.
void add_transition(std::size_t e, std::size_t h, const lang::Distrib< T > &d, const ResetMarginal &reset=ResetMarginal())
addTransition: enable e -> h with a distribution and a reset policy.
std::vector< double > prob_env
probEnv
A network plus its refreshed NetworkStruct.
Courtois decomposition of a nearly completely decomposable (NCD) CTMC.
What refreshProcessRepresentations and refreshLST compute FROM a distribution: the (D0,...
The exception types the port throws.
Enumerations and the minimal distribution descriptor shared by the model layer of the C++ port.
LayeredNetworkStruct, the flattened description of a layered queueing network.
Cumulative distribution of the inter-arrival time of a MAP.
Markovian arrival process descriptors: stationary vectors, rate, moments, autocorrelation and the ind...
Dense matrix and non-owning view.
Marked MAP (MMAP) algebra: per-class rates, class probabilities, superposition, normalization and sca...
std::function< Matrix< double >(const Matrix< double > &)> ResetMarginal
The reset policy of a transition, resetFun in the reference.
qn::NetworkStruct< T > env_degraded_model(const qn::NetworkStruct< T > &base, const std::string &node_name, const lang::Distrib< T > &down_service)
The DOWN stage network of addNodeBreakdown: the base network with ONE node's service replaced by its ...
std::function< lang::Distrib< T >(const lang::Distrib< T > &, const Matrix< double > &, const Matrix< double > &, const Matrix< double > &)> ResetEnvRates
resetEnvRatesFun in the reference: the state-dependent environment rate.
ResetMarginal env_reset_policy(const std::string &name)
The two NAMED reset policies of Environment.resolveResetPolicy, which are the only ones the JSON inte...
void prior_refresh_moments(Distrib< T > &d)
Write the mixture moments onto a Prior, the counterpart of dist_refresh_moments for the Markovian fam...
const char * process_to_text(ProcessType p)
The MATLAB ProcessType name, as sn.procid prints it.
bool process_is_markovian(ProcessType p)
ProcessType.isMarkovian: true when sn.proc carries an exact matrix representation of the law,...
void dist_refresh_moments(Distrib< T > &d)
Fill in the first two moments of a distribution given by its matrices.
Mmap< T > mmap_normalize(const Mmap< T > &in)
Clamp negative off-diagonal and per-class entries to zero and rebuild D1 and the diagonal of D0 from ...
Matrix< T > krons(const Matrix< T > &A, const Matrix< T > &B)
Kronecker sum, MATLAB's krons: kron(A, I_nb) + kron(I_na, B).
T map_mean(const Map< T > &m)
Mean inter-arrival time, 1/lambda.
std::vector< T > map_cdf(const Map< T > &m, const std::vector< T > &points)
Cumulative distribution of the inter-arrival time at the given points.
std::vector< T > mmap_count_lambda(const Mmap< T > &m)
Per-class arrival rates, lambda_c = theta D1^(c) e.
ReducibleResult< T > ctmc_solve_reducible(const Matrix< T > &Q, const std::vector< T > &pi0, double zeroColTol=1e-12)
Limiting distribution of a CTMC whose generator may be reducible.
SmpStageQuad smp_stage_quad(const std::vector< lang::Distrib< T > > &arcs, const std::vector< double > &probs)
SmpStageCif smp_stage_cif(const std::vector< lang::Distrib< T > > &arcs, const std::vector< double > &probs, const std::vector< double > &t)
CIF and holding-time CDF of a stage at the ascending instants t.
Conservation laws of a layered queueing network, enumerated from its structure.
A queueing network and its refreshed NetworkStruct.
Prior: parameter uncertainty as a weighted set of alternative models.
Cumulative incidence functions of one semi-Markov stage.
Embedded jump probabilities and mean holding time of a semi-Markov stage.
The <kind> part of a LINE:<category>:<kind> identifier (see _kb/17-error-vocabulary....
One arc of the environment process.
lang::Distrib< T > dist
the e -> h transition time
ResetMarginal reset
empty means the identity
ResetEnvRates< T > reset_rates
empty means the rate does not depend on the state
One stage: a name, a category, and the model in force while it lasts.
std::string type
the stage category, informational only
lqn::LqnStruct< T > lqn_model
The layered model, when this stage holds a LayeredNetwork.
bool declared() const
True when the stage carries a model of either kind.
qn::NetworkStruct< T > model
getReliabilityTable: MTTF, MTTR, MTBF and availability of an environment built out of node breakdowns...
double mttr
mean time to repair, DOWN -> UP
double availability
stationary probability of being UP
double mttf
mean time to failure, UP -> any DOWN
getStageTable: one row per stage.
std::size_t stage
1-based, as the reference prints it
Environment.nodeFailures{k}: the declarative record of one node breakdown.
std::string repair_reset
empty when there is no repair
std::string breakdown_reset
std::string node
the node that breaks down
lang::Distrib< T > down_service
the node's service while it is down
bool has_repair
false for a breakdown with no repair arc
lang::Distrib< T > breakdown
time to failure, the UP -> DOWN transition
lang::Distrib< T > repair
time to repair, the DOWN -> UP transition
bool has_map() const
True when the type carries a (D0,D1) pair of its own.
Matrix< T > D0
The (D0,D1) pair when the type carries one directly.
An MMAP: the underlying MAP plus the per-class arrival matrices.
std::vector< Matrix< T > > Dc
per-class matrices, sum_c Dc = D1
std::vector< double > Fhold
What smp_stage_quad returns.
std::vector< double > P
the embedded jump probabilities, one per arc
double m
the mean holding time