5#ifndef LINE_SOLVERS_MAM_SOLVER_MAM_BASIC_MMAP_H
6#define LINE_SOLVERS_MAM_SOLVER_MAM_BASIC_MMAP_H
119namespace basic_mmap_detail {
155 std::vector<std::vector<Map<T>>> PH;
156 std::vector<std::vector<PhService<T>>> svc;
157 std::vector<std::vector<bool>> known;
166 t.PH.assign(M, std::vector<Map<T>>(K));
167 t.svc.assign(M, std::vector<PhService<T>>(K));
168 t.known.assign(M, std::vector<bool>(K,
false));
169 for (std::size_t i = 0; i < M; ++i) {
182 const double ns = L.
stations[i].nservers;
183 for (std::size_t r = 0; r < K; ++r) {
186 t.svc[i][r].sigma.assign(1, one);
187 t.svc[i][r].S =
Matrix<T>(1, 1, T(-imm));
191 if (divide && std::isfinite(ns) && ns > 0.0)
194 t.svc[i][r].sigma =
map_pie(ph);
195 t.svc[i][r].S = ph.D0;
196 t.known[i][r] =
true;
215T exp_max_mean(
const std::vector<T>& rate) {
216 const std::size_t n = rate.size();
219 "solver_mam_basic_mmap: the join synchronizes " + std::to_string(n) +
220 " branches, and the reference's expected-maximum formula is an alternating sum over "
221 "all 2^n subsets of them; that is not evaluable at this width");
222 const T zero = num_traits<T>::from_int(0);
224 for (std::size_t mask = 1; mask < (std::size_t(1) << n); ++mask) {
226 std::size_t bits = 0;
227 for (std::size_t i = 0; i < n; ++i)
228 if (mask & (std::size_t(1) << i)) {
232 if (!(s > zero))
continue;
233 const T term = T(num_traits<T>::from_int(1) / s);
234 if (bits % 2 == 1) acc += term;
242Mmap<T> compress_arrival(
const Mmap<T>& m) {
243 if constexpr (num_traits<T>::has_transcendental) {
248 "solver_mam_basic_mmap: the arrival superposition passed config.space_max and must be "
249 "compressed, which fits an APH(2) and needs transcendental arithmetic");
267 const std::vector<T>& lambda,
268 std::size_t* totiter) {
270 (void)L; (void)
opt; (void)cfg; (void)lambda; (void)totiter;
272 "solver_mam_basic_mmap_inner: the departure-process fixed point stops on a tolerance, "
273 "MMAP[K]/PH[K]/1 runs the ADDA doubling iteration and the ETAQA departure process "
274 "needs transcendental arithmetic; rerun with --arith double or --arith real");
276 using namespace basic_mmap_detail;
277 using basic_detail::station_visits;
278 using basic_detail::truncate_renorm;
279 using basic_detail::zero_nans;
284 if (lambda.size() != K)
285 throw InputError(
"solver_mam_basic_mmap_inner: lambda is not indexed over the classes");
289 for (std::size_t i = 0; i < M; ++i)
290 for (std::size_t r = 0; r < K; ++r)
293 const MmapPhTable<T> ph = mmap_ph_table(L);
298 Matrix<T> QN(M, K, zero), UN(M, K, zero), RN(M, K, zero), TN(M, K, zero);
301 for (std::size_t i = 0; i < M; ++i)
302 if (L.
stations[i].sched == SchedStrategy::EXT)
303 for (std::size_t r = 0; r < K; ++r)
307 std::vector<bool> car_warned(M,
false);
309 auto sweep = [&](
const std::vector<T>&,
310 std::size_t itnum) -> std::pair<std::vector<T>, std::vector<T>> {
313 for (std::size_t ind = 0; ind < I; ++ind) {
315 const bool isfj = (ty == qn::NodeType::Fork || ty == qn::NodeType::Join);
316 if (L.
nodes[ind].station != 0 && !isfj) {
317 const std::size_t ist = L.
nodes[ind].station - 1;
318 for (std::size_t r = 0; r < K; ++r) {
319 if (V(ist, r) > zero && lambda[r] > zero)
321 map_scale(ph.PH[ist][r], T(one / T(lambda[r] * V(ist, r))));
323 DEP[ind][r] = ph.PH[ist][r];
326 for (std::size_t r = 0; r < K; ++r)
337 std::vector<T> xref(M * K, zero);
338 for (std::size_t i = 0; i < M; ++i)
339 for (std::size_t r = 0; r < K; ++r) xref[i * K + r] = QN(i, r);
342 for (std::size_t i = 0; i < M; ++i) {
346 const double ns = L.
stations[i].nservers;
348 if (ty == qn::NodeType::Join) {
351 for (std::size_t r = 0; r < K; ++r) {
352 TN(i, r) = lambda[r];
359 if (ty != qn::NodeType::Queue) {
360 if (sc == SchedStrategy::INF) {
361 if (ARV[ind].order() > 0) {
363 for (std::size_t r = 0; r < K; ++r) TN(i, r) = lam[r];
365 for (std::size_t r = 0; r < K; ++r)
366 if (TN(i, r) > zero) {
367 UN(i, r) = T(S(i, r) * TN(i, r));
368 QN(i, r) = T(TN(i, r) * S(i, r));
375 if (ARV[ind].order() == 0)
continue;
376 if (ARV[ind].order() > tcfg.
space_max) ARV[ind] = compress_arrival(ARV[ind]);
378 bool finiteCapUsed =
false, exactStation =
false;
379 std::vector<PhService<T>> sl;
380 for (std::size_t r = 0; r < K; ++r) sl.push_back(ph.svc[i][r]);
382 if (sc == SchedStrategy::FCFS || sc == SchedStrategy::HOL) {
383 if (std::isfinite(L.
stations[i].cap)) {
384 const std::size_t capK =
385 static_cast<std::size_t
>(std::llround(L.
stations[i].cap));
386 T meanQ = zero, lossProb = zero;
391 for (
const T& v : lam)
394 lamTot, det.
muRate,
static_cast<unsigned>(std::llround(ns)),
395 static_cast<unsigned>(capK));
399 const basic_detail::TruncRenorm<T>
tr = truncate_renorm(ARV[ind], sl, capK);
401 lossProb =
tr.lossProb;
404 std::vector<T> eff(K, zero), Sact(K, zero);
406 for (std::size_t r = 0; r < K; ++r) {
409 eff[r] = T(inflow * T(one - lossProb));
418 for (std::size_t r = 0; r < K; ++r) {
419 const T c = T(eff[r] * Sact[r]);
422 const T w = T(T(meanQ / sumTN) - T(sw / sumTN));
423 Wq = (w > zero) ? w : zero;
425 for (std::size_t r = 0; r < K; ++r) {
427 UN(i, r) = T(TN(i, r) *
map_mean(ph.PH[i][r]));
428 if (TN(i, r) > zero) {
429 RN(i, r) = T(Wq + Sact[r]);
430 QN(i, r) = T(TN(i, r) * RN(i, r));
436 finiteCapUsed =
true;
440 for (std::size_t r = 0; r < K; ++r) {
441 const T u = T(lam[r] *
map_mean(ph.PH[i][r]));
444 if (rho < T(one - ftol)) {
449 (K == 1) && (ns == 1.0) && ph.known[i][0] &&
451 map_acf(ph.PH[i][0], std::vector<unsigned>{1})[0])) >
452 GlobalConstants::CoarseTol;
455 std::vector<bool> corrSvc(K,
false);
457 corrSvc = basic_detail::corr_service_classes(L, i, ph.PH[i], ph.known[i]);
459 std::find(corrSvc.begin(), corrSvc.end(),
true) != corrSvc.end();
460 if (K == 1 && anyCorr && std::isfinite(ns) && ns > 1.0) {
463 arv.
D0 = ARV[ind].D0;
464 arv.
D1 = ARV[ind].Dc[0];
469 static_cast<unsigned>(std::llround(ns)),
470 static_cast<std::size_t
>(500),
471 static_cast<std::size_t
>(0))
474 }
catch (
const std::exception&) {
475 exactStation =
false;
478 if (anyCorr && !exactStation && !car_warned[i]) {
479 car_warned[i] =
true;
480 basic_detail::warn_carried(L, i, corrSvc);
484 }
else if (anyCorr) {
485 std::vector<Map<T>> svcK(ph.PH[i].begin(), ph.PH[i].begin() + K);
491 arv.
D0 = ARV[ind].D0;
492 arv.
D1 = ARV[ind].Dc[0];
496 for (std::size_t r = 0; r < K; ++r)
497 QN(i, r) = m[ARV[ind].classes() == 1 ? 0 : r];
503 for (std::size_t r = 0; r < K; ++r)
504 QN(i, r) = std::isfinite(L.
classes[r].population)
508 for (std::size_t r = 0; r < K; ++r) TN(i, r) = lam[r];
510 }
else if (sc == SchedStrategy::PS) {
512 for (std::size_t r = 0; r < K; ++r) {
518 UN(i, r) = T(TN(i, r) * S(i, r));
521 for (std::size_t r = 0; r < K; ++r) usum += UN(i, r);
522 const T uden = (usum < T(one - ftol)) ? usum : T(one - ftol);
523 for (std::size_t r = 0; r < K; ++r) QN(i, r) = T(UN(i, r) / T(one - uden));
526 if (!finiteCapUsed) {
527 for (std::size_t r = 0; r < K; ++r) {
528 UN(i, r) = T(TN(i, r) *
map_mean(ph.PH[i][r]));
531 if (std::isfinite(ns) && !exactStation)
532 QN(i, r) = T(QN(i, r) + TN(i, r) *
536 RN(i, r) = T(QN(i, r) / TN(i, r));
542 for (std::size_t i = 0; i < M; ++i) {
546 if (ty == qn::NodeType::Join) {
547 for (std::size_t r = 0; r < K; ++r)
551 if (ty != qn::NodeType::Queue || ARV[ind].order() == 0)
continue;
552 const bool fcfs = (sc == SchedStrategy::FCFS || sc == SchedStrategy::HOL);
553 if (!fcfs && sc != SchedStrategy::PS)
continue;
556 for (std::size_t r = 0; r < K; ++r) rho += UN(i, r);
557 for (std::size_t r = 0; r < K; ++r) {
558 const bool scalable = (V(i, r) > zero && lambda[r] > zero);
562 if (!fcfs && !scalable)
continue;
564 const Map<T>& Srv = ph.PH[i][r];
565 const std::size_t etaqa_sz =
568 if (etaqa_sz <= tcfg.
space_max && rho < T(one - ftol)) {
575 }
catch (
const Error&) {
579 if (scalable) dep =
map_scale(dep, T(one / T(lambda[r] * V(i, r))));
584 std::vector<T> xnew(M * K, zero);
585 for (std::size_t i = 0; i < M; ++i)
586 for (std::size_t r = 0; r < K; ++r) xnew[i * K + r] = QN(i, r);
587 return std::make_pair(xnew, xref);
591 fo.
iter_max =
static_cast<std::size_t
>(
opt.iter_max);
603 for (std::size_t j = 0; j < I; ++j) {
604 if (L.
nodes[j].nodetype != qn::NodeType::Join)
continue;
605 if (L.
nodes[j].station == 0)
continue;
606 const std::size_t jst = L.
nodes[j].station - 1;
607 std::map<std::size_t, std::vector<std::size_t>> groups;
608 for (std::size_t b = 0; b < I; ++b) {
609 const std::size_t gid =
fj.node_sync[j][b];
610 if (gid > 0) groups[gid].push_back(b);
612 for (std::size_t r = 0; r < K; ++r) {
613 if (!(TN(jst, r) > zero))
continue;
614 T syncDelay = zero, joinArrivalRate = zero;
615 for (
const std::pair<
const std::size_t, std::vector<std::size_t>>& g : groups) {
616 std::vector<T> branchRt, branchTput;
617 for (std::size_t b : g.second) {
618 if (L.
nodes[b].station == 0)
continue;
619 const std::size_t bst = L.
nodes[b].station - 1;
620 if (!(RN(bst, r) > zero))
continue;
621 branchRt.push_back(RN(bst, r));
622 branchTput.push_back(TN(bst, r));
624 if (branchRt.size() < 2)
continue;
625 std::vector<T> rate(branchRt.size(), zero);
627 for (std::size_t b = 0; b < branchRt.size(); ++b) {
628 rate[b] = T(one / branchRt[b]);
629 meanRt += branchRt[b];
632 const T excess = T(exp_max_mean(rate) - meanRt);
633 if (excess > zero) syncDelay += excess;
634 for (
const T& t : branchTput) joinArrivalRate += t;
636 RN(jst, r) = syncDelay;
637 QN(jst, r) = T(joinArrivalRate * syncDelay);
647 out.
C.assign(K, zero);
648 for (std::size_t r = 0; r < K; ++r)
649 for (std::size_t i = 0; i < M; ++i) out.
C[r] += RN(i, r);
651 out.
X.assign(K, zero);
656 for (std::size_t r = 0; r < K; ++r)
658 out.
method =
"dec.source.mmap";
673 std::size_t* totiter) {
675 (void)L; (void)
opt; (void)cfg; (void)totiter;
677 "solver_mam_basic_mmap_closed: the throughput bisection wraps the inner MMAP "
678 "decomposition, which needs transcendental arithmetic; rerun with --arith double or "
681 using namespace basic_mmap_detail;
682 using basic_detail::zero_nans;
694 "solver_mam_basic_mmap_closed: the reference renormalizes chain c's queue lengths with "
695 "the class-indexed sn.njobs(c), which is only correct when each chain holds exactly "
696 "one class; this model has " +
697 std::to_string(C) +
" chains over " + std::to_string(K) +
" classes");
703 std::vector<T> lambda_lb(K, zero), lambda_ub(K, zero);
704 for (std::size_t r = 0; r < K; ++r) {
707 for (std::size_t i = 0; i < M; ++i) {
708 if (!std::isfinite(L.
stations[i].nservers))
continue;
711 if (!any || v < best) { best = v; any =
true; }
714 for (std::size_t i = 0; i < M; ++i) {
715 if (std::isfinite(L.
stations[i].nservers))
continue;
718 if (!any || v > best) { best = v; any =
true; }
723 std::vector<T> lambda = lambda_ub;
725 std::vector<T> QNc(K, zero);
726 for (std::size_t r = 0; r < K; ++r)
728 QNc[r] = std::isfinite(L.
classes[r].population)
731 std::vector<T> QN_chain(K, zero);
734 inner.
iter_max = std::max(20, (
opt.iter_max + 9) / 10);
741 bool have_good =
false, algorithm_ok =
false;
742 const double bisect_tol = std::max(
opt.tol, 1e-3);
747 for (std::size_t r = 0; r < K; ++r)
749 if (!(gap > bisect_tol) || it_out >=
opt.iter_max)
break;
752 bool bracket_collapsed =
true;
753 for (std::size_t r = 0; r < K; ++r) {
754 if (!std::isfinite(L.
classes[r].population) || !(QNc[r] > zero))
continue;
755 if (QN_chain[r] < QNc[r]) lambda_lb[r] = lambda[r];
756 else lambda_ub[r] = lambda[r];
763 if (width > GlobalConstants::FineTol *
765 bracket_collapsed =
false;
767 if (bracket_collapsed) {
774 std::size_t inner_iter = 0;
777 }
catch (
const Error&) {
781 algorithm_ok =
false;
785 for (std::size_t r = 0; r < K; ++r) {
787 for (std::size_t i = 0; i < M; ++i) QN_chain[r] += sol.
Q(i, r);
794 for (std::size_t r = 0; r < K; ++r)
800 if (!algorithm_ok && have_good) sol = last;
801 if (sol.
Q.rows() != M) {
808 sol.
C.assign(K, zero);
809 sol.
X.assign(K, zero);
813 for (std::size_t c = 0; c < C; ++c) {
814 if (!std::isfinite(L.
classes[c].population))
continue;
816 for (std::size_t k : L.
inchain[c])
817 for (std::size_t i = 0; i < M; ++i) sumQ += sol.
Q(i, k - 1);
818 if (!(sumQ > zero))
continue;
820 for (std::size_t k : L.
inchain[c])
821 for (std::size_t i = 0; i < M; ++i) sol.
Q(i, k - 1) = T(Nc * sol.
Q(i, k - 1) / sumQ);
825 for (std::size_t i = 0; i < M; ++i)
826 if (L.
stations[i].sched == SchedStrategy::INF)
827 for (std::size_t r = 0; r < K; ++r) sol.
U(i, r) = sol.
Q(i, r);
829 sol.
C.assign(K, zero);
830 for (std::size_t r = 0; r < K; ++r)
831 for (std::size_t i = 0; i < M; ++i) sol.
C[r] += sol.
R(i, r);
836 for (std::size_t r = 0; r < K; ++r)
839 if (totiter) *totiter =
static_cast<std::size_t
>(it_out);
855 std::size_t iter = 0;
861 std::vector<T> lambda(L.
nclasses, zero);
862 for (std::size_t c = 0; c < L.
nchains; ++c) {
863 if (L.
inchain[c].empty())
continue;
864 const std::size_t rs = L.
classes[L.
inchain[c][0] - 1].refstat - 1;
866 for (std::size_t k : L.
inchain[c]) {
867 if (L.
disabled[rs][k - 1])
continue;
869 if (!std::isfinite(v))
continue;
870 tot += L.
rates(rs, k - 1);
872 for (std::size_t k : L.
inchain[c]) lambda[k - 1] = tot;
874 std::size_t iter = 0;
Base error for the multiprecision C++ port.
UnsupportedError(const std::string &what)
A network plus its refreshed NetworkStruct.
std::size_t nof_nodes() const
std::vector< std::vector< Distrib< T > > > service
service[i][r], 0-based station and class; a disabled entry marks a pair never visited.
bool has_service_law(std::size_t i, std::size_t r) const
Does (station i, class r) have a service law an analyzer may convert?
std::vector< std::vector< bool > > disabled
std::vector< JobClass > classes
std::vector< Station< T > > stations
stations[k-1] is the k-th station
Matrix< T > rates
(nstations x nclasses) service rates and SCVs, with a PARALLEL disabled flag instead of MATLAB's NaN ...
std::vector< std::vector< std::size_t > > inchain
1-based class indices per chain
std::size_t node_of_station(std::size_t st) const
1-based node index of station st, 0 when the map has no entry.
std::vector< NodeDef > nodes
every node, in creation order
bool is_open_model() const
sn_is_open_model: EVERY class is open, which is not has_open_classes.
Damped fixed-point iteration, the shared driver of the decomposition algorithms.
What refreshProcessRepresentations and refreshLST compute FROM a distribution: the (D0,...
The exception types the port throws.
The option and result types SolverMAM shares with its analyzers.
Markovian arrival process descriptors: stationary vectors, rate, moments, autocorrelation and the ind...
Dense matrix and non-owning view.
Compression of a marked MAP into a smaller representation, and the two M3A primitives it is built fro...
Marked MAP (MMAP) algebra: per-class rates, class probabilities, superposition, normalization and sca...
The MMAP[K]/PH[K]/1 FCFS queue: per-class mean number in system and per-class queue-length distributi...
FpiResult< T > da_fpi(const std::function< std::pair< std::vector< T >, std::vector< T > >(const std::vector< T > &, std::size_t)> &iterfun, const std::vector< T > &x0, const FpiOptions &options=FpiOptions())
Damped fixed-point iteration, the shared driver of the decomposition algorithms.
mam::Map< T > dist_to_map(const Distrib< T > &d)
The (D0,D1) pair that reaches sn.proc.
SchedStrategy
Scheduling disciplines, with the values of MATLAB SchedStrategy.
NodeType
Node kinds, with the values of MATLAB NodeType.
FjSyncMap sn_build_fj_sync_map(const qn::NetworkStruct< T > &sn)
sn_build_fj_sync_map.
std::vector< T > map_acf(const Map< T > &m, const std::vector< unsigned > &lags)
Autocorrelation coefficients of the inter-arrival times at the given lags,.
std::vector< T > mmapph1fcfs_ncmean(const Mmap< T > &arrival, const std::vector< PhService< T > > &svc)
Per-class mean number of customers in the system, BUTools' 'ncMoms', 1.
MmckDetection< T > mam_detect_mmck(const qn::NetworkStruct< T > &L, std::size_t ist, const Mmap< T > &arv)
Port of mam_detect_mmck.m: is the exact M/M/c/K closed form legitimate at this station?
@ MixtureOrder1
'default', 'mixture', 'mixture.order1'
std::vector< std::vector< Map< T > > > DepTable
DEP{i,r}, the departure process of class r from i in (D0,D1) form.
mva::MvaSolution< T > solver_mam_basic_mmap_inner(const qn::NetworkStruct< T > &L, const MamOptions &opt, const MmapDecConfig &cfg, const std::vector< T > &lambda, std::size_t *totiter)
Port of solver_mam_basic_mmap_inner.m.
TrafficConfig traffic_config(const MamOptions &opt)
The traffic step's view of SolverOptions('MAM').
std::vector< T > mmap_lambda(const Mmap< T > &m)
Alias kept for parity with the MATLAB name.
Mmap< T > mmap_hide_but(const Mmap< T > &in, std::size_t keep)
mmap_hide(m, setdiff(1:K, keep)): keep ONE mark, hide every other.
mva::MvaSolution< T > solver_mam_basic_mmap(const qn::NetworkStruct< T > &L, const MamOptions &opt)
Port of solver_mam_basic_mmap.m, the top-level dispatcher of the MMAP fork-join decomposition: an ope...
Map< T > qbd_depproc_etaqa(const Map< T > &arrival, const Map< T > &service, std::size_t n)
MAP descriptor of the departure process of a MAP/MAP/1-FCFS queue, ETAQA-truncated at level n (qbd_de...
QbdMapMap1Result< T > qbd_mapmap1(const Map< T > &arrival, const Map< T > &service_in, const T &util, std::size_t max_levels)
MAP/MAP/1 queue (qbd_mapmap1.m).
std::vector< Mmap< T > > solver_mam_traffic_mmap(const qn::NetworkStruct< T > &sn, const DepTable< T > &DEP, const TrafficConfig &config, const FjSyncMap &fjSyncMap)
Port of solver_mam_traffic_mmap.m, the fork-join aware traffic step.
T map_mean(const Map< T > &m)
Mean inter-arrival time, 1/lambda.
Map< T > qbd_depproc_etaqa_ps(const Map< T > &arrival, const Map< T > &service, std::size_t n)
MAP descriptor of the departure process of a MAP/MAP/1-PS queue, ETAQA-truncated at level n (qbd_depp...
Mmap< T > mmap_compress(const Mmap< T > &in, MmapCompressMethod method)
Compress an MMAP (mmap_compress.m).
Map< T > map_exponential_mean(const T &mean)
Poisson process with the given mean inter-arrival time (map_exponential.m).
Map< T > map_scale(const Map< T > &in, const T &new_mean)
Rescale time so that the mean inter-arrival time becomes new_mean.
mva::MvaSolution< T > solver_mam_basic_mmap_closed(const qn::NetworkStruct< T > &L, const MamOptions &opt, const MmapDecConfig &cfg, std::size_t *totiter)
Port of solver_mam_basic_mmap_closed.m: the per-class bisection on the surrogate arrival rate that ma...
std::vector< T > map_pie(const Map< T > &m)
Phase distribution seen by an arriving job, pie = pi D1 / (pi D1 e).
Map< T > map_normalize(const Map< T > &in)
Clamp negative off-diagonal entries of D0 and negative entries of D1 to zero, then rebuild the diagon...
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.
MmckResult< T > qsys_mmck(const T &lambda, const T &mu, unsigned c, unsigned K)
Exact analysis of the M/M/c/K queue (truncated Erlang form).
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.
Conservation laws of a layered queueing network, enumerated from its structure.
A queueing network and its refreshed NetworkStruct.
Departure process of a MAP/MAP/1 queue: the ETAQA-truncated MAP descriptor under FCFS and under PS,...
The MAP/MAP/1 queue solved as a quasi-birth-death process.
The MAP/MAP/c FCFS queue whose service MAP is CARRIED in service-start order.
The MMAP[K]/MAP[K]/1 FCFS queue in which each class's service phase is CARRIED.
Exact analysis of the M/M/c/K queue (truncated Erlang form).
Port of solver_mam_basic.m, the dec.source analyzer and the default algorithm of SolverMAM.
The batch-arrival and batch-service queues of the MAM solver, and the two finite-capacity helpers sol...
Port of solver_mam_traffic.m and solver_mam_traffic_mmap.m: the traffic step of the dec....
The <kind> part of a LINE:<category>:<kind> identifier (see _kb/17-error-vocabulary....
Options mirroring the fields MATLAB reads off the options struct.
std::size_t miniter
iterations before the stopping test applies
bool relative_norm
config.da_norm, the increment norm.
The MATLAB GlobalConstants, as reported by lineStart at its defaults.
sn_build_fj_sync_map: which incoming flows at a Join must be synchronized.
The options SolverMAM reads.
int iter_max
SolverOptions('MAM') lowers this from the global 1000 to 100.
std::size_t space_max
options.config.space_max: the order budget of the per-station arrival superposition,...
A MAP as the pair of matrices (D0, D1).
The options.config fields the MMAP decomposition reads on top of MamOptions.
std::size_t etaqa_trunc
config.etaqa_trunc, the ETAQA level truncation of the departure process.
std::size_t fj_sync_q_len
config.fj_sync_q_len, the synchronization queue at a join.
An MMAP: the underlying MAP plus the per-class arrival matrices.
std::size_t order() const
What mam_detect_mmck returns; muRate is meaningful only when isMmck.
The fields of options.config the traffic step reads.
std::size_t fj_sync_q_len
config.fj_sync_q_len, the join's synchronization queue; MATLAB's default.
Class-level results, the [Q,U,R,T,C,X] of the MATLAB analyzers.
double lG
log of the normalizing constant, the reference's lG.
Return value of qsys_mmapmap1, mirroring the MATLAB struct.
std::vector< T > meanQueueLength
E[N_k].
T meanQueueLength
L, mean number in system.