5#ifndef LINE_LANG_QN_STATE_EVENTS_H
6#define LINE_LANG_QN_STATE_EVENTS_H
54 std::vector<std::vector<T>>
space;
62 std::vector<std::vector<std::size_t>>
start;
64 std::vector<std::vector<std::size_t>>
preempt;
76 if (out.
space.empty())
return;
79 if (start_cls) out.
start.back().push_back(start_cls);
80 if (preempt_cls) out.
preempt.back().push_back(preempt_cls);
111 const std::vector<T>& state_i) {
112 const std::size_t R =
sn.nclasses;
114 std::vector<T> nir(R, zero);
115 if (ind == 0 || ind >
sn.nodes.size())
116 throw InputError(
"to_marginal_aggr: node index is out of range");
118 const std::size_t ist = nd.
station;
119 const std::size_t nvar =
sn.nvars_of(ind);
125 if (
sn.isfjaugmented && nd.
nodetype == NodeType::Join && state_i.size() >= R) {
127 for (std::size_t r = 0; r < R; ++r) {
128 nir[r] = state_i[state_i.size() - R + r];
131 return std::make_pair(ni, nir);
138 const std::size_t bufw = state_i.size() > nvar ? state_i.size() - nvar : 0;
139 for (std::size_t r = 0; r < R && r < bufw; ++r) nir[r] = state_i[r];
141 for (std::size_t r = 0; r < R; ++r) ni += nir[r];
142 return std::make_pair(ni, nir);
148 if (nd.
nodetype == NodeType::Source)
return std::make_pair(zero, nir);
150 std::vector<std::size_t> K(R, 1), Ks(R, 0);
151 std::size_t srvw = 0;
152 for (std::size_t r = 0; r < R; ++r) {
153 K[r] =
sn.phasessz_of(ist, r + 1);
157 if (state_i.size() < nvar + srvw)
158 throw InputError(
"to_marginal_aggr: state row is narrower than its server block");
159 const std::size_t srv0 = state_i.size() - nvar - srvw;
161 for (std::size_t r = 0; r < R; ++r)
162 for (std::size_t k = 0; k < K[r]; ++k) nir[r] += state_i[srv0 + Ks[r] + k];
165 if (sched == SchedStrategy::EXT) {
173 std::numeric_limits<double>::infinity());
174 for (std::size_t r = 0; r < R; ++r) nir[r] = ext;
175 }
else if (state_detail::buffer_is_class_tag(sched)) {
176 for (std::size_t r = 0; r < R; ++r) {
178 for (std::size_t b = 0; b < srv0; ++b)
181 }
else if (state_detail::buffer_is_tag_phase_pairs(sched)) {
187 for (std::size_t r = 0; r < R; ++r) {
189 for (std::size_t b = 0; b < srv0; b += 2)
192 }
else if (state_detail::buffer_is_per_class_count(sched)) {
193 for (std::size_t r = 0; r < R && r < srv0; ++r) nir[r] += state_i[r];
194 }
else if (sched == SchedStrategy::PAS || sched == SchedStrategy::OI) {
208 for (std::size_t r = 0; r < R; ++r) nir[r] = zero;
209 const std::size_t w = state_i.size() > nvar ? state_i.size() - nvar : 0;
210 for (std::size_t b = 0; b < w; ++b) {
212 const long tag =
static_cast<long>(v + 0.5);
213 if (tag >= 1 &&
static_cast<std::size_t
>(tag) <= R)
221 for (std::size_t r = 0; r < R; ++r)
222 if (
sn.disabled[ist - 1][r]) nir[r] = zero;
225 for (std::size_t r = 0; r < R; ++r) ni += nir[r];
226 return std::make_pair(ni, nir);
246 if (
sn.droprule.size() < ist ||
sn.droprule[ist - 1].size() < cls)
return false;
248 return dr != DropStrategy::WAITQ &&
static_cast<int>(dr) != 0;
269 if (
sn.droprule.size() >= ist &&
sn.droprule[ist - 1].size() >= cls) {
271 if (dr == DropStrategy::BAS || dr == DropStrategy::BBS || dr == DropStrategy::RSRD)
281 if (
sn.isbasdestination.size() >= ist &&
sn.isbasdestination[ist - 1].size() >= cls &&
282 sn.isbasdestination[ist - 1][cls - 1])
286 const double nj =
sn.njobs()[cls - 1];
287 return !std::isfinite(nj);
293 std::vector<std::size_t>
K;
294 std::vector<std::size_t>
Ks;
302 const std::size_t R =
sn.nclasses;
303 const std::size_t ist =
sn.nodes[ind - 1].station;
307 for (std::size_t r = 0; r < R; ++r) {
308 L.
K[r] =
sn.phasessz_of(ist, r + 1);
312 L.
nvar =
sn.nvars_of(ind);
314 throw InputError(
"after_event_station: the state row is narrower than its server block");
331 const std::size_t nph =
sn.phases_of(ist, cls);
334 if (d.
D0.rows() == nph && d.
D1.rows() == nph && nph > 0 && !d.
disabled) {
340 }
catch (
const Error&) {
344 bool ok = pie.size() == nph;
347 for (std::size_t k = 0; k < nph; ++k) s += pie[k];
354 static_cast<long>(nph)));
355 for (std::size_t k = 0; k < nph; ++k) pie[k] = u;
371 std::size_t& pos, std::size_t& swk,
long& ctr);
374 std::size_t swk,
long ctr);
377 std::size_t R,
bool arrived, std::size_t& q,
int& mode,
long& budget);
380 std::size_t q,
int mode,
long budget,
const std::vector<T>& buf,
381 const std::vector<T>& srv,
const std::vector<T>& var,
const RowLayout<T>& L,
382 std::vector<std::vector<T>>& rows, std::vector<T>& probs);
395 const std::vector<T>& inspace,
EventType event,
415 const std::vector<T>& inspace, std::size_t cls) {
416 const std::size_t R =
sn.nclasses;
417 const std::size_t ist =
sn.nodes[ind - 1].station;
421 if (ist == 0)
throw InputError(
"after_event_station_arv: node is not a station");
425 if (sched == SchedStrategy::PAS || sched == SchedStrategy::OI)
434 if (
sn.nodes[ind - 1].nodetype == NodeType::Place) {
435 std::vector<T> row = inspace;
436 const double cap =
sn.classcap[ist - 1][cls - 1];
439 out.
space.push_back(row);
440 out.
rate.push_back(minus_one);
441 out.
prob.push_back(one);
444 out.
space.push_back(row);
445 out.
rate.push_back(minus_one);
446 out.
prob.push_back(zero);
454 const double cap_i =
sn.cap[ist - 1];
455 const double ccap =
sn.classcap[ist - 1][cls - 1];
456 const double S =
sn.stations[ist - 1].nservers;
459 for (std::size_t kentry = 0; kentry < L.
K[cls - 1]; ++kentry) {
460 std::vector<T> buf(inspace.begin(), inspace.begin() + L.
bufw);
461 std::vector<T> srv(inspace.begin() + L.
bufw, inspace.begin() + L.
bufw + L.
srvw);
462 std::vector<T> var(inspace.begin() + L.
bufw + L.
srvw, inspace.end());
463 std::vector<std::vector<T>> cand;
464 std::vector<T> cand_prob;
468 std::vector<std::size_t> cand_start, cand_preempt;
473 if (sched == SchedStrategy::EXT) {
476 if (!std::isfinite(
sn.njobs()[cls - 1])) {
477 out.
space.push_back(inspace);
478 out.
rate.push_back(zero);
479 out.
prob.push_back(one);
485 if (sched == SchedStrategy::PS || sched == SchedStrategy::INF ||
486 sched == SchedStrategy::DPS || sched == SchedStrategy::GPS ||
487 sched == SchedStrategy::PSPRIO || sched == SchedStrategy::DPSPRIO ||
488 sched == SchedStrategy::GPSPRIO || sched == SchedStrategy::LPS) {
490 const std::size_t col = L.
Ks[cls - 1] + kentry;
491 std::size_t started = 0;
495 cand_prob.push_back(pentry[kentry]);
497 cand_prob.push_back(zero);
499 std::vector<T> row = buf;
500 row.insert(row.end(), srv.begin(), srv.end());
501 row.insert(row.end(), var.begin(), var.end());
503 cand_start.push_back(started);
504 cand_preempt.push_back(0);
505 }
else if (sched == SchedStrategy::POLLING) {
513 std::size_t srvclass = 0;
514 for (std::size_t r = 1; r <= R; ++r) {
516 for (std::size_t p = 0; p < L.
K[r - 1]; ++p)
518 if (tot > 0) { srvclass = r;
break; }
520 std::size_t pos = 0, swk = 0;
523 if (srvclass == 0 && swk == 0) {
524 std::vector<long> nbuf(R, 0);
525 for (std::size_t r = 0; r < R && r < L.
bufw; ++r)
531 polling_next(pinfo, pos, nbuf, R,
true, q, mode, budget);
532 srv[L.
Ks[cls - 1] + kentry] += one;
534 cand_start.push_back(cls);
537 cand_start.push_back(0);
539 cand_preempt.push_back(0);
540 cand_prob.push_back(pentry[kentry]);
541 std::vector<T> row = buf;
542 row.insert(row.end(), srv.begin(), srv.end());
543 row.insert(row.end(), var.begin(), var.end());
545 }
else if (sched == SchedStrategy::SIRO || sched == SchedStrategy::SEPT ||
546 sched == SchedStrategy::LEPT) {
552 srv[L.
Ks[cls - 1] + kentry] += one;
553 cand_start.push_back(cls);
556 cand_start.push_back(0);
558 cand_preempt.push_back(0);
559 cand_prob.push_back(pentry[kentry]);
560 std::vector<T> row = buf;
561 row.insert(row.end(), srv.begin(), srv.end());
562 row.insert(row.end(), var.begin(), var.end());
564 }
else if (state_detail::buffer_is_class_tag(sched)) {
574 srv[L.
Ks[cls - 1] + kentry] += one;
575 std::vector<T> row = buf;
576 row.insert(row.end(), srv.begin(), srv.end());
577 row.insert(row.end(), var.begin(), var.end());
579 cand_prob.push_back(pentry[kentry]);
580 cand_start.push_back(cls);
581 cand_preempt.push_back(0);
583 std::size_t slot = 0;
584 for (std::size_t b = 0; b < L.
bufw; ++b)
591 ? (ni < cap_i && nir_c < ccap)
593 if (slot > 0 && has_room) {
595 std::vector<T> row = buf;
596 row.insert(row.end(), srv.begin(), srv.end());
597 row.insert(row.end(), var.begin(), var.end());
599 cand_prob.push_back(pentry[kentry]);
600 cand_start.push_back(0);
601 cand_preempt.push_back(0);
621 cand.push_back(inspace);
622 cand_prob.push_back(pentry[kentry]);
623 cand_start.push_back(0);
624 cand_preempt.push_back(0);
630 }
else if (state_detail::buffer_is_tag_phase_pairs(sched)) {
637 srv[L.
Ks[cls - 1] + kentry] += one;
638 std::vector<T> row = buf;
639 row.insert(row.end(), srv.begin(), srv.end());
640 row.insert(row.end(), var.begin(), var.end());
642 cand_prob.push_back(pentry[kentry]);
643 cand_start.push_back(cls);
644 cand_preempt.push_back(0);
650 const bool prio_aware = sched == SchedStrategy::FCFSPRPRIO ||
651 sched == SchedStrategy::FCFSPIPRIO ||
652 sched == SchedStrategy::LCFSPRPRIO ||
653 sched == SchedStrategy::LCFSPIPRIO;
654 const bool lcfs_family = sched == SchedStrategy::LCFSPRPRIO ||
655 sched == SchedStrategy::LCFSPIPRIO;
659 const bool resume = sched == SchedStrategy::LCFSPR ||
660 sched == SchedStrategy::LCFSPRPRIO ||
661 sched == SchedStrategy::FCFSPR ||
662 sched == SchedStrategy::FCFSPRPRIO;
663 bool can_preempt_any =
false;
664 for (std::size_t cp = 1; cp <= R; ++cp) {
671 const int pa =
sn.classes[cls - 1].prio;
672 const int pv =
sn.classes[cp - 1].prio;
673 if (lcfs_family ? (pa > pv) : (pa >= pv))
continue;
675 for (std::size_t pp = 0; pp < L.
K[cp - 1]; ++pp) {
676 const std::size_t vcol = L.
Ks[cp - 1] + pp;
678 if (busy <= 0)
continue;
679 can_preempt_any =
true;
680 std::vector<T> b2 = buf, s2 = srv;
682 s2[L.
Ks[cls - 1] + kentry] += one;
686 std::size_t slot = 0;
687 for (std::size_t b = 0; b < L.
bufw; ++b)
689 if (slot == 0)
continue;
693 std::vector<T> row = b2;
694 row.insert(row.end(), s2.begin(), s2.end());
695 row.insert(row.end(), var.begin(), var.end());
699 cand_start.push_back(cls);
700 cand_preempt.push_back(cp);
714 if (prio_aware && !can_preempt_any) {
715 std::size_t slot = 0;
716 for (std::size_t b = 0; b < L.
bufw; ++b)
719 std::vector<T> b2 = buf;
722 std::vector<T> row = b2;
723 row.insert(row.end(), srv.begin(), srv.end());
724 row.insert(row.end(), var.begin(), var.end());
726 cand_prob.push_back(pentry[kentry]);
727 cand_start.push_back(0);
728 cand_preempt.push_back(0);
735 " discipline is not ported yet");
740 for (std::size_t c = 0; c < cand.size(); ++c) {
744 out.
space.push_back(cand[c]);
745 out.
rate.push_back(minus_one);
746 out.
prob.push_back(cand_prob[c]);
748 tag_last(out, c < cand_start.size() ? cand_start[c] : 0,
749 c < cand_preempt.size() ? cand_preempt[c] : 0);
769 std::size_t ist, std::size_t cls) {
771 const std::size_t n =
sn.phases_of(ist, cls);
773 if (d.
D0.rows() != n || d.
D1.rows() != n)
return std::make_pair(mu, phi);
774 for (std::size_t k = 0; k < n; ++k) {
775 const T dk = T(-d.
D0(k, k));
782 for (std::size_t j = 0; j < n; ++j) s += d.
D1(k, j);
785 return std::make_pair(mu, phi);
791 const std::vector<T>& s =
sn.stations[ist - 1].lldscaling;
795 if (!std::isfinite(n) || n >=
static_cast<double>(s.size()))
return s.back();
797 return s[
static_cast<std::size_t
>(n) - 1];
823 for (std::size_t h = 0; h < 2; ++h) {
826 const std::vector<T> v = fun(nir);
829 "cd_factor: the class-dependence map returned an empty scaling vector");
830 f = T(f * v[std::min(cls, v.size()) - 1]);
855 std::size_t cls,
double ni,
double S) {
856 const std::size_t R =
sn.nclasses;
861 const bool prio_aware = sched == SchedStrategy::PSPRIO ||
862 sched == SchedStrategy::DPSPRIO ||
863 sched == SchedStrategy::GPSPRIO;
864 if (!prio_aware || ni <= S)
return p;
865 double best = std::numeric_limits<double>::infinity();
866 for (std::size_t r = 0; r < R; ++r)
868 best = std::min(best,
static_cast<double>(
sn.classes[r].prio));
869 if (
static_cast<double>(
sn.classes[cls - 1].prio) != best) {
875 for (std::size_t r = 0; r < R; ++r) {
876 if (
static_cast<double>(
sn.classes[r].prio) != best)
885T
service_share(
const NetworkStruct<T>&
sn, std::size_t ist,
const Marginal<T>& m,
886 std::size_t cls,
double ni,
double S);
905 const std::vector<T>& inspace, std::size_t cls,
906 bool no_promote =
false) {
907 const std::size_t R =
sn.nclasses;
908 const std::size_t ist =
sn.nodes[ind - 1].station;
911 if (ist == 0)
throw InputError(
"after_event_station_dep: node is not a station");
913 if (sched == SchedStrategy::PAS || sched == SchedStrategy::OI)
916 const double S =
sn.stations[ist - 1].nservers;
918 std::vector<std::size_t> ph(R, 1), shift(R, 0);
919 for (std::size_t r = 0; r < R; ++r) {
926 const std::pair<std::vector<T>, std::vector<T>> mp =
phase_rates(
sn, ist, cls);
927 const std::vector<T>& mu = mp.first;
928 const std::vector<T>& phi = mp.second;
932 for (std::size_t r = 0; r < R; ++r) ni += num_traits<T>::to_double(m.
nir[r]);
943 const bool cd_takes_prio =
944 pp.
masked && (sched == SchedStrategy::DPSPRIO || sched == SchedStrategy::GPSPRIO);
952 bool suppress_promote = no_promote;
954 const typename std::map<std::size_t, RetrialParam<T>>::const_iterator rit =
955 sn.retrialparam.find(ist);
956 if (rit !=
sn.retrialparam.end())
957 for (std::size_t r = 0; r < rit->second.retrial_proc.size(); ++r)
958 if (!rit->second.retrial_proc[r].disabled) { suppress_promote =
true;
break; }
961 for (std::size_t k = 0; k < L.
K[cls - 1]; ++k) {
962 std::vector<T> buf(inspace.begin(), inspace.begin() + L.
bufw);
963 std::vector<T> srv(inspace.begin() + L.
bufw, inspace.begin() + L.
bufw + L.
srvw);
964 std::vector<T> var(inspace.begin() + L.
bufw + L.
srvw, inspace.end());
965 const std::size_t col = L.
Ks[cls - 1] + k;
967 const T kir = m.
kir[cls - 1][k];
969 if (sched == SchedStrategy::EXT) {
976 if (!std::isfinite(
sn.njobs()[cls - 1])) {
977 for (std::size_t ke = 0; ke < L.
K[cls - 1]; ++ke) {
978 const T arv = d.
D1(k, ke);
980 std::vector<T> row = inspace;
981 row[L.
bufw + L.
Ks[cls - 1] + k] -= one;
982 row[L.
bufw + L.
Ks[cls - 1] + ke] += one;
983 out.
space.push_back(row);
984 out.
rate.push_back(T(lld * arv));
985 out.
prob.push_back(one);
988 }
else if (sched == SchedStrategy::INF || sched == SchedStrategy::PS ||
989 sched == SchedStrategy::LPS || sched == SchedStrategy::DPS ||
990 sched == SchedStrategy::GPS || sched == SchedStrategy::PSPRIO ||
991 sched == SchedStrategy::DPSPRIO || sched == SchedStrategy::GPSPRIO) {
996 const T rate = T(mu[k] * phi[k] * kir *
service_share(
sn, ist, m, cls, ni, S));
997 std::vector<T> row = buf;
998 row.insert(row.end(), srv.begin(), srv.end());
999 row.insert(row.end(), var.begin(), var.end());
1000 out.
space.push_back(row);
1001 out.
rate.push_back(T(lld * rate));
1002 out.
prob.push_back(one);
1003 }
else if (state_detail::buffer_is_class_tag(sched) && sched != SchedStrategy::FCFS) {
1008 const bool has_waiting = ni > S && !suppress_promote;
1009 const T rate = T(mu[k] * phi[k] * kir);
1012 std::vector<T> row = buf;
1013 row.insert(row.end(), srv.begin(), srv.end());
1014 row.insert(row.end(), var.begin(), var.end());
1015 out.
space.push_back(row);
1016 out.
rate.push_back(T(lld * rate));
1017 out.
prob.push_back(one);
1021 std::size_t pos = L.
bufw;
1022 if (sched == SchedStrategy::LCFS) {
1028 for (std::size_t b = 0; b < L.
bufw; ++b)
1036 double best = std::numeric_limits<double>::infinity();
1037 for (std::size_t b = 0; b < L.
bufw; ++b) {
1039 if (v <= 0)
continue;
1040 const double p =
sn.classes[
static_cast<std::size_t
>(v) - 1].prio;
1041 if (p < best) best = p;
1043 if (std::isfinite(best))
1044 for (std::size_t b = 0; b < L.
bufw; ++b) {
1046 if (v <= 0)
continue;
1047 if (
sn.classes[
static_cast<std::size_t
>(v) - 1].prio != best)
continue;
1049 if (sched == SchedStrategy::LCFSPRIO)
break;
1052 if (pos == L.
bufw)
continue;
1054 std::vector<T> b2 = buf;
1055 if (sched == SchedStrategy::LCFS) {
1061 for (std::size_t b = pos; b > 0; --b) b2[b] = b2[b - 1];
1065 for (std::size_t ke = 0; ke < L.
K[hc - 1]; ++ke) {
1066 std::vector<T> s3 = srv;
1067 s3[L.
Ks[hc - 1] + ke] += one;
1068 std::vector<T> row = b2;
1069 row.insert(row.end(), s3.begin(), s3.end());
1070 row.insert(row.end(), var.begin(), var.end());
1071 out.
space.push_back(row);
1072 out.
rate.push_back(T(lld * rate * pentry[ke]));
1073 out.
prob.push_back(one);
1076 }
else if (state_detail::buffer_is_class_tag(sched)) {
1086 std::vector<T> var2 = var;
1087 bool holds_reply =
false;
1088 if (
sn.replyblock.size() >= ind &&
sn.replyblock[ind - 1].size() >= cls &&
1089 sn.replyblock[ind - 1][cls - 1]) {
1091 const std::size_t sl = ri.
slot[cls - 1];
1092 if (sl !=
static_cast<std::size_t
>(-1) && sl < var2.size()) {
1098 const bool has_waiting = ni > (S - nb) && !suppress_promote && !holds_reply;
1099 for (std::size_t kd = 0; kd < L.
K[cls - 1]; ++kd) {
1100 const T rate = T(d.
D1(k, kd) * kir);
1101 std::vector<T> s2 = srv;
1104 std::vector<T> row = buf;
1105 row.insert(row.end(), s2.begin(), s2.end());
1106 row.insert(row.end(), var2.begin(), var2.end());
1107 out.
space.push_back(row);
1108 out.
rate.push_back(T(lld * rate));
1109 out.
prob.push_back(one);
1116 if (headv <= 0)
continue;
1117 const std::size_t hc =
static_cast<std::size_t
>(headv);
1118 std::vector<T> b2(L.
bufw, zero);
1119 for (std::size_t b = 1; b < L.
bufw; ++b) b2[b] = buf[b - 1];
1121 for (std::size_t ke = 0; ke < L.
K[hc - 1]; ++ke) {
1122 std::vector<T> s3 = s2;
1123 s3[L.
Ks[hc - 1] + ke] += one;
1124 std::vector<T> row = b2;
1125 row.insert(row.end(), s3.begin(), s3.end());
1126 row.insert(row.end(), var2.begin(), var2.end());
1127 const T r3 = T(lld * rate * pentry[ke]);
1128 out.
space.push_back(row);
1129 out.
rate.push_back(r3);
1137 }
else if (sched == SchedStrategy::POLLING) {
1142 const T rate = T(mu[k] * phi[k] * kir);
1144 std::size_t pos = 0, swk = 0;
1148 if (swk != 0)
continue;
1149 std::vector<long> nbuf(R, 0);
1150 for (std::size_t r = 0; r < R && r < L.
bufw; ++r)
1155 switch (pinfo.
ptype) {
1158 goon = nbuf[cls - 1] > 0;
1166 goon = ctrnext > 0 && nbuf[cls - 1] > 0;
1170 goon = nbuf[cls - 1] > ctr;
1173 std::size_t q = cls;
1175 long budget = ctrnext;
1176 if (!goon)
polling_next(pinfo, cls, nbuf, R,
false, q, mode, budget);
1177 std::vector<std::vector<T>> rows;
1178 std::vector<T> probs;
1179 polling_land(
sn, ist, pinfo, q, mode, budget, buf, srv, var, L, rows, probs);
1180 for (std::size_t j = 0; j < rows.size(); ++j) {
1181 out.
space.push_back(rows[j]);
1182 out.
rate.push_back(T(lld * rate * probs[j]));
1183 out.
prob.push_back(one);
1186 tag_last(out, mode == 1 ? q : 0, 0);
1188 }
else if (state_detail::buffer_is_tag_phase_pairs(sched)) {
1194 const T rate = T(mu[k] * phi[k] * kir);
1196 const bool prio_aware = sched == SchedStrategy::FCFSPRPRIO ||
1197 sched == SchedStrategy::FCFSPIPRIO ||
1198 sched == SchedStrategy::LCFSPRPRIO ||
1199 sched == SchedStrategy::LCFSPIPRIO;
1200 const bool lcfs = sched == SchedStrategy::LCFSPR ||
1201 sched == SchedStrategy::LCFSPI ||
1202 sched == SchedStrategy::LCFSPRPRIO ||
1203 sched == SchedStrategy::LCFSPIPRIO;
1207 const bool resume = sched == SchedStrategy::LCFSPR ||
1208 sched == SchedStrategy::LCFSPRPRIO ||
1209 sched == SchedStrategy::FCFSPR ||
1210 sched == SchedStrategy::FCFSPRPRIO;
1212 std::size_t pos = L.
bufw;
1213 if (ni > S && !suppress_promote && L.
bufw >= 2) {
1214 double best = std::numeric_limits<double>::infinity();
1221 for (std::size_t b = 0; b + 1 < L.
bufw; b += 2) {
1223 if (v <= 0)
continue;
1224 const double p =
sn.classes[
static_cast<std::size_t
>(v) - 1].prio;
1225 if (p < best) best = p;
1227 for (std::size_t b = 0; b + 1 < L.
bufw; b += 2) {
1229 if (v <= 0)
continue;
1230 if (prio_aware &&
sn.classes[
static_cast<std::size_t
>(v) - 1].prio != best)
1239 if (pos == L.
bufw) {
1240 std::vector<T> row = buf;
1241 row.insert(row.end(), srv.begin(), srv.end());
1242 row.insert(row.end(), var.begin(), var.end());
1243 out.
space.push_back(row);
1244 out.
rate.push_back(T(lld * rate));
1245 out.
prob.push_back(one);
1249 const std::size_t kst =
1251 if (hc == 0 || hc > R || kst == 0 || kst > L.
K[hc - 1])
1252 throw InputError(
"after_event_station_dep: station '" +
1253 sn.stations[ist - 1].name +
1254 "' holds a waiting job whose [class, phase] pair is malformed");
1261 std::vector<T> b2(L.
bufw, zero);
1262 for (std::size_t b = 2; b <= pos + 1; ++b) b2[b] = buf[b - 2];
1263 for (std::size_t b = pos + 2; b < L.
bufw; ++b) b2[b] = buf[b];
1265 std::vector<T> s3 = srv;
1266 s3[L.
Ks[hc - 1] + kst - 1] += one;
1267 std::vector<T> row = b2;
1268 row.insert(row.end(), s3.begin(), s3.end());
1269 row.insert(row.end(), var.begin(), var.end());
1270 out.
space.push_back(row);
1271 out.
rate.push_back(T(lld * rate));
1272 out.
prob.push_back(one);
1276 for (std::size_t ke = 0; ke < L.
K[hc - 1]; ++ke) {
1277 std::vector<T> s3 = srv;
1278 s3[L.
Ks[hc - 1] + ke] += one;
1279 std::vector<T> row = b2;
1280 row.insert(row.end(), s3.begin(), s3.end());
1281 row.insert(row.end(), var.begin(), var.end());
1282 out.
space.push_back(row);
1283 out.
rate.push_back(T(lld * rate * pentry[ke]));
1284 out.
prob.push_back(one);
1288 }
else if (state_detail::buffer_is_per_class_count(sched)) {
1293 const T rate = T(mu[k] * phi[k] * kir);
1295 for (std::size_t r = 0; r < R; ++r) waiting += num_traits<T>::to_double(buf[r]);
1296 if (waiting <= 0 || suppress_promote) {
1297 std::vector<T> row = buf;
1298 row.insert(row.end(), srv.begin(), srv.end());
1299 row.insert(row.end(), var.begin(), var.end());
1300 out.
space.push_back(row);
1301 out.
rate.push_back(T(lld * rate));
1302 out.
prob.push_back(one);
1305 for (std::size_t r = 1; r <= R; ++r) {
1307 if (nb <= 0)
continue;
1309 for (std::size_t ke = 0; ke < L.
K[r - 1]; ++ke) {
1310 std::vector<T> b2 = buf, s2 = srv;
1312 s2[L.
Ks[r - 1] + ke] += one;
1313 std::vector<T> row = b2;
1314 row.insert(row.end(), s2.begin(), s2.end());
1315 row.insert(row.end(), var.begin(), var.end());
1316 out.
space.push_back(row);
1317 out.
rate.push_back(T(lld * rate));
1325 " discipline is not ported yet");
1343 std::size_t cls,
double ni,
double S) {
1344 const std::size_t R =
sn.nclasses;
1354 if (!p.
served)
return zero;
1355 const std::vector<T>& nir = p.
nir;
1356 const double nieff = p.
ni;
1358 if (sched == SchedStrategy::PS || sched == SchedStrategy::LPS ||
1359 sched == SchedStrategy::PSPRIO)
1361 if (sched == SchedStrategy::DPS || sched == SchedStrategy::GPS ||
1362 sched == SchedStrategy::DPSPRIO || sched == SchedStrategy::GPSPRIO) {
1365 "state_events: multi-server DPS/GPS stations are not supported");
1366 const bool dps = sched == SchedStrategy::DPS || sched == SchedStrategy::DPSPRIO;
1367 const std::vector<T>& w =
sn.stations[ist - 1].schedparam;
1369 for (std::size_t r = 0; r < R; ++r) wsum += w[r];
1371 for (std::size_t r = 0; r < R; ++r) {
1375 denom += T(w[r] / wsum * nr);
1377 const T
nc = nir[cls - 1];
1380 const T sh = T((w[cls - 1] / wsum) / denom);
1381 return dps ? sh : T(sh /
nc);
1398 const std::vector<T>& inspace, std::size_t cls) {
1399 const std::size_t R =
sn.nclasses;
1400 const std::size_t ist =
sn.nodes[ind - 1].station;
1403 if (ist == 0)
throw InputError(
"after_event_station_phase: node is not a station");
1405 const double S =
sn.stations[ist - 1].nservers;
1407 std::vector<std::size_t> ph(R, 1), shift(R, 0);
1408 for (std::size_t r = 0; r < R; ++r) {
1416 for (std::size_t r = 0; r < R; ++r) ni += num_traits<T>::to_double(m.
nir[r]);
1424 if (d.
D0.rows() != L.
K[cls - 1])
return out;
1426 for (std::size_t k = 0; k < L.
K[cls - 1]; ++k) {
1428 for (std::size_t kd = 0; kd < L.
K[cls - 1]; ++kd) {
1429 if (kd == k)
continue;
1430 std::vector<T> row = inspace;
1431 row[L.
bufw + L.
Ks[cls - 1] + k] -= one;
1432 row[L.
bufw + L.
Ks[cls - 1] + kd] += one;
1433 out.
space.push_back(row);
1434 out.
rate.push_back(T(lld * d.
D0(k, kd) * m.
kir[cls - 1][k] * share));
1435 out.
prob.push_back(one);
1453 const std::vector<T>& inspace, std::size_t cls,
1454 const T& impatience_mu) {
1455 const std::size_t R =
sn.nclasses;
1456 const std::size_t ist =
sn.nodes[ind - 1].station;
1458 if (ist == 0)
throw InputError(
"after_event_station_renege: node is not a station");
1461 std::vector<std::size_t> ph(R, 1), shift(R, 0);
1462 for (std::size_t r = 0; r < R; ++r) {
1469 if (waiting <= 0)
return out;
1472 std::size_t slot = L.
bufw;
1473 for (std::size_t b = 0; b < L.
bufw; ++b)
1474 if (inspace[b] == tag) { slot = b;
break; }
1475 if (slot == L.
bufw)
return out;
1477 std::vector<T> row = inspace;
1478 for (std::size_t b = slot; b > 0; --b) row[b] = row[b - 1];
1480 out.
space.push_back(row);
1505 const std::vector<T>& inspace, std::size_t cls,
1506 const T& retrial_mu,
bool constant_policy =
false) {
1507 const std::size_t R =
sn.nclasses;
1508 const std::size_t ist =
sn.nodes[ind - 1].station;
1511 if (ist == 0)
throw InputError(
"after_event_station_retry: node is not a station");
1513 const double S =
sn.stations[ist - 1].nservers;
1515 std::vector<std::size_t> ph(R, 1), shift(R, 0);
1516 for (std::size_t r = 0; r < R; ++r) {
1525 if (orbit <= 0 || occ >= S)
return out;
1528 std::size_t slot = L.
bufw;
1529 for (std::size_t b = 0; b < L.
bufw; ++b)
1530 if (inspace[b] == tag) { slot = b;
break; }
1531 if (slot == L.
bufw)
return out;
1534 const T agg = constant_policy ? retrial_mu
1536 for (std::size_t ke = 0; ke < L.
K[cls - 1]; ++ke) {
1538 std::vector<T> row = inspace;
1539 for (std::size_t b = slot; b > 0; --b) row[b] = row[b - 1];
1541 row[L.
bufw + L.
Ks[cls - 1] + ke] += one;
1542 out.
space.push_back(row);
1543 out.
rate.push_back(T(agg * pentry[ke]));
1544 out.
prob.push_back(one);
1570 const std::vector<T>& inspace,
bool up,
1573 if (inspace.empty())
return out;
1579 if ((up && status != 0) || (!up && status != 1))
return out;
1580 std::vector<T> row = inspace;
1582 out.
space.push_back(row);
1583 out.
rate.push_back(mu);
1603 const std::vector<T>& inspace,
EventType event,
1605 const std::size_t R =
sn.nclasses;
1607 if (event != EventType::ARV)
return out;
1608 if (inspace.size() < R)
1609 throw InputError(
"after_event_fork: the Fork state row at node '" +
sn.nodes[ind - 1].name +
1610 "' is narrower than the class set");
1611 std::vector<T> row = inspace;
1615 out.
space.push_back(row);
1639 const std::vector<T>& inspace,
EventType event,
1641 const std::size_t R =
sn.nclasses;
1644 if (inspace.size() < R)
1645 throw InputError(
"after_event_join: the Join state row at node '" +
sn.nodes[ind - 1].name +
1646 "' is narrower than the class set");
1647 const std::size_t off = inspace.size() - R;
1649 if (event == EventType::ARV) {
1650 std::vector<T> row = inspace;
1651 row[off + cls - 1] += one;
1652 out.
space.push_back(row);
1654 out.
prob.push_back(one);
1657 if (event != EventType::DEP)
return out;
1659 const typename std::map<std::size_t, FjJoinParam>::const_iterator jit =
1660 sn.fjjoinparam.find(ind);
1661 const FjJoinParam* fjp = jit ==
sn.fjjoinparam.end() ? 0 : &jit->second;
1664 for (std::size_t x = 0; x < fjp->
origclasses.size(); ++x) {
1665 const std::map<std::size_t, std::vector<std::vector<std::size_t>>>::const_iterator ait =
1667 if (ait == fjp->
auxmatrix.end())
continue;
1668 for (std::size_t b = 0; b < ait->second.size(); ++b)
1669 for (std::size_t t = 0; t < ait->second[b].size(); ++t)
1670 if (ait->second[b][t] == cls)
return out;
1678 std::vector<T> row = inspace;
1679 row[off + cls - 1] -= one;
1680 out.
space.push_back(row);
1681 out.
rate.push_back(imm);
1682 out.
prob.push_back(one);
1685 if (!fjp)
return out;
1686 const std::map<std::size_t, std::vector<std::vector<std::size_t>>>::const_iterator ait =
1688 const std::map<std::size_t, std::vector<std::size_t>>::const_iterator rit =
1691 const std::vector<std::vector<std::size_t>>& aux = ait->second;
1692 const std::vector<std::size_t>& req = rit->second;
1693 if (aux.empty())
return out;
1694 const std::size_t B = aux.size(), Tt = aux[0].size();
1695 for (std::size_t t = 0; t < Tt; ++t) {
1696 bool complete =
true;
1697 for (std::size_t b = 0; b < B && complete; ++b) {
1698 const std::size_t a = aux[b][t];
1699 const double need = b < req.size() ?
static_cast<double>(req[b]) : 1.0;
1702 if (!complete)
continue;
1703 std::vector<T> row = inspace;
1704 for (std::size_t b = 0; b < B; ++b) {
1705 const std::size_t a = aux[b][t];
1706 const long need = b < req.size() ?
static_cast<long>(req[b]) : 1;
1709 out.
space.push_back(row);
1710 out.
rate.push_back(imm);
1711 out.
prob.push_back(one);
1727void rr_advance_row(
const NetworkStruct<T>&
sn, std::size_t ind, std::size_t cls,
1728 std::vector<std::vector<T>>& rows);
1743 const std::vector<T>& inspace,
EventType event,
1746 const std::size_t R =
sn.nclasses;
1747 if (inspace.size() < R)
return out;
1749 if (event == EventType::ARV) {
1750 std::vector<T> row = inspace;
1751 row[cls - 1] = T(row[cls - 1] + one);
1752 out.
space.push_back(row);
1755 out.
prob.push_back(one);
1758 if (event == EventType::DEP) {
1760 std::vector<T> row = inspace;
1761 row[cls - 1] = T(row[cls - 1] - one);
1762 out.
space.push_back(row);
1764 out.
prob.push_back(one);
1780 std::vector<std::vector<T>>& rows) {
1781 if (
sn.rr_var_slot(ind, cls) == 0)
return;
1782 const std::size_t w =
sn.nvars_of(ind);
1784 for (std::size_t i = 0; i < rows.size(); ++i) {
1785 if (rows[i].size() < w)
continue;
1786 std::vector<T> var(rows[i].end() - w, rows[i].end());
1787 sn.rr_advance(ind, cls, var);
1788 std::copy(var.begin(), var.end(), rows[i].end() - w);
1794 const std::vector<T>& inspace,
EventType event,
1795 std::size_t cls,
bool no_promote =
false,
1798 case EventType::ARV:
1803 if (
sn.issignal.size() >= cls &&
sn.issignal[cls - 1]) {
1804 if (!(
sn.signaltype.size() >= cls &&
1814 case EventType::DEP: {
1834 if (ind <=
sn.isbasblocking.size() &&
sn.isbasblocking[ind - 1] &&
1836 !out.
space.empty()) {
1843 for (std::size_t i = 0; i < out.
space.size(); ++i) {
1850 case EventType::PHASE:
1852 case EventType::RENEGE:
1854 case EventType::RETRY:
1856 case EventType::SWITCH:
1858 case EventType::FAILURE:
1860 case EventType::REPAIR:
1862 case EventType::LOCAL:
1867 " event is not ported yet");
1889 const std::vector<T>& inspace,
EventType event,
1892 if (event != EventType::PHASE)
return out;
1893 const typename std::map<std::size_t, TransitionParam<T>>::const_iterator it =
1894 sn.transparam.find(ind);
1895 if (it ==
sn.transparam.end())
1896 throw InputError(
"after_event_transition: node has no TransitionParam");
1898 if (mode == 0 || mode > tp.
nmodes)
1899 throw InputError(
"after_event_transition: mode index is out of range");
1902 std::vector<std::size_t> fK(tp.
nmodes, 1), fKs(tp.
nmodes, 0);
1903 std::size_t tot = 0;
1904 for (std::size_t m = 0; m < tp.
nmodes; ++m) {
1909 if (fK[mode - 1] <= 1)
return out;
1911 tp.
firingproc[mode - 1].D0.rows() != fK[mode - 1])
1915 for (std::size_t k = 0; k < fK[mode - 1]; ++k) {
1916 const std::size_t idx = tp.
nmodes + fKs[mode - 1] + k;
1917 const T cnt = inspace[idx];
1919 for (std::size_t kd = 0; kd < fK[mode - 1]; ++kd) {
1920 if (kd == k)
continue;
1922 std::vector<T> row = inspace;
1924 row[tp.
nmodes + fKs[mode - 1] + kd] += one;
1925 out.
space.push_back(row);
1926 out.
rate.push_back(T(D0(k, kd) * cnt));
1927 out.
prob.push_back(one);
1949 const std::vector<T>& inspace,
EventType event, std::size_t cls,
1950 bool no_promote =
false,
1952 if (ind == 0 || ind >
sn.nodes.size())
1953 throw InputError(
"after_event: node index is out of range");
1964 const bool cls_is_mode = (nd.
nodetype == NodeType::Transition &&
event == EventType::PHASE);
1965 if (!cls_is_mode && (cls == 0 || cls >
sn.nclasses))
1966 throw InputError(
"after_event: class index is out of range");
1971 if (
sn.isfjaugmented && nd.
nodetype == NodeType::Join)
1984 if (nd.
nodetype == NodeType::Transition)
1989 "' are not ported yet");
1992namespace signal_detail {
1996void merge_states(std::vector<std::vector<T>>& sp, std::vector<T>& pr) {
1997 std::vector<std::vector<T>> us;
1999 for (std::size_t i = 0; i < sp.size(); ++i) {
2000 std::size_t at = us.size();
2001 for (std::size_t j = 0; j < us.size(); ++j)
2002 if (us[j] == sp[i]) { at = j;
break; }
2003 if (at == us.size()) {
2004 us.push_back(sp[i]);
2005 up.push_back(pr[i]);
2027 std::vector<std::size_t> kv;
2029 if (
sn.signalremdist.size() < cls ||
sn.signalremdist[cls - 1].empty()) {
2032 return std::make_pair(kv, kp);
2034 const std::vector<T>& d =
sn.signalremdist[cls - 1];
2036 for (std::size_t b = 0; b < ntot; ++b) {
2052 return std::make_pair(kv, kp);
2055 for (std::size_t i = 0; i < kp.size(); ++i) tot += kp[i];
2057 for (std::size_t i = 0; i < kp.size(); ++i) kp[i] = T(kp[i] / tot);
2058 return std::make_pair(kv, kp);
2076 const std::vector<T>& inspace, std::size_t cls) {
2077 const std::size_t R =
sn.nclasses;
2078 const std::size_t ist =
sn.nodes[ind - 1].station;
2082 if (ist == 0)
throw InputError(
"after_event_station_signal: node is not a station");
2085 const double S =
sn.stations[ist - 1].nservers;
2087 std::vector<std::size_t> ph(R, 1), shift(R, 0);
2088 for (std::size_t r = 0; r < R; ++r) {
2097 std::vector<T> row(L.
bufw + L.
srvw, zero);
2098 row.insert(row.end(), inspace.end() - L.
nvar, inspace.end());
2099 out.
space.push_back(row);
2100 out.
rate.push_back(minus_one);
2101 out.
prob.push_back(one);
2107 std::vector<std::size_t> tgt;
2108 const std::size_t declared =
sn.signaltarget.size() >= cls ?
sn.signaltarget[cls - 1] : 0;
2109 if (declared >= 1) {
2110 tgt.push_back(declared);
2112 for (std::size_t r = 1; r <= R; ++r)
2113 if (
sn.issignal.size() < r || !
sn.issignal[r - 1]) tgt.push_back(r);
2115 std::vector<std::size_t> elig;
2116 std::size_t ntot = 0;
2117 for (std::size_t i = 0; i < tgt.size(); ++i) {
2120 elig.push_back(tgt[i]);
2121 ntot +=
static_cast<std::size_t
>(nr);
2126 out.
space.push_back(inspace);
2127 out.
rate.push_back(minus_one);
2128 out.
prob.push_back(one);
2133 ?
sn.signalrempolicy[cls - 1]
2135 const bool ordered = state_detail::buffer_is_class_tag(sched) ||
2136 state_detail::buffer_is_tag_phase_pairs(sched);
2137 const bool paired = state_detail::buffer_is_tag_phase_pairs(sched);
2138 const bool counted = state_detail::buffer_is_per_class_count(sched);
2139 const std::pair<std::vector<std::size_t>, std::vector<T>> pmf =
2142 std::vector<std::vector<T>> acc;
2143 std::vector<T> accp;
2144 for (std::size_t ik = 0; ik < pmf.first.size(); ++ik) {
2146 std::vector<std::vector<T>> cur(1, inspace);
2147 std::vector<T> curp(1, one);
2150 for (std::size_t step = 0; step < pmf.first[ik]; ++step) {
2151 std::vector<std::vector<T>> nxt;
2152 std::vector<T> nxtp;
2153 for (std::size_t row = 0; row < cur.size(); ++row) {
2154 std::vector<T> buf(cur[row].begin(), cur[row].begin() + L.
bufw);
2155 std::vector<T> srv(cur[row].begin() + L.
bufw,
2156 cur[row].begin() + L.
bufw + L.
srvw);
2157 const std::vector<T> var(cur[row].begin() + L.
bufw + L.
srvw, cur[row].end());
2160 std::vector<std::size_t> wpos, wcls, wwt;
2162 for (std::size_t b = 0; b < L.
bufw; b += paired ? 2 : 1) {
2164 if (v <= 0)
continue;
2166 for (std::size_t e = 0; e < elig.size(); ++e)
2167 if (elig[e] ==
static_cast<std::size_t
>(v)) ok =
true;
2170 wcls.push_back(
static_cast<std::size_t
>(v));
2173 }
else if (counted) {
2174 for (std::size_t e = 0; e < elig.size(); ++e) {
2175 const std::size_t r = elig[e];
2176 if (r > L.
bufw)
continue;
2178 if (v <= 0)
continue;
2179 wpos.push_back(r - 1);
2181 wwt.push_back(
static_cast<std::size_t
>(v));
2185 std::vector<std::size_t> scls, sph, scnt;
2186 for (std::size_t e = 0; e < elig.size(); ++e) {
2187 const std::size_t r = elig[e];
2188 for (std::size_t p = 0; p < L.
K[r - 1]; ++p) {
2190 if (v <= 0)
continue;
2193 scnt.push_back(
static_cast<std::size_t
>(v));
2196 std::size_t nwait = 0, nsrv = 0;
2197 for (std::size_t i = 0; i < wwt.size(); ++i) nwait += wwt[i];
2198 for (std::size_t i = 0; i < scnt.size(); ++i) nsrv += scnt[i];
2199 if (nwait == 0 && nsrv == 0) {
2201 nxt.push_back(cur[row]);
2202 nxtp.push_back(curp[row]);
2206 std::vector<std::vector<T>> sp;
2208 const bool age_ordered =
2211 if (age_ordered && nwait > 0) {
2214 std::size_t pick = 0;
2215 for (std::size_t i = 0; i < wpos.size(); ++i)
2217 : wpos[i] < wpos[pick])
2219 std::vector<T> b2 = buf;
2220 b2.erase(b2.begin() + wpos[pick], b2.begin() + wpos[pick] + (paired ? 2 : 1));
2221 b2.insert(b2.begin(), paired ? 2 : 1, zero);
2222 std::vector<T> nr = b2;
2223 nr.insert(nr.end(), srv.begin(), srv.end());
2224 nr.insert(nr.end(), var.begin(), var.end());
2233 : (nwait > 0 ? nwait : nsrv);
2234 for (std::size_t i = 0; i < wpos.size(); ++i) {
2235 std::vector<T> b2 = buf;
2237 b2[wcls[i] - 1] -= one;
2239 b2.erase(b2.begin() + wpos[i],
2240 b2.begin() + wpos[i] + (paired ? 2 : 1));
2241 b2.insert(b2.begin(), paired ? 2 : 1, zero);
2243 std::vector<T> nr = b2;
2244 nr.insert(nr.end(), srv.begin(), srv.end());
2245 nr.insert(nr.end(), var.begin(), var.end());
2248 static_cast<double>(total)));
2251 for (std::size_t i = 0; i < scls.size(); ++i) {
2252 std::vector<T> b2 = buf, s2 = srv;
2253 s2[L.
Ks[scls[i] - 1] + sph[i]] -= one;
2257 for (std::size_t j = 0; j < s2.size(); ++j)
2259 if (L.
bufw > 0 && occ < S) {
2261 std::size_t hp = L.
bufw;
2262 for (std::size_t b = 0; b < L.
bufw; b += paired ? 2 : 1)
2265 const std::size_t pc =
static_cast<std::size_t
>(
2271 pp = v >= 1 ?
static_cast<std::size_t
>(v) - 1 : 0;
2273 b2.erase(b2.begin() + hp,
2274 b2.begin() + hp + (paired ? 2 : 1));
2275 b2.insert(b2.begin(), paired ? 2 : 1, zero);
2276 s2[L.
Ks[pc - 1] + pp] += one;
2278 }
else if (counted) {
2283 for (std::size_t r = 1; r <= R && r <= L.
bufw; ++r)
2286 s2[L.
Ks[r - 1]] += one;
2291 std::vector<T> nr = b2;
2292 nr.insert(nr.end(), s2.begin(), s2.end());
2293 nr.insert(nr.end(), var.begin(), var.end());
2296 static_cast<double>(scnt[i]) /
static_cast<double>(total)));
2300 signal_detail::merge_states(sp, pr);
2301 for (std::size_t i = 0; i < sp.size(); ++i) {
2302 nxt.push_back(sp[i]);
2303 nxtp.push_back(T(curp[row] * pr[i]));
2306 signal_detail::merge_states(nxt, nxtp);
2310 for (std::size_t i = 0; i < cur.size(); ++i) {
2311 acc.push_back(cur[i]);
2312 accp.push_back(T(pmf.second[ik] * curp[i]));
2315 signal_detail::merge_states(acc, accp);
2316 out.
space.swap(acc);
2317 out.
prob.swap(accp);
2318 out.
rate.assign(out.
space.size(), minus_one);
2339 const std::vector<std::size_t>& c, std::size_t p,
2340 const std::vector<std::vector<bool>>& G) {
2341 const std::size_t n = c.size();
2342 if (p >= n)
throw InputError(
"pass_and_swap: position is out of range for the state");
2343 std::vector<std::size_t> chain(1, p);
2344 std::size_t moving = c[p], cur = p;
2347 for (std::size_t j = cur + 1; j < n; ++j)
2348 if (moving - 1 < G.size() && c[j] - 1 < G[moving - 1].size() &&
2349 G[moving - 1][c[j] - 1]) {
2358 const std::size_t dep = c[chain.back()];
2361 std::vector<std::size_t> cnew = c;
2362 for (std::size_t i = 0; i + 1 < chain.size(); ++i) cnew[chain[i + 1]] = c[chain[i]];
2363 cnew.erase(cnew.begin() + chain[0]);
2364 return std::make_pair(cnew, dep);
2379template <
class T,
class F>
2380inline std::vector<double>
pas_increments(
const F& mu_fun,
const std::vector<std::size_t>& c) {
2381 std::vector<double> inc(c.size(), 0.0);
2382 double mu_prev = 0.0;
2383 for (std::size_t p = 0; p < c.size(); ++p) {
2384 const std::vector<std::size_t> prefix(c.begin(), c.begin() + p + 1);
2386 inc[p] = mu_cur - mu_prev;
2398template <
class T,
class F>
2400 const std::vector<std::size_t>& cold,
2401 const std::vector<std::size_t>& cnew) {
2402 if (!mu_fun || out.
space.empty())
return;
2405 for (std::size_t p = 0; p < inc_new.size(); ++p) {
2406 if (inc_new[p] <= 0)
continue;
2407 if (p < inc_old.size() && inc_old[p] > 0)
continue;
2414 const std::vector<T>& inspace,
EventType event,
2416 const std::size_t ist =
sn.nodes[ind - 1].station;
2419 if (ist == 0)
throw InputError(
"after_event_station_pas: node is not a station");
2420 const typename std::map<std::size_t, typename NetworkStruct<T>::PasParam>::const_iterator it =
2421 sn.pasparam.find(ist);
2422 if (it ==
sn.pasparam.end() || !it->second.svc_rate_fun)
2424 "after_event_station_pas: the station has no service rate function mu(c); set one "
2427 const std::size_t V =
sn.nvars_of(ind);
2428 const std::size_t W = inspace.size() - V;
2429 std::vector<std::size_t> c;
2430 for (std::size_t i = 0; i < W; ++i) {
2432 if (v > 0) c.push_back(
static_cast<std::size_t
>(v));
2434 const std::vector<T> var(inspace.begin() + W, inspace.end());
2435 const double cap =
sn.cap[ist - 1];
2437 if (event == EventType::ARV) {
2440 if (
static_cast<double>(c.size()) >= cap)
return out;
2441 std::vector<std::size_t>
nc = c;
2452 if (
nc.size() > W)
return out;
2454 for (std::size_t i = 0; i <
nc.size(); ++i)
2456 row.resize(W, zero);
2457 row.insert(row.end(), var.begin(), var.end());
2458 out.
space.push_back(row);
2460 out.
prob.push_back(one);
2471 if (event != EventType::DEP)
return out;
2477 for (std::size_t p = 0; p < c.size(); ++p) {
2478 const std::vector<std::size_t> prefix(c.begin(), c.begin() + p + 1);
2479 const T mu_cur = it->second.svc_rate_fun(prefix);
2480 const T ratep = T(mu_cur - mu_prev);
2483 const std::pair<std::vector<std::size_t>, std::size_t> ps =
2487 if (ps.second != cls)
continue;
2489 for (std::size_t i = 0; i < ps.first.size(); ++i)
2491 row.resize(W, zero);
2492 row.insert(row.end(), var.begin(), var.end());
2493 out.
space.push_back(row);
2494 out.
rate.push_back(ratep);
2495 out.
prob.push_back(one);
2512 const std::size_t R =
sn.nclasses;
2514 ri.
slot.assign(R,
static_cast<std::size_t
>(-1));
2515 if (
sn.nvars.size() < ind ||
sn.nvars[ind - 1].size() < 3 * R + 1)
return ri;
2516 std::size_t pos = 0;
2517 for (std::size_t j = 0; j < 2 * R + 1; ++j) pos +=
sn.nvars[ind - 1][j];
2518 for (std::size_t r = 1; r <= R; ++r)
2519 if (
sn.nvars[ind - 1][2 * R + r] > 0) {
2520 ri.
slot[r - 1] = pos;
2533 for (std::size_t i = 0; i < ri.
classes.size(); ++i) {
2537 if (s !=
static_cast<std::size_t
>(-1) && s < var.size())
2561 const std::vector<T>& inspace, std::size_t cls) {
2562 const std::size_t R =
sn.nclasses;
2563 const std::size_t ist =
sn.nodes[ind - 1].station;
2566 if (ist == 0)
throw InputError(
"after_event_station_reply: node is not a station");
2569 const double S =
sn.stations[ist - 1].nservers;
2573 std::size_t callclass = 0;
2574 for (std::size_t i = 0; i < ri.
classes.size(); ++i) {
2575 const std::size_t r = ri.
classes[i];
2576 if (
sn.syncreply.size() >= r &&
sn.syncreply[r - 1] == cls) {
2582 std::vector<T> buf(inspace.begin(), inspace.begin() + L.
bufw);
2583 std::vector<T> srv(inspace.begin() + L.
bufw, inspace.begin() + L.
bufw + L.
srvw);
2584 std::vector<T> var(inspace.begin() + L.
bufw + L.
srvw, inspace.end());
2586 if (callclass > 0) {
2587 const std::size_t s = ri.
slot[callclass - 1];
2588 if (s !=
static_cast<std::size_t
>(-1) && s < var.size() &&
2601 for (std::size_t ke = 0; ke < L.
K[cls - 1]; ++ke) {
2603 std::vector<T> s2 = srv;
2604 s2[L.
Ks[cls - 1] + ke] += one;
2605 std::vector<T> row = buf;
2606 row.insert(row.end(), s2.begin(), s2.end());
2607 row.insert(row.end(), var.begin(), var.end());
2608 out.
space.push_back(row);
2610 out.
prob.push_back(pentry[ke]);
2616 std::vector<T> b2 = buf;
2617 std::size_t slot = b2.size();
2618 for (std::size_t b = 0; b < b2.size(); ++b)
2620 if (slot == b2.size()) {
2621 b2.insert(b2.begin(), zero);
2625 std::vector<T> row = b2;
2626 row.insert(row.end(), srv.begin(), srv.end());
2627 row.insert(row.end(), var.begin(), var.end());
2628 out.
space.push_back(row);
2630 out.
prob.push_back(one);
2638 std::size_t& pos, std::size_t& swk,
long& ctr) {
2639 pos = pi.
ipos !=
static_cast<std::size_t
>(-1)
2641 : (srvclass > 0 ? srvclass : 1);
2642 swk = pi.
iswk !=
static_cast<std::size_t
>(-1)
2645 ctr = pi.
ictr !=
static_cast<std::size_t
>(-1)
2653 std::size_t swk,
long ctr) {
2654 if (pi.
ipos !=
static_cast<std::size_t
>(-1))
2656 if (pi.
iswk !=
static_cast<std::size_t
>(-1))
2658 if (pi.
ictr !=
static_cast<std::size_t
>(-1))
2671 default:
throw InputError(
"polling_budget: unsupported polling type");
2685 std::size_t R,
bool arrived, std::size_t& q,
int& mode,
long& budget) {
2686 if (arrived && pi.
polled[pos - 1] && nbuf[pos - 1] > 0) {
2693 std::size_t p = pos;
2694 for (std::size_t step = 0; step < R; ++step) {
2696 if (!pi.
polled[p - 1])
continue;
2703 if (nbuf[p - 1] > 0) {
2718 std::size_t q,
int mode,
long budget,
const std::vector<T>& buf,
2719 const std::vector<T>& srv,
const std::vector<T>& var,
const RowLayout<T>& L,
2720 std::vector<std::vector<T>>& rows, std::vector<T>& probs) {
2724 std::vector<T> b2 = buf;
2727 for (std::size_t ke = 0; ke < L.
K[q - 1]; ++ke) {
2729 std::vector<T> s2 = srv;
2730 s2[L.
Ks[q - 1] + ke] += one;
2731 std::vector<T> row = b2;
2732 row.insert(row.end(), s2.begin(), s2.end());
2733 const std::vector<T> v2 =
polling_set(pi, var, q, 0, budget);
2734 row.insert(row.end(), v2.begin(), v2.end());
2735 rows.push_back(row);
2736 probs.push_back(pentry[ke]);
2738 }
else if (mode == 2) {
2740 for (std::size_t ke = 0; ke < pi.
ksw[q - 1]; ++ke) {
2742 std::vector<T> row = buf;
2743 row.insert(row.end(), srv.begin(), srv.end());
2744 const std::vector<T> v2 =
polling_set(pi, var, q, ke + 1, 0);
2745 row.insert(row.end(), v2.begin(), v2.end());
2746 rows.push_back(row);
2747 probs.push_back(pi.
sw_pie[q - 1][ke]);
2751 std::vector<T> row = buf;
2752 row.insert(row.end(), srv.begin(), srv.end());
2753 const std::vector<T> v2 =
polling_set(pi, var, q, 0, 0);
2754 row.insert(row.end(), v2.begin(), v2.end());
2755 rows.push_back(row);
2756 probs.push_back(one);
2772 const std::vector<T>& inspace, std::size_t cls) {
2773 const std::size_t R =
sn.nclasses;
2774 const std::size_t ist =
sn.nodes[ind - 1].station;
2777 if (ist == 0)
throw InputError(
"after_event_station_switch: node is not a station");
2779 if (!pinfo.
valid || !pinfo.
has_sw[cls - 1])
return out;
2782 const std::vector<T> buf(inspace.begin(), inspace.begin() + L.
bufw);
2783 const std::vector<T> srv(inspace.begin() + L.
bufw, inspace.begin() + L.
bufw + L.
srvw);
2784 const std::vector<T> var(inspace.begin() + L.
bufw + L.
srvw, inspace.end());
2786 std::size_t pos = 0, swk = 0;
2790 if (pos != cls || swk == 0)
return out;
2793 for (std::size_t kd = 0; kd < pinfo.
ksw[cls - 1]; ++kd) {
2794 if (kd + 1 == swk)
continue;
2795 const T r0 = pinfo.
sw_d0[cls - 1](swk - 1, kd);
2797 std::vector<T> row = buf;
2798 row.insert(row.end(), srv.begin(), srv.end());
2799 const std::vector<T> v2 =
polling_set(pinfo, var, cls, kd + 1, 0);
2800 row.insert(row.end(), v2.begin(), v2.end());
2801 out.
space.push_back(row);
2802 out.
rate.push_back(r0);
2803 out.
prob.push_back(one);
2807 for (std::size_t j = 0; j < pinfo.
ksw[cls - 1]; ++j) rate += pinfo.
sw_d1[cls - 1](swk - 1, j);
2809 std::vector<long> nbuf(R, 0);
2810 for (std::size_t r = 0; r < R && r < L.
bufw; ++r)
2815 polling_next(pinfo, cls, nbuf, R,
true, q, mode, budget);
2816 std::vector<std::vector<T>> rows;
2817 std::vector<T> probs;
2818 polling_land(
sn, ist, pinfo, q, mode, budget, buf, srv, var, L, rows, probs);
2819 for (std::size_t j = 0; j < rows.size(); ++j) {
2824 if (rows[j] == inspace)
continue;
2825 out.
space.push_back(rows[j]);
2826 out.
rate.push_back(T(rate * probs[j]));
2827 out.
prob.push_back(one);
2834 tag_last(out, mode == 1 ? q : 0, 0);
2856 const std::vector<T>& inspace,
EventType event,
2858 const std::size_t R =
sn.nclasses;
2862 const typename std::map<std::size_t, CacheParam<T>>::const_iterator ci =
sn.nodeparam.find(ind);
2863 if (ci ==
sn.nodeparam.end())
throw InputError(
"after_event_cache: node has no CacheParam");
2865 const std::size_t h = cp.
itemcap.size();
2866 const std::size_t n = cp.
nitems;
2867 std::size_t tcc = 0;
2868 for (std::size_t i = 0; i < h; ++i)
2869 if (cp.
itemcap[i] > 0) tcc +=
static_cast<std::size_t
>(cp.
itemcap[i]);
2871 const std::vector<int>& m = cp.
itemcap;
2873 const std::vector<int>& m;
2874 std::size_t operator()(std::size_t i, std::size_t j)
const {
2875 std::size_t base = 0;
2876 for (std::size_t t = 0; t + 1 < i; ++t) base +=
static_cast<std::size_t
>(m[t]);
2877 return base + j - 1;
2881 std::vector<T> srv(inspace.begin(), inspace.begin() + R);
2882 std::vector<T> var(inspace.begin() + R, inspace.end());
2884 if (event == EventType::ARV) {
2885 srv[cls - 1] += one;
2886 std::vector<T> row = srv;
2887 row.insert(row.end(), var.begin(), var.end());
2888 out.
space.push_back(row);
2890 out.
prob.push_back(one);
2894 if (event == EventType::DEP) {
2899 srv[cls - 1] -= one;
2900 std::vector<T> row = srv;
2901 row.insert(row.end(), var.begin(), var.end());
2902 out.
space.push_back(row);
2903 out.
rate.push_back(imm);
2904 out.
prob.push_back(one);
2908 if (event != EventType::READ)
return out;
2912 for (std::size_t r = 0; r < R; ++r) tot += num_traits<T>::to_double(srv[r]);
2914 if (cls - 1 >= cp.
pread.size() || cp.
pread[cls - 1].empty())
return out;
2915 const std::vector<T>& p = cp.
pread[cls - 1];
2923 std::vector<std::size_t> rc_list, rc_items, rc_orig;
2925 const std::size_t block_b = tcc + n;
2926 std::size_t width_b = var.size() > block_b ? var.size() - block_b : 0;
2927 if (width_b != rc_list.size()) width_b = 0;
2932 ? std::numeric_limits<double>::infinity()
2934 bool from_retrieval =
false;
2935 for (std::size_t j = 0; j < rc_list.size(); ++j)
2936 if (rc_list[j] == cls) from_retrieval =
true;
2938 for (std::size_t k = 1; k <= n; ++k) {
2940 std::vector<T> srv_e = srv;
2941 srv_e[cls - 1] -= one;
2944 std::size_t posk = 0;
2945 for (std::size_t c = 0; c < tcc && c < var.size(); ++c)
2954 if (from_retrieval) posk = 0;
2956 k - 1 >= cp.
accost[cls - 1].size()
2958 : cp.
accost[cls - 1][k - 1];
2959 const bool have_ac = ac.
rows() >= h + 1 && ac.
cols() >= h + 1;
2964 const bool in_flight =
2966 std::size_t r_class = 0;
2972 if (from_retrieval && !in_flight)
continue;
2974 if (!from_retrieval && r_class != 0) {
2979 std::vector<T> srv_b = srv_e;
2980 std::vector<T> var_b = var;
2982 srv_b[r_class - 1] += one;
2983 if (tcc + k <= var_b.size()) var_b[tcc + k - 1] = one;
2985 if (width_b == 0)
continue;
2986 std::size_t bslot = width_b;
2987 for (std::size_t j = 0; j < rc_list.size(); ++j)
2988 if (rc_list[j] == r_class) { bslot = j;
break; }
2989 if (bslot >= width_b)
continue;
2991 for (std::size_t j = 0; j < width_b; ++j)
2993 if (pend >= maxpend)
continue;
2994 var_b[block_b + bslot] += one;
2996 std::vector<T> row = srv_b;
2997 row.insert(row.end(), var_b.begin(), var_b.end());
2998 out.
space.push_back(row);
2999 out.
rate.push_back(T(p[k - 1] * imm));
3000 out.
prob.push_back(one);
3009 std::vector<T> srv_m = srv_e;
3010 srv_m[cp.
missclass[cls - 1] - 1] += one;
3011 std::vector<T> var_m = var;
3012 if (tcc + k <= var_m.size()) var_m[tcc + k - 1] = zero;
3013 for (std::size_t j = 0; j < width_b; ++j) {
3014 if (rc_items[j] != k)
continue;
3016 if (held <= 0)
continue;
3017 const std::size_t oc = rc_orig[j];
3019 srv_m[cp.
hitclass[oc - 1] - 1] += var_m[block_b + j];
3020 var_m[block_b + j] = zero;
3025 const T rej = have_ac ? ac(0, 0) : zero;
3027 std::vector<T> row = srv_m;
3028 row.insert(row.end(), var_m.begin(), var_m.end());
3029 out.
space.push_back(row);
3030 out.
rate.push_back(T(rej * p[k - 1] * imm));
3031 out.
prob.push_back(one);
3033 for (std::size_t l = 1; l <= h; ++l) {
3034 const T w = have_ac ? ac(0, l) : (l == 1 ? one : zero);
3036 if (m[l - 1] <= 0)
continue;
3037 const std::size_t ml =
static_cast<std::size_t
>(m[l - 1]);
3040 for (std::size_t rr = 1; rr <= ml; ++rr) {
3041 std::vector<T> vp = var_m;
3043 std::vector<T> row = srv_m;
3044 row.insert(row.end(), vp.begin(), vp.end());
3045 out.
space.push_back(row);
3046 out.
rate.push_back(T(w * p[k - 1] /
3048 out.
prob.push_back(one);
3053 std::vector<T> vp = var_m;
3054 for (std::size_t j = ml; j >= 2; --j) vp[cpos(l, j)] = var_m[cpos(l, j - 1)];
3056 T rate = T(w * p[k - 1] * imm);
3060 const T q = cp.
qlru;
3062 std::vector<T> row0 = srv_m;
3063 row0.insert(row0.end(), var_m.begin(), var_m.end());
3064 out.
space.push_back(row0);
3065 out.
rate.push_back(T(rate * T(one - q)));
3066 out.
prob.push_back(one);
3071 std::vector<T> row = srv_m;
3072 row.insert(row.end(), vp.begin(), vp.end());
3073 out.
space.push_back(row);
3074 out.
rate.push_back(rate);
3075 out.
prob.push_back(one);
3082 std::vector<T> srv_h = srv_e;
3083 srv_h[cp.
hitclass[cls - 1] - 1] += one;
3084 std::size_t li = 1, acc = 0;
3085 for (std::size_t t = 0; t < h; ++t) {
3086 const std::size_t mt = m[t] > 0 ?
static_cast<std::size_t
>(m[t]) : 0;
3087 if (posk <= acc + mt) { li = t + 1;
break; }
3090 const std::size_t j = posk - acc;
3102 for (std::size_t inew = li; inew <= h; ++inew) {
3103 if (m[inew - 1] <= 0)
continue;
3104 const std::size_t mn =
static_cast<std::size_t
>(m[inew - 1]);
3105 const T w = have_ac ? ac(li, inew) : (inew == li + 1 ? one : zero);
3109 for (std::size_t r = 1; r <= mn; ++r) {
3110 std::vector<T> vp = var;
3111 vp[cpos(li, j)] = var[cpos(inew, r)];
3113 std::vector<T> row = srv_h;
3114 row.insert(row.end(), vp.begin(), vp.end());
3115 out.
space.push_back(row);
3119 out.
prob.push_back(one);
3126 std::vector<T> vp = var;
3131 for (std::size_t t = j; t >= 2; --t) vp[cpos(li, t)] = var[cpos(li, t - 1)];
3134 vp[cpos(li, ordered ? 1 : j)] = var[cpos(inew, mn)];
3135 for (std::size_t t = mn; t >= 2; --t) vp[cpos(inew, t)] = var[cpos(inew, t - 1)];
3137 std::vector<T> row = srv_h;
3138 row.insert(row.end(), vp.begin(), vp.end());
3139 out.
space.push_back(row);
3140 out.
rate.push_back(T(w * p[k - 1] * imm));
3141 out.
prob.push_back(one);
3148 std::vector<T> row = srv_h;
3149 row.insert(row.end(), var.begin(), var.end());
3150 out.
space.push_back(row);
3151 out.
rate.push_back(T(p[k - 1] * imm));
3152 out.
prob.push_back(one);
3156 std::vector<T> vp = var;
3157 for (std::size_t t = j; t >= 2; --t) vp[cpos(li, t)] = var[cpos(li, t - 1)];
3158 vp[cpos(li, 1)] = var[cpos(li, j)];
3159 std::vector<T> row = srv_h;
3160 row.insert(row.end(), vp.begin(), vp.end());
3161 out.
space.push_back(row);
3162 out.
rate.push_back(T(p[k - 1] * imm));
3163 out.
prob.push_back(one);
3205 std::vector<GlobalSync<T>> gsync;
3207 for (std::size_t ind = 1; ind <=
sn.nodes.size(); ++ind) {
3208 if (
sn.nodes[ind - 1].nodetype != NodeType::Transition)
continue;
3209 const typename std::map<std::size_t, TransitionParam<T>>::const_iterator it =
3210 sn.transparam.find(ind);
3211 if (it ==
sn.transparam.end())
continue;
3213 for (
int pass = 0; pass < 2; ++pass) {
3214 for (std::size_t m = 1; m <= tp.
nmodes; ++m) {
3219 std::vector<std::pair<std::size_t, std::size_t>> enab, fire, inhib;
3223 for (std::size_t q = 0; q < en.
rows(); ++q)
3224 for (std::size_t r = 0; r < en.
cols(); ++r)
3226 enab.push_back(std::make_pair(q + 1, r + 1));
3227 for (std::size_t q = 0; q < fi.
rows(); ++q)
3228 for (std::size_t r = 0; r < fi.
cols(); ++r)
3230 fire.push_back(std::make_pair(q + 1, r + 1));
3231 for (std::size_t q = 0; q < ih.
rows(); ++q)
3232 for (std::size_t r = 0; r < ih.
cols(); ++r) {
3239 for (std::size_t i = 0; i < enab.size(); ++i)
3240 dup = dup || enab[i].first == q + 1;
3241 for (std::size_t i = 0; i < fire.size(); ++i)
3242 dup = dup || fire[i].first == q + 1;
3243 for (std::size_t i = 0; i < inhib.size(); ++i)
3244 dup = dup || inhib[i].first == q + 1;
3245 if (!dup) inhib.push_back(std::make_pair(q + 1, r + 1));
3248 g.
active.event = pass == 0 ? EventType::ENABLE : EventType::FIRE;
3255 std::vector<std::size_t> seen;
3256 auto once = [&](std::size_t q, std::size_t r) {
3257 for (std::size_t i = 0; i < seen.size(); ++i)
3258 if (seen[i] == q)
return;
3262 for (std::size_t i = 0; i < enab.size(); ++i) once(enab[i].first, enab[i].second);
3263 for (std::size_t i = 0; i < inhib.size(); ++i)
3264 once(inhib[i].first, inhib[i].second);
3266 for (std::size_t i = 0; i < enab.size(); ++i)
3269 en(enab[i].first - 1, enab[i].second - 1)});
3270 for (std::size_t i = 0; i < fire.size(); ++i)
3273 fi(fire[i].first - 1, fire[i].second - 1)});
3274 for (std::size_t i = 0; i < inhib.size(); ++i)
3276 inhib[i].second, one});
3311 const std::size_t R =
sn.nclasses;
3312 const std::size_t ind = gl.
active.node;
3313 const std::size_t mode = gl.
active.mode;
3317 const std::size_t isf =
sn.stateful_index(ind);
3318 if (isf == 0)
throw InputError(
"after_global_event: the transition is not stateful");
3319 const typename std::map<std::size_t, TransitionParam<T>>::const_iterator it =
3320 sn.transparam.find(ind);
3321 if (it ==
sn.transparam.end())
throw InputError(
"after_global_event: node has no TransitionParam");
3324 std::vector<std::size_t> fK(tp.
nmodes, 1), fKs(tp.
nmodes, 0);
3325 std::size_t tot = 0;
3326 for (std::size_t m = 0; m < tp.
nmodes; ++m) {
3331 const std::vector<T>& row = glspace.
local[isf - 1];
3332 std::vector<T> buf(row.begin(), row.begin() + tp.
nmodes);
3333 std::vector<T> srv(row.begin() + tp.
nmodes, row.begin() + tp.
nmodes + tot);
3334 std::vector<T> fired(row.begin() + tp.
nmodes + tot,
3335 row.begin() + 2 * tp.
nmodes + tot);
3336 const std::vector<T> var(row.begin() + 2 * tp.
nmodes + tot, row.end());
3339 std::vector<std::vector<T>> ep(
sn.nodes.size() + 1, std::vector<T>(R, zero));
3340 for (std::size_t j = 0; j < gl.
passive.size(); ++j) {
3341 const std::size_t pn = gl.
passive[j].node;
3342 const std::size_t pisf =
sn.stateful_index(pn);
3343 if (pisf == 0)
continue;
3359 bool inhibited =
false;
3360 for (std::size_t q = 0; q < ih_m.
rows(); ++q)
3361 for (std::size_t r = 0; r < ih_m.
cols() && r < R; ++r) {
3363 if (std::isinf(thr))
continue;
3367 for (std::size_t q = 0; q < en_m.
rows(); ++q)
3368 for (std::size_t r = 0; r < en_m.
cols() && r < R; ++r) {
3370 if (need <= 0)
continue;
3373 long mark_degree = 0;
3374 if (!inhibited && !under) {
3378 for (std::size_t q = 0; q < en_m.
rows() && ok; ++q)
3379 for (std::size_t r = 0; r < en_m.
cols() && r < R && ok; ++r) {
3381 if (need <= 0)
continue;
3387 mark_degree = d - 1;
3390 const long nsrv = std::isfinite(svm) ?
static_cast<long>(svm)
3393 if (gl.
active.event == EventType::ENABLE) {
3395 for (std::size_t k = 0; k < fK[mode - 1]; ++k)
3397 if (inhibited || under) {
3399 std::vector<T> b2 = buf, s2 = srv;
3401 for (std::size_t k = 0; k < fK[mode - 1]; ++k) s2[fKs[mode - 1] + k] = zero;
3402 std::vector<T> nr = b2;
3403 nr.insert(nr.end(), s2.begin(), s2.end());
3404 nr.insert(nr.end(), fired.begin(), fired.end());
3405 nr.insert(nr.end(), var.begin(), var.end());
3406 if (nr == row)
return out;
3408 ns.
local[isf - 1] = nr;
3409 out.
space.push_back(ns);
3410 out.
rate.push_back(imm);
3411 out.
prob.push_back(one);
3415 const long want = std::min(mark_degree, nsrv);
3416 if (running == want)
return out;
3417 if (running < want) {
3421 const long nadd = want - running;
3422 std::vector<T> pe(fK[mode - 1], zero);
3424 static_cast<std::size_t
>(fK[mode - 1])) {
3429 for (std::size_t k = 0; k < fK[mode - 1]; ++k) pe[k] = pv[k];
3434 std::vector<std::vector<long>> combs;
3435 std::vector<long> cur(fK[mode - 1], 0);
3436 std::function<void(std::size_t,
long)> rec = [&](std::size_t k,
long left) {
3437 if (k + 1 == fK[mode - 1]) {
3439 combs.push_back(cur);
3442 for (
long v = left; v >= 0; --v) {
3444 rec(k + 1, left - v);
3448 for (std::size_t i = 0; i < combs.size(); ++i) {
3449 std::vector<T> b2 = buf, s2 = srv;
3451 double logp = std::lgamma(
static_cast<double>(nadd) + 1.0);
3452 bool zeroprob =
false;
3453 for (std::size_t k = 0; k < fK[mode - 1]; ++k) {
3457 logp += combs[i][k] * std::log(pk) -
3458 std::lgamma(
static_cast<double>(combs[i][k]) + 1.0);
3459 else if (combs[i][k] > 0)
3462 std::vector<T> nr = b2;
3463 nr.insert(nr.end(), s2.begin(), s2.end());
3464 nr.insert(nr.end(), fired.begin(), fired.end());
3465 nr.insert(nr.end(), var.begin(), var.end());
3467 ns.
local[isf - 1] = nr;
3468 out.
space.push_back(ns);
3469 out.
rate.push_back(imm);
3477 const long ndiff = running - want;
3478 std::vector<long> sv(fK[mode - 1], 0);
3479 for (std::size_t k = 0; k < fK[mode - 1]; ++k)
3481 std::vector<std::vector<long>> combs;
3482 std::vector<long> cur(fK[mode - 1], 0);
3483 std::function<void(std::size_t,
long)> rec = [&](std::size_t k,
long left) {
3484 if (k + 1 == fK[mode - 1]) {
3485 if (left > sv[k])
return;
3487 combs.push_back(cur);
3490 for (
long v = std::min(left, sv[k]); v >= 0; --v) {
3492 rec(k + 1, left - v);
3496 std::vector<double> w(combs.size(), 0.0);
3497 double wmax = -1e300;
3498 for (std::size_t i = 0; i < combs.size(); ++i) {
3500 for (std::size_t k = 0; k < fK[mode - 1]; ++k)
3501 lw += std::lgamma(
static_cast<double>(sv[k]) + 1.0) -
3502 std::lgamma(
static_cast<double>(combs[i][k]) + 1.0) -
3503 std::lgamma(
static_cast<double>(sv[k] - combs[i][k]) + 1.0);
3505 wmax = std::max(wmax, lw);
3508 for (std::size_t i = 0; i < w.size(); ++i) {
3509 w[i] = std::exp(w[i] - wmax);
3512 for (std::size_t i = 0; i < combs.size(); ++i) {
3513 std::vector<T> b2 = buf, s2 = srv;
3514 for (std::size_t k = 0; k < fK[mode - 1]; ++k)
3517 std::vector<T> nr = b2;
3518 nr.insert(nr.end(), s2.begin(), s2.end());
3519 nr.insert(nr.end(), fired.begin(), fired.end());
3520 nr.insert(nr.end(), var.begin(), var.end());
3522 ns.
local[isf - 1] = nr;
3523 out.
space.push_back(ns);
3524 out.
rate.push_back(imm);
3531 if (gl.
active.event != EventType::FIRE)
return out;
3533 const bool immediate_mode = mode - 1 < tp.
timing.size() &&
3535 const T fw = immediate_mode && mode - 1 < tp.
fireweight.size() ? tp.
fireweight[mode - 1] : one;
3536 const long en_degree = inhibited ? 0 : std::min(mark_degree, nsrv);
3537 const long imm_servers = immediate_mode ? std::min(mark_degree, nsrv) : 0;
3539 for (std::size_t k = 0; k < fK[mode - 1]; ++k) {
3541 const bool fires = immediate_mode ? (k == 0 && imm_servers >= 1)
3542 : (in_k > 0 && en_degree >= 1);
3543 if (!fires)
continue;
3545 if (immediate_mode) {
3550 for (std::size_t j = 0; j < tp.
firingproc[mode - 1].D1.cols(); ++j)
3557 for (std::size_t q = 1; q <=
sn.nodes.size(); ++q) {
3559 for (std::size_t r = 0; r < R; ++r) s2 += ep[q][r];
3562 rate = T(rate * tp.
firingdep[mode - 1](mk));
3567 std::vector<T> b2 = buf, s2 = srv;
3569 s2[fKs[mode - 1] + k] -= one;
3570 b2[mode - 1] += one;
3573 std::vector<T> nr = b2;
3574 nr.insert(nr.end(), s2.begin(), s2.end());
3575 nr.insert(nr.end(), fired.begin(), fired.end());
3576 nr.insert(nr.end(), var.begin(), var.end());
3577 ns.
local[isf - 1] = nr;
3583 for (std::size_t j = 0; j < gl.
passive.size(); ++j) {
3585 if (pe2.
event != EventType::PRE && pe2.
event != EventType::POST)
continue;
3586 const std::size_t pisf =
sn.stateful_index(pe2.
node);
3587 if (pisf == 0)
continue;
3588 std::vector<T>& prow = ns.
local[pisf - 1];
3590 const std::size_t pist =
sn.nodes[pe2.
node - 1].station;
3592 pist != 0 ?
sn.stations[pist - 1].sched : SchedStrategy::INF;
3593 const std::size_t c = pe2.
cls;
3594 if (pe2.
event == EventType::PRE) {
3595 if (state_detail::buffer_is_class_tag(psched)) {
3598 long left =
static_cast<long>(wgt);
3600 if (psched == SchedStrategy::LCFS) {
3601 for (std::size_t b = 0; b < prow.size() && left > 0; ++b)
3602 if (prow[b] == tag) { prow[b] = zero; --left; }
3604 for (std::size_t b = prow.size(); b-- > 0 && left > 0;)
3605 if (prow[b] == tag) { prow[b] = zero; --left; }
3607 }
else if (prow.size() > R) {
3613 prow[R + c - 1] = zero;
3614 }
else if (c - 1 < prow.size()) {
3618 if (state_detail::buffer_is_class_tag(psched)) {
3619 for (
long q = 0; q < static_cast<long>(wgt); ++q)
3621 }
else if (c - 1 < prow.size()) {
3626 out.
space.push_back(ns);
3627 out.
rate.push_back(rate);
3628 out.
prob.push_back(one);
3685 const std::vector<std::vector<bool>>& impatience_classes = std::vector<std::vector<bool>>(),
3686 const std::vector<std::size_t>& breakdown_nodes = std::vector<std::size_t>()) {
3687 const std::size_t R =
sn.nclasses;
3688 const std::size_t local =
sn.nodes.size() + 1;
3690 std::vector<Sync<T>> sync;
3692 for (std::size_t ind = 1; ind <=
sn.nodes.size(); ++ind) {
3694 const std::size_t ist = nd.
station;
3695 for (std::size_t r = 1; r <= R; ++r) {
3698 if (ist != 0 &&
sn.phases_of(ist, r) > 1) {
3704 if (ist != 0 && impatience_classes.size() >= ist &&
3705 impatience_classes[ist - 1].size() >= r && impatience_classes[ist - 1][r - 1]) {
3712 const typename std::map<std::size_t, RetrialParam<T>>::const_iterator rit =
3713 sn.retrialparam.find(ist);
3714 if (rit !=
sn.retrialparam.end() && rit->second.retrial_proc.size() >= r &&
3715 !rit->second.retrial_proc[r - 1].disabled) {
3725 if (ist != 0 && r == 1) {
3726 bool has_bd =
false;
3727 for (std::size_t b = 0; b < breakdown_nodes.size(); ++b)
3728 if (breakdown_nodes[b] == ind) { has_bd =
true;
break; }
3741 if (ist != 0 &&
sn.stations[ist - 1].sched == SchedStrategy::POLLING) {
3753 if (nd.
nodetype == NodeType::Fork)
continue;
3767 bool cache_read_class =
false;
3768 if (nd.
nodetype == NodeType::Cache) {
3769 const typename std::map<std::size_t, CacheParam<T>>::const_iterator ci =
3770 sn.nodeparam.find(ind);
3771 if (ci !=
sn.nodeparam.end()) {
3772 if (r - 1 < ci->second.pread.size() && !ci->second.pread[r - 1].empty()) {
3779 r - 1 < ci->second.hitclass.size() && ci->second.hitclass[r - 1] != 0;
3786 if (nd.
nodetype == NodeType::Transition && r == 1) {
3787 const typename std::map<std::size_t, TransitionParam<T>>::const_iterator ti =
3788 sn.transparam.find(ind);
3789 if (ti !=
sn.transparam.end()) {
3790 for (std::size_t m = 1; m <= ti->second.nmodes; ++m) {
3798 if (cache_read_class)
continue;
3800 const std::size_t isf =
sn.stateful_index(ind);
3801 for (std::size_t jnd = 1; jnd <=
sn.nodes.size(); ++jnd) {
3802 if (!
sn.nodes[jnd - 1].stateful)
continue;
3803 const std::size_t jsf =
sn.stateful_index(jnd);
3804 for (std::size_t s = 1; s <= R; ++s) {
3805 const T p =
sn.rt((isf - 1) * R + (r - 1), (jsf - 1) * R + (s - 1));
3816 if (nd.
routing.size() >= s && nd.
routing[s - 1] == RoutingStrategy::SDR) {
3818 ns.
passive.rt_row = (isf - 1) * R + (r - 1);
3819 ns.
passive.rt_col = (jsf - 1) * R + (s - 1);
3859 const std::size_t R =
sn.nclasses;
3861 const std::size_t isf_f =
sn.stateful_index(e.
fork);
3862 if (isf_f == 0)
return out;
3863 const std::vector<T>& fs = gl.
local[isf_f - 1];
3864 if (fs.size() < R)
return out;
3868 const std::size_t B = e.
auxall.size();
3869 if (B == 0 || e.
tag == 0 || e.
tag > e.
auxall[0].size())
return out;
3870 const std::size_t Tt = e.
auxall[0].size();
3871 std::vector<double> nglobal(R, 0.0);
3872 for (std::size_t isf = 1; isf <=
sn.stateful_nodes.size(); ++isf) {
3873 const std::pair<T, std::vector<T>> mg =
3875 for (std::size_t r = 0; r < R; ++r) {
3881 if (std::isfinite(v)) nglobal[r] += v;
3884 std::vector<double> occ(Tt, 0.0);
3885 for (std::size_t t = 0; t < Tt; ++t)
3886 for (std::size_t b = 0; b < B; ++b) occ[t] += nglobal[e.
auxall[b][t] - 1];
3887 if (occ[e.
tag - 1] > 0)
return out;
3888 for (std::size_t t = 0; t + 1 < e.
tag; ++t)
3889 if (occ[t] == 0)
return out;
3892 seed.
local[isf_f - 1][seed.
local[isf_f - 1].size() - R + e.
cls - 1] -=
3895 std::vector<NetState<T>> partials(1, seed);
3901 std::vector<std::size_t> emissions;
3904 for (std::size_t rep = 0; rep < w; ++rep)
3905 for (std::size_t b = 0; b < B; ++b) emissions.push_back(b);
3907 std::size_t wmax = 0;
3908 for (std::size_t b = 0; b < e.
weightlink.size(); ++b)
3910 for (std::size_t rep = 1; rep <= wmax; ++rep)
3911 for (std::size_t b = 0; b < B; ++b)
3914 for (std::size_t ei = 0; ei < emissions.size(); ++ei) {
3915 const std::size_t b = emissions[ei];
3917 const std::size_t isf_b =
sn.stateful_index(bh);
3920 std::vector<NetState<T>> nextp;
3921 std::vector<T> nextq;
3922 for (std::size_t pp = 0; pp < partials.size(); ++pp) {
3924 after_event(
sn, bh, partials[pp].local[isf_b - 1], EventType::ARV, a);
3926 for (std::size_t
io = 0;
io < arv.
space.size(); ++
io) {
3929 nextp.push_back(ns);
3930 nextq.push_back(
io < arv.
prob.size() ? T(partprob[pp] * arv.
prob[
io])
3934 partials.swap(nextp);
3935 partprob.swap(nextq);
3938 out.
space = partials;
3939 for (std::size_t i = 0; i < partials.size(); ++i) {
3941 out.
prob.push_back(T(partprob[i] * e.
prob));
Base error for the multiprecision C++ port.
UnsupportedError(const std::string &what)
A network plus its refreshed NetworkStruct.
The exception types the port throws.
Enumerations and the minimal distribution descriptor shared by the model layer of the C++ port.
Markovian arrival process descriptors: stationary vectors, rate, moments, autocorrelation and the ind...
SchedStrategy
Scheduling disciplines, with the values of MATLAB SchedStrategy.
DropStrategy
Blocking and loss rules, with the values of MATLAB DropStrategy.
@ IMMEDIATE
fires with zero delay, resolved by weight and priority
@ REPLY
completes a synchronous call, releasing a held server
@ CATASTROPHE
removes EVERY job at the station
RemovalPolicy
Which job a negative signal removes, with the values of MATLAB RemovalPolicy.
@ FCFS
the oldest waiting job; servers only once nobody waits
@ LCFS
the newest waiting job; servers only once nobody waits
@ RANDOM
uniform over waiting AND in-service jobs
EventType
The events a state can undergo, with the values of MATLAB EventType.
@ KLIMITED
serve at most K per visit (K in pollingPar)
@ EXHAUSTIVE
serve until the queue empties
@ GATED
serve exactly the jobs present at the polling instant
@ DECREMENTING
serve until the queue is one shorter than at arrival
const char * sched_to_text(SchedStrategy s)
std::function< std::vector< T >(const std::vector< T > &)> CdScaling
A class-dependent scaling map, sn.cdscaling.
const char * event_to_text(EventType e)
@ QLRU
q-LRU: LRU with probabilistic admission on a miss
@ FIFO
first in, first out
std::vector< T > map_pie(const Map< T > &m)
Phase distribution seen by an arriving job, pie = pi D1 / (pi D1 e).
std::vector< T > entry_phase_dist(const NetworkStruct< T > &sn, std::size_t ist, std::size_t cls)
The entry-phase distribution pie{ist}{class}: which phase a service STARTS in.
long polling_budget(const PollingInfo< T > &pi, long nbufq)
Port of State.pollingBudget: how many services this visit may perform.
EventOutcome< T > after_event_join(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, EventType event, std::size_t cls)
Port of State.afterEventJoin: an event at a Join node of an FJ-augmented struct.
EventOutcome< T > after_event_station_pas(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, EventType event, std::size_t cls)
Defined below; the ARV and DEP branches divert to it before any slicing.
void tag_last(EventOutcome< T > &out, std::size_t start_cls, std::size_t preempt_cls)
Tag the successor row just appended to OUT: START_CLS begins service on it and PREEMPT_CLS is displac...
void cache_retrieval_class_map(const CacheParam< T > &cp, std::vector< std::size_t > &rc_list, std::vector< std::size_t > &rc_items, std::vector< std::size_t > &rc_orig)
Port of State.cacheRetrievalClassMap: the canonical order of a cache's retrieval classes,...
std::pair< std::vector< std::size_t >, std::vector< T > > signal_batch_pmf(const NetworkStruct< T > &sn, std::size_t cls, std::size_t ntot)
Port of State.signalBatchPMF: the batch size a negative signal removes.
ReplyBlockInfo reply_block_info(const NetworkStruct< T > &sn, std::size_t ind)
Defined below; the departure branch records a server held for a reply.
Marginal< T > to_marginal(const NetworkStruct< T > &sn, std::size_t ist, const std::vector< T > &state_i, const std::vector< std::size_t > &phasesz, const std::vector< std::size_t > &phaseshift, std::size_t nvar=0)
Port of State.toMarginal for a STATION, one state row at a time.
void polling_get(const PollingInfo< T > &pi, const std::vector< T > &var, std::size_t srvclass, std::size_t &pos, std::size_t &swk, long &ctr)
Defined below; the polling branches of ARV, DEP and SWITCH use these.
EventOutcome< T > after_event_station_switch(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, std::size_t cls)
Port of the SWITCH branch: a polling server advances its switchover timer.
void rr_advance_row(const NetworkStruct< T > &sn, std::size_t ind, std::size_t cls, std::vector< std::vector< T > > &rows)
Port of State.afterEventStation's dispatch: the successors of one event at one station.
void polling_next(const PollingInfo< T > &pi, std::size_t pos, const std::vector< long > &nbuf, std::size_t R, bool arrived, std::size_t &q, int &mode, long &budget)
Port of State.pollingNext: where the server goes from buffer pos.
std::vector< T > polling_set(const PollingInfo< T > &pi, std::vector< T > var, std::size_t pos, std::size_t swk, long ctr)
Write (pos, swk, ctr) back into the local-variable block.
GlobalOutcome< T > after_global_event(const NetworkStruct< T > &sn, const NetState< T > &glspace, const GlobalSync< T > &gl)
Port of State.afterGlobalEvent: an SPN mode ENABLEs or FIREs.
EventOutcome< T > after_event_station_reply(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, std::size_t cls)
Port of State.afterEventStationReply: a REPLY signal completes a synchronous call at the station hold...
EventOutcome< T > after_event_station_arv(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, std::size_t cls)
Port of the ARV branch of State.afterEventStation: an arriving class-cls job joins node ind,...
EventOutcome< T > after_event_station_renege(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, std::size_t cls, const T &impatience_mu)
Port of the RENEGE branch: a WAITING class-cls job abandons the queue.
EventOutcome< T > after_event_cache(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, EventType event, std::size_t cls)
Port of State.afterEventCache: events at a Cache node.
EventOutcome< T > after_event_station_signal(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, std::size_t cls)
Port of State.afterEventStationSignal: a G-network signal arrives.
bool is_physical_capacity(const NetworkStruct< T > &sn, std::size_t ist, std::size_t cls)
Port of State.isPhysicalCapacity: true when the bound at (ist, class) is a PHYSICAL capacity rather t...
PrioPop< T > prio_pop(const NetworkStruct< T > &sn, std::size_t ist, const Marginal< T > &m, std::size_t cls, double ni, double S)
Compute the *PRIO effective population; a no-op for every other discipline.
T cd_factor(const NetworkStruct< T > &sn, std::size_t ist, const std::vector< T > &nir, std::size_t cls)
Port of State.cdclassfactor: the class-dependence multiplier of a class-cls rate at the per-class pop...
EventOutcome< T > after_event_station_phase(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, std::size_t cls)
Port of the PHASE branch of State.afterEventStation: service advances a phase WITHOUT completing.
std::pair< std::vector< T >, std::vector< T > > phase_rates(const NetworkStruct< T > &sn, std::size_t ist, std::size_t cls)
sn.mu and sn.phi for one (station, class), derived as MATLAB's Markovian.getMu / getPhi derive them f...
EventOutcome< T > after_event_transition(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, EventType event, std::size_t mode)
Port of State.afterEventTransition, the PHASE arm: one running server of the given mode advances its ...
EventOutcome< T > after_event_router(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, EventType event, std::size_t cls)
Port of State.afterEventRouter: a Router holds a job for the instant it takes to decide where it goes...
T lld_factor(const NetworkStruct< T > &sn, std::size_t ist, double n)
The limited-load-dependent multiplier at population n, 1 when unset.
void pad_tags(EventOutcome< T > &out)
Bring the tag vectors up to one entry per successor, so a caller can index them exactly like space.
void pas_tag_started(EventOutcome< T > &out, const F &mu_fun, const std::vector< std::size_t > &cold, const std::vector< std::size_t > &cnew)
Tag the successor just appended to OUT with the PAS positions that started service on it: those of CN...
std::vector< Sync< T > > refresh_sync(const NetworkStruct< T > &sn, const std::vector< std::vector< bool > > &impatience_classes=std::vector< std::vector< bool > >(), const std::vector< std::size_t > &breakdown_nodes=std::vector< std::size_t >())
Port of MNetwork.refreshSync: the synchronization list.
EventOutcome< T > after_event(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, EventType event, std::size_t cls, bool no_promote=false, const T &aux_rate=num_traits< T >::from_int(0))
Port of State.afterEvent: the successors of one event at one NODE.
std::pair< std::vector< std::size_t >, std::size_t > pass_and_swap(const std::vector< std::size_t > &c, std::size_t p, const std::vector< std::vector< bool > > &G)
Port of State.passAndSwap: the transition a service completion triggers at a pass-and-swap station (D...
std::pair< T, std::vector< T > > to_marginal_aggr(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &state_i)
Port of State.toMarginalAggr: the job counts of one node's state row, without the per-phase detail to...
EventOutcome< T > after_event_fork(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, EventType event, std::size_t cls)
Port of State.afterEventFork: an event at a STATEFUL Fork node.
EventOutcome< T > after_event_station(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, EventType event, std::size_t cls, bool no_promote=false, const T &aux_rate=num_traits< T >::from_int(0))
std::vector< GlobalSync< T > > refresh_global_sync(const NetworkStruct< T > &sn)
Port of MNetwork.refreshGlobalSync: the ENABLE and FIRE synchronizations.
std::vector< double > pas_increments(const F &mu_fun, const std::vector< std::size_t > &c)
Port of State.afterEventStationPAS: events at a pass-and-swap station.
T service_share(const NetworkStruct< T > &sn, std::size_t ist, const Marginal< T > &m, std::size_t cls, double ni, double S)
Defined below; DEP and PHASE must share one definition of the share.
GlobalOutcome< T > after_fj_event(const NetworkStruct< T > &sn, const FjSync< T > &e, const NetState< T > &gl)
Port of State.afterFJEvent: fire ONE entry of the fork firing list.
RowLayout< T > row_layout(const NetworkStruct< T > &sn, std::size_t ind, std::size_t width)
EventOutcome< T > after_event_station_dep(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, std::size_t cls, bool no_promote=false)
Port of the DEP branch of State.afterEventStation: a class-cls job completes service at station ind.
PollingInfo< T > polling_info(const NetworkStruct< T > &sn, std::size_t ind)
EventOutcome< T > after_event_station_breakdown(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, bool up, const T &mu)
Port of the FAILURE and REPAIR branches: the server goes down, or comes back.
bool arrival_is_lost(const NetworkStruct< T > &sn, std::size_t ist, std::size_t cls)
Port of State.arrivalIsLost: true when an arrival that finds no room is LOST, false when it must BLOC...
EventOutcome< T > after_event_station_retry(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, std::size_t cls, const T &retrial_mu, bool constant_policy=false)
Port of the RETRY branch: an ORBITING class-cls job retries entry.
void polling_land(const NetworkStruct< T > &sn, std::size_t ist, const PollingInfo< T > &pi, std::size_t q, int mode, long budget, const std::vector< T > &buf, const std::vector< T > &srv, const std::vector< T > &var, const RowLayout< T > &L, std::vector< std::vector< T > > &rows, std::vector< T > &probs)
Port of State.pollingLand: the states the walk lands in, with weights.
double reply_blocked(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &var)
Defined below; the reply block subtracts held servers in the ARV branch.
A queueing network and its refreshed NetworkStruct.
State.pollingInfo and the controller description it returns.
Port of the MATLAB +State package: the encoding that turns a station's state row into marginal job co...
Matrix< T > D0
The (D0,D1) pair when the type carries one directly.
static constexpr double Immediate
Rate of an Immediate distribution; its mean is 1/Immediate = 1e-8.
A MAP as the pair of matrices (D0, D1).
T qlru
Delayed-hit retrieval system (Cache.setRetrievalSystem).
std::vector< std::vector< Matrix< T > > > accost
(u) x (n) of (h+1)x(h+1), or empty
long max_pending_retrieval
Truncation level of block B: how many secondary requests may be merged onto the in-flight fetches of ...
std::vector< std::vector< std::size_t > > retrieval_classes
(nitems x nclasses), 1-based
std::vector< int > itemcap
std::vector< std::size_t > missclass
std::vector< std::size_t > hitclass
lang::ReplacementStrategy replacestrat
std::vector< std::vector< T > > pread
(u) x (n), empty row = NaN
What one event produces at one node: the successor rows, their rates and their probabilities,...
std::vector< T > prob
per-row probability of the choice
std::vector< std::vector< T > > space
successor local state rows
std::vector< T > rate
per-row rate, -1 on a passive half
std::vector< std::vector< std::size_t > > start
START annotation: the 1-based classes that BEGIN or RESUME holding a server on each successor row.
std::vector< std::vector< std::size_t > > preempt
PREEMPT annotation: the 1-based classes pushed back into the buffer.
sn.nodeparam{j}.fj: what a Join node needs to fire on identity.
std::vector< std::size_t > origclasses
std::map< std::size_t, std::vector< std::vector< std::size_t > > > auxmatrix
std::map< std::size_t, std::vector< std::size_t > > required
One fork firing synchronization: sn.fjsync{k}.
std::size_t fork
1-based Fork node
std::vector< std::size_t > weightlink
Per-branch tasksPerLink, EMPTY when every branch carries weight.
std::size_t weight
tasksPerLink: siblings emitted per branch
std::vector< std::size_t > branchheads
1-based node per branch
std::size_t cls
1-based ORIGINAL class being forked
std::vector< std::vector< std::size_t > > auxall
(B x T) every auxiliary class of this (fork, class), for the tag scan.
std::vector< std::size_t > auxclasses
the tag's auxiliary class per branch
std::size_t tag
1-based tag this entry allocates
static constexpr double Immediate
Rate of an Immediate distribution; its mean is 1/Immediate = 1e-8.
static constexpr double MaxInt
Stand-in for an unbounded COUNT, MATLAB GlobalConstants.MaxInt.
What one global event produces: a whole network state per outcome.
std::vector< NetState< T > > space
std::vector< bool > completion
True where the outcome is a firing COMPLETION, i.e.
A GLOBAL synchronization: an SPN mode event and the place arcs it drives.
std::vector< ModeEvent< T > > passive
What State.toMarginal returns for one station and one state row.
std::vector< std::vector< T > > kir
jobs in service per class and phase
std::vector< T > nir
jobs per class
std::vector< T > sir
jobs in service per class
One half of a GLOBAL synchronization: a mode event at a node.
std::size_t mode
1-based mode index
std::size_t node
1-based node index (a Transition, or a place)
std::size_t cls
1-based class the arc moves
One network state: the per-stateful-node local rows it is composed of.
std::vector< std::vector< T > > local
local[isf] is that node's state row
std::vector< RoutingStrategy > routing
sn.routing, per class.
Port of State.pollingInfo: the derived description of a polling controller.
std::vector< bool > has_sw
std::vector< std::size_t > ksw
std::vector< std::vector< T > > sw_pie
std::vector< Matrix< T > > sw_d0
std::vector< Matrix< T > > sw_d1
std::vector< bool > polled
The population the *PRIO disciplines actually share the server among.
std::vector< T > nir
nirprio when masked, the plain marginal otherwise
bool served
false when cls is not in the most urgent group
double ni
niprio when masked, the plain total otherwise
bool masked
whether the saturated-station mask was applied
Where node ind keeps its reply-block counters inside the local vars.
std::vector< std::size_t > slot
slot[r-1] = 0-based column, or npos
std::vector< std::size_t > classes
1-based calling classes holding a block
How a station's state row splits into [buffer | server | local vars].
std::size_t srvw
total server width
std::size_t bufw
buffer width, the only discipline-dependent part
std::vector< std::size_t > Ks
offset of class r's phase block
std::size_t nvar
local-variable width
std::vector< std::size_t > K
phases per class
One station of the network.
CdScaling< T > jdscaling
sn.jdscaling for this station: MATLAB's Station.ljdScaling, the JOINT dependence map eta_i(n),...
CdScaling< T > cdscaling
sn.cdscaling for this station: the class-dependence map, empty when unset.
One half of a synchronization: an event at a node, in a class.
std::size_t cls
1-based class index
T prob
routing probability, passive half
std::size_t rt_row
(isf-1)*nclasses + (r-1) of the active half
std::size_t rt_col
(jsf-1)*nclasses + (s-1) of this passive half
std::size_t node
1-based node index, or local for the dummy
bool statedep
The routing probability is a FUNCTION of the network state, so prob holds only the state-independent ...
One synchronization: an ACTIVE event and the PASSIVE event it drives.
The parameters of a Cache node, MATLAB's sn.nodeparam{ind} for a Cache.
std::vector< lang::TimingStrategy > timing
immediate or timed
std::vector< lang::Distrib< T > > firingproc
firing distribution per mode
std::vector< double > nmodeservers
servers per mode, may be infinite
std::vector< T > fireweight
weight among simultaneously enabled modes
std::vector< Matrix< T > > firing
firing[m](p,r): class-r tokens mode m moves to/from place p when it fires.
std::vector< Matrix< T > > enabling
enabling[m](p,r): class-r tokens of place p (0-based node) mode m needs.
std::vector< std::function< T(const std::vector< T > &)> > firingdep
Marking-dependent firing-rate multiplier g_m(marking); an empty entry is the unit multiplier.
std::vector< Matrix< T > > inhibiting
inhibiting[m](p,r): class-r tokens of p that BLOCK mode m (Inf = never).
std::vector< std::size_t > firingphases
phase count per mode, 0 when non-Markovian