30namespace mapqn_detail {
32bool is_delay(
const qn::Station<T>& st) {
37 return t == ProcessType::EXP || t == ProcessType::ERLANG || t == ProcessType::HYPEREXP ||
38 t == ProcessType::PH || t == ProcessType::APH || t == ProcessType::COXIAN ||
39 t == ProcessType::COX2 || t == ProcessType::MAP || t == ProcessType::MMPP2;
46 using mapqn_detail::is_delay;
47 using mapqn_detail::is_markovian;
51 return "solver_mapqn: Method 'amva.mapqn' requires exactly two stations: one delay (infinite server) "
53 std::size_t
id = 0, ndelay = 0;
54 for (std::size_t i = 0; i < M; ++i)
55 if (is_delay(L.
stations[i])) {
id = i; ++ndelay; }
57 return "solver_mapqn: Method 'amva.mapqn' requires exactly one delay (infinite-server) station and one queue";
58 const std::size_t iq = 1 - id;
60 return "solver_mapqn: Method 'amva.mapqn' requires FCFS scheduling at the queue; station " +
61 std::to_string(iq + 1) +
" is not FCFS";
63 return "solver_mapqn: Method 'amva.mapqn' supports a single-server queue only";
64 const std::vector<double> njobs = L.
njobs();
65 for (std::size_t r = 0; r < R; ++r)
66 if (std::isinf(njobs[r]))
return "solver_mapqn: Method 'amva.mapqn' supports closed models only";
67 if (L.
nclosedjobs() <= 0)
return "solver_mapqn: Method 'amva.mapqn' supports closed models only";
70 for (std::size_t r = 0; r < R; ++r) {
71 if (njobs[r] <= 0)
continue;
73 return "solver_mapqn: Method 'amva.mapqn' requires exponential think times; class " +
74 std::to_string(r + 1) +
" has a non-exponential think time";
75 if (!is_markovian(L.
procid(iq + 1, r + 1)) || L.
service[iq][r].disabled)
76 return "solver_mapqn: Method 'amva.mapqn' requires a Markovian (MAP-representable) service process "
77 "at the queue; class " + std::to_string(r + 1) +
" is not";
80 return "solver_mapqn: Method 'amva.mapqn' requires every class to cycle delay -> queue -> delay "
81 "without class switching; class " + std::to_string(r + 1) +
" does not";
88 using mapqn_detail::is_delay;
94 for (std::size_t i = 0; i < M; ++i)
96 const std::size_t iq = 1 - id;
97 const std::vector<double> pop = L.
njobs();
98 std::vector<int> N(R, 0);
100 std::vector<Matrix<T>> D0s(R), D1s(R);
101 for (std::size_t r = 0; r < R; ++r) {
102 N[r] =
static_cast<int>(std::lround(pop[r]));
104 mu[r] = L.
rates(
id, r);
120 sol.
C.assign(R, zero);
121 sol.
X.assign(R, zero);
122 for (std::size_t r = 0; r < R; ++r) {
124 const T X = res.
X[r];
126 sol.
Q(iq, r) = res.
Qq[r];
127 sol.
U(iq, r) = res.
U[r];
129 sol.
R(iq, r) = res.
Qq[r] / X;
130 sol.
Q(
id, r) = X / mu[r];
131 sol.
U(
id, r) = X / mu[r];
136 sol.
method =
"amva.mapqn";
138 for (std::size_t r = 0; r < R; ++r) iter *= (N[r] + 1);
140 sol.
lG = std::numeric_limits<double>::quiet_NaN();
UnsupportedError(const std::string &what)
A network plus its refreshed NetworkStruct.
std::vector< std::vector< Distrib< T > > > service
service[i][r], 0-based station and class; a disabled entry marks a pair never visited.
ProcessType procid(std::size_t ist, std::size_t r) const
sn.procid(i,r): the process type of a (station, class) pair.
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 ...
T route_eff(std::size_t r, std::size_t s, std::size_t i, std::size_t j) const
The routing actually in force: the expansion when there is one, else P.
std::vector< double > njobs() const
sn.njobs: the population of each class, infinite for an open one.
double nclosedjobs() const
sn.nclosedjobs: the total population of the closed classes.
std::vector< std::size_t > station_to_node
(nstations) 1-based node index
What refreshProcessRepresentations and refreshLST compute FROM a distribution: the (D0,...
The exception types the port throws.
Horizontal-cut mean value analysis for a MAP server (SolverMVA method 'amva.mapqn').
The option and result types every MVA analyzer shares.
mam::Map< T > dist_to_map(const Distrib< T > &d)
ProcessType
Distribution kinds, with the values of MATLAB ProcessType.
MapqnAmvaResult< T > mapqn_amva(const std::vector< T > &mu_in, const std::vector< Matrix< T > > &D0s, const std::vector< Matrix< T > > &D1s, const std::vector< int > &N)
std::string mva_mapqn_reason(const qn::NetworkStruct< T > &L, const std::string &method)
The reason 'amva.mapqn' cannot solve L, or "" when it can (and "" for any other method).
MvaSolution< T > solver_mapqn(const qn::NetworkStruct< T > &L, const MvaOptions &opt)
std::string mva_base_method(const std::string &method)
SolverMVA.getFeatureSet, plus getMethodFeatureSet's per-method deltas.
A queueing network and its refreshed NetworkStruct.
The DECLARED side of the gate: one feature set per solver.
A MAP as the pair of matrices (D0, D1).
X: class throughputs; Qq: mean queue lengths at the MAP station (job in service included); U: busy pr...
The options SolverMVA reads.
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.