29#include <initializer_list>
128std::size_t prefix_count(
const Args& a, std::initializer_list<const char*> keys,
129 const std::string& fn) {
132 const char* missing =
nullptr;
133 for (
const char* k : keys) {
136 throw InputError(fn +
": '" + k +
"' follows '" + missing +
137 "' positionally in the port; give '" + missing +
"' as well");
148bool all_or_none(
const Args& a, std::initializer_list<const char*> keys,
const std::string& fn) {
151 for (
const char* k : keys) {
153 if (!names.empty()) names +=
", ";
154 names += std::string(
"'") + k +
"'";
156 if (n != 0 && n != keys.size())
157 throw InputError(fn +
": " + names +
" tune one computation together; give all of them "
162std::vector<unsigned> read_uints(
Args& a,
const char* key,
const std::string& fn) {
163 const std::vector<int> v = a.ints(key);
164 std::vector<unsigned> out;
165 for (std::size_t i = 0; i < v.size(); ++i) {
167 throw InputError(fn +
": '" + key +
"' holds counts and cannot be negative");
168 out.push_back(
static_cast<unsigned>(v[i]));
174bool required_flag(
Args& a,
const char* key,
const std::string& fn) {
175 if (!a.has(key))
throw InputError(fn +
": missing required argument '" + key +
"'");
176 return a.boolean(key,
false);
181mam::Map<T> read_map(
Args& a,
const char* d0,
const char* d1) {
183 m.D0 = a.matrix<T>(d0);
184 m.D1 = a.matrix<T>(d1);
190mam::Map<T> map_from_pair(
const Json& j,
const std::string& where) {
191 if (!j.is_array() || j.size() != 2)
192 throw InputError(where +
": expected the MAP as a list [D0, D1] of two matrices");
201std::vector<mam::Map<T> > maps_from_json(
const Json& j,
const std::string& where) {
202 if (!j.is_array())
throw InputError(where +
": expected a list of [D0, D1] pairs");
203 std::vector<mam::Map<T> > out;
204 for (std::size_t i = 0; i < j.size(); ++i)
205 out.push_back(map_from_pair<T>(j[i], where +
"[" + std::to_string(i) +
"]"));
216lang::Distrib<T> dist_record(
const Json& j,
const std::string& where) {
217 if (!j.is_object() || !j.contains(
"type"))
218 throw InputError(where +
": expected a distribution record {\"type\": ..., ...} as "
219 "written to model.json");
221 return io::detail::dist_from_json<T>(j);
222 }
catch (
const Json::exception& e) {
223 throw InputError(where +
": malformed distribution record: " + e.what());
233qsys::ServiceLaw<T> read_svc(
Args& a,
const std::string& fn) {
234 Args sv(a.get(
"svc"), fn +
": svc");
235 const std::string type = sv.text(
"type",
"");
236 qsys::ServiceLaw<T> svc;
239 }
else if (type ==
"gamma") {
240 const T al = sv.number<T>(
"alpha");
242 }
else if (type ==
"ph") {
243 const std::vector<T> al = sv.vector<T>(
"alpha");
245 }
else if (type ==
"density") {
247 fn +
": a 'density' service law is a function handle and has no named-JSON form; "
248 "use 'det', 'gamma' or 'ph', or call it from the library");
251 fn +
": svc.type must be 'det', 'gamma' or 'ph', got '" + type +
"'");
259Json encode_shaped(
const std::vector<T>& v,
bool scalar) {
265std::string sim_exact_refusal(
const char* fn,
const char* why) {
266 return std::string(fn) +
": " + why +
267 ", so exact rational arithmetic has nothing to preserve and is refused; rerun with "
268 "--arith double or --arith real";
276void tensor_fill(
const Json& node, std::size_t depth, std::size_t offset,
277 const std::vector<std::size_t>& sz,
const std::vector<std::size_t>& stride,
278 std::vector<T>& data,
const std::string& where) {
279 if (depth == sz.size()) {
281 throw InputError(where +
": the tensor is nested deeper than its first element");
285 if (!node.is_array() || node.size() != sz[depth])
286 throw InputError(where +
": ragged tensor, dimension " + std::to_string(depth + 1) +
287 " must have " + std::to_string(sz[depth]) +
" entries throughout");
288 for (std::size_t i = 0; i < sz[depth]; ++i)
289 tensor_fill<T>(node[i], depth + 1, offset + i * stride[depth], sz, stride, data, where);
298moment::MomentTensor<T> tensor_from_json(
const Json& j,
const std::string& where) {
299 std::vector<std::size_t> sz;
304 while (p->is_array()) {
305 sz.push_back(p->size());
306 if (p->empty())
break;
310 std::vector<std::size_t> stride(sz.size(), 1);
311 for (std::size_t l = 1; l < sz.size(); ++l) stride[l] = stride[l - 1] * sz[l - 1];
312 moment::MomentTensor<T> t(sz);
315 else if (t.numel() > 0)
316 tensor_fill<T>(j, 0, 0, sz, stride, t.data, where);
321Json tensor_nest(
const moment::MomentTensor<T>& t, std::size_t depth, std::size_t offset) {
322 Json out = Json::array();
323 const std::size_t st = t.stride(depth);
324 for (std::size_t i = 0; i < t.sz[depth]; ++i) {
325 if (depth + 1 == t.order())
328 out.push_back(tensor_nest(t, depth + 1, offset + i * st));
335Json encode_tensor(
const moment::MomentTensor<T>& t) {
336 return tensor_nest(t, 0, 0);
339Json encode_sizes(
const std::vector<std::size_t>& v) {
340 Json out = Json::array();
341 for (std::size_t i = 0; i < v.size(); ++i) out.push_back(
encode_count(v[i]));
349#define LINE_MOMENT_VEC_OP(OPNAME, FN, IN, OUT) \
352 static Json run(Args& a) { \
353 const std::vector<T> x = a.vector<T>(IN); \
356 out[OUT] = encode_vector(moment::FN<T>(x)); \
363LINE_MOMENT_VEC_OP(OpMomentFactcumulantFromFactorial, moment_factcumulant_from_factorial,
"f",
365LINE_MOMENT_VEC_OP(OpMomentFactorialFromFactcumulant, moment_factorial_from_factcumulant,
369#undef LINE_MOMENT_VEC_OP
375#define LINE_MOMENT_TENSOR_OP(OPNAME, FN, IN, OUT) \
378 static Json run(Args& a) { \
379 const moment::MomentTensor<T> x = \
380 tensor_from_json<T>(a.get(IN), std::string(#FN ": ") + IN); \
383 out[OUT] = encode_tensor(moment::FN<T>(x)); \
416#undef LINE_MOMENT_TENSOR_OP
418struct OpMjCentralFromRawMean {
420 static Json run(Args& a) {
421 const moment::MomentTensor<T> m =
422 tensor_from_json<T>(a.get(
"m"),
"moment_joint_central_from_raw_mean: m");
423 const std::vector<T> mu = a.vector<T>(
"mu");
431struct OpMjRawFromCentral {
433 static Json run(Args& a) {
434 const moment::MomentTensor<T> mc =
435 tensor_from_json<T>(a.get(
"mc"),
"moment_joint_raw_from_central: mc");
436 const std::vector<T> mu = a.vector<T>(
"mu");
444struct OpMjAggregate {
446 static Json run(Args& a) {
447 const moment::MomentTensor<T> F =
448 tensor_from_json<T>(a.get(
"F"),
"moment_joint_aggregate: F");
458 static Json run(Args& a) {
459 const std::vector<T> f = a.vector<T>(
"f");
460 const std::vector<T> p = a.vector<T>(
"p");
461 const std::vector<unsigned> d = read_uints(a,
"dims",
"moment_joint_marking");
463 const std::vector<std::size_t> dims(d.begin(), d.end());
470struct OpMomentHousematrix {
472 static Json run(Args& a) {
473 const std::string edge = a.text(
"edge",
"");
474 if (edge.empty())
throw InputError(
"moment_housematrix: missing required argument 'edge'");
475 const int n = a.required_integer(
"n");
483struct OpMomentTensorsize {
485 static Json run(Args& a) {
486 const moment::MomentTensor<T> A = tensor_from_json<T>(a.get(
"A"),
"moment_tensorsize: A");
494struct OpMomentTensortrans {
496 static Json run(Args& a) {
497 const moment::MomentTensor<T> A = tensor_from_json<T>(a.get(
"A"),
"moment_tensortrans: A");
498 const Matrix<T> Tm = a.matrix<T>(
"T");
499 const std::size_t mode = a.count(
"mode");
502 if (mode < 1)
throw InputError(
"moment_tensortrans: 'mode' is 1-based and must be >= 1");
509struct OpMomentJointtrans {
511 static Json run(Args& a) {
512 const moment::MomentTensor<T> A = tensor_from_json<T>(a.get(
"A"),
"moment_jointtrans: A");
513 const std::string edge = a.text(
"edge",
"");
514 if (edge.empty())
throw InputError(
"moment_jointtrans: missing required argument 'edge'");
532 static Json run(Args& a) {
533 const std::vector<T> D = a.vector<T>(
"D");
534 const std::vector<unsigned>
P = read_uints(a,
"P",
"fj_amva");
535 const unsigned M = a.uinteger(
"M");
536 const T Z = a.number<T>(
"Z");
550 static Json run(Args& a) {
551 const std::vector<T> D = a.vector<T>(
"D");
552 const std::vector<unsigned>
P = read_uints(a,
"P",
"fj_qgb");
553 const unsigned M = a.uinteger(
"M");
554 const T Z = a.number<T>(
"Z");
564struct OpFjCharMaxBlom {
566 static Json run(Args& a) {
567 const unsigned K = a.uinteger(
"K");
568 a.unsupported(
"Finv",
"it is a quantile function handle; omit it for the standard "
569 "normal the port selects");
570 const std::size_t n = prefix_count(a, {
"alpha",
"beta"},
"fj_char_max_blom");
571 const T alpha = n >= 1 ? a.number<T>(
"alpha") : T();
572 const T beta = n >= 2 ? a.number<T>(
"beta") : T();
574 const std::function<T(
const T&)> none;
575 const fj::FJCharMaxBlomResult<T> r =
583 if (r.bracket_available) {
591struct OpFjCharMaxDiscrete {
593 static Json run(Args& a) {
594 const unsigned K = a.uinteger(
"K");
595 std::string type = a.text(
"dist_type",
"");
596 const T par = a.number<T>(
"param");
598 for (std::size_t i = 0; i < type.size(); ++i)
599 type[i] =
static_cast<char>(std::tolower(
static_cast<unsigned char>(type[i])));
601 if (type ==
"geometric" || type ==
"geom")
603 else if (type ==
"poisson" || type ==
"pois")
607 "fj_char_max_discrete: dist_type must be 'geometric' or 'poisson', got '" + type +
612 out[
"mK"] =
static_cast<long long>(r.mK);
620 static Json run(Args& a) {
621 const T m1 = a.number<T>(
"m1");
622 const T c2 = a.number<T>(
"c2");
629 out[
"kmin"] =
static_cast<long long>(r.kmin);
630 out[
"kmax"] =
static_cast<long long>(r.kmax);
635struct OpFjDagMakespan {
637 static Json run(Args& a) {
638 const Matrix<T> pred = a.matrix<T>(
"pred");
639 Matrix<T> rate = a.matrix<T>(
"rate");
643 const std::size_t n = pred.rows();
644 if ((rate.rows() == 1 || rate.cols() == 1) && rate.rows() * rate.cols() == n && n > 1) {
645 Matrix<T> full(n, n);
646 for (std::size_t i = 0; i < n; ++i)
647 for (std::size_t k = 0; k < n; ++k)
648 full(i, k) = rate.rows() == 1 ? rate(0, i) : rate(i, 0);
662unsigned panels_from_npoints(
Args& o,
const std::string& fn) {
663 const unsigned np = o.uinteger(
"npoints");
664 if (np < 2)
throw InputError(fn +
": options.npoints must be at least 2");
676 static Json run(Args& a) {
677 const std::vector<unsigned> shape = read_uints(a,
"shape",
"fj_delay_opt");
678 const std::vector<T> rate = a.vector<T>(
"rate");
680 unsigned maxsweeps = 0, npanels = 0;
682 if (
const Json* oj = a.opt(
"options")) {
683 Args o(*oj,
"fj_delay_opt: options");
684 o.unsupported(
"tol",
"the port fixes the dispersion tolerance of the inner "
685 "fj_dispersion calls and takes no argument for it");
686 n = prefix_count(o, {
"maxsweeps",
"dtol",
"npoints"},
"fj_delay_opt: options");
687 if (n >= 1) maxsweeps = o.uinteger(
"maxsweeps");
688 if (n >= 2) dtol = o.number<T>(
"dtol");
689 if (n >= 3) npanels = panels_from_npoints(o,
"fj_delay_opt");
693 fj::FJDelayOptResult<T> r;
711struct OpFjDispersion {
713 static Json run(Args& a) {
714 const std::vector<unsigned> shape = read_uints(a,
"shape",
"fj_dispersion");
715 const std::vector<T> rate = a.vector<T>(
"rate");
716 const bool hasD = a.has(
"d");
717 const std::vector<T> d = a.vector_or_empty<T>(
"d");
719 unsigned npanels = 0;
721 if (
const Json* oj = a.opt(
"options")) {
723 throw InputError(
"fj_dispersion: 'options' follows 'd' positionally in the port; "
725 Args o(*oj,
"fj_dispersion: options");
726 n = prefix_count(o, {
"tol",
"npoints"},
"fj_dispersion: options");
727 if (n >= 1) tol = o.number<T>(
"tol");
728 if (n >= 2) npanels = panels_from_npoints(o,
"fj_dispersion");
732 fj::FJDispersionResult<T> r;
747 static Json run(Args& a) {
748 const T lambda = a.number<T>(
"lambda");
749 const T mu = a.number<T>(
"mu");
750 const unsigned s = a.uinteger(
"s");
751 const std::vector<T> c = a.vector<T>(
"c");
775struct OpFjLstMaxHet {
777 static Json run(Args& a) {
778 const std::vector<T> lambda = a.vector<T>(
"lambda");
779 const T s = a.number<T>(
"s");
787struct OpFjResptBulk {
789 static Json run(Args& a) {
790 const unsigned K = a.uinteger(
"K");
791 const T lambda = a.number<T>(
"lambda");
792 const T mu = a.number<T>(
"mu");
793 const unsigned c = a.uinteger(
"c");
794 const bool hasN = a.has(
"nmax");
795 const std::size_t nmax = a.count(
"nmax", 0);
808struct OpFjResptClosed {
810 static Json run(Args& a) {
811 const unsigned K = a.uinteger(
"K");
812 const T x = a.number<T>(
"x");
813 const unsigned M = a.uinteger(
"M");
814 const bool hasA = a.has(
"A");
815 const T A = hasA ? a.number<T>(
"A") : T();
817 const fj::FJResptClosedResult<T> r =
821 out[
"exact"] = r.exact;
826struct OpFjResptNosplit {
828 static Json run(Args& a) {
829 const unsigned K = a.uinteger(
"K");
830 const T lambda = a.number<T>(
"lambda");
831 const T mu = a.number<T>(
"mu");
841struct OpFjSerialization {
843 static Json run(Args& a) {
844 const std::vector<T> Rs = a.vector<T>(
"Rs");
845 const T R0 = a.number<T>(
"R0");
846 const unsigned M = a.uinteger(
"M");
847 const bool hasAlpha = a.has(
"alpha");
848 const T alpha = hasAlpha ? a.number<T>(
"alpha") : T();
850 const fj::FJSerializationResult<T> r = hasAlpha
861struct OpFjTsmCapacity {
863 static Json run(Args& a) {
864 const unsigned s = a.uinteger(
"s");
865 const std::vector<T> f = a.vector<T>(
"f");
866 const std::vector<unsigned> rr = read_uints(a,
"r",
"fj_tsm_capacity");
867 const std::vector<T> x = a.vector<T>(
"x");
875 Json states = Json::array();
876 for (std::size_t i = 0; i < r.states.size(); ++i) {
877 Json row = Json::array();
878 for (std::size_t k = 0; k < r.states[i].size(); ++k)
879 row.push_back(
static_cast<long long>(r.states[i][k]));
880 states.push_back(row);
883 p[
"states"] = states;
890struct OpFjXmaxCoxian {
892 static Json run(Args& a) {
893 const unsigned K = a.uinteger(
"K");
894 const T mu1 = a.number<T>(
"mu1");
895 const T mu2 = a.number<T>(
"mu2");
896 const T q = a.number<T>(
"q");
909 static Json run(Args& a) {
910 const std::vector<T> lambda = a.vector<T>(
"lambda");
911 const bool hasN = a.has(
"n");
912 const unsigned n = a.uinteger(
"n", 0);
920struct OpFjXmaxMomentsHet {
922 static Json run(Args& a) {
923 const std::vector<T> lambda = a.vector<T>(
"lambda");
924 const bool hasN = a.has(
"n");
925 const unsigned n = a.uinteger(
"n", 0);
936 static Json run(Args& a) {
937 const T m1 = a.number<T>(
"m1");
938 const T m2 = a.number<T>(
"m2");
939 const unsigned K = a.uinteger(
"K");
949struct OpFjMg1ResptMoments {
951 static Json run(Args& a) {
952 const T lambda = a.number<T>(
"lambda");
953 const T ES = a.number<T>(
"ES");
954 const T ES2 = a.number<T>(
"ES2");
955 const T ES3 = a.number<T>(
"ES3");
966Json forktail_results(
const fj::ForkTailResult<T>& r) {
975struct OpFjTailForktail {
977 static Json run(Args& a) {
978 const std::vector<T> ET = a.vector<T>(
"ET");
979 const std::vector<T> VT = a.vector<T>(
"VT");
980 const std::size_t n = prefix_count(a, {
"K",
"p",
"P"},
"fj_tail_forktail");
981 const std::vector<T> K = n >= 1 ? a.vector<T>(
"K") : std::vector<T>();
982 const T p = n >= 2 ? a.number<T>(
"p") : T();
983 const std::vector<T>
P = n >= 3 ? a.vector<T>(
"P") : std::vector<T>();
993struct OpFjTailOrdstat {
995 static Json run(Args& a) {
996 const std::vector<T> ET = a.vector<T>(
"ET");
997 const std::vector<T> VT = a.vector<T>(
"VT");
998 const std::size_t n = prefix_count(a, {
"K",
"p",
"kreq"},
"fj_tail_ordstat");
999 const std::size_t K = n >= 1 ? a.count(
"K") : 0;
1000 const T p = n >= 2 ? a.number<T>(
"p") : T();
1001 const std::size_t kreq = n >= 3 ? a.count(
"kreq") : 0;
1015struct OpFjBranchMembers {
1017 static Json run(Args& a) {
1018 Args l(a.get(
"lqn"),
"fj_branch_members: lqn");
1019 fj::LqnBranchView<T> v;
1020 v.graph = l.matrix<T>(
"graph");
1021 v.ashift = l.count(
"ashift");
1022 v.nacts = l.count(
"nacts");
1023 v.actposttype = l.ints(
"actposttype");
1025 const std::size_t joinaidx = a.count(
"joinaidx");
1028 Json members = Json::array();
1029 for (std::size_t i = 0; i < m.size(); ++i) members.push_back(encode_sizes(m[i]));
1031 out[
"members"] = members;
1043 static Json run(Args& a) {
1044 const mam::Map<T> m = map_from_pair<T>(a.get(
"lineMAP"),
"fj_dist2fj: lineMAP");
1045 const std::string distType = a.text(
"distType",
"");
1046 Args sn(a.get(
"sn"),
"fj_dist2fj: sn");
1047 const Matrix<double> procid = sn.matrix<
double>(
"procid");
1049 const std::size_t ist = a.count(
"ist");
1050 const std::size_t r = a.count(
"r");
1053 if (distType ==
"arrival")
1055 else if (distType ==
"service")
1058 throw InputError(
"fj_dist2fj: distType must be 'arrival' or 'service', got '" +
1060 if (ist < 1 || r < 1 || ist > procid.rows() || r > procid.cols())
1061 throw InputError(
"fj_dist2fj: (ist, r) are 1-based and must index sn.procid");
1062 const double code = procid(ist - 1, r - 1);
1070 "fj_dist2fj: sn.procid(ist, r) = " + std::to_string(code) +
1071 " is not a process FJ_codes takes (EXP=0, ERLANG=1, HYPEREXP=2, MAP=5)");
1080 out[
"ArrChoice"] = d.choice;
1086 out[
"SerChoice"] = d.choice;
1102 const std::vector<T> s = a.vector<T>(
"s");
1104 std::vector<T> v(s.size());
1105 for (std::size_t i = 0; i < s.size(); ++i) v[i] = L(s[i]);
1113 static Json run(Args& a) {
1114 const T d = a.number<T>(
"d");
1119struct OpAoiLstErlang {
1121 static Json run(Args& a) {
1122 const unsigned k = a.uinteger(
"k");
1123 const T mu = a.number<T>(
"mu");
1130 static Json run(Args& a) {
1131 const T mu = a.number<T>(
"mu");
1138 static Json run(Args& a) {
1139 const std::vector<T> alpha = a.vector<T>(
"alpha");
1140 const Matrix<T> Tm = a.matrix<T>(
"T");
1146struct OpAoiDist2ph {
1148 static Json run(Args& a) {
1149 const mam::Map<T> m = map_from_pair<T>(a.get(
"proc"),
"aoi_dist2ph: proc");
1168 std::size_t nmax = 0;
1172Truncation<T> read_truncation(
Args& a,
const std::string& fn) {
1174 tr.given = all_or_none(a, {
"tol",
"nmax"}, fn);
1176 tr.tol = a.number<T>(
"tol");
1177 tr.nmax = a.count(
"nmax");
1185struct OpQsysMapg1k {
1187 static Json run(Args& a) {
1188 const mam::Map<T> arrival = read_map<T>(a,
"D0",
"D1");
1189 const qsys::ServiceLaw<T> svc = read_svc<T>(a,
"qsys_mapg1k");
1190 const std::size_t K = a.count(
"K");
1191 const Truncation<T> tr = read_truncation<T>(a,
"qsys_mapg1k");
1193 const qsys::MapG1kResult<T> r = tr.given
1211 out[
"countingResidual"] =
encode_scalar(r.countingResidual);
1216struct OpQsysMmapg1k {
1218 static Json run(Args& a) {
1219 const Matrix<T> D0 = a.matrix<T>(
"D0");
1220 const std::vector<Matrix<T> > D1c = a.matrices<T>(
"D1c");
1221 const qsys::ServiceLaw<T> svc = read_svc<T>(a,
"qsys_mmapg1k");
1222 const std::size_t K = a.count(
"K");
1223 const Truncation<T> tr = read_truncation<T>(a,
"qsys_mmapg1k");
1225 const qsys::MmapG1kResult<T> r =
1233 out[
"throughputAggregate"] =
encode_scalar(r.throughputAggregate);
1248struct OpQsysMapg1kPerflow {
1250 static Json run(Args& a) {
1251 const std::vector<mam::Map<T> > flows =
1252 maps_from_json<T>(a.get(
"MAPS"),
"qsys_mapg1k_perflow: MAPS");
1253 const qsys::ServiceLaw<T> svc = read_svc<T>(a,
"qsys_mapg1k_perflow");
1254 const std::size_t K = a.count(
"K");
1255 const Truncation<T> tr = read_truncation<T>(a,
"qsys_mapg1k_perflow");
1257 const qsys::MapG1kPerflowResult<T> r =
1265 out[
"throughputAggregate"] =
encode_scalar(r.throughputAggregate);
1275struct OpQsysSvclawCoeffs {
1277 static Json run(Args& a) {
1278 const qsys::ServiceLaw<T> svc = read_svc<T>(a,
"qsys_svclaw_coeffs");
1279 const T theta = a.number<T>(
"theta");
1280 const T tol = a.number<T>(
"tol");
1281 const std::size_t nmaxCap = a.count(
"nmaxCap");
1304struct OpQsysLdpsWorkload {
1306 static Json run(Args& a) {
1307 const T lambda = a.number<T>(
"lambda");
1308 const lang::Distrib<T> law = dist_record<T>(a.get(
"B"),
"qsys_ldps_workload: B");
1309 const std::vector<T> alpha = a.vector<T>(
"alpha");
1310 const std::size_t N = a.count(
"N");
1311 const bool tuned = a.has(
"t") || a.has(
"ngrid");
1312 if (tuned && !a.has(
"ngrid"))
1313 throw InputError(
"qsys_ldps_workload: the port takes 't' and 'ngrid' together; give "
1314 "'ngrid' with 't'");
1315 const std::vector<T> t = a.vector_or_empty<T>(
"t");
1316 const std::size_t ngrid = a.count(
"ngrid", 0);
1318 qsys::WorkloadServiceLaw<T> B;
1321 B.scv = T(m2 / (B.mean * B.mean) - num_traits<T>::from_int(1));
1323 const qsys::LdpsWorkloadResult<T> r =
1342struct OpQsysMmapgk1 {
1344 static Json run(Args& a) {
1345 const std::vector<Matrix<T> >
MMAP = a.matrices<T>(
"MMAP");
1346 const Json& sj = a.get(
"svc");
1347 if (!sj.is_array())
throw InputError(
"qsys_mmapgk1: svc must be a list, one law per type");
1348 std::vector<qsys::MmapGk1Service<T> > svc;
1349 for (std::size_t k = 0; k < sj.size(); ++k) {
1350 const std::string where =
"qsys_mmapgk1: svc[" + std::to_string(k) +
"]";
1351 if (sj[k].is_array()) {
1352 svc.push_back(qsys::MmapGk1Service<T>(map_from_pair<T>(sj[k], where)));
1353 }
else if (sj[k].is_object() && sj[k].contains(
"lst")) {
1355 where +
": a transform struct carries an lst function handle, which cannot "
1356 "cross the JSON API boundary; give the law as a distribution record "
1357 "or a [D0, D1] pair");
1359 svc.push_back(qsys::MmapGk1Service<T>(dist_record<T>(sj[k], where)));
1362 const bool tuned = all_or_none(a, {
"wPoints",
"numWMoms",
"tol",
"iterMax"},
"qsys_mmapgk1");
1363 if (a.has(
"quadNodes") && !tuned)
1364 throw InputError(
"qsys_mmapgk1: 'quadNodes' follows 'wPoints', 'numWMoms', 'tol' and "
1365 "'iterMax' positionally in the port; give them as well");
1366 const std::vector<T> w = a.vector_or_empty<T>(
"wPoints");
1367 const std::size_t nm = a.count(
"numWMoms", 0);
1368 const double tol = a.scalar<
double>(
"tol", 0.0);
1369 const std::size_t iterMax = a.count(
"iterMax", 0);
1370 const bool hasQ = a.has(
"quadNodes");
1371 const std::size_t q = a.count(
"quadNodes", 0);
1373 qsys::MmapGk1Result<T> r;
1399struct OpQsysMmapgk1Lcfspr {
1401 static Json run(Args& a) {
1402 const std::vector<Matrix<T> >
MMAP = a.matrices<T>(
"MMAP");
1403 const Json& sj = a.get(
"svc");
1405 throw InputError(
"qsys_mmapgk1_lcfspr: svc must be a list, one law per type");
1406 std::vector<qsys::MmapGk1Service<T> > svc;
1407 for (std::size_t k = 0; k < sj.size(); ++k) {
1408 const std::string where =
"qsys_mmapgk1_lcfspr: svc[" + std::to_string(k) +
"]";
1409 if (sj[k].is_array()) {
1410 svc.push_back(qsys::MmapGk1Service<T>(map_from_pair<T>(sj[k], where)));
1411 }
else if (sj[k].is_object() && sj[k].contains(
"lst")) {
1413 where +
": a transform struct carries an lst function handle, which cannot "
1414 "cross the JSON API boundary; give the law as a distribution record "
1415 "or a [D0, D1] pair");
1417 svc.push_back(qsys::MmapGk1Service<T>(dist_record<T>(sj[k], where)));
1420 qsys::MmapGk1LcfsprOptions<T> opt;
1421 if (a.has(
"nMax")) opt.nMax =
static_cast<long>(a.count(
"nMax"));
1422 opt.wPoints = a.vector_or_empty<T>(
"wPoints");
1423 opt.quadNodes = a.count(
"quadNodes", 120);
1424 opt.tol = a.scalar<
double>(
"tol", 1e-12);
1425 const bool wantLst = a.has(
"s");
1426 const std::vector<T> sPts = wantLst ? a.vector<T>(
"s") : std::vector<T>();
1437 out[
"classMeanQueueLength"] =
encode_vector(r.classMeanQueueLength);
1440 out[
"queueLengthDistr"] =
encode_vector(r.queueLengthDistr);
1441 out[
"classQueueLengthDistr"] =
encode_vectors(r.classQueueLengthDistr);
1445 const std::size_t K = r.lambdas.size();
1446 std::vector<std::vector<T> > lv(K, std::vector<T>(sPts.size()));
1447 for (std::size_t i = 0; i < sPts.size(); ++i) {
1448 const std::vector<std::complex<double> > w =
1449 r.respLST(std::complex<double>(num_traits<T>::to_double(sPts[i]), 0.0));
1450 for (std::size_t k = 0; k < K; ++k) lv[k][i] = num_traits<T>::from_double(w[k].real());
1454 out[
"analyzer"] = r.analyzer;
1465struct OpQsysTandemUbCiucu {
1467 static Json run(Args& a) {
1468 const std::vector<T> x = a.vector<T>(
"x");
1469 const lang::Distrib<T> law = dist_record<T>(a.get(
"lst"),
"qsys_tandem_ub_ciucu: lst");
1470 const std::vector<T> p = a.vector<T>(
"p");
1471 const std::vector<T> mu = a.vector<T>(
"mu");
1472 a.unsupported(
"dlst",
"it is a function handle; omit it and the port differentiates the "
1473 "transform of lst numerically");
1475 const std::function<T(
const T&)> lst = [law](
const T& s) {
return lang::dist_lst(law, s); };
1486 out[
"analyzer"] = r.analyzer;
1496Json lindley_results(
const qsys::LindleyResult<T>& r,
bool scalar) {
1498 out[
"mean"] = encode_shaped(r.mean, scalar);
1499 out[
"var"] = encode_shaped(r.var, scalar);
1501 out[
"mmax"] =
static_cast<long long>(r.mmax);
1502 out[
"analyzer"] = r.analyzer;
1506struct OpQsysHh1Lindley {
1508 static Json run(Args& a) {
1509 const std::vector<T> lambda = a.vector<T>(
"lambda");
1510 const std::vector<T> pa = a.vector<T>(
"pa");
1511 const std::vector<T> mu = a.vector<T>(
"mu");
1512 const std::vector<T> ps = a.vector<T>(
"ps");
1513 const bool scalar = !a.get(
"Wn").is_array();
1514 const std::vector<T> Wn = a.vector<T>(
"Wn");
1515 const bool hasM = a.has(
"mmax");
1516 const unsigned mmax = a.uinteger(
"mmax", 0);
1519 return lindley_results(
1529struct OpQsysMm1Lindley {
1531 static Json run(Args& a) {
1532 const T lambda = a.number<T>(
"lambda");
1533 const T mu = a.number<T>(
"mu");
1534 const bool scalar = !a.get(
"Wn").is_array();
1535 const std::vector<T> Wn = a.vector<T>(
"Wn");
1536 const bool hasM = a.has(
"mmax");
1537 const unsigned mmax = a.uinteger(
"mmax", 0);
1549struct OpQsysLindleyMoment {
1551 static Json run(Args& a) {
1552 const T lambda = a.number<T>(
"lambda");
1553 const T mu = a.number<T>(
"mu");
1554 const bool scalar = !a.get(
"Wn").is_array();
1555 const std::vector<T> Wn = a.vector<T>(
"Wn");
1556 const unsigned m = a.uinteger(
"m");
1567struct OpQsysMm1TandemLindley {
1569 static Json run(Args& a) {
1570 const T lambda = a.number<T>(
"lambda");
1571 const T mu1 = a.number<T>(
"mu1");
1572 const T mu2 = a.number<T>(
"mu2");
1573 const bool s1 = !a.get(
"Wk").is_array();
1574 const bool s2 = !a.get(
"Wk1").is_array();
1575 const std::vector<T> Wk = a.vector<T>(
"Wk");
1576 const std::vector<T> Wk1 = a.vector<T>(
"Wk1");
1578 const bool scalar = s1 && s2;
1579 const qsys::Mm1TandemLindleyResult<T> r =
1583 out[
"mean"] = encode_shaped(r.mean, scalar);
1584 out[
"interdepMean"] = encode_shaped(r.interdepMean, scalar);
1585 out[
"idleProb"] = encode_shaped(r.idleProb, scalar);
1586 out[
"analyzer"] = r.analyzer;
1591struct OpQsysTandemLindley {
1593 static Json run(Args& a) {
1594 const std::vector<T> A = a.vector<T>(
"A");
1595 const Matrix<T> S = a.matrix<T>(
"S");
1596 const bool hasW0 = a.has(
"W0");
1597 const std::vector<T> W0 = a.vector_or_empty<T>(
"W0");
1599 const qsys::TandemLindleyResult<T> r =
1606 out[
"analyzer"] = r.analyzer;
1613 static Json run(Args& a) {
1614 const std::vector<T> lambda = a.vector<T>(
"lambda");
1615 const std::vector<T> mu = a.vector<T>(
"mu");
1638 static Json run(Args& a) {
1639 const double lambda = a.number<
double>(
"lambda");
1640 if (a.get(
"svc").is_string())
1642 "qsys_mg1_ps: argument 'svc' cannot cross the JSON API boundary as a transform "
1643 "handle; give the phase-type initial vector alpha, with svcparam its "
1645 const std::vector<double> alpha = a.vector<
double>(
"svc");
1646 const Matrix<double> Tm = a.matrix<
double>(
"svcparam");
1647 qsys::Mg1PsOptions opt;
1648 if (a.has(
"x")) opt.x = a.vector<
double>(
"x");
1649 if (a.has(
"s")) opt.s = a.vector<
double>(
"s");
1650 if (a.has(
"t")) opt.t = a.vector<
double>(
"t");
1651 opt.nterms = a.count(
"nterms", opt.nterms);
1652 a.unsupported(
"pdf",
"it is a density function handle; on the phase-type path the port "
1653 "derives the density itself");
1666 out[
"atomUncond"] = r.atomUncond;
1670 out[
"meanUncond"] = r.meanUncond;
1671 out[
"m2Uncond"] = r.m2Uncond;
1672 out[
"varUncond"] = r.varUncond;
1688struct OpQsysBmapm1 {
1690 static Json run(Args& a) {
1691 const std::vector<Matrix<T> > D = a.matrices<T>(
"D");
1692 const T mu = a.number<T>(
"mu");
1693 const bool tuned = a.has(
"Uniformization") || a.has(
"MaxLevel") || a.has(
"MaxIter") ||
1694 a.has(
"Tolerance") || a.has(
"TailTolerance");
1695 if (tuned && !(a.has(
"MaxIter") && a.has(
"Tolerance") && a.has(
"TailTolerance")))
1696 throw InputError(
"qsys_bmapm1: the port takes its options together; with any of them "
1697 "give 'MaxIter', 'Tolerance' and 'TailTolerance'");
1698 const T q = a.scalar<T>(
"Uniformization", num_traits<T>::from_int(0));
1699 const std::size_t maxLevel = a.count(
"MaxLevel", 0);
1700 const unsigned maxIter = a.uinteger(
"MaxIter", 0);
1701 const T tol = a.scalar<T>(
"Tolerance", num_traits<T>::from_int(0));
1702 const double tailTol = a.scalar<
double>(
"TailTolerance", 0.0);
1704 const qsys::BmapM1Result<T> r =
1720 out[
"decayRate"] = r.decayRate;
1727 out[
"truncError"] = r.truncError;
1728 out[
"gConverged"] = r.gConverged;
1734struct OpQsysMaximaTwomoment {
1736 static Json run(Args& a) {
1737 const std::size_t n = a.count(
"n");
1738 const T mean = a.number<T>(
"mean_");
1739 const T cs2 = a.number<T>(
"cs2");
1740 const std::size_t k = prefix_count(a, {
"q",
"exactFitted"},
"qsys_maxima_twomoment");
1741 const T q = k >= 1 ? a.number<T>(
"q") : T();
1742 const bool ef = k >= 2 ? a.boolean(
"exactFitted",
false) :
false;
1744 const qsys::MaximaResult<T> r =
1753 out[
"reliable"] = r.reliable;
1754 out[
"family"] = r.family;
1755 if (r.hasFitted) out[
"exactFittedValue"] =
encode_scalar(r.exactFittedValue);
1766struct OpQsysMgisrgiWhitt {
1768 static Json run(Args& a) {
1769 const T lambda = a.number<T>(
"lambda");
1770 const T mu = a.number<T>(
"mu");
1771 const unsigned s = a.uinteger(
"s");
1772 const double r = a.number<
double>(
"r");
1773 const Json& pj = a.get(
"patience");
1774 if (pj.is_object() || pj.is_string())
1776 "qsys_mgisrgi_whitt: argument 'patience' cannot cross the JSON API boundary as a "
1777 "hazard or ccdf function handle; give the exponential rate theta as a number");
1778 const qsys::Patience<T> patience =
1780 qsys::MgisrgiOptions opt;
1781 if (a.has(
"wPoints")) opt.wPoints = a.vector<
double>(
"wPoints");
1782 opt.maxQueue = a.count(
"maxQueue", opt.maxQueue);
1783 opt.tol = a.scalar<
double>(
"tol", opt.tol);
1784 opt.invMethod = a.text(
"invMethod", opt.invMethod);
1785 opt.invN = a.count(
"invN", opt.invN);
1787 const qsys::QsysAbandonResult<T> res =
1790 out[
"queueLengthDist"] =
encode_vector(res.queueLengthDist);
1797 out[
"meanQueueLength"] =
encode_scalar(res.meanQueueLength);
1804 out[
"meanWaitAbandon"] =
encode_scalar(res.meanWaitAbandon);
1807 out[
"secondMomentWait"] =
encode_scalar(res.secondMomentWait);
1809 out[
"totalAbandonRates"] =
encode_vector(res.totalAbandonRates);
1810 out[
"numWaitingSpaces"] =
encode_count(res.numWaitingSpaces);
1811 out[
"exponentialPatience"] = res.exponentialPatience;
1822struct OpQsysMapmapc {
1824 static Json run(Args& a) {
1825 const mam::Map<T> arrival = read_map<T>(a,
"D0",
"D1");
1826 const mam::Map<T> service = read_map<T>(a,
"S0",
"S1");
1827 const unsigned c = a.uinteger(
"c");
1828 const std::size_t k = prefix_count(a, {
"maxNumComp",
"numWMoms"},
"qsys_mapmapc");
1829 const std::size_t dsz = k >= 1 ? a.count(
"maxNumComp") : 0;
1830 const std::size_t nw = k >= 2 ? a.count(
"numWMoms") : 0;
1832 const qsys::MapPhcResult<T> r =
1834 : (k == 1 ? qsys::
qsys_mapmapc<T>(arrival, service, c, dsz)
1835 : qsys::
qsys_mapmapc<T>(arrival, service, c, dsz, nw));
1842 out[
"waitingTimeMoments"] =
encode_vector(r.waitingTimeMoments);
1844 out[
"waitingTimePoints"] =
encode_vector(r.waitingTimePoints);
1856struct OpQsysMmapmap1 {
1858 static Json run(Args& a) {
1859 const std::vector<Matrix<T> > D = a.matrices<T>(
"D");
1860 const std::vector<mam::Map<T> > svc = maps_from_json<T>(a.get(
"svc"),
"qsys_mmapmap1: svc");
1861 const bool hasCarry = a.has(
"carry");
1862 const std::vector<int> ci = a.ints_or_empty(
"carry");
1865 throw InputError(
"qsys_mmapmap1: D must be {D0, D1_1, ..., D1_K} with K >= 1");
1869 mm.Dc.push_back(D[1]);
1870 for (std::size_t k = 2; k < D.size(); ++k) {
1871 if (D[k].rows() != mm.D1.rows() || D[k].cols() != mm.D1.cols())
1872 throw InputError(
"qsys_mmapmap1: the blocks of D must share one size");
1873 for (std::size_t i = 0; i < mm.D1.rows(); ++i)
1874 for (std::size_t j = 0; j < mm.D1.cols(); ++j)
1875 mm.D1(i, j) = T(mm.D1(i, j) + D[k](i, j));
1876 mm.Dc.push_back(D[k]);
1878 std::vector<bool> carry;
1879 for (std::size_t i = 0; i < ci.size(); ++i) {
1880 if (ci[i] != 0 && ci[i] != 1)
1881 throw InputError(
"qsys_mmapmap1: 'carry' holds flags, 0 or 1");
1882 carry.push_back(ci[i] != 0);
1890 Json cj = Json::array();
1891 for (std::size_t i = 0; i < r.carry.size(); ++i) cj.push_back(
static_cast<bool>(r.carry[i]));
1903struct OpSimQuestOptions {
1904 static Json run(Args& a) {
1905 sim::QuestOptions
in;
1906 const Json* oj = a.opt(
"options");
1908 Args o(*oj,
"sim_quest_options: options");
1909 in.b0 =
static_cast<long>(o.integer(
"b0",
static_cast<int>(
in.b0)));
1910 in.m0 =
static_cast<long>(o.integer(
"m0",
static_cast<int>(
in.m0)));
1912 const std::vector<int> s = o.ints(
"s");
1913 in.s.assign(s.begin(), s.end());
1915 in.beta = o.scalar<
double>(
"beta",
in.beta);
1916 in.eta = o.scalar<
double>(
"eta",
in.eta);
1917 in.theta = o.scalar<
double>(
"theta",
in.theta);
1918 in.weight = o.scalar<
double>(
"weight",
in.weight);
1919 in.force = o.boolean(
"force",
in.force);
1925 opt[
"b0"] =
static_cast<long long>(r.b0);
1926 opt[
"m0"] =
static_cast<long long>(r.m0);
1927 Json s = Json::array();
1928 for (std::size_t i = 0; i < r.s.size(); ++i) s.push_back(
static_cast<long long>(r.s[i]));
1930 opt[
"beta"] = r.beta;
1932 opt[
"theta"] = r.theta;
1933 opt[
"weight"] = r.weight;
1934 opt[
"force"] = r.force;
1941struct OpSimQuestHeuristicCi {
1943 static Json run(Args& a) {
1944 if constexpr (!num_traits<T>::has_transcendental) {
1946 "sim_quest_heuristic_ci",
"the interval is a quantile times a square root"));
1948 const std::vector<T> bqe = a.vector<T>(
"bqe");
1949 const T centre = a.number<T>(
"centre");
1950 const T Ap = a.number<T>(
"Ap");
1951 const T Np = a.number<T>(
"Np");
1952 const std::size_t nstar = a.count(
"nstar");
1953 const double alpha = a.number<
double>(
"alpha");
1954 const bool ac = required_flag(a,
"useAutocorr",
"sim_quest_heuristic_ci");
1956 const sim::QuestInterval<T> r =
1967struct OpSimRunlength {
1969 static Json run(Args& a) {
1970 if constexpr (!num_traits<T>::has_transcendental) {
1972 "sim_runlength",
"the run length is set by a normal quantile"));
1974 const T mean = a.number<T>(
"mean_");
1975 const T av = a.number<T>(
"asymVar");
1976 const std::size_t k =
1977 prefix_count(a, {
"relPrecision",
"confidence",
"runLength"},
"sim_runlength");
1978 const T rp = k >= 1 ? a.number<T>(
"relPrecision") : T();
1979 const T cf = k >= 2 ? a.number<T>(
"confidence") : T();
1980 const T rl = k >= 3 ? a.number<T>(
"runLength") : T();
1982 sim::RunLengthResult<T> r;
1988 out[
"requiredRunLength"] =
encode_scalar(r.requiredRunLength);
1992 out[
"achievedRelPrecision"] =
encode_scalar(r.achievedRelPrecision);
2006[[noreturn]]
void refuse_lst_handle(
const std::string& fn,
const char* key) {
2008 fn +
": argument '" + key +
"' cannot cross the JSON API boundary as an LST function "
2009 "handle; give it as a distribution record {\"type\": ..., ...}");
2014 static Json run(Args& a) {
2015 const double alpha = a.number<
double>(
"alpha");
2016 const double mu = a.number<
double>(
"mu");
2017 const unsigned c = a.uinteger(
"c");
2018 const unsigned K = a.uinteger(
"K");
2026struct OpQsysEngset {
2027 static Json run(Args& a) {
2028 const double alpha = a.number<
double>(
"alpha");
2029 const double mu = a.number<
double>(
"mu");
2030 const unsigned c = a.uinteger(
"c");
2031 const unsigned K = a.uinteger(
"K");
2039 static Json run(Args& a) {
2040 const double alpha = a.number<
double>(
"alpha");
2041 const unsigned K = a.uinteger(
"K");
2042 if (a.get(
"svc").is_string()) refuse_lst_handle(
"qsys_mg1kk",
"svc");
2043 const lang::Distrib<double> svc = dist_record<double>(a.get(
"svc"),
"qsys_mg1kk: svc");
2045 if (a.has(
"ES")) (void)a.number<
double>(
"ES");
2054 static Json run(Args& a) {
2055 const T EO = a.number<T>(
"EO");
2056 const T ES = a.number<T>(
"ES");
2057 const unsigned c = a.uinteger(
"c");
2058 const unsigned K = a.uinteger(
"K");
2065struct OpQsysMg1Setup {
2067 static Json run(Args& a) {
2068 const T lambda = a.number<T>(
"lambda");
2069 const T mu = a.number<T>(
"mu");
2070 const T cs = a.number<T>(
"cs");
2071 qsys::Mg1SetupResult<T> r;
2072 if (a.get(
"EU").is_object()) {
2073 const lang::Distrib<T> U = dist_record<T>(a.get(
"EU"),
"qsys_mg1_setup: EU");
2077 const T EU = a.number<T>(
"EU");
2080 "qsys_mg1_setup: qsys_mg1_setup needs the second moment EU2 of the setup time "
2081 "after EU, or a setup Distribution in place of EU");
2082 const T EU2 = a.number<T>(
"EU2");
2097struct OpQsysMg1Exceptional {
2099 static Json run(Args& a) {
2100 const T lambda = a.number<T>(
"lambda");
2101 const T mu = a.number<T>(
"mu");
2102 const T cs = a.number<T>(
"cs");
2103 const T muf = a.number<T>(
"muf");
2104 const T csf = a.number<T>(
"csf");
2119 static Json run(Args& a) {
2120 const double lambda = a.number<
double>(
"lambda");
2121 const double mu = a.number<
double>(
"mu");
2122 const unsigned c = a.uinteger(
"c");
2130 static Json run(Args& a) {
2131 const double lambda = a.number<
double>(
"lambda");
2132 const double mu = a.number<
double>(
"mu");
2133 const unsigned c = a.uinteger(
"c");
2140struct OpQsysMg1PrioPr {
2142 static Json run(Args& a) {
2143 const std::vector<T> lambda = a.vector<T>(
"lambda");
2144 const std::vector<T> mu = a.vector<T>(
"mu");
2145 const std::vector<T> cs = a.vector<T>(
"cs");
2146 const std::vector<T> ES3 = a.vector_or_empty<T>(
"ES3");
2158struct OpQsysMmcPrio {
2160 static Json run(Args& a) {
2161 const std::vector<T> lambda = a.vector<T>(
"lambda");
2162 const T mu = a.number<T>(
"mu");
2163 const unsigned c = a.uinteger(
"c");
2175struct OpQsysMmcPrioTardiness {
2176 static Json run(Args& a) {
2177 const std::vector<double> lambda = a.vector<
double>(
"lambda");
2178 const double mu = a.number<
double>(
"mu");
2179 const unsigned c = a.uinteger(
"c");
2180 const std::vector<double> d = a.vector<
double>(
"d");
2181 const std::string type = a.text(
"type",
"np");
2182 const std::string method = a.text(
"method",
"euler");
2194struct OpQsysMmcPrioEta {
2195 static Json run(Args& a) {
2196 const std::vector<double> lambda = a.vector<
double>(
"lambda");
2197 const double mu = a.number<
double>(
"mu");
2198 const unsigned c = a.uinteger(
"c");
2199 const unsigned r = a.uinteger(
"r");
2200 const unsigned v = a.uinteger(
"v");
2201 const unsigned q = a.uinteger(
"q");
2202 const std::vector<double> d = a.vector<
double>(
"d");
2203 const std::string type = a.text(
"type",
"np");
2204 const std::string method = a.text(
"method",
"euler");
2216struct OpQsysMg1Conservation {
2218 static Json run(Args& a) {
2219 const std::vector<T> lambda = a.vector<T>(
"lambda");
2220 const std::vector<T> mu = a.vector<T>(
"mu");
2221 const std::vector<T> cs = a.vector<T>(
"cs");
2222 const std::vector<T> W = a.vector_or_empty<T>(
"W");
2225 Json res = Json::object();
2238struct OpQsysMg1Sjf {
2239 static Json run(Args& a) {
2240 const std::vector<double> lambda = a.vector<
double>(
"lambda");
2241 const std::vector<double> mu = a.vector<
double>(
"mu");
2242 const std::vector<double> cs = a.vector<
double>(
"cs");
2247 out[
"rhohat"] = r.rhohat;
2254struct OpQsysMg1Busy {
2255 static Json run(Args& a) {
2256 const double lambda = a.number<
double>(
"lambda");
2257 const double mu = a.number<
double>(
"mu");
2258 const double cs = a.number<
double>(
"cs");
2259 qsys::Mg1BusyOptions o;
2260 if (a.has(
"ES3")) o.ES3 = a.number<
double>(
"ES3");
2262 if (a.get(
"lst").is_string()) refuse_lst_handle(
"qsys_mg1_busy",
"lst");
2263 const lang::Distrib<double> d = dist_record<double>(a.get(
"lst"),
"qsys_mg1_busy: lst");
2266 if (a.has(
"sPoints")) o.sPoints = a.vector<
double>(
"sPoints");
2274 static Json run(Args& a) {
2275 if (a.get(
"LA").is_string()) refuse_lst_handle(
"qsys_gimc",
"LA");
2276 const lang::Distrib<double> LA = dist_record<double>(a.get(
"LA"),
"qsys_gimc: LA");
2277 const double mu = a.number<
double>(
"mu");
2278 const unsigned c = a.uinteger(
"c");
2279 const double lambda = a.has(
"lambda") ? a.number<
double>(
"lambda") : -1.0;
2288 static Json run(Args& a) {
2289 const double lambda = a.number<
double>(
"lambda");
2290 const double mu = a.number<
double>(
"mu");
2291 const long nmax = a.has(
"nmax") ?
static_cast<long>(a.count(
"nmax")) : -1L;
2298Json encode_cplx_pairs(
const std::vector<std::complex<double> >& v) {
2299 Json out = Json::array();
2300 for (
const std::complex<double>& z : v) out.push_back(Json::array({
z.real(),
z.imag()}));
2306 static Json run(Args& a) {
2307 const double lambda = a.number<
double>(
"lambda");
2308 const double mu = a.number<
double>(
"mu");
2309 const unsigned r = a.uinteger(
"r");
2315 out[
"roots"] = encode_cplx_pairs(m.roots);
2316 out[
"coeffs"] = encode_cplx_pairs(m.coeffs);
2323 static Json run(Args& a) {
2324 const double lambda = a.number<
double>(
"lambda");
2325 const double p1 = a.number<
double>(
"p1");
2326 const double mu1 = a.number<
double>(
"mu1");
2327 const double mu2 = a.number<
double>(
"mu2");
2460 "its interarrival law IaFun is a function handle (a CDF or transform evaluated by the "
2461 "port), and the port offers no constructor that builds it from a named law.";
2462 t[
"qsys_mg1k_loss"] =
2463 "its service law svc_density is a density function handle the port integrates, and the "
2464 "port takes no named-law form for it.";
2465 t[
"qsys_ggingi_tga"] =
2466 "its patience law (patienceCcdf, patiencePdf) and service law (serviceCcdf) are function "
2467 "handles the port integrates, with no named-law form.";
2468 t[
"qsys_ggisgi_fluid"] =
2469 "its patience and service laws (patienceCcdf, servingCcdf) are function handles the port "
2470 "integrates, with no named-law form.";
2471 t[
"qsys_gtmtst_fluid"] =
2472 "its time-varying arrival rate, staffing and service rate (lambdaFun, sFun, muFun) and "
2473 "its patience law (patienceCcdf) are function handles of time.";
2475 "its time-varying arrival rate lambdaFun is a function handle of time and its service law "
2476 "serviceCcdf a function handle, with no named-law form.";
2477 t[
"qsys_mtgs0_mol"] =
2478 "its time-varying arrival rate lambdaFun is a function handle of time and its service law "
2479 "serviceCcdf a function handle, with no named-law form.";
2480 t[
"fj_order_stat"] =
2481 "its branch law F_X is a CDF function handle the port evaluates, with no named-law form.";
2482 t[
"fj_xmax_hz_het"] =
2483 "its branch laws are a list of CDF function handles the port integrates, with no "
MAP to PH conversion for the age-of-information solvers.
Laplace-Stieltjes transform of a deterministic (constant) distribution.
Laplace-Stieltjes transform of an Erlang-k distribution.
Laplace-Stieltjes transform of an exponential distribution.
Laplace-Stieltjes transform of a phase-type distribution PH(alpha, T).
Internal to the –api dispatcher: what a per-domain translation unit needs to add entries to the table...
#define LINE_MOMENT_TENSOR_OP(OPNAME, FN, IN, OUT)
#define LINE_MOMENT_VEC_OP(OPNAME, FN, IN, OUT)
UnsupportedError(const std::string &what)
Named-argument reader over the parsed JSON object.
What refreshProcessRepresentations and refreshLST compute FROM a distribution: the (D0,...
Mean value analysis of a closed network of fork-join subnetworks.
Activities belonging to each branch of an AND-join.
Blom-corrected plotting position for the characteristic maximum.
Characteristic maximum of a lattice random variable.
Two-stage Coxian fit of a mean and a squared coefficient of variation.
Makespan of a task system with precedence constraints.
Deterministic subtask delays that minimise mean dispersion.
Mean subtask dispersion of a split-merge system with Erlang branches.
Conversion of a LINE MAP into the arrival or service descriptor of the fork-join response-time-tail a...
Green's independent server model of simultaneous server requests.
Laplace-Stieltjes transform of the maximum of heterogeneous exponentials.
Mean and variance of the M/G/1 response time, as ForkTail inputs.
Geometric bound on the queue length of a fork-join subnetwork.
Centralized splitting analysed as an M[K]/M/c bulk arrival system.
Varki bound on the residence time of a closed fork-join subnetwork.
Mean response time of the distributed no-splitting parallel system.
Blocking probability and pseudoserver delay of serialization phases.
ForkTail black-box tail-latency approximation for fork-join requests.
Tail latency of a k-of-n (QUORUM) fork-join request.
Saturation throughput of the team service model.
Expected maximum of K i.i.d.
Exact moments of the maximum of heterogeneous exponentials.
Harrison-Zertal approximation of the maximum of i.i.d.
Moments of the maximum of heterogeneous exponentials by recurrence.
Enumerations and the minimal distribution descriptor shared by the model layer of the C++ port.
Cumulants from raw moments and the inverse, plus the factorial-cumulant pair.
Conversion matrix of one edge of the house of moments.
Joint moment conversions on the house of moments.
Binomial moments from tail moments and the inverse.
Joint moment arrays and the mode products used by every joint conversion.
std::function< T(const T &)> Lst
A Laplace-Stieltjes transform evaluated at real arguments.
Lst< T > aoi_lst_exp(const T &mu)
Laplace-Stieltjes transform of an exponential distribution.
Lst< T > aoi_lst_erlang(unsigned k, const T &mu)
Laplace-Stieltjes transform of an Erlang-k distribution.
Lst< T > aoi_lst_ph(const std::vector< T > &alpha, const Matrix< T > &Tmat)
Laplace-Stieltjes transform of a phase-type distribution PH(alpha, T).
AoiPh< T > aoi_dist2ph(const Matrix< T > &D0, const Matrix< T > &D1)
Convert a MAP (D0, D1) into the PH pair (alpha, T).
Lst< T > aoi_lst_det(const T &d)
Laplace-Stieltjes transform of a deterministic (constant) distribution.
std::vector< T > fj_xmax_moments_het(const std::vector< T > &lambda, unsigned n=1)
Moments of the maximum of heterogeneous exponentials by recurrence.
FjDistKind
Which of the two descriptors to build.
FJCharMaxBlomResult< T > fj_char_max_blom(unsigned K, const std::function< T(const T &)> &Finv=std::function< T(const T &)>(), const T &alpha=num_traits< T >::from_double(0.4886), const T &beta=num_traits< T >::from_double(0.3140))
Blom-corrected plotting position for the characteristic maximum.
T fj_lst_max_het(const std::vector< T > &lambda, const T &s)
Laplace-Stieltjes transform of the maximum of heterogeneous exponentials.
FJIsmGreenResult< T > fj_ism_green(const T &lambda, const T &mu, unsigned s, const std::vector< T > &c)
Green's independent server model of simultaneous server requests.
FJDelayOptResult< T > fj_delay_opt(const std::vector< unsigned > &shape, const std::vector< T > &rate, unsigned maxsweeps=40, const T &dtol=num_traits< T >::from_double(1e-8), unsigned npanels=2000)
Deterministic subtask delays that minimise mean dispersion.
FJXmaxCoxianResult< T > fj_xmax_coxian(unsigned K, const T &mu1, const T &mu2, const T &q)
Expected maximum of K i.i.d.
std::vector< std::vector< std::size_t > > fj_branch_members(const LqnBranchView< T > &lqn, std::size_t joinaidx)
Branch membership of an AND-join.
FJDagMakespanResult< T > fj_dag_makespan(const Matrix< T > &pred, const Matrix< T > &rate)
Makespan of a task system with precedence constraints.
FJResptNosplitResult< T > fj_respt_nosplit(unsigned K, const T &lambda, const T &mu)
Mean response time of the distributed no-splitting parallel system.
FJTsmCapacityResult< T > fj_tsm_capacity(unsigned s, const std::vector< T > &f, const std::vector< unsigned > &r, const std::vector< T > &x)
Saturation throughput of the team service model.
T fj_xmax_het(const std::vector< T > &lambda, unsigned n=1)
Exact moments of the maximum of heterogeneous exponentials.
FJCharMaxDiscreteResult< T > fj_char_max_discrete(unsigned K, FJDiscreteDist dist, const T &par)
Characteristic maximum of a lattice random variable.
FJSerializationResult< T > fj_serialization(const std::vector< T > &Rs, const T &R0, unsigned M, const T &alpha=num_traits< T >::from_double(0.5))
Blocking probability and pseudoserver delay of serialization phases.
Mg1ResptMoments< T > fj_mg1_respt_moments(const T &lambda, const T &ES, const T &ES2, const T &ES3)
Mean and variance of the M/G/1 response time, as ForkTail inputs.
FjDist< T > fj_dist2fj(const mam::Map< T > &m, FjDistKind kind, FjProcType procType)
Build the fork-join descriptor of a MAP.
ForkTailResult< T > fj_tail_forktail(const std::vector< T > &ET, const std::vector< T > &VT, const std::vector< T > &K=std::vector< T >(), const T &p_in=num_traits< T >::from_int(99), const std::vector< T > &P=std::vector< T >())
ForkTail black-box tail-latency approximation for fork-join requests.
FJResptClosedResult< T > fj_respt_closed(unsigned K, const T &x, unsigned M, const T &A)
Varki bound on the residence time of a closed fork-join subnetwork.
FJQgbResult< T > fj_qgb(const std::vector< T > &D, const std::vector< unsigned > &P, unsigned M, const T &Z)
Geometric bound on the queue length of a fork-join subnetwork.
FJXmaxHzResult< T > fj_xmax_hz(const T &m1, const T &m2, unsigned K)
Harrison-Zertal approximation of the maximum of i.i.d.
ForkTailResult< T > fj_tail_ordstat(const std::vector< T > &ET, const std::vector< T > &VT, std::size_t K=1, const T &p_in=num_traits< T >::from_int(99), std::size_t kreq=0)
Tail latency of a k-of-n (QUORUM) fork-join request.
FJAmvaResult< T > fj_amva(const std::vector< T > &D, const std::vector< unsigned > &P, unsigned M, const T &Z)
Mean value analysis of a closed network of fork-join subnetworks.
FJCoxFitResult< T > fj_cox_fit(const T &m1, const T &c2)
Two-stage Coxian fit of a mean and a squared coefficient of variation.
FJDispersionResult< T > fj_dispersion(const std::vector< unsigned > &shape, const std::vector< T > &rate, const std::vector< T > &d, const T &tol=num_traits< T >::from_double(1e-10), unsigned npanels=4000)
Mean subtask dispersion of a split-merge system with Erlang branches.
FjProcType
The subset of ProcessType that the fork-join algorithm accepts.
FJResptBulkResult< T > fj_respt_bulk(unsigned K, const T &lambda, const T &mu, unsigned c, std::size_t nmax=0)
Centralized splitting analysed as an M[K]/M/c bulk arrival system.
FJDiscreteDist
The lattice laws for which the characteristic maximum is closed.
T dist_lst(const Distrib< T > &d, const T &s)
sn.lst: the Laplace-Stieltjes transform E[exp(-sX)].
T dist_cdf(const Distrib< T > &d, const T &x)
F(x) = P{X <= x}, MATLAB's Distribution.evalCDF.
T dist_moment(const Distrib< T > &d, unsigned k)
The k-th raw moment.
bool in(const std::string &s, std::initializer_list< const char * > set)
std::vector< T > moment_joint_aggregate(const MomentTensor< T > &F)
Factorial moments of a total count from the joint factorial moments of its parts.
MomentTensor< T > moment_joint_marking(const std::vector< T > &f, const std::vector< T > &p, const std::vector< std::size_t > &dims)
Joint factorial moments of a multinomially marked count from the aggregate ones.
std::vector< std::size_t > moment_tensorsize(const MomentTensor< T > &A)
Extents with the trailing singleton dimensions removed.
Matrix< T > moment_housematrix(MomentEdge edge, int n)
(n+1)x(n+1) conversion table of the given edge.
MomentTensor< T > moment_tensortrans(const MomentTensor< T > &A, const Matrix< T > &Tm, std::size_t mode)
Mode product: every fibre of A along dimension mode is replaced by Tm times that fibre.
MomentTensor< T > moment_joint_central_from_raw_mean(const MomentTensor< T > &m, const std::vector< T > &mu)
Joint central moments from joint raw moments about a given mean vector.
MomentTensor< T > moment_jointtrans(const MomentTensor< T > &A, MomentEdge edge)
Applies the conversion matrix of one edge along every dimension of A.
MomentTensor< T > moment_joint_raw_from_central(const MomentTensor< T > &mc, const std::vector< T > &mu)
Joint raw moments from joint central moments about a given mean vector.
Mg1ConservationResult< T > qsys_mg1_conservation(const std::vector< T > &lambda, const std::vector< T > &mu, const std::vector< T > &cs, const std::vector< T > &W=std::vector< T >())
The M/G/1 conservation-law invariant.
MaximaResult< T > qsys_maxima_twomoment(std::size_t n, const T &mean, const T &cs2, const T &q=num_traits< T >::from_int(0), bool exactFitted=true)
Two-moment approximation for the maximum of n iid non-negative variables.
MapG1kResult< T > qsys_mapg1k(const mam::Map< T > &arrival, const ServiceLaw< T > &svc, std::size_t K, const T &tol, std::size_t nmaxCap)
MAP/G/1/K with tail drop.
QsysRes qsys_gimc(const std::function< double(double)> &lst, double lambda, double mu, unsigned c, const QsysResOptions &o=QsysResOptions())
Exact GI/M/c queue, interarrival law given by its LST.
LindleyResult< T > qsys_hh1_lindley(const std::vector< T > &lambda, const std::vector< T > &pa, const std::vector< T > &mu, const std::vector< T > &ps, const std::vector< T > &Wn, unsigned mmax=2)
Conditional waiting-time moments of the Hl/Hn/1 Lindley recursion.
Mer1Result qsys_mer1(double lambda, double mu, unsigned r, const QsysResOptions &o=QsysResOptions())
Exact M/Er/1 queue.
LdpsWorkloadResult< T > qsys_ldps_workload(const T &lambda, const WorkloadServiceLaw< T > &B, const std::vector< T > &alpha, std::size_t N, const std::vector< T > &t, std::size_t ngrid)
Workload distribution of the load-dependent PS station with blocking.
MapPhcResult< T > qsys_mapmapc(const mam::Map< T > &arrival, const mam::Map< T > &service, unsigned c, std::size_t dist_size=500, std::size_t num_w_moms=3)
MAP/MAP/c FCFS with the service phase carried in start order, exactly.
Mg1SjfResult qsys_mg1_sjf(const std::vector< double > &lambda, const std::vector< double > &mu, const std::vector< double > &cs)
M/G/1 non-preemptive SJF.
Mm1TandemLindleyResult< T > qsys_mm1_tandem_lindley(const T &lambda, const T &mu1, const T &mu2, const std::vector< T > &Wk, const std::vector< T > &Wk1)
Conditional waiting time at the SECOND station of an M/M/1 -> /M/1 tandem.
Mm1PsResult< T > qsys_mm1_ps(const std::vector< T > &lambda, const std::vector< T > &mu)
Exact sojourn-time moments of the multiclass M/M/1-PS queue.
Mg1ExceptionalResult< T > qsys_mg1_exceptional(const T &lambda, const T &mu, const T &cs, const T &muf, const T &csf)
M/G/1 with exceptional first service.
MmapGk1Result< T > qsys_mmapgk1(const std::vector< Matrix< T > > &MMAP, const std::vector< MmapGk1Service< T > > &svc, const std::vector< T > &w_points, std::size_t num_w_moms, double tol, std::size_t iter_max, std::size_t quad_nodes)
MMAP[K]/G[K]/1 FCFS, per type.
SvclawCoeffsResult< T > qsys_svclaw_coeffs(const ServiceLaw< T > &svc, const T &theta, const T &tol, std::size_t nmaxCap)
qsys_svclaw_coeffs: uniformization coefficients of a service-time descriptor; see qsys_svclaw_coeffs....
MmcPrioTardinessResult qsys_mmc_prio_tardiness(const std::vector< double > &lambda, double mu, unsigned c, const std::vector< double > &d, const std::string &type="np", const std::string &method="euler")
Stationary per-class expected tardiness of a priority M/M/c queue.
MmcPrioResult< T > qsys_mmc_prio(const std::vector< T > &lambda, const T &mu, unsigned c)
M/M/c with head-of-line priorities.
QsysRes qsys_mmckk(double alpha, double mu, unsigned c, unsigned K, const QsysResOptions &o=QsysResOptions())
Exact M/M/c/K/K finite-source queue.
QsysAbandonResult< T > qsys_mgisrgi_whitt(const T &lambda, const T &mu, unsigned s, double r, const Patience< T > &patience, const MgisrgiOptions &opts=MgisrgiOptions())
Engineering solution of the call-center model M/GI/s/r+GI.
QsysRes qsys_mh21(double lambda, double p1, double mu1, double mu2, const QsysResOptions &o=QsysResOptions())
Exact M/H2/1 queue.
TandemLindleyResult< T > qsys_tandem_lindley(const std::vector< T > &A, const Matrix< T > &S, const std::vector< T > &W0=std::vector< T >())
Sample-path Lindley recursion along a tandem of single-server FCFS queues.
QsysResT< T > qsys_ddckk(const T &EO, const T &ES, unsigned c, unsigned K)
Exact D/D/c/K/K finite-source queue.
LindleyResult< T > qsys_mm1_lindley(const T &lambda, const T &mu, const std::vector< T > &Wn, unsigned mmax=2)
Conditional waiting-time moments of the M/M/1 Lindley recursion.
Mg1SetupResult< T > qsys_mg1_setup(const T &lambda, const T &mu, const T &cs, const T &EU, const T &EU2)
M/G/1 with setup times, setup given by its first two moments.
QsysRes qsys_mg1kk(double alpha, unsigned K, const std::function< double(double)> &lst, double ES)
Exact M/G/1/K/K finite-source queue, service given by its LST.
BmapM1Result< T > qsys_bmapm1(const std::vector< Matrix< T > > &D, const T &mu, const T &qParam, std::size_t maxLevelParam, unsigned maxIter, const T &tol, double tailTol)
BMAP/M/1 by the matrix-analytic (M/G/1-type) method.
TandemUbResult< T > qsys_tandem_ub_ciucu(const std::vector< T > &x, const std::function< T(const T &)> &lst, const std::vector< T > &p, const std::vector< T > &mu, const std::function< T(const T &)> &dlst=std::function< T(const T &)>())
Tail bounds for a GI/Hn/1 -> .
MmapMap1Result< T > qsys_mmapmap1(const mam::Mmap< T > &arrival, const std::vector< mam::Map< T > > &svc, std::vector< bool > carry=std::vector< bool >())
MMAP[K]/MAP[K]/1 FCFS with per-class carried service phases, exactly.
QsysRes qsys_engset(double alpha, double mu, unsigned c, unsigned K)
Exact Engset M/G/c/c/K loss system.
QsysRes qsys_mmcc(double lambda, double mu, unsigned c)
Exact M/M/c/c Erlang loss system.
Mg1PsResult qsys_mg1_ps(double lambda, const std::vector< double > &alpha, const Matrix< double > &Tmat, const Mg1PsOptions &opt)
Sojourn-time distribution of the M/G/1 processor-sharing queue.
QsysRes qsys_mg1_busy(double lambda, double mu, double cs, const Mg1BusyOptions &o=Mg1BusyOptions())
Busy-period measures of the M/G/1 queue.
QsysRes qsys_mgc_ps(double lambda, double mu, unsigned c)
Exact M/G/c-PS queue.
Mg1PrioPrResult< T > qsys_mg1_prio_pr(const std::vector< T > &lambda, const std::vector< T > &mu, const std::vector< T > &cs, const std::vector< T > &ES3=std::vector< T >())
M/G/1 with preemptive-resume priorities.
MmapG1kResult< T > qsys_mmapg1k(const Matrix< T > &D0, const std::vector< Matrix< T > > &D1c, const ServiceLaw< T > &svc, std::size_t K, const T &tol, std::size_t nmaxCap)
MMAP[K]/G/1/K with tail drop.
MmapGk1LcfsprResult< T > qsys_mmapgk1_lcfspr(const std::vector< Matrix< T > > &MMAP, const std::vector< MmapGk1Service< T > > &svc, const MmapGk1LcfsprOptions< T > &opt)
MMAP[K]/G[K]/1 LCFS-PR, per type, by Takine's matrix product form.
MapG1kPerflowResult< T > qsys_mapg1k_perflow(const std::vector< mam::Map< T > > &flows, const ServiceLaw< T > &svc, std::size_t K, const T &tol, std::size_t nmaxCap)
Per-flow analysis of a MAP-fed tail-drop buffer.
QsysRes qsys_md1(double lambda, double mu, long nmax=-1)
Exact M/D/1 queue.
std::vector< T > qsys_lindley_moment(const T &lambda, const T &mu, const std::vector< T > &Wn, unsigned m)
One conditional Lindley moment for exponential primitives.
MmcPrioEtaResult qsys_mmc_prio_eta(const std::vector< double > &lambda, double mu, unsigned c, unsigned r, unsigned v, unsigned q, const std::vector< double > &d, const std::string &type="np", const std::string &method="euler")
Expected tardiness at arrival of a class-r order.
Json encode_vectors(const std::vector< std::vector< T > > &v)
A list of vectors, the shape a per-class or per-segment result returns.
Matrix< T > matrix_from_json(const Json &j, const std::string &where)
A matrix from a JSON value: 2-D array as rows, 1-D array as a row vector, scalar as 1x1,...
Json encode_matrices(const std::vector< Matrix< T > > &v)
A list of matrices, the shape the MMAP/BMAP families return as {D0,D1,...}.
void register_api_qsys(DispatchTable &t)
qsys::QsysResOptions read_qsys_res_options(Args &a, bool with_nmax=true)
The 'tPoints', 'percentiles' and 'nmax' options those functions share.
T number_from_json(const Json &j, const std::string &where)
Json encode_vector(const std::vector< T > &v)
Json encode_matrix(const Matrix< T > &m)
void register_library_only_qsys(LibraryOnlyTable &t)
Json encode_scalar(const T &v)
Json encode_count(std::size_t n)
A count.
std::map< std::string, std::string > LibraryOnlyTable
name -> why the function has no named-JSON-argument form.
Json encode_qsys_res(const qsys::QsysResT< T > &r)
MATLAB's res struct of the exact queueing-system functions: one key per measure, in the reference's f...
std::map< std::string, Invoker > DispatchTable
QuestOptions sim_quest_options(const QuestOptions &options=QuestOptions())
Validates an option set and returns it.
QuestInterval< T > sim_quest_heuristic_ci(const std::vector< T > &bqe, const T ¢re, const T &Ap, const T &Np, std::size_t nstar, double alpha, bool useAutocorr)
Fallback interval used when a QUEST stage test fails.
RunLengthResult< T > sim_runlength(const T &mean, const T &asymVar, const T &relPrecision=num_traits< T >::from_rational(1, 20), const T &confidence=num_traits< T >::from_rational(19, 20), const T &runLength=num_traits< T >::from_int(0))
Run length for a steady-state estimate of a given relative precision.
Conservation laws of a layered queueing network, enumerated from its structure.
Reader for the LINE model.json interchange (a Network model) into a qn::Network<T> built through the ...
BMAP/M/1 by the matrix-analytic (M/G/1-type) method.
Exact analysis of the finite-source D/D/c/K/K machine-repair model.
Exact analysis of the Engset loss system M/G/c/c/K: K sources, each idle for an Exp(alpha) time,...
Exact analysis of the GI/M/c queue (Takacs, 1962).
Conditional waiting-time moments of the Hl/Hn/1 Lindley recursion.
Stationary distribution of the unfinished work in a single-stage load-dependent generalized-processor...
One conditional Lindley moment for exponential primitives.
The MAP/G/1/K queue with tail drop: Markovian arrivals, an arbitrary service law F,...
Per-flow throughput and loss ratio of a tail-drop FIFO buffer fed by N flows of mutually different st...
The MAP/MAP/c FCFS queue whose service MAP is CARRIED in service-start order.
Two-moment approximation for the maximum of n iid non-negative variables.
Exact analysis of the M/D/1 queue: the M/G/1 moments with deterministic service plus the queue-length...
Exact analysis of the M/Er/1 queue (Erlang-r service of total rate mu/r per phase-sum,...
Busy-period measures of the M/G/1 queue.
Kleinrock's conservation law for work-conserving non-preemptive M/G/1 disciplines.
M/G/1 with exceptional first service: the job that starts a busy period has service law Bf,...
M/G/1 with preemptive-resume priorities: per-class mean (and optionally variance of the) response tim...
Sojourn-time distribution of the M/G/1 processor-sharing queue.
M/G/1 with setup times: the server switches off when empty and needs a setup time U before serving th...
M/G/1 with non-preemptive shortest-job-first scheduling: per-class mean response times.
Exact analysis of the finite-source M/G/1/K/K (machine-repair) queue.
Exact analysis of the M/G/c processor-sharing queue.
Engineering solution of the call-center model M/GI/s/r+GI.
Exact analysis of the M/H2/1 queue: hyperexponential service with branch probabilities (p1,...
Conditional waiting-time moments of the M/M/1 Lindley recursion.
Exact sojourn-time moments of the multiclass M/M/1-PS queue.
Conditional waiting time at the SECOND station of an M/M/1 -> /M/1 tandem.
Exact per-class throughput and loss ratio of an MMAP[K]/G/1/K tail-drop queue.
The MMAP[K]/G[K]/1 FCFS queue: K customer types with class-dependent GENERAL service,...
The MMAP[K]/G[K]/1 LCFS-PR queue: K customer types with class-dependent GENERAL service under preempt...
The MMAP[K]/MAP[K]/1 FCFS queue in which each class's service phase is CARRIED.
M/M/c with non-preemptive (head-of-line) priorities and a common exponential service rate (Cobham,...
Expected tardiness at arrival (ETA) in a multiclass priority M/M/c queue, conditional on the state th...
Exact stationary expected tardiness in a multiclass priority M/M/c queue (Hafizoglu,...
Exact analysis of the M/M/c/c (Erlang loss) system.
Exact analysis of the finite-source M/M/c/K/K (machine-repair) queue.
Sample-path Lindley recursion along a tandem of single-server FCFS queues.
Tail bounds for a GI/Hn/1 -> .
Fallback interval used when a QUEST stage test fails.
Options of the QUEST procedures, with the published FQUEST defaults.
Run-length planning for steady-state simulation.
static Patience exponential(const T &theta)
Exponential patience of rate theta, h(t) = theta, the Erlang A case.
static ServiceLaw deterministic(const T &d)
Constant service time d.
static ServiceLaw phase_type(const std::vector< T > &alpha, const Matrix< T > &Tmat)
Phase type (alpha, Tmat).
static ServiceLaw gamma(const T &shape, const T &scale)
Gamma(shape, scale).