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;
461 const std::size_t mslotA = mcA ?
sn.map_var_slot(ind, cls) : 0;
464 for (std::size_t t = 0; t < mcA->
pairs.size(); ++t)
465 pentry[t] =
static_cast<long>(mcA->
pairs[t].first) + 1 == hA
466 ? mcA->
V(mcA->
pairs[t].first, mcA->
pairs[t].second) : zero;
467 for (std::size_t t = 0; mcA->
single && t < mcA->
p; ++t)
468 pentry[t] =
static_cast<long>(t) + 1 == hA ? one : zero;
471 for (std::size_t kentry = 0; kentry < L.
K[cls - 1]; ++kentry) {
473 std::vector<T> buf(inspace.begin(), inspace.begin() + L.
bufw);
474 std::vector<T> srv(inspace.begin() + L.
bufw, inspace.begin() + L.
bufw + L.
srvw);
475 std::vector<T> var(inspace.begin() + L.
bufw + L.
srvw, inspace.end());
476 std::vector<std::vector<T>> cand;
477 std::vector<T> cand_prob;
481 std::vector<std::size_t> cand_start, cand_preempt;
486 if (sched == SchedStrategy::EXT) {
489 if (!std::isfinite(
sn.njobs()[cls - 1])) {
490 out.
space.push_back(inspace);
491 out.
rate.push_back(zero);
492 out.
prob.push_back(one);
498 if (sched == SchedStrategy::PS || sched == SchedStrategy::INF ||
499 sched == SchedStrategy::DPS || sched == SchedStrategy::GPS ||
500 sched == SchedStrategy::PSPRIO || sched == SchedStrategy::DPSPRIO ||
501 sched == SchedStrategy::GPSPRIO || sched == SchedStrategy::LPS) {
503 const std::size_t col = L.
Ks[cls - 1] + kentry;
504 std::size_t started = 0;
508 cand_prob.push_back(pentry[kentry]);
510 cand_prob.push_back(zero);
512 std::vector<T> row = buf;
513 row.insert(row.end(), srv.begin(), srv.end());
514 row.insert(row.end(), var.begin(), var.end());
516 cand_start.push_back(started);
517 cand_preempt.push_back(0);
518 }
else if (sched == SchedStrategy::POLLING) {
526 std::size_t srvclass = 0;
527 for (std::size_t r = 1; r <= R; ++r) {
529 for (std::size_t p = 0; p < L.
K[r - 1]; ++p)
531 if (tot > 0) { srvclass = r;
break; }
533 std::size_t pos = 0, swk = 0;
536 if (srvclass == 0 && swk == 0) {
537 std::vector<long> nbuf(R, 0);
538 for (std::size_t r = 0; r < R && r < L.
bufw; ++r)
544 polling_next(pinfo, pos, nbuf, R,
true, q, mode, budget);
545 srv[L.
Ks[cls - 1] + kentry] += one;
547 cand_start.push_back(cls);
550 cand_start.push_back(0);
552 cand_preempt.push_back(0);
553 cand_prob.push_back(pentry[kentry]);
554 std::vector<T> row = buf;
555 row.insert(row.end(), srv.begin(), srv.end());
556 row.insert(row.end(), var.begin(), var.end());
558 }
else if (sched == SchedStrategy::SIRO || sched == SchedStrategy::SEPT ||
559 sched == SchedStrategy::LEPT) {
565 srv[L.
Ks[cls - 1] + kentry] += one;
566 cand_start.push_back(cls);
569 cand_start.push_back(0);
571 cand_preempt.push_back(0);
572 cand_prob.push_back(pentry[kentry]);
573 std::vector<T> row = buf;
574 row.insert(row.end(), srv.begin(), srv.end());
575 row.insert(row.end(), var.begin(), var.end());
577 }
else if (state_detail::buffer_is_class_tag(sched)) {
587 srv[L.
Ks[cls - 1] + kentry] += one;
590 std::vector<T> row = buf;
591 row.insert(row.end(), srv.begin(), srv.end());
592 row.insert(row.end(), var.begin(), var.end());
594 cand_prob.push_back(pentry[kentry]);
595 cand_start.push_back(cls);
596 cand_preempt.push_back(0);
598 std::size_t slot = 0;
599 for (std::size_t b = 0; b < L.
bufw; ++b)
606 ? (ni < cap_i && nir_c < ccap)
608 if (slot > 0 && has_room) {
610 std::vector<T> row = buf;
611 row.insert(row.end(), srv.begin(), srv.end());
612 row.insert(row.end(), var.begin(), var.end());
614 cand_prob.push_back(pentry[kentry]);
615 cand_start.push_back(0);
616 cand_preempt.push_back(0);
636 cand.push_back(inspace);
637 cand_prob.push_back(pentry[kentry]);
638 cand_start.push_back(0);
639 cand_preempt.push_back(0);
645 }
else if (state_detail::buffer_is_tag_phase_pairs(sched)) {
652 srv[L.
Ks[cls - 1] + kentry] += one;
653 std::vector<T> row = buf;
654 row.insert(row.end(), srv.begin(), srv.end());
655 row.insert(row.end(), var.begin(), var.end());
657 cand_prob.push_back(pentry[kentry]);
658 cand_start.push_back(cls);
659 cand_preempt.push_back(0);
665 const bool prio_aware = sched == SchedStrategy::FCFSPRPRIO ||
666 sched == SchedStrategy::FCFSPIPRIO ||
667 sched == SchedStrategy::LCFSPRPRIO ||
668 sched == SchedStrategy::LCFSPIPRIO;
669 const bool lcfs_family = sched == SchedStrategy::LCFSPRPRIO ||
670 sched == SchedStrategy::LCFSPIPRIO;
683 const bool fcfs_never_preempts = sched == SchedStrategy::FCFSPR ||
684 sched == SchedStrategy::FCFSPI;
688 const bool resume = sched == SchedStrategy::LCFSPR ||
689 sched == SchedStrategy::LCFSPRPRIO ||
690 sched == SchedStrategy::FCFSPR ||
691 sched == SchedStrategy::FCFSPRPRIO;
692 bool can_preempt_any =
false;
693 for (std::size_t cp = 1; cp <= R && !fcfs_never_preempts; ++cp) {
700 const int pa =
sn.classes[cls - 1].prio;
701 const int pv =
sn.classes[cp - 1].prio;
702 if (lcfs_family ? (pa > pv) : (pa >= pv))
continue;
704 for (std::size_t pp = 0; pp < L.
K[cp - 1]; ++pp) {
705 const std::size_t vcol = L.
Ks[cp - 1] + pp;
707 if (busy <= 0)
continue;
708 can_preempt_any =
true;
709 std::vector<T> b2 = buf, s2 = srv;
711 s2[L.
Ks[cls - 1] + kentry] += one;
715 std::size_t slot = 0;
716 for (std::size_t b = 0; b < L.
bufw; ++b)
718 if (slot == 0)
continue;
722 std::vector<T> row = b2;
723 row.insert(row.end(), s2.begin(), s2.end());
724 row.insert(row.end(), var.begin(), var.end());
728 cand_start.push_back(cls);
729 cand_preempt.push_back(cp);
743 if ((prio_aware || fcfs_never_preempts) && !can_preempt_any) {
744 std::size_t slot = 0;
745 for (std::size_t b = 0; b < L.
bufw; ++b)
748 std::vector<T> b2 = buf;
751 std::vector<T> row = b2;
752 row.insert(row.end(), srv.begin(), srv.end());
753 row.insert(row.end(), var.begin(), var.end());
755 cand_prob.push_back(pentry[kentry]);
756 cand_start.push_back(0);
757 cand_preempt.push_back(0);
764 " discipline is not ported yet");
769 for (std::size_t c = 0; c < cand.size(); ++c) {
773 out.
space.push_back(cand[c]);
774 out.
rate.push_back(minus_one);
775 out.
prob.push_back(cand_prob[c]);
777 tag_last(out, c < cand_start.size() ? cand_start[c] : 0,
778 c < cand_preempt.size() ? cand_preempt[c] : 0);
798 std::size_t ist, std::size_t cls) {
800 const std::size_t n =
sn.phases_of(ist, cls);
802 if (d.
D0.rows() != n || d.
D1.rows() != n)
return std::make_pair(mu, phi);
803 for (std::size_t k = 0; k < n; ++k) {
804 const T dk = T(-d.
D0(k, k));
811 for (std::size_t j = 0; j < n; ++j) s += d.
D1(k, j);
814 return std::make_pair(mu, phi);
820 const std::vector<T>& s =
sn.stations[ist - 1].lldscaling;
824 if (!std::isfinite(n) || n >=
static_cast<double>(s.size()))
return s.back();
826 return s[
static_cast<std::size_t
>(n) - 1];
852 for (std::size_t h = 0; h < 2; ++h) {
855 const std::vector<T> v = fun(nir);
858 "cd_factor: the class-dependence map returned an empty scaling vector");
859 f = T(f * v[std::min(cls, v.size()) - 1]);
884 std::size_t cls,
double ni,
double S) {
885 const std::size_t R =
sn.nclasses;
890 const bool prio_aware = sched == SchedStrategy::PSPRIO ||
891 sched == SchedStrategy::DPSPRIO ||
892 sched == SchedStrategy::GPSPRIO;
893 if (!prio_aware || ni <= S)
return p;
894 double best = std::numeric_limits<double>::infinity();
895 for (std::size_t r = 0; r < R; ++r)
897 best = std::min(best,
static_cast<double>(
sn.classes[r].prio));
898 if (
static_cast<double>(
sn.classes[cls - 1].prio) != best) {
904 for (std::size_t r = 0; r < R; ++r) {
905 if (
static_cast<double>(
sn.classes[r].prio) != best)
914T
service_share(
const NetworkStruct<T>&
sn, std::size_t ist,
const Marginal<T>& m,
915 std::size_t cls,
double ni,
double S);
934 const std::vector<T>& inspace, std::size_t cls,
935 bool no_promote =
false) {
936 const std::size_t R =
sn.nclasses;
937 const std::size_t ist =
sn.nodes[ind - 1].station;
940 if (ist == 0)
throw InputError(
"after_event_station_dep: node is not a station");
942 if (sched == SchedStrategy::PAS || sched == SchedStrategy::OI)
945 const double S =
sn.stations[ist - 1].nservers;
947 std::vector<std::size_t> ph(R, 1), shift(R, 0);
948 for (std::size_t r = 0; r < R; ++r) {
958 const std::size_t markof = sched == SchedStrategy::EXT ?
sn.markidx_of(ist, cls) : 0;
959 std::size_t phcls = cls;
961 const std::size_t carrier =
sn.mark_carrier_of(ist);
962 if (carrier >= 1 && carrier <= R) phcls = carrier;
968 const std::pair<std::vector<T>, std::vector<T>> mp =
phase_rates(
sn, ist, cls);
969 const std::vector<T>& mu = mp.first;
970 const std::vector<T>& phi = mp.second;
974 for (std::size_t r = 0; r < R; ++r) ni += num_traits<T>::to_double(m.
nir[r]);
985 const bool cd_takes_prio =
986 pp.
masked && (sched == SchedStrategy::DPSPRIO || sched == SchedStrategy::GPSPRIO);
994 bool suppress_promote = no_promote;
996 const typename std::map<std::size_t, RetrialParam<T>>::const_iterator rit =
997 sn.retrialparam.find(ist);
998 if (rit !=
sn.retrialparam.end())
999 for (std::size_t r = 0; r < rit->second.retrial_proc.size(); ++r)
1000 if (!rit->second.retrial_proc[r].disabled) { suppress_promote =
true;
break; }
1003 for (std::size_t k = 0; k < L.
K[phcls - 1]; ++k) {
1004 std::vector<T> buf(inspace.begin(), inspace.begin() + L.
bufw);
1005 std::vector<T> srv(inspace.begin() + L.
bufw, inspace.begin() + L.
bufw + L.
srvw);
1006 std::vector<T> var(inspace.begin() + L.
bufw + L.
srvw, inspace.end());
1007 const std::size_t col = L.
Ks[phcls - 1] + k;
1009 const T kir = m.
kir[phcls - 1][k];
1011 if (sched == SchedStrategy::EXT) {
1018 if (!std::isfinite(
sn.njobs()[cls - 1])) {
1026 markof > 0 && markof <= d.
Dmark.size() ? d.
Dmark[markof - 1] : d.
D1;
1027 for (std::size_t ke = 0; ke < L.
K[phcls - 1]; ++ke) {
1028 const T arv = D1k(k, ke);
1030 std::vector<T> row = inspace;
1031 row[L.
bufw + L.
Ks[phcls - 1] + k] -= one;
1032 row[L.
bufw + L.
Ks[phcls - 1] + ke] += one;
1033 out.
space.push_back(row);
1034 out.
rate.push_back(T(lld * arv));
1035 out.
prob.push_back(one);
1038 }
else if (sched == SchedStrategy::INF || sched == SchedStrategy::PS ||
1039 sched == SchedStrategy::LPS || sched == SchedStrategy::DPS ||
1040 sched == SchedStrategy::GPS || sched == SchedStrategy::PSPRIO ||
1041 sched == SchedStrategy::DPSPRIO || sched == SchedStrategy::GPSPRIO) {
1046 const T rate = T(mu[k] * phi[k] * kir *
service_share(
sn, ist, m, cls, ni, S));
1047 std::vector<T> row = buf;
1048 row.insert(row.end(), srv.begin(), srv.end());
1049 row.insert(row.end(), var.begin(), var.end());
1050 out.
space.push_back(row);
1051 out.
rate.push_back(T(lld * rate));
1052 out.
prob.push_back(one);
1053 }
else if (state_detail::buffer_is_class_tag(sched) && sched != SchedStrategy::FCFS) {
1058 const bool has_waiting = ni > S && !suppress_promote;
1059 const T rate = T(mu[k] * phi[k] * kir);
1062 std::vector<T> row = buf;
1063 row.insert(row.end(), srv.begin(), srv.end());
1064 row.insert(row.end(), var.begin(), var.end());
1065 out.
space.push_back(row);
1066 out.
rate.push_back(T(lld * rate));
1067 out.
prob.push_back(one);
1071 std::size_t pos = L.
bufw;
1072 if (sched == SchedStrategy::LCFS) {
1078 for (std::size_t b = 0; b < L.
bufw; ++b)
1086 double best = std::numeric_limits<double>::infinity();
1087 for (std::size_t b = 0; b < L.
bufw; ++b) {
1089 if (v <= 0)
continue;
1090 const double p =
sn.classes[
static_cast<std::size_t
>(v) - 1].prio;
1091 if (p < best) best = p;
1093 if (std::isfinite(best))
1094 for (std::size_t b = 0; b < L.
bufw; ++b) {
1096 if (v <= 0)
continue;
1097 if (
sn.classes[
static_cast<std::size_t
>(v) - 1].prio != best)
continue;
1099 if (sched == SchedStrategy::LCFSPRIO)
break;
1102 if (pos == L.
bufw)
continue;
1104 std::vector<T> b2 = buf;
1105 if (sched == SchedStrategy::LCFS) {
1111 for (std::size_t b = pos; b > 0; --b) b2[b] = b2[b - 1];
1115 for (std::size_t ke = 0; ke < L.
K[hc - 1]; ++ke) {
1116 std::vector<T> s3 = srv;
1117 s3[L.
Ks[hc - 1] + ke] += one;
1118 std::vector<T> row = b2;
1119 row.insert(row.end(), s3.begin(), s3.end());
1120 row.insert(row.end(), var.begin(), var.end());
1121 out.
space.push_back(row);
1122 out.
rate.push_back(T(lld * rate * pentry[ke]));
1123 out.
prob.push_back(one);
1126 }
else if (state_detail::buffer_is_class_tag(sched)) {
1136 std::vector<T> var2 = var;
1137 bool holds_reply =
false;
1138 if (
sn.replyblock.size() >= ind &&
sn.replyblock[ind - 1].size() >= cls &&
1139 sn.replyblock[ind - 1][cls - 1]) {
1141 const std::size_t sl = ri.
slot[cls - 1];
1142 if (sl !=
static_cast<std::size_t
>(-1) && sl < var2.size()) {
1148 const bool has_waiting = ni > (S - nb) && !suppress_promote && !holds_reply;
1152 const bool pairD = mcD && !mcD->single;
1153 const std::size_t mslotD = mcD ?
sn.map_var_slot(ind, cls) : 0;
1154 const std::vector<T> var2_in = var2;
1155 for (std::size_t kd = 0; kd < L.
K[cls - 1]; ++kd) {
1156 if (pairD && kd > 0)
break;
1157 const T rate = pairD ? T(mcD->done[k] * kir) : T(d.
D1(k, kd) * kir);
1160 std::vector<T> s2 = srv;
1163 std::vector<T> row = buf;
1164 row.insert(row.end(), s2.begin(), s2.end());
1165 row.insert(row.end(), var2.begin(), var2.end());
1166 out.
space.push_back(row);
1167 out.
rate.push_back(T(lld * rate));
1168 out.
prob.push_back(one);
1175 if (headv <= 0)
continue;
1176 const std::size_t hc =
static_cast<std::size_t
>(headv);
1177 std::vector<T> b2(L.
bufw, zero);
1178 for (std::size_t b = 1; b < L.
bufw; ++b) b2[b] = buf[b - 1];
1182 const std::size_t mslotP = mcP ?
sn.map_var_slot(ind, hc) : 0;
1185 for (std::size_t t = 0; t < mcP->
pairs.size(); ++t)
1186 pentry[t] =
static_cast<long>(mcP->
pairs[t].first) + 1 == hP
1187 ? mcP->
V(mcP->
pairs[t].first, mcP->
pairs[t].second) : zero;
1188 for (std::size_t t = 0; mcP->
single && t < mcP->
p; ++t)
1189 pentry[t] =
static_cast<long>(t) + 1 == hP ? one : zero;
1191 for (std::size_t ke = 0; ke < L.
K[hc - 1]; ++ke) {
1193 std::vector<T> s3 = s2;
1194 s3[L.
Ks[hc - 1] + ke] += one;
1195 std::vector<T> var3 = var2;
1198 std::vector<T> row = b2;
1199 row.insert(row.end(), s3.begin(), s3.end());
1200 row.insert(row.end(), var3.begin(), var3.end());
1201 const T r3 = T(lld * rate * pentry[ke]);
1202 out.
space.push_back(row);
1203 out.
rate.push_back(r3);
1211 }
else if (sched == SchedStrategy::POLLING) {
1216 const T rate = T(mu[k] * phi[k] * kir);
1218 std::size_t pos = 0, swk = 0;
1222 if (swk != 0)
continue;
1223 std::vector<long> nbuf(R, 0);
1224 for (std::size_t r = 0; r < R && r < L.
bufw; ++r)
1229 switch (pinfo.
ptype) {
1232 goon = nbuf[cls - 1] > 0;
1240 goon = ctrnext > 0 && nbuf[cls - 1] > 0;
1244 goon = nbuf[cls - 1] > ctr;
1247 std::size_t q = cls;
1249 long budget = ctrnext;
1250 if (!goon)
polling_next(pinfo, cls, nbuf, R,
false, q, mode, budget);
1251 std::vector<std::vector<T>> rows;
1252 std::vector<T> probs;
1253 polling_land(
sn, ist, pinfo, q, mode, budget, buf, srv, var, L, rows, probs);
1254 for (std::size_t j = 0; j < rows.size(); ++j) {
1255 out.
space.push_back(rows[j]);
1256 out.
rate.push_back(T(lld * rate * probs[j]));
1257 out.
prob.push_back(one);
1260 tag_last(out, mode == 1 ? q : 0, 0);
1262 }
else if (state_detail::buffer_is_tag_phase_pairs(sched)) {
1268 const T rate = T(mu[k] * phi[k] * kir);
1270 const bool prio_aware = sched == SchedStrategy::FCFSPRPRIO ||
1271 sched == SchedStrategy::FCFSPIPRIO ||
1272 sched == SchedStrategy::LCFSPRPRIO ||
1273 sched == SchedStrategy::LCFSPIPRIO;
1274 const bool lcfs = sched == SchedStrategy::LCFSPR ||
1275 sched == SchedStrategy::LCFSPI ||
1276 sched == SchedStrategy::LCFSPRPRIO ||
1277 sched == SchedStrategy::LCFSPIPRIO;
1281 const bool resume = sched == SchedStrategy::LCFSPR ||
1282 sched == SchedStrategy::LCFSPRPRIO ||
1283 sched == SchedStrategy::FCFSPR ||
1284 sched == SchedStrategy::FCFSPRPRIO;
1286 std::size_t pos = L.
bufw;
1287 if (ni > S && !suppress_promote && L.
bufw >= 2) {
1288 double best = std::numeric_limits<double>::infinity();
1295 for (std::size_t b = 0; b + 1 < L.
bufw; b += 2) {
1297 if (v <= 0)
continue;
1298 const double p =
sn.classes[
static_cast<std::size_t
>(v) - 1].prio;
1299 if (p < best) best = p;
1301 for (std::size_t b = 0; b + 1 < L.
bufw; b += 2) {
1303 if (v <= 0)
continue;
1304 if (prio_aware &&
sn.classes[
static_cast<std::size_t
>(v) - 1].prio != best)
1313 if (pos == L.
bufw) {
1314 std::vector<T> row = buf;
1315 row.insert(row.end(), srv.begin(), srv.end());
1316 row.insert(row.end(), var.begin(), var.end());
1317 out.
space.push_back(row);
1318 out.
rate.push_back(T(lld * rate));
1319 out.
prob.push_back(one);
1323 const std::size_t kst =
1325 if (hc == 0 || hc > R || kst == 0 || kst > L.
K[hc - 1])
1326 throw InputError(
"after_event_station_dep: station '" +
1327 sn.stations[ist - 1].name +
1328 "' holds a waiting job whose [class, phase] pair is malformed");
1335 std::vector<T> b2(L.
bufw, zero);
1336 for (std::size_t b = 2; b <= pos + 1; ++b) b2[b] = buf[b - 2];
1337 for (std::size_t b = pos + 2; b < L.
bufw; ++b) b2[b] = buf[b];
1339 std::vector<T> s3 = srv;
1340 s3[L.
Ks[hc - 1] + kst - 1] += one;
1341 std::vector<T> row = b2;
1342 row.insert(row.end(), s3.begin(), s3.end());
1343 row.insert(row.end(), var.begin(), var.end());
1344 out.
space.push_back(row);
1345 out.
rate.push_back(T(lld * rate));
1346 out.
prob.push_back(one);
1350 for (std::size_t ke = 0; ke < L.
K[hc - 1]; ++ke) {
1351 std::vector<T> s3 = srv;
1352 s3[L.
Ks[hc - 1] + ke] += one;
1353 std::vector<T> row = b2;
1354 row.insert(row.end(), s3.begin(), s3.end());
1355 row.insert(row.end(), var.begin(), var.end());
1356 out.
space.push_back(row);
1357 out.
rate.push_back(T(lld * rate * pentry[ke]));
1358 out.
prob.push_back(one);
1362 }
else if (state_detail::buffer_is_per_class_count(sched)) {
1367 const T rate = T(mu[k] * phi[k] * kir);
1369 for (std::size_t r = 0; r < R; ++r) waiting += num_traits<T>::to_double(buf[r]);
1370 if (waiting <= 0 || suppress_promote) {
1371 std::vector<T> row = buf;
1372 row.insert(row.end(), srv.begin(), srv.end());
1373 row.insert(row.end(), var.begin(), var.end());
1374 out.
space.push_back(row);
1375 out.
rate.push_back(T(lld * rate));
1376 out.
prob.push_back(one);
1379 for (std::size_t r = 1; r <= R; ++r) {
1381 if (nb <= 0)
continue;
1383 for (std::size_t ke = 0; ke < L.
K[r - 1]; ++ke) {
1384 std::vector<T> b2 = buf, s2 = srv;
1386 s2[L.
Ks[r - 1] + ke] += one;
1387 std::vector<T> row = b2;
1388 row.insert(row.end(), s2.begin(), s2.end());
1389 row.insert(row.end(), var.begin(), var.end());
1390 out.
space.push_back(row);
1391 out.
rate.push_back(T(lld * rate));
1399 " discipline is not ported yet");
1417 std::size_t cls,
double ni,
double S) {
1418 const std::size_t R =
sn.nclasses;
1428 if (!p.
served)
return zero;
1429 const std::vector<T>& nir = p.
nir;
1430 const double nieff = p.
ni;
1432 if (sched == SchedStrategy::PS || sched == SchedStrategy::LPS ||
1433 sched == SchedStrategy::PSPRIO)
1435 if (sched == SchedStrategy::DPS || sched == SchedStrategy::GPS ||
1436 sched == SchedStrategy::DPSPRIO || sched == SchedStrategy::GPSPRIO) {
1439 "state_events: multi-server DPS/GPS stations are not supported");
1440 const bool dps = sched == SchedStrategy::DPS || sched == SchedStrategy::DPSPRIO;
1441 const std::vector<T>& w =
sn.stations[ist - 1].schedparam;
1443 for (std::size_t r = 0; r < R; ++r) wsum += w[r];
1445 for (std::size_t r = 0; r < R; ++r) {
1449 denom += T(w[r] / wsum * nr);
1451 const T
nc = nir[cls - 1];
1454 const T sh = T((w[cls - 1] / wsum) / denom);
1455 return dps ? sh : T(sh /
nc);
1472 const std::vector<T>& inspace, std::size_t cls) {
1473 const std::size_t R =
sn.nclasses;
1474 const std::size_t ist =
sn.nodes[ind - 1].station;
1477 if (ist == 0)
throw InputError(
"after_event_station_phase: node is not a station");
1479 const double S =
sn.stations[ist - 1].nservers;
1481 std::vector<std::size_t> ph(R, 1), shift(R, 0);
1482 for (std::size_t r = 0; r < R; ++r) {
1490 for (std::size_t r = 0; r < R; ++r) ni += num_traits<T>::to_double(m.
nir[r]);
1498 if (d.
D0.rows() != L.
K[cls - 1])
return out;
1501 for (std::size_t k = 0; k < L.
K[cls - 1]; ++k) {
1503 for (std::size_t kd = 0; kd < L.
K[cls - 1]; ++kd) {
1504 if (kd == k)
continue;
1505 std::vector<T> row = inspace;
1506 row[L.
bufw + L.
Ks[cls - 1] + k] -= one;
1507 row[L.
bufw + L.
Ks[cls - 1] + kd] += one;
1511 out.
space.push_back(row);
1512 out.
rate.push_back(T(lld * d.
D0(k, kd) * m.
kir[cls - 1][k] * share));
1513 out.
prob.push_back(one);
1531 const std::vector<T>& inspace, std::size_t cls,
1532 const T& impatience_mu) {
1533 const std::size_t R =
sn.nclasses;
1534 const std::size_t ist =
sn.nodes[ind - 1].station;
1536 if (ist == 0)
throw InputError(
"after_event_station_renege: node is not a station");
1539 std::vector<std::size_t> ph(R, 1), shift(R, 0);
1540 for (std::size_t r = 0; r < R; ++r) {
1547 if (waiting <= 0)
return out;
1550 std::size_t slot = L.
bufw;
1551 for (std::size_t b = 0; b < L.
bufw; ++b)
1552 if (inspace[b] == tag) { slot = b;
break; }
1553 if (slot == L.
bufw)
return out;
1555 std::vector<T> row = inspace;
1556 for (std::size_t b = slot; b > 0; --b) row[b] = row[b - 1];
1558 out.
space.push_back(row);
1583 const std::vector<T>& inspace, std::size_t cls,
1584 const T& retrial_mu,
bool constant_policy =
false) {
1585 const std::size_t R =
sn.nclasses;
1586 const std::size_t ist =
sn.nodes[ind - 1].station;
1589 if (ist == 0)
throw InputError(
"after_event_station_retry: node is not a station");
1591 const double S =
sn.stations[ist - 1].nservers;
1593 std::vector<std::size_t> ph(R, 1), shift(R, 0);
1594 for (std::size_t r = 0; r < R; ++r) {
1603 if (orbit <= 0 || occ >= S)
return out;
1606 std::size_t slot = L.
bufw;
1607 for (std::size_t b = 0; b < L.
bufw; ++b)
1608 if (inspace[b] == tag) { slot = b;
break; }
1609 if (slot == L.
bufw)
return out;
1612 const T agg = constant_policy ? retrial_mu
1614 for (std::size_t ke = 0; ke < L.
K[cls - 1]; ++ke) {
1616 std::vector<T> row = inspace;
1617 for (std::size_t b = slot; b > 0; --b) row[b] = row[b - 1];
1619 row[L.
bufw + L.
Ks[cls - 1] + ke] += one;
1620 out.
space.push_back(row);
1621 out.
rate.push_back(T(agg * pentry[ke]));
1622 out.
prob.push_back(one);
1648 const std::vector<T>& inspace,
bool up,
1651 if (inspace.empty() || !
sn.has_breakdown_node(ind))
return out;
1655 if ((up && status != 0) || (!up && status != 1))
return out;
1656 std::vector<T> row = inspace;
1665 out.
space.push_back(row);
1666 out.
rate.push_back(rate);
1686 const std::vector<T>& inspace,
EventType event,
1688 const std::size_t R =
sn.nclasses;
1690 if (event != EventType::ARV)
return out;
1691 if (inspace.size() < R)
1692 throw InputError(
"after_event_fork: the Fork state row at node '" +
sn.nodes[ind - 1].name +
1693 "' is narrower than the class set");
1694 std::vector<T> row = inspace;
1698 out.
space.push_back(row);
1722 const std::vector<T>& inspace,
EventType event,
1724 const std::size_t R =
sn.nclasses;
1727 if (inspace.size() < R)
1728 throw InputError(
"after_event_join: the Join state row at node '" +
sn.nodes[ind - 1].name +
1729 "' is narrower than the class set");
1730 const std::size_t off = inspace.size() - R;
1732 if (event == EventType::ARV) {
1733 std::vector<T> row = inspace;
1734 row[off + cls - 1] += one;
1735 out.
space.push_back(row);
1737 out.
prob.push_back(one);
1740 if (event != EventType::DEP)
return out;
1742 const typename std::map<std::size_t, FjJoinParam>::const_iterator jit =
1743 sn.fjjoinparam.find(ind);
1744 const FjJoinParam* fjp = jit ==
sn.fjjoinparam.end() ? 0 : &jit->second;
1747 for (std::size_t x = 0; x < fjp->
origclasses.size(); ++x) {
1748 const std::map<std::size_t, std::vector<std::vector<std::size_t>>>::const_iterator ait =
1750 if (ait == fjp->
auxmatrix.end())
continue;
1751 for (std::size_t b = 0; b < ait->second.size(); ++b)
1752 for (std::size_t t = 0; t < ait->second[b].size(); ++t)
1753 if (ait->second[b][t] == cls)
return out;
1761 std::vector<T> row = inspace;
1762 row[off + cls - 1] -= one;
1763 out.
space.push_back(row);
1764 out.
rate.push_back(imm);
1765 out.
prob.push_back(one);
1768 if (!fjp)
return out;
1769 const std::map<std::size_t, std::vector<std::vector<std::size_t>>>::const_iterator ait =
1771 const std::map<std::size_t, std::vector<std::size_t>>::const_iterator rit =
1774 const std::vector<std::vector<std::size_t>>& aux = ait->second;
1775 const std::vector<std::size_t>& req = rit->second;
1776 if (aux.empty())
return out;
1777 const std::size_t B = aux.size(), Tt = aux[0].size();
1778 for (std::size_t t = 0; t < Tt; ++t) {
1779 bool complete =
true;
1780 for (std::size_t b = 0; b < B && complete; ++b) {
1781 const std::size_t a = aux[b][t];
1782 const double need = b < req.size() ?
static_cast<double>(req[b]) : 1.0;
1785 if (!complete)
continue;
1786 std::vector<T> row = inspace;
1787 for (std::size_t b = 0; b < B; ++b) {
1788 const std::size_t a = aux[b][t];
1789 const long need = b < req.size() ?
static_cast<long>(req[b]) : 1;
1792 out.
space.push_back(row);
1793 out.
rate.push_back(imm);
1794 out.
prob.push_back(one);
1810void rr_advance_row(
const NetworkStruct<T>&
sn, std::size_t ind, std::size_t cls,
1811 std::vector<std::vector<T>>& rows);
1826 const std::vector<T>& inspace,
EventType event,
1829 const std::size_t R =
sn.nclasses;
1830 if (inspace.size() < R)
return out;
1832 if (event == EventType::ARV) {
1833 std::vector<T> row = inspace;
1834 row[cls - 1] = T(row[cls - 1] + one);
1835 out.
space.push_back(row);
1838 out.
prob.push_back(one);
1841 if (event == EventType::DEP) {
1843 std::vector<T> row = inspace;
1844 row[cls - 1] = T(row[cls - 1] - one);
1845 out.
space.push_back(row);
1847 out.
prob.push_back(one);
1863 std::vector<std::vector<T>>& rows) {
1864 if (
sn.rr_var_slot(ind, cls) == 0)
return;
1865 const std::size_t w =
sn.nvars_of(ind);
1867 for (std::size_t i = 0; i < rows.size(); ++i) {
1868 if (rows[i].size() < w)
continue;
1869 std::vector<T> var(rows[i].end() - w, rows[i].end());
1870 sn.rr_advance(ind, cls, var);
1871 std::copy(var.begin(), var.end(), rows[i].end() - w);
1888 const std::vector<T>& buf,
const std::vector<T>& srv, std::size_t s,
1889 std::size_t t,
const T& w, std::vector<
PoolStart<T>>& out) {
1890 const std::vector<std::size_t>& ps = pool.
pools[s - 1];
1892 while (k < ps.size() && ps[k] != t) ++k;
1893 const std::vector<T>& a = pool.
alpha[s - 1][k];
1894 for (std::size_t j = 0; j < a.size(); ++j) {
1906 const std::vector<T>& buf,
const std::vector<T>& srv,
1908 const std::size_t R =
sn.nclasses;
1910 std::vector<PoolStart<T>> out;
1911 if (sched == SchedStrategy::SIRO) {
1913 for (std::size_t s = 0; s < R; ++s)
1919 for (std::size_t s = 0; s < R; ++s) {
1921 if (!pool.
compat[t - 1][s] || bs <= 0)
continue;
1922 std::vector<T> b = buf;
1928 std::vector<std::size_t> pos;
1929 for (std::size_t p = 0; p < buf.size(); ++p) {
1931 if (c >= 1 &&
static_cast<std::size_t
>(c) <= R && pool.
compat[t - 1][c - 1]) pos.push_back(p);
1937 const auto cls_at = [&](std::size_t p) {
1940 if (sched == SchedStrategy::HOL || sched == SchedStrategy::LCFSPRIO) {
1941 int best =
sn.classes[cls_at(pos[0]) - 1].prio;
1942 for (std::size_t i = 1; i < pos.size(); ++i)
1943 best = std::min(best,
sn.classes[cls_at(pos[i]) - 1].prio);
1944 std::vector<std::size_t> keep;
1945 for (std::size_t i = 0; i < pos.size(); ++i)
1946 if (
sn.classes[cls_at(pos[i]) - 1].prio == best) keep.push_back(pos[i]);
1950 const bool lcfs = sched == SchedStrategy::LCFS || sched == SchedStrategy::LCFSPRIO;
1951 const std::size_t p = lcfs ? pos.front() : pos.back();
1952 const std::size_t s = cls_at(p);
1953 std::vector<T> b(1, zero);
1954 for (std::size_t q = 0; q < buf.size(); ++q)
1955 if (q != p) b.push_back(buf[q]);
1956 pool_start(pool, Ks, b, srv, s, t, one, out);
1976 const std::vector<T>& inspace,
EventType event,
1979 const std::size_t R =
sn.nclasses;
1980 const std::size_t ist =
sn.nodes[ind - 1].station;
1985 const std::vector<T> buf(inspace.begin(), inspace.begin() + L.
bufw);
1986 const std::vector<T> srv(inspace.begin() + L.
bufw, inspace.begin() + L.
bufw + L.
srvw);
1987 const std::vector<T> var(inspace.begin() + L.
bufw + L.
srvw, inspace.end());
1988 const std::vector<std::size_t>& myp = pool.
pools[cls - 1];
1990 const auto emit = [&](
const std::vector<T>& b,
const std::vector<T>& s,
const std::vector<T>& v,
1991 const T& rate,
const T& prob, std::size_t started) {
1992 std::vector<T> row = b;
1993 row.insert(row.end(), s.begin(), s.end());
1994 row.insert(row.end(), v.begin(), v.end());
1995 out.
space.push_back(row);
1996 out.
rate.push_back(rate);
1997 out.
prob.push_back(prob);
2000 if (myp.empty())
return out;
2001 if (event == EventType::ARV) {
2006 (ni >=
sn.cap[ist - 1] || nir >=
sn.classcap[ist - 1][cls - 1])) {
2012 std::vector<double> busy(pool.
ntypes, 0.0);
2013 for (std::size_t r = 0; r < R; ++r)
2014 for (std::size_t k = 0; k < pool.
pools[r].size(); ++k)
2015 for (std::size_t j = 0; j < pool.
len[r][k]; ++j)
2016 busy[pool.
pools[r][k] - 1] +=
2018 std::vector<std::size_t> cand;
2019 for (std::size_t k = 0; k < myp.size(); ++k)
2020 if (busy[myp[k] - 1] < pool.
count[myp[k] - 1]) cand.push_back(myp[k]);
2023 std::vector<T> b = buf;
2024 if (sched == SchedStrategy::SIRO) {
2027 std::size_t slot = 0;
2028 for (std::size_t q = 0; q < b.size(); ++q)
2036 emit(b, srv, var, minus_one, one, 0);
2040 std::vector<std::size_t> choice(1, cand[0]);
2041 std::vector<T> pchoice(1, one);
2042 std::vector<T> varc = var;
2043 if (cand.size() > 1) {
2046 for (std::size_t q = 0; q < pool.
alfsorder.size(); ++q)
2047 if (std::find(cand.begin(), cand.end(), pool.
alfsorder[q]) != cand.end()) {
2054 for (std::size_t q = 1; q < cand.size(); ++q)
2055 if (pool.
fsfrate[cand[q] - 1][cls - 1] > pool.
fsfrate[cand[at] - 1][cls - 1]) at = q;
2056 choice[0] = cand[at];
2066 const std::size_t vp = varc.size() - 1;
2067 const std::size_t pid =
2069 std::vector<std::size_t> ord = pool.
perms.at(pid - 1);
2070 for (std::size_t q = 0; q < ord.size(); ++q)
2071 if (std::find(cand.begin(), cand.end(), ord[q]) != cand.end()) {
2073 ord.erase(ord.begin() +
static_cast<std::ptrdiff_t
>(q));
2074 ord.push_back(choice[0]);
2084 std::vector<PoolStart<T>> starts;
2085 for (std::size_t c = 0; c < choice.size(); ++c)
2087 for (std::size_t i = 0; i < starts.size(); ++i)
2088 emit(starts[i].buf, starts[i].srv, varc, minus_one, starts[i].p, cls);
2092 for (std::size_t k = 0; k < myp.size(); ++k) {
2093 const std::size_t t = myp[k];
2094 for (std::size_t j = 0; j < pool.
len[cls - 1][k]; ++j) {
2095 const std::size_t col = L.
Ks[cls - 1] + pool.
off[cls - 1][k] + j;
2096 const T nj = srv[col];
2098 if (event == EventType::DEP) {
2099 const T ex = pool.
exit[cls - 1][k][j];
2101 std::vector<T> sd = srv;
2103 const std::vector<PoolStart<T>> nx =
2105 for (std::size_t b = 0; b < nx.size(); ++b)
2106 emit(nx[b].buf, nx[b].srv, var, T(ex * nj * nx[b].p), one, nx[b].cls);
2107 }
else if (event == EventType::PHASE) {
2109 for (std::size_t jd = 0; jd < pool.
len[cls - 1][k]; ++jd) {
2111 std::vector<T> sp = srv;
2113 sp[L.
Ks[cls - 1] + pool.
off[cls - 1][k] + jd] += one;
2114 emit(buf, sp, var, T(D0(j, jd) * nj), one, 0);
2125 const std::vector<T>& inspace,
EventType event,
2126 std::size_t cls,
bool no_promote =
false,
2133 if ((event == EventType::DEP || event == EventType::PHASE) && !inspace.empty() &&
2135 const std::size_t ist =
sn.nodes[ind - 1].station;
2136 const T down =
sn.breakdownparam.at(ist).down_rate_of(cls);
2138 const T upr =
sn.rates(ist - 1, cls - 1);
2140 if (!std::isfinite(upd) || !(upd > 0.0))
2141 throw InputError(
"Station '" +
sn.nodes[ind - 1].name +
2142 "' declares a down-server service rate for class '" +
2143 sn.classes[cls - 1].name +
2144 "' but has no finite up-server service rate to rescale.");
2148 std::vector<T> upspace = inspace;
2152 const T scale = T(down / upr);
2153 for (std::size_t i = 0; i < o.
space.size(); ++i) {
2160 if ((event == EventType::ARV || event == EventType::DEP || event == EventType::PHASE) &&
2161 !
sn.ctmcpool.empty() &&
sn.ctmcpool.count(ind))
2164 case EventType::ARV:
2169 if (
sn.issignal.size() >= cls &&
sn.issignal[cls - 1]) {
2170 if (!(
sn.signaltype.size() >= cls &&
2180 case EventType::DEP: {
2200 if (ind <=
sn.isbasblocking.size() &&
sn.isbasblocking[ind - 1] &&
2202 !out.
space.empty()) {
2209 for (std::size_t i = 0; i < out.
space.size(); ++i) {
2216 case EventType::PHASE:
2218 case EventType::RENEGE:
2220 case EventType::RETRY:
2222 case EventType::SWITCH:
2224 case EventType::FAILURE:
2226 case EventType::REPAIR:
2228 case EventType::LOCAL:
2233 " event is not ported yet");
2255 const std::vector<T>& inspace,
EventType event,
2258 if (event != EventType::PHASE)
return out;
2259 const typename std::map<std::size_t, TransitionParam<T>>::const_iterator it =
2260 sn.transparam.find(ind);
2261 if (it ==
sn.transparam.end())
2262 throw InputError(
"after_event_transition: node has no TransitionParam");
2264 if (mode == 0 || mode > tp.
nmodes)
2265 throw InputError(
"after_event_transition: mode index is out of range");
2268 std::vector<std::size_t> fK(tp.
nmodes, 1), fKs(tp.
nmodes, 0);
2269 std::size_t tot = 0;
2270 for (std::size_t m = 0; m < tp.
nmodes; ++m) {
2275 if (fK[mode - 1] <= 1)
return out;
2277 tp.
firingproc[mode - 1].D0.rows() != fK[mode - 1])
2281 for (std::size_t k = 0; k < fK[mode - 1]; ++k) {
2282 const std::size_t idx = tp.
nmodes + fKs[mode - 1] + k;
2283 const T cnt = inspace[idx];
2285 for (std::size_t kd = 0; kd < fK[mode - 1]; ++kd) {
2286 if (kd == k)
continue;
2288 std::vector<T> row = inspace;
2290 row[tp.
nmodes + fKs[mode - 1] + kd] += one;
2291 out.
space.push_back(row);
2292 out.
rate.push_back(T(D0(k, kd) * cnt));
2293 out.
prob.push_back(one);
2315 const std::vector<T>& inspace,
EventType event, std::size_t cls,
2316 bool no_promote =
false,
2318 if (ind == 0 || ind >
sn.nodes.size())
2319 throw InputError(
"after_event: node index is out of range");
2330 const bool cls_is_mode = (nd.
nodetype == NodeType::Transition &&
event == EventType::PHASE);
2331 if (!cls_is_mode && (cls == 0 || cls >
sn.nclasses))
2332 throw InputError(
"after_event: class index is out of range");
2337 if (
sn.isfjaugmented && nd.
nodetype == NodeType::Join)
2350 if (nd.
nodetype == NodeType::Transition)
2355 "' are not ported yet");
2358namespace signal_detail {
2362void merge_states(std::vector<std::vector<T>>& sp, std::vector<T>& pr) {
2363 std::vector<std::vector<T>> us;
2365 for (std::size_t i = 0; i < sp.size(); ++i) {
2366 std::size_t at = us.size();
2367 for (std::size_t j = 0; j < us.size(); ++j)
2368 if (us[j] == sp[i]) { at = j;
break; }
2369 if (at == us.size()) {
2370 us.push_back(sp[i]);
2371 up.push_back(pr[i]);
2393 std::vector<std::size_t> kv;
2395 if (
sn.signalremdist.size() < cls ||
sn.signalremdist[cls - 1].empty()) {
2398 return std::make_pair(kv, kp);
2400 const std::vector<T>& d =
sn.signalremdist[cls - 1];
2402 for (std::size_t b = 0; b < ntot; ++b) {
2418 return std::make_pair(kv, kp);
2421 for (std::size_t i = 0; i < kp.size(); ++i) tot += kp[i];
2423 for (std::size_t i = 0; i < kp.size(); ++i) kp[i] = T(kp[i] / tot);
2424 return std::make_pair(kv, kp);
2442 const std::vector<T>& inspace, std::size_t cls) {
2443 const std::size_t R =
sn.nclasses;
2444 const std::size_t ist =
sn.nodes[ind - 1].station;
2448 if (ist == 0)
throw InputError(
"after_event_station_signal: node is not a station");
2451 const double S =
sn.stations[ist - 1].nservers;
2453 std::vector<std::size_t> ph(R, 1), shift(R, 0);
2454 for (std::size_t r = 0; r < R; ++r) {
2463 std::vector<T> row(L.
bufw + L.
srvw, zero);
2464 row.insert(row.end(), inspace.end() - L.
nvar, inspace.end());
2465 out.
space.push_back(row);
2466 out.
rate.push_back(minus_one);
2467 out.
prob.push_back(one);
2473 std::vector<std::size_t> tgt;
2474 const std::size_t declared =
sn.signaltarget.size() >= cls ?
sn.signaltarget[cls - 1] : 0;
2475 if (declared >= 1) {
2476 tgt.push_back(declared);
2478 for (std::size_t r = 1; r <= R; ++r)
2479 if (
sn.issignal.size() < r || !
sn.issignal[r - 1]) tgt.push_back(r);
2481 std::vector<std::size_t> elig;
2482 std::size_t ntot = 0;
2483 for (std::size_t i = 0; i < tgt.size(); ++i) {
2486 elig.push_back(tgt[i]);
2487 ntot +=
static_cast<std::size_t
>(nr);
2492 out.
space.push_back(inspace);
2493 out.
rate.push_back(minus_one);
2494 out.
prob.push_back(one);
2499 ?
sn.signalrempolicy[cls - 1]
2501 const bool ordered = state_detail::buffer_is_class_tag(sched) ||
2502 state_detail::buffer_is_tag_phase_pairs(sched);
2503 const bool paired = state_detail::buffer_is_tag_phase_pairs(sched);
2504 const bool counted = state_detail::buffer_is_per_class_count(sched);
2505 const std::pair<std::vector<std::size_t>, std::vector<T>> pmf =
2508 std::vector<std::vector<T>> acc;
2509 std::vector<T> accp;
2510 for (std::size_t ik = 0; ik < pmf.first.size(); ++ik) {
2512 std::vector<std::vector<T>> cur(1, inspace);
2513 std::vector<T> curp(1, one);
2516 for (std::size_t step = 0; step < pmf.first[ik]; ++step) {
2517 std::vector<std::vector<T>> nxt;
2518 std::vector<T> nxtp;
2519 for (std::size_t row = 0; row < cur.size(); ++row) {
2520 std::vector<T> buf(cur[row].begin(), cur[row].begin() + L.
bufw);
2521 std::vector<T> srv(cur[row].begin() + L.
bufw,
2522 cur[row].begin() + L.
bufw + L.
srvw);
2523 const std::vector<T> var(cur[row].begin() + L.
bufw + L.
srvw, cur[row].end());
2526 std::vector<std::size_t> wpos, wcls, wwt;
2528 for (std::size_t b = 0; b < L.
bufw; b += paired ? 2 : 1) {
2530 if (v <= 0)
continue;
2532 for (std::size_t e = 0; e < elig.size(); ++e)
2533 if (elig[e] ==
static_cast<std::size_t
>(v)) ok =
true;
2536 wcls.push_back(
static_cast<std::size_t
>(v));
2539 }
else if (counted) {
2540 for (std::size_t e = 0; e < elig.size(); ++e) {
2541 const std::size_t r = elig[e];
2542 if (r > L.
bufw)
continue;
2544 if (v <= 0)
continue;
2545 wpos.push_back(r - 1);
2547 wwt.push_back(
static_cast<std::size_t
>(v));
2551 std::vector<std::size_t> scls, sph, scnt;
2552 for (std::size_t e = 0; e < elig.size(); ++e) {
2553 const std::size_t r = elig[e];
2554 for (std::size_t p = 0; p < L.
K[r - 1]; ++p) {
2556 if (v <= 0)
continue;
2559 scnt.push_back(
static_cast<std::size_t
>(v));
2562 std::size_t nwait = 0, nsrv = 0;
2563 for (std::size_t i = 0; i < wwt.size(); ++i) nwait += wwt[i];
2564 for (std::size_t i = 0; i < scnt.size(); ++i) nsrv += scnt[i];
2565 if (nwait == 0 && nsrv == 0) {
2567 nxt.push_back(cur[row]);
2568 nxtp.push_back(curp[row]);
2572 std::vector<std::vector<T>> sp;
2574 const bool age_ordered =
2577 if (age_ordered && nwait > 0) {
2580 std::size_t pick = 0;
2581 for (std::size_t i = 0; i < wpos.size(); ++i)
2583 : wpos[i] < wpos[pick])
2585 std::vector<T> b2 = buf;
2586 b2.erase(b2.begin() + wpos[pick], b2.begin() + wpos[pick] + (paired ? 2 : 1));
2587 b2.insert(b2.begin(), paired ? 2 : 1, zero);
2588 std::vector<T> nr = b2;
2589 nr.insert(nr.end(), srv.begin(), srv.end());
2590 nr.insert(nr.end(), var.begin(), var.end());
2599 : (nwait > 0 ? nwait : nsrv);
2600 for (std::size_t i = 0; i < wpos.size(); ++i) {
2601 std::vector<T> b2 = buf;
2603 b2[wcls[i] - 1] -= one;
2605 b2.erase(b2.begin() + wpos[i],
2606 b2.begin() + wpos[i] + (paired ? 2 : 1));
2607 b2.insert(b2.begin(), paired ? 2 : 1, zero);
2609 std::vector<T> nr = b2;
2610 nr.insert(nr.end(), srv.begin(), srv.end());
2611 nr.insert(nr.end(), var.begin(), var.end());
2614 static_cast<double>(total)));
2617 for (std::size_t i = 0; i < scls.size(); ++i) {
2618 std::vector<T> b2 = buf, s2 = srv;
2619 s2[L.
Ks[scls[i] - 1] + sph[i]] -= one;
2623 for (std::size_t j = 0; j < s2.size(); ++j)
2625 if (L.
bufw > 0 && occ < S) {
2627 std::size_t hp = L.
bufw;
2628 for (std::size_t b = 0; b < L.
bufw; b += paired ? 2 : 1)
2631 const std::size_t pc =
static_cast<std::size_t
>(
2637 pp = v >= 1 ?
static_cast<std::size_t
>(v) - 1 : 0;
2639 b2.erase(b2.begin() + hp,
2640 b2.begin() + hp + (paired ? 2 : 1));
2641 b2.insert(b2.begin(), paired ? 2 : 1, zero);
2642 s2[L.
Ks[pc - 1] + pp] += one;
2644 }
else if (counted) {
2649 for (std::size_t r = 1; r <= R && r <= L.
bufw; ++r)
2652 s2[L.
Ks[r - 1]] += one;
2657 std::vector<T> nr = b2;
2658 nr.insert(nr.end(), s2.begin(), s2.end());
2659 nr.insert(nr.end(), var.begin(), var.end());
2662 static_cast<double>(scnt[i]) /
static_cast<double>(total)));
2666 signal_detail::merge_states(sp, pr);
2667 for (std::size_t i = 0; i < sp.size(); ++i) {
2668 nxt.push_back(sp[i]);
2669 nxtp.push_back(T(curp[row] * pr[i]));
2672 signal_detail::merge_states(nxt, nxtp);
2676 for (std::size_t i = 0; i < cur.size(); ++i) {
2677 acc.push_back(cur[i]);
2678 accp.push_back(T(pmf.second[ik] * curp[i]));
2681 signal_detail::merge_states(acc, accp);
2682 out.
space.swap(acc);
2683 out.
prob.swap(accp);
2684 out.
rate.assign(out.
space.size(), minus_one);
2705 const std::vector<std::size_t>& c, std::size_t p,
2706 const std::vector<std::vector<bool>>& G) {
2707 const std::size_t n = c.size();
2708 if (p >= n)
throw InputError(
"pass_and_swap: position is out of range for the state");
2709 std::vector<std::size_t> chain(1, p);
2710 std::size_t moving = c[p], cur = p;
2713 for (std::size_t j = cur + 1; j < n; ++j)
2714 if (moving - 1 < G.size() && c[j] - 1 < G[moving - 1].size() &&
2715 G[moving - 1][c[j] - 1]) {
2724 const std::size_t dep = c[chain.back()];
2727 std::vector<std::size_t> cnew = c;
2728 for (std::size_t i = 0; i + 1 < chain.size(); ++i) cnew[chain[i + 1]] = c[chain[i]];
2729 cnew.erase(cnew.begin() + chain[0]);
2730 return std::make_pair(cnew, dep);
2745template <
class T,
class F>
2746inline std::vector<double>
pas_increments(
const F& mu_fun,
const std::vector<std::size_t>& c) {
2747 std::vector<double> inc(c.size(), 0.0);
2748 double mu_prev = 0.0;
2749 for (std::size_t p = 0; p < c.size(); ++p) {
2750 const std::vector<std::size_t> prefix(c.begin(), c.begin() + p + 1);
2752 inc[p] = mu_cur - mu_prev;
2764template <
class T,
class F>
2766 const std::vector<std::size_t>& cold,
2767 const std::vector<std::size_t>& cnew) {
2768 if (!mu_fun || out.
space.empty())
return;
2771 for (std::size_t p = 0; p < inc_new.size(); ++p) {
2772 if (inc_new[p] <= 0)
continue;
2773 if (p < inc_old.size() && inc_old[p] > 0)
continue;
2780 const std::vector<T>& inspace,
EventType event,
2782 const std::size_t ist =
sn.nodes[ind - 1].station;
2785 if (ist == 0)
throw InputError(
"after_event_station_pas: node is not a station");
2786 const typename std::map<std::size_t, typename NetworkStruct<T>::PasParam>::const_iterator it =
2787 sn.pasparam.find(ist);
2788 if (it ==
sn.pasparam.end() || !it->second.svc_rate_fun)
2790 "after_event_station_pas: the station has no service rate function mu(c); set one "
2793 const std::size_t V =
sn.nvars_of(ind);
2794 const std::size_t W = inspace.size() - V;
2795 std::vector<std::size_t> c;
2796 for (std::size_t i = 0; i < W; ++i) {
2798 if (v > 0) c.push_back(
static_cast<std::size_t
>(v));
2800 const std::vector<T> var(inspace.begin() + W, inspace.end());
2801 const double cap =
sn.cap[ist - 1];
2803 if (event == EventType::ARV) {
2806 if (
static_cast<double>(c.size()) >= cap)
return out;
2807 std::vector<std::size_t>
nc = c;
2818 if (
nc.size() > W)
return out;
2820 for (std::size_t i = 0; i <
nc.size(); ++i)
2822 row.resize(W, zero);
2823 row.insert(row.end(), var.begin(), var.end());
2824 out.
space.push_back(row);
2826 out.
prob.push_back(one);
2837 if (event != EventType::DEP)
return out;
2843 for (std::size_t p = 0; p < c.size(); ++p) {
2844 const std::vector<std::size_t> prefix(c.begin(), c.begin() + p + 1);
2845 const T mu_cur = it->second.svc_rate_fun(prefix);
2846 const T ratep = T(mu_cur - mu_prev);
2849 const std::pair<std::vector<std::size_t>, std::size_t> ps =
2853 if (ps.second != cls)
continue;
2855 for (std::size_t i = 0; i < ps.first.size(); ++i)
2857 row.resize(W, zero);
2858 row.insert(row.end(), var.begin(), var.end());
2859 out.
space.push_back(row);
2860 out.
rate.push_back(ratep);
2861 out.
prob.push_back(one);
2878 const std::size_t R =
sn.nclasses;
2880 ri.
slot.assign(R,
static_cast<std::size_t
>(-1));
2881 if (
sn.nvars.size() < ind ||
sn.nvars[ind - 1].size() < 3 * R + 1)
return ri;
2882 std::size_t pos = 0;
2883 for (std::size_t j = 0; j < 2 * R + 1; ++j) pos +=
sn.nvars[ind - 1][j];
2884 for (std::size_t r = 1; r <= R; ++r)
2885 if (
sn.nvars[ind - 1][2 * R + r] > 0) {
2886 ri.
slot[r - 1] = pos;
2899 for (std::size_t i = 0; i < ri.
classes.size(); ++i) {
2903 if (s !=
static_cast<std::size_t
>(-1) && s < var.size())
2927 const std::vector<T>& inspace, std::size_t cls) {
2928 const std::size_t R =
sn.nclasses;
2929 const std::size_t ist =
sn.nodes[ind - 1].station;
2932 if (ist == 0)
throw InputError(
"after_event_station_reply: node is not a station");
2935 const double S =
sn.stations[ist - 1].nservers;
2939 std::size_t callclass = 0;
2940 for (std::size_t i = 0; i < ri.
classes.size(); ++i) {
2941 const std::size_t r = ri.
classes[i];
2942 if (
sn.syncreply.size() >= r &&
sn.syncreply[r - 1] == cls) {
2948 std::vector<T> buf(inspace.begin(), inspace.begin() + L.
bufw);
2949 std::vector<T> srv(inspace.begin() + L.
bufw, inspace.begin() + L.
bufw + L.
srvw);
2950 std::vector<T> var(inspace.begin() + L.
bufw + L.
srvw, inspace.end());
2952 if (callclass > 0) {
2953 const std::size_t s = ri.
slot[callclass - 1];
2954 if (s !=
static_cast<std::size_t
>(-1) && s < var.size() &&
2967 for (std::size_t ke = 0; ke < L.
K[cls - 1]; ++ke) {
2969 std::vector<T> s2 = srv;
2970 s2[L.
Ks[cls - 1] + ke] += one;
2971 std::vector<T> row = buf;
2972 row.insert(row.end(), s2.begin(), s2.end());
2973 row.insert(row.end(), var.begin(), var.end());
2974 out.
space.push_back(row);
2976 out.
prob.push_back(pentry[ke]);
2982 std::vector<T> b2 = buf;
2983 std::size_t slot = b2.size();
2984 for (std::size_t b = 0; b < b2.size(); ++b)
2986 if (slot == b2.size()) {
2987 b2.insert(b2.begin(), zero);
2991 std::vector<T> row = b2;
2992 row.insert(row.end(), srv.begin(), srv.end());
2993 row.insert(row.end(), var.begin(), var.end());
2994 out.
space.push_back(row);
2996 out.
prob.push_back(one);
3004 std::size_t& pos, std::size_t& swk,
long& ctr) {
3005 pos = pi.
ipos !=
static_cast<std::size_t
>(-1)
3007 : (srvclass > 0 ? srvclass : 1);
3008 swk = pi.
iswk !=
static_cast<std::size_t
>(-1)
3011 ctr = pi.
ictr !=
static_cast<std::size_t
>(-1)
3019 std::size_t swk,
long ctr) {
3020 if (pi.
ipos !=
static_cast<std::size_t
>(-1))
3022 if (pi.
iswk !=
static_cast<std::size_t
>(-1))
3024 if (pi.
ictr !=
static_cast<std::size_t
>(-1))
3037 default:
throw InputError(
"polling_budget: unsupported polling type");
3051 std::size_t R,
bool arrived, std::size_t& q,
int& mode,
long& budget) {
3052 if (arrived && pi.
polled[pos - 1] && nbuf[pos - 1] > 0) {
3059 std::size_t p = pos;
3060 for (std::size_t step = 0; step < R; ++step) {
3062 if (!pi.
polled[p - 1])
continue;
3069 if (nbuf[p - 1] > 0) {
3084 std::size_t q,
int mode,
long budget,
const std::vector<T>& buf,
3085 const std::vector<T>& srv,
const std::vector<T>& var,
const RowLayout<T>& L,
3086 std::vector<std::vector<T>>& rows, std::vector<T>& probs) {
3090 std::vector<T> b2 = buf;
3093 for (std::size_t ke = 0; ke < L.
K[q - 1]; ++ke) {
3095 std::vector<T> s2 = srv;
3096 s2[L.
Ks[q - 1] + ke] += one;
3097 std::vector<T> row = b2;
3098 row.insert(row.end(), s2.begin(), s2.end());
3099 const std::vector<T> v2 =
polling_set(pi, var, q, 0, budget);
3100 row.insert(row.end(), v2.begin(), v2.end());
3101 rows.push_back(row);
3102 probs.push_back(pentry[ke]);
3104 }
else if (mode == 2) {
3106 for (std::size_t ke = 0; ke < pi.
ksw[q - 1]; ++ke) {
3108 std::vector<T> row = buf;
3109 row.insert(row.end(), srv.begin(), srv.end());
3110 const std::vector<T> v2 =
polling_set(pi, var, q, ke + 1, 0);
3111 row.insert(row.end(), v2.begin(), v2.end());
3112 rows.push_back(row);
3113 probs.push_back(pi.
sw_pie[q - 1][ke]);
3117 std::vector<T> row = buf;
3118 row.insert(row.end(), srv.begin(), srv.end());
3119 const std::vector<T> v2 =
polling_set(pi, var, q, 0, 0);
3120 row.insert(row.end(), v2.begin(), v2.end());
3121 rows.push_back(row);
3122 probs.push_back(one);
3138 const std::vector<T>& inspace, std::size_t cls) {
3139 const std::size_t R =
sn.nclasses;
3140 const std::size_t ist =
sn.nodes[ind - 1].station;
3143 if (ist == 0)
throw InputError(
"after_event_station_switch: node is not a station");
3145 if (!pinfo.
valid || !pinfo.
has_sw[cls - 1])
return out;
3148 const std::vector<T> buf(inspace.begin(), inspace.begin() + L.
bufw);
3149 const std::vector<T> srv(inspace.begin() + L.
bufw, inspace.begin() + L.
bufw + L.
srvw);
3150 const std::vector<T> var(inspace.begin() + L.
bufw + L.
srvw, inspace.end());
3152 std::size_t pos = 0, swk = 0;
3156 if (pos != cls || swk == 0)
return out;
3159 for (std::size_t kd = 0; kd < pinfo.
ksw[cls - 1]; ++kd) {
3160 if (kd + 1 == swk)
continue;
3161 const T r0 = pinfo.
sw_d0[cls - 1](swk - 1, kd);
3163 std::vector<T> row = buf;
3164 row.insert(row.end(), srv.begin(), srv.end());
3165 const std::vector<T> v2 =
polling_set(pinfo, var, cls, kd + 1, 0);
3166 row.insert(row.end(), v2.begin(), v2.end());
3167 out.
space.push_back(row);
3168 out.
rate.push_back(r0);
3169 out.
prob.push_back(one);
3173 for (std::size_t j = 0; j < pinfo.
ksw[cls - 1]; ++j) rate += pinfo.
sw_d1[cls - 1](swk - 1, j);
3175 std::vector<long> nbuf(R, 0);
3176 for (std::size_t r = 0; r < R && r < L.
bufw; ++r)
3181 polling_next(pinfo, cls, nbuf, R,
true, q, mode, budget);
3182 std::vector<std::vector<T>> rows;
3183 std::vector<T> probs;
3184 polling_land(
sn, ist, pinfo, q, mode, budget, buf, srv, var, L, rows, probs);
3185 for (std::size_t j = 0; j < rows.size(); ++j) {
3190 if (rows[j] == inspace)
continue;
3191 out.
space.push_back(rows[j]);
3192 out.
rate.push_back(T(rate * probs[j]));
3193 out.
prob.push_back(one);
3200 tag_last(out, mode == 1 ? q : 0, 0);
3222 const std::vector<T>& inspace,
EventType event,
3224 const std::size_t R =
sn.nclasses;
3228 const typename std::map<std::size_t, CacheParam<T>>::const_iterator ci =
sn.nodeparam.find(ind);
3229 if (ci ==
sn.nodeparam.end())
throw InputError(
"after_event_cache: node has no CacheParam");
3231 const std::size_t h = cp.
itemcap.size();
3232 const std::size_t n = cp.
nitems;
3233 std::size_t tcc = 0;
3234 for (std::size_t i = 0; i < h; ++i)
3235 if (cp.
itemcap[i] > 0) tcc +=
static_cast<std::size_t
>(cp.
itemcap[i]);
3237 const std::vector<int>& m = cp.
itemcap;
3239 const std::vector<int>& m;
3240 std::size_t operator()(std::size_t i, std::size_t j)
const {
3241 std::size_t base = 0;
3242 for (std::size_t t = 0; t + 1 < i; ++t) base +=
static_cast<std::size_t
>(m[t]);
3243 return base + j - 1;
3247 std::vector<T> srv(inspace.begin(), inspace.begin() + R);
3248 std::vector<T> var(inspace.begin() + R, inspace.end());
3250 if (event == EventType::ARV) {
3251 srv[cls - 1] += one;
3252 std::vector<T> row = srv;
3253 row.insert(row.end(), var.begin(), var.end());
3254 out.
space.push_back(row);
3256 out.
prob.push_back(one);
3260 if (event == EventType::DEP) {
3279 std::size_t item_dep = 0;
3286 if (item_dep != 0) {
3287 const std::size_t bitcol = tcc + item_dep - 1;
3288 if (bitcol < var.size()) {
3291 for (std::size_t r = 0; r < R; ++r)
3293 if (srvtot == 1)
return out;
3311 const std::size_t hc =
3312 cls - 1 < cp.
hitclass.size() ?
static_cast<std::size_t
>(cp.
hitclass[cls - 1]) : 0;
3313 const std::size_t
mc =
3315 if (hc != cls &&
mc != cls)
return out;
3319 srv[cls - 1] -= one;
3320 std::vector<T> row = srv;
3321 row.insert(row.end(), var.begin(), var.end());
3322 out.
space.push_back(row);
3323 out.
rate.push_back(imm);
3324 out.
prob.push_back(one);
3328 if (event != EventType::READ)
return out;
3332 for (std::size_t r = 0; r < R; ++r) tot += num_traits<T>::to_double(srv[r]);
3334 if (cls - 1 >= cp.
pread.size() || cp.
pread[cls - 1].empty())
return out;
3335 const std::vector<T>& p = cp.
pread[cls - 1];
3343 std::vector<std::size_t> rc_list, rc_items, rc_orig;
3345 const std::size_t block_b = tcc + n;
3346 std::size_t width_b = var.size() > block_b ? var.size() - block_b : 0;
3347 if (width_b != rc_list.size()) width_b = 0;
3352 ? std::numeric_limits<double>::infinity()
3354 bool from_retrieval =
false;
3355 for (std::size_t j = 0; j < rc_list.size(); ++j)
3356 if (rc_list[j] == cls) from_retrieval =
true;
3358 for (std::size_t k = 1; k <= n; ++k) {
3360 std::vector<T> srv_e = srv;
3361 srv_e[cls - 1] -= one;
3364 std::size_t posk = 0;
3365 for (std::size_t c = 0; c < tcc && c < var.size(); ++c)
3374 if (from_retrieval) posk = 0;
3376 k - 1 >= cp.
accost[cls - 1].size()
3378 : cp.
accost[cls - 1][k - 1];
3379 const bool have_ac = ac.
rows() >= h + 1 && ac.
cols() >= h + 1;
3384 const bool in_flight =
3386 std::size_t r_class = 0;
3393 if (from_retrieval && !in_flight)
continue;
3395 if (!from_retrieval && r_class != 0) {
3400 std::vector<T> srv_b = srv_e;
3401 std::vector<T> var_b = var;
3408 srv_b[r_class - 1] += one;
3410 if (width_b == 0)
continue;
3411 std::size_t bslot = width_b;
3412 for (std::size_t j = 0; j < rc_list.size(); ++j)
3413 if (rc_list[j] == r_class) { bslot = j;
break; }
3414 if (bslot >= width_b)
continue;
3416 for (std::size_t j = 0; j < width_b; ++j)
3418 if (pend >= maxpend)
continue;
3419 var_b[block_b + bslot] += one;
3421 std::vector<T> row = srv_b;
3422 row.insert(row.end(), var_b.begin(), var_b.end());
3423 out.
space.push_back(row);
3424 out.
rate.push_back(T(p[k - 1] * imm));
3425 out.
prob.push_back(one);
3434 std::vector<T> srv_m = srv_e;
3435 srv_m[cp.
missclass[cls - 1] - 1] += one;
3436 std::vector<T> var_m = var;
3437 if (tcc + k <= var_m.size()) var_m[tcc + k - 1] = zero;
3438 for (std::size_t j = 0; j < width_b; ++j) {
3439 if (rc_items[j] != k)
continue;
3441 if (held <= 0)
continue;
3442 const std::size_t oc = rc_orig[j];
3444 srv_m[cp.
hitclass[oc - 1] - 1] += var_m[block_b + j];
3445 var_m[block_b + j] = zero;
3450 const T rej = have_ac ? ac(0, 0) : zero;
3452 std::vector<T> row = srv_m;
3453 row.insert(row.end(), var_m.begin(), var_m.end());
3454 out.
space.push_back(row);
3455 out.
rate.push_back(T(rej * p[k - 1] * imm));
3456 out.
prob.push_back(one);
3458 for (std::size_t l = 1; l <= h; ++l) {
3459 const T w = have_ac ? ac(0, l) : (l == 1 ? one : zero);
3461 if (m[l - 1] <= 0)
continue;
3462 const std::size_t ml =
static_cast<std::size_t
>(m[l - 1]);
3465 for (std::size_t rr = 1; rr <= ml; ++rr) {
3466 std::vector<T> vp = var_m;
3468 std::vector<T> row = srv_m;
3469 row.insert(row.end(), vp.begin(), vp.end());
3470 out.
space.push_back(row);
3471 out.
rate.push_back(T(w * p[k - 1] /
3473 out.
prob.push_back(one);
3478 std::vector<T> vp = var_m;
3479 for (std::size_t j = ml; j >= 2; --j) vp[cpos(l, j)] = var_m[cpos(l, j - 1)];
3481 T rate = T(w * p[k - 1] * imm);
3485 const T q = cp.
qlru;
3487 std::vector<T> row0 = srv_m;
3488 row0.insert(row0.end(), var_m.begin(), var_m.end());
3489 out.
space.push_back(row0);
3490 out.
rate.push_back(T(rate * T(one - q)));
3491 out.
prob.push_back(one);
3496 std::vector<T> row = srv_m;
3497 row.insert(row.end(), vp.begin(), vp.end());
3498 out.
space.push_back(row);
3499 out.
rate.push_back(rate);
3500 out.
prob.push_back(one);
3507 std::vector<T> srv_h = srv_e;
3508 srv_h[cp.
hitclass[cls - 1] - 1] += one;
3509 std::size_t li = 1, acc = 0;
3510 for (std::size_t t = 0; t < h; ++t) {
3511 const std::size_t mt = m[t] > 0 ?
static_cast<std::size_t
>(m[t]) : 0;
3512 if (posk <= acc + mt) { li = t + 1;
break; }
3515 const std::size_t j = posk - acc;
3527 for (std::size_t inew = li; inew <= h; ++inew) {
3528 if (m[inew - 1] <= 0)
continue;
3529 const std::size_t mn =
static_cast<std::size_t
>(m[inew - 1]);
3530 const T w = have_ac ? ac(li, inew) : (inew == li + 1 ? one : zero);
3534 for (std::size_t r = 1; r <= mn; ++r) {
3535 std::vector<T> vp = var;
3536 vp[cpos(li, j)] = var[cpos(inew, r)];
3538 std::vector<T> row = srv_h;
3539 row.insert(row.end(), vp.begin(), vp.end());
3540 out.
space.push_back(row);
3544 out.
prob.push_back(one);
3551 std::vector<T> vp = var;
3556 for (std::size_t t = j; t >= 2; --t) vp[cpos(li, t)] = var[cpos(li, t - 1)];
3559 vp[cpos(li, ordered ? 1 : j)] = var[cpos(inew, mn)];
3560 for (std::size_t t = mn; t >= 2; --t) vp[cpos(inew, t)] = var[cpos(inew, t - 1)];
3562 std::vector<T> row = srv_h;
3563 row.insert(row.end(), vp.begin(), vp.end());
3564 out.
space.push_back(row);
3565 out.
rate.push_back(T(w * p[k - 1] * imm));
3566 out.
prob.push_back(one);
3573 std::vector<T> row = srv_h;
3574 row.insert(row.end(), var.begin(), var.end());
3575 out.
space.push_back(row);
3576 out.
rate.push_back(T(p[k - 1] * imm));
3577 out.
prob.push_back(one);
3581 std::vector<T> vp = var;
3582 for (std::size_t t = j; t >= 2; --t) vp[cpos(li, t)] = var[cpos(li, t - 1)];
3583 vp[cpos(li, 1)] = var[cpos(li, j)];
3584 std::vector<T> row = srv_h;
3585 row.insert(row.end(), vp.begin(), vp.end());
3586 out.
space.push_back(row);
3587 out.
rate.push_back(T(p[k - 1] * imm));
3588 out.
prob.push_back(one);
3630 std::vector<GlobalSync<T>> gsync;
3632 for (std::size_t ind = 1; ind <=
sn.nodes.size(); ++ind) {
3633 if (
sn.nodes[ind - 1].nodetype != NodeType::Transition)
continue;
3634 const typename std::map<std::size_t, TransitionParam<T>>::const_iterator it =
3635 sn.transparam.find(ind);
3636 if (it ==
sn.transparam.end())
continue;
3638 for (
int pass = 0; pass < 2; ++pass) {
3639 for (std::size_t m = 1; m <= tp.
nmodes; ++m) {
3644 std::vector<std::pair<std::size_t, std::size_t>> enab, fire, inhib;
3648 for (std::size_t q = 0; q < en.
rows(); ++q)
3649 for (std::size_t r = 0; r < en.
cols(); ++r)
3651 enab.push_back(std::make_pair(q + 1, r + 1));
3652 for (std::size_t q = 0; q < fi.
rows(); ++q)
3653 for (std::size_t r = 0; r < fi.
cols(); ++r)
3655 fire.push_back(std::make_pair(q + 1, r + 1));
3656 for (std::size_t q = 0; q < ih.
rows(); ++q)
3657 for (std::size_t r = 0; r < ih.
cols(); ++r) {
3664 for (std::size_t i = 0; i < enab.size(); ++i)
3665 dup = dup || enab[i].first == q + 1;
3666 for (std::size_t i = 0; i < fire.size(); ++i)
3667 dup = dup || fire[i].first == q + 1;
3668 for (std::size_t i = 0; i < inhib.size(); ++i)
3669 dup = dup || inhib[i].first == q + 1;
3670 if (!dup) inhib.push_back(std::make_pair(q + 1, r + 1));
3673 g.
active.event = pass == 0 ? EventType::ENABLE : EventType::FIRE;
3680 std::vector<std::size_t> seen;
3681 auto once = [&](std::size_t q, std::size_t r) {
3682 for (std::size_t i = 0; i < seen.size(); ++i)
3683 if (seen[i] == q)
return;
3687 for (std::size_t i = 0; i < enab.size(); ++i) once(enab[i].first, enab[i].second);
3688 for (std::size_t i = 0; i < inhib.size(); ++i)
3689 once(inhib[i].first, inhib[i].second);
3691 for (std::size_t i = 0; i < enab.size(); ++i)
3694 en(enab[i].first - 1, enab[i].second - 1)});
3695 for (std::size_t i = 0; i < fire.size(); ++i)
3698 fi(fire[i].first - 1, fire[i].second - 1)});
3699 for (std::size_t i = 0; i < inhib.size(); ++i)
3701 inhib[i].second, one});
3736 const std::size_t R =
sn.nclasses;
3737 const std::size_t ind = gl.
active.node;
3738 const std::size_t mode = gl.
active.mode;
3742 const std::size_t isf =
sn.stateful_index(ind);
3743 if (isf == 0)
throw InputError(
"after_global_event: the transition is not stateful");
3744 const typename std::map<std::size_t, TransitionParam<T>>::const_iterator it =
3745 sn.transparam.find(ind);
3746 if (it ==
sn.transparam.end())
throw InputError(
"after_global_event: node has no TransitionParam");
3749 std::vector<std::size_t> fK(tp.
nmodes, 1), fKs(tp.
nmodes, 0);
3750 std::size_t tot = 0;
3751 for (std::size_t m = 0; m < tp.
nmodes; ++m) {
3756 const std::vector<T>& row = glspace.
local[isf - 1];
3757 std::vector<T> buf(row.begin(), row.begin() + tp.
nmodes);
3758 std::vector<T> srv(row.begin() + tp.
nmodes, row.begin() + tp.
nmodes + tot);
3759 std::vector<T> fired(row.begin() + tp.
nmodes + tot,
3760 row.begin() + 2 * tp.
nmodes + tot);
3761 const std::vector<T> var(row.begin() + 2 * tp.
nmodes + tot, row.end());
3764 std::vector<std::vector<T>> ep(
sn.nodes.size() + 1, std::vector<T>(R, zero));
3765 for (std::size_t j = 0; j < gl.
passive.size(); ++j) {
3766 const std::size_t pn = gl.
passive[j].node;
3767 const std::size_t pisf =
sn.stateful_index(pn);
3768 if (pisf == 0)
continue;
3784 bool inhibited =
false;
3785 for (std::size_t q = 0; q < ih_m.
rows(); ++q)
3786 for (std::size_t r = 0; r < ih_m.
cols() && r < R; ++r) {
3788 if (std::isinf(thr))
continue;
3792 for (std::size_t q = 0; q < en_m.
rows(); ++q)
3793 for (std::size_t r = 0; r < en_m.
cols() && r < R; ++r) {
3795 if (need <= 0)
continue;
3798 long mark_degree = 0;
3799 if (!inhibited && !under) {
3803 for (std::size_t q = 0; q < en_m.
rows() && ok; ++q)
3804 for (std::size_t r = 0; r < en_m.
cols() && r < R && ok; ++r) {
3806 if (need <= 0)
continue;
3812 mark_degree = d - 1;
3815 const long nsrv = std::isfinite(svm) ?
static_cast<long>(svm)
3818 if (gl.
active.event == EventType::ENABLE) {
3820 for (std::size_t k = 0; k < fK[mode - 1]; ++k)
3822 if (inhibited || under) {
3824 std::vector<T> b2 = buf, s2 = srv;
3826 for (std::size_t k = 0; k < fK[mode - 1]; ++k) s2[fKs[mode - 1] + k] = zero;
3827 std::vector<T> nr = b2;
3828 nr.insert(nr.end(), s2.begin(), s2.end());
3829 nr.insert(nr.end(), fired.begin(), fired.end());
3830 nr.insert(nr.end(), var.begin(), var.end());
3831 if (nr == row)
return out;
3833 ns.
local[isf - 1] = nr;
3834 out.
space.push_back(ns);
3835 out.
rate.push_back(imm);
3836 out.
prob.push_back(one);
3840 const long want = std::min(mark_degree, nsrv);
3841 if (running == want)
return out;
3842 if (running < want) {
3846 const long nadd = want - running;
3847 std::vector<T> pe(fK[mode - 1], zero);
3849 static_cast<std::size_t
>(fK[mode - 1])) {
3854 for (std::size_t k = 0; k < fK[mode - 1]; ++k) pe[k] = pv[k];
3859 std::vector<std::vector<long>> combs;
3860 std::vector<long> cur(fK[mode - 1], 0);
3861 std::function<void(std::size_t,
long)> rec = [&](std::size_t k,
long left) {
3862 if (k + 1 == fK[mode - 1]) {
3864 combs.push_back(cur);
3867 for (
long v = left; v >= 0; --v) {
3869 rec(k + 1, left - v);
3873 for (std::size_t i = 0; i < combs.size(); ++i) {
3874 std::vector<T> b2 = buf, s2 = srv;
3876 double logp = std::lgamma(
static_cast<double>(nadd) + 1.0);
3877 bool zeroprob =
false;
3878 for (std::size_t k = 0; k < fK[mode - 1]; ++k) {
3882 logp += combs[i][k] * std::log(pk) -
3883 std::lgamma(
static_cast<double>(combs[i][k]) + 1.0);
3884 else if (combs[i][k] > 0)
3887 std::vector<T> nr = b2;
3888 nr.insert(nr.end(), s2.begin(), s2.end());
3889 nr.insert(nr.end(), fired.begin(), fired.end());
3890 nr.insert(nr.end(), var.begin(), var.end());
3892 ns.
local[isf - 1] = nr;
3893 out.
space.push_back(ns);
3894 out.
rate.push_back(imm);
3902 const long ndiff = running - want;
3903 std::vector<long> sv(fK[mode - 1], 0);
3904 for (std::size_t k = 0; k < fK[mode - 1]; ++k)
3906 std::vector<std::vector<long>> combs;
3907 std::vector<long> cur(fK[mode - 1], 0);
3908 std::function<void(std::size_t,
long)> rec = [&](std::size_t k,
long left) {
3909 if (k + 1 == fK[mode - 1]) {
3910 if (left > sv[k])
return;
3912 combs.push_back(cur);
3915 for (
long v = std::min(left, sv[k]); v >= 0; --v) {
3917 rec(k + 1, left - v);
3921 std::vector<double> w(combs.size(), 0.0);
3922 double wmax = -1e300;
3923 for (std::size_t i = 0; i < combs.size(); ++i) {
3925 for (std::size_t k = 0; k < fK[mode - 1]; ++k)
3926 lw += std::lgamma(
static_cast<double>(sv[k]) + 1.0) -
3927 std::lgamma(
static_cast<double>(combs[i][k]) + 1.0) -
3928 std::lgamma(
static_cast<double>(sv[k] - combs[i][k]) + 1.0);
3930 wmax = std::max(wmax, lw);
3933 for (std::size_t i = 0; i < w.size(); ++i) {
3934 w[i] = std::exp(w[i] - wmax);
3937 for (std::size_t i = 0; i < combs.size(); ++i) {
3938 std::vector<T> b2 = buf, s2 = srv;
3939 for (std::size_t k = 0; k < fK[mode - 1]; ++k)
3942 std::vector<T> nr = b2;
3943 nr.insert(nr.end(), s2.begin(), s2.end());
3944 nr.insert(nr.end(), fired.begin(), fired.end());
3945 nr.insert(nr.end(), var.begin(), var.end());
3947 ns.
local[isf - 1] = nr;
3948 out.
space.push_back(ns);
3949 out.
rate.push_back(imm);
3956 if (gl.
active.event != EventType::FIRE)
return out;
3958 const bool immediate_mode = mode - 1 < tp.
timing.size() &&
3960 const T fw = immediate_mode && mode - 1 < tp.
fireweight.size() ? tp.
fireweight[mode - 1] : one;
3961 const long en_degree = inhibited ? 0 : std::min(mark_degree, nsrv);
3962 const long imm_servers = immediate_mode ? std::min(mark_degree, nsrv) : 0;
3964 for (std::size_t k = 0; k < fK[mode - 1]; ++k) {
3966 const bool fires = immediate_mode ? (k == 0 && imm_servers >= 1)
3967 : (in_k > 0 && en_degree >= 1);
3968 if (!fires)
continue;
3970 if (immediate_mode) {
3975 for (std::size_t j = 0; j < tp.
firingproc[mode - 1].D1.cols(); ++j)
3982 for (std::size_t q = 1; q <=
sn.nodes.size(); ++q) {
3984 for (std::size_t r = 0; r < R; ++r) s2 += ep[q][r];
3987 rate = T(rate * tp.
firingdep[mode - 1](mk));
3992 std::vector<T> b2 = buf, s2 = srv;
3994 s2[fKs[mode - 1] + k] -= one;
3995 b2[mode - 1] += one;
3998 std::vector<T> nr = b2;
3999 nr.insert(nr.end(), s2.begin(), s2.end());
4000 nr.insert(nr.end(), fired.begin(), fired.end());
4001 nr.insert(nr.end(), var.begin(), var.end());
4002 ns.
local[isf - 1] = nr;
4008 for (std::size_t j = 0; j < gl.
passive.size(); ++j) {
4010 if (pe2.
event != EventType::PRE && pe2.
event != EventType::POST)
continue;
4011 const std::size_t pisf =
sn.stateful_index(pe2.
node);
4012 if (pisf == 0)
continue;
4013 std::vector<T>& prow = ns.
local[pisf - 1];
4015 const std::size_t pist =
sn.nodes[pe2.
node - 1].station;
4017 pist != 0 ?
sn.stations[pist - 1].sched : SchedStrategy::INF;
4018 const std::size_t c = pe2.
cls;
4019 if (pe2.
event == EventType::PRE) {
4020 if (state_detail::buffer_is_class_tag(psched)) {
4023 long left =
static_cast<long>(wgt);
4025 if (psched == SchedStrategy::LCFS) {
4026 for (std::size_t b = 0; b < prow.size() && left > 0; ++b)
4027 if (prow[b] == tag) { prow[b] = zero; --left; }
4029 for (std::size_t b = prow.size(); b-- > 0 && left > 0;)
4030 if (prow[b] == tag) { prow[b] = zero; --left; }
4032 }
else if (prow.size() > R) {
4038 prow[R + c - 1] = zero;
4039 }
else if (c - 1 < prow.size()) {
4043 if (state_detail::buffer_is_class_tag(psched)) {
4044 for (
long q = 0; q < static_cast<long>(wgt); ++q)
4046 }
else if (c - 1 < prow.size()) {
4051 out.
space.push_back(ns);
4052 out.
rate.push_back(rate);
4053 out.
prob.push_back(one);
4115 if (sy.
active.node == 0 || sy.
active.node >
sn.nodes.size())
return false;
4116 const std::size_t ist =
sn.nodes[sy.
active.node - 1].station;
4117 if (ist == 0)
return false;
4118 const std::size_t cls_p = sy.
passive.cls;
4119 if (ist >
sn.immfeed.size() || cls_p == 0 || cls_p >
sn.immfeed[ist - 1].size())
return false;
4120 return sn.immfeed[ist - 1][cls_p - 1];
4138 const std::vector<std::vector<bool>>& impatience_classes = std::vector<std::vector<bool>>(),
4139 const std::vector<std::size_t>& breakdown_nodes = std::vector<std::size_t>()) {
4140 const std::size_t R =
sn.nclasses;
4141 const std::size_t local =
sn.nodes.size() + 1;
4143 std::vector<Sync<T>> sync;
4145 for (std::size_t ind = 1; ind <=
sn.nodes.size(); ++ind) {
4147 const std::size_t ist = nd.
station;
4148 for (std::size_t r = 1; r <= R; ++r) {
4151 if (ist != 0 &&
sn.phases_of(ist, r) > 1) {
4157 if (ist != 0 && impatience_classes.size() >= ist &&
4158 impatience_classes[ist - 1].size() >= r && impatience_classes[ist - 1][r - 1]) {
4165 const typename std::map<std::size_t, RetrialParam<T>>::const_iterator rit =
4166 sn.retrialparam.find(ist);
4167 if (rit !=
sn.retrialparam.end() && rit->second.retrial_proc.size() >= r &&
4168 !rit->second.retrial_proc[r - 1].disabled) {
4178 if (ist != 0 && r == 1) {
4179 bool has_bd =
sn.has_breakdown_node(ind);
4180 for (std::size_t b = 0; b < breakdown_nodes.size() && !has_bd; ++b)
4181 if (breakdown_nodes[b] == ind) { has_bd =
true;
break; }
4194 if (ist != 0 &&
sn.stations[ist - 1].sched == SchedStrategy::POLLING) {
4206 if (nd.
nodetype == NodeType::Fork)
continue;
4220 bool cache_read_class =
false;
4221 if (nd.
nodetype == NodeType::Cache) {
4222 const typename std::map<std::size_t, CacheParam<T>>::const_iterator ci =
4223 sn.nodeparam.find(ind);
4224 if (ci !=
sn.nodeparam.end()) {
4225 if (r - 1 < ci->second.pread.size() && !ci->second.pread[r - 1].empty()) {
4232 r - 1 < ci->second.hitclass.size() && ci->second.hitclass[r - 1] != 0;
4239 if (nd.
nodetype == NodeType::Transition && r == 1) {
4240 const typename std::map<std::size_t, TransitionParam<T>>::const_iterator ti =
4241 sn.transparam.find(ind);
4242 if (ti !=
sn.transparam.end()) {
4243 for (std::size_t m = 1; m <= ti->second.nmodes; ++m) {
4251 if (cache_read_class)
continue;
4253 const std::size_t isf =
sn.stateful_index(ind);
4254 for (std::size_t jnd = 1; jnd <=
sn.nodes.size(); ++jnd) {
4255 if (!
sn.nodes[jnd - 1].stateful)
continue;
4256 const std::size_t jsf =
sn.stateful_index(jnd);
4257 for (std::size_t s = 1; s <= R; ++s) {
4258 const T p =
sn.rt((isf - 1) * R + (r - 1), (jsf - 1) * R + (s - 1));
4269 if (nd.
routing.size() >= s && nd.
routing[s - 1] == RoutingStrategy::SDR) {
4271 ns.
passive.rt_row = (isf - 1) * R + (r - 1);
4272 ns.
passive.rt_col = (jsf - 1) * R + (s - 1);
4312 const std::size_t R =
sn.nclasses;
4314 const std::size_t isf_f =
sn.stateful_index(e.
fork);
4315 if (isf_f == 0)
return out;
4316 const std::vector<T>& fs = gl.
local[isf_f - 1];
4317 if (fs.size() < R)
return out;
4321 const std::size_t B = e.
auxall.size();
4322 if (B == 0 || e.
tag == 0 || e.
tag > e.
auxall[0].size())
return out;
4323 const std::size_t Tt = e.
auxall[0].size();
4324 std::vector<double> nglobal(R, 0.0);
4325 for (std::size_t isf = 1; isf <=
sn.stateful_nodes.size(); ++isf) {
4326 const std::pair<T, std::vector<T>> mg =
4328 for (std::size_t r = 0; r < R; ++r) {
4334 if (std::isfinite(v)) nglobal[r] += v;
4337 std::vector<double> occ(Tt, 0.0);
4338 for (std::size_t t = 0; t < Tt; ++t)
4339 for (std::size_t b = 0; b < B; ++b) occ[t] += nglobal[e.
auxall[b][t] - 1];
4340 if (occ[e.
tag - 1] > 0)
return out;
4341 for (std::size_t t = 0; t + 1 < e.
tag; ++t)
4342 if (occ[t] == 0)
return out;
4345 seed.
local[isf_f - 1][seed.
local[isf_f - 1].size() - R + e.
cls - 1] -=
4348 std::vector<NetState<T>> partials(1, seed);
4354 std::vector<std::size_t> emissions;
4357 for (std::size_t rep = 0; rep < w; ++rep)
4358 for (std::size_t b = 0; b < B; ++b) emissions.push_back(b);
4360 std::size_t wmax = 0;
4361 for (std::size_t b = 0; b < e.
weightlink.size(); ++b)
4363 for (std::size_t rep = 1; rep <= wmax; ++rep)
4364 for (std::size_t b = 0; b < B; ++b)
4367 for (std::size_t ei = 0; ei < emissions.size(); ++ei) {
4368 const std::size_t b = emissions[ei];
4370 const std::size_t isf_b =
sn.stateful_index(bh);
4373 std::vector<NetState<T>> nextp;
4374 std::vector<T> nextq;
4375 for (std::size_t pp = 0; pp < partials.size(); ++pp) {
4377 after_event(
sn, bh, partials[pp].local[isf_b - 1], EventType::ARV, a);
4379 for (std::size_t
io = 0;
io < arv.
space.size(); ++
io) {
4382 nextp.push_back(ns);
4383 nextq.push_back(
io < arv.
prob.size() ? T(partprob[pp] * arv.
prob[
io])
4387 partials.swap(nextp);
4388 partprob.swap(nextq);
4391 out.
space = partials;
4392 for (std::size_t i = 0; i < partials.size(); ++i) {
4394 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< PoolStart< T > > pool_serve_next(const NetworkStruct< T > &sn, const CtmcPool< T > &pool, SchedStrategy sched, const std::vector< std::size_t > &Ks, const std::vector< T > &buf, const std::vector< T > &srv, std::size_t t)
The freed server of pool t takes the next compatible waiting job, in the discipline's order.
void pool_start(const CtmcPool< T > &pool, const std::vector< std::size_t > &Ks, const std::vector< T > &buf, const std::vector< T > &srv, std::size_t s, std::size_t t, const T &w, std::vector< PoolStart< T > > &out)
Class s starts service on pool t in every entry phase of the pool's block.
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.
bool immfeed_self_loop(const NetworkStruct< T > &sn, const Sync< T > &sy)
True when a synchronization is an IMMEDIATE-FEEDBACK SELF-LOOP: a departure whose passive half is an ...
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.
EventOutcome< T > after_event_station_pool(const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, EventType event, std::size_t cls)
Port of State.afterEventStationPool: ARV, DEP and PHASE at a station whose heterogeneous server pools...
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.
Conservation laws of a layered queueing network, enumerated from its structure.
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.
std::vector< Matrix< T > > Dmark
MMAP per-class D1 blocks / BMAP per-batch-size blocks; empty otherwise.
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).
Server breakdown and repair of a station whose server fails and is repaired.
T failure_rate
sn.breakdownMu: 1 / mean failure time
T repair_rate
sn.repairMu: 1 / mean repair time
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
CTMC pair form of a MAP service at an FCFS station, written by ctmc::ctmc_mapc on the solver's privat...
Matrix< T > V
landing law (-D0)^-1 D1
std::size_t p
phases of the original MAP
std::vector< std::pair< std::size_t, std::size_t > > pairs
0-based (i,j), i-major, V(i,j) > 0
bool single
c = 1: carried phase, no pairs
CTMC bookkeeping of a heterogeneous-server station, written by ctmc::ctmc_pools on the solver's priva...
std::vector< std::vector< std::size_t > > len
offset and length of block k of class r
std::vector< std::vector< std::vector< T > > > alpha
entry vector of block k of class r
std::vector< std::vector< std::vector< T > > > exit
exit rates of block k of class r
std::vector< std::vector< bool > > compat
compat[t-1][r-1]
std::vector< double > count
servers per pool
std::vector< std::size_t > alfsorder
pools by ascending class count (ALFS)
std::vector< std::vector< Matrix< T > > > D0
D0 of block k of class r.
std::vector< std::vector< std::size_t > > pools
pools[r-1]: compatible pools of r, ascending
lang::HeteroSchedPolicy policy
bool rotate
ALIS/FAIRNESS order is part of the state.
std::vector< std::vector< std::size_t > > off
std::size_t perm_index(const std::vector< std::size_t > &order) const
1-based index of order in perms, 0 when absent.
std::vector< std::vector< double > > fsfrate
fsfrate[t-1][r-1] = 1/mean (FSF)
std::vector< std::vector< std::size_t > > perms
every pool order, identity first
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
One successor of a pooled service start: the buffer, the servers, its weight and the class started.