128 "solver_mva_sjn_analyzer: the SJN conditional waiting time recursion needs "
129 "transcendental arithmetic (regularized incomplete gammas on a quadrature grid); "
130 "rerun this model with --arith double or --arith real");
135 for (std::size_t c = 0; c < C; ++c)
136 if (std::isinf(d.
Nchain[c]))
138 "SolverMVA supports shortest-job-next (SJF) scheduling only in closed models, the "
139 "conditional waiting time equation being a population recursion. Use SolverLDES, "
140 "or SolverMVA with SRPT or PSJF for the preemptive size-based open queue");
145 std::vector<std::size_t> rows, infrows, sjnrows;
146 for (std::size_t i = 0; i < M; ++i) {
148 const double k = L.
stations[i].nservers;
149 if (s == SchedStrategy::EXT)
continue;
150 if (s == SchedStrategy::INF) {
151 infrows.push_back(i);
154 if (s == SchedStrategy::SJF) {
157 "solver_mva_sjn_analyzer: SJN scheduling at station " +
158 std::to_string(i + 1) +
159 " requires a single server, the response time equation is a single-server one");
161 sjnrows.push_back(rows.size() - 1);
164 if (s == SchedStrategy::PS || s == SchedStrategy::LCFSPR || s == SchedStrategy::FCFS ||
165 s == SchedStrategy::SIRO) {
168 "solver_mva_sjn_analyzer: station " + std::to_string(i + 1) +
" has " +
169 (std::isfinite(k) ? std::to_string(
static_cast<long long>(k))
170 : std::string(
"infinitely many")) +
171 " servers, the SJN analyzer solves the remaining stations with the "
172 "single-server MVA equation");
176 throw UnsupportedError(
"solver_mva_sjn_analyzer: the SJN analyzer does not support " +
178 " scheduling at the other stations");
181 const std::size_t Mq = rows.size();
183 for (std::size_t j = 0; j < Mq; ++j) {
184 const std::size_t i = rows[j];
185 for (std::size_t c = 0; c < C; ++c) {
192 for (std::size_t j : sjnrows) {
193 const std::size_t i = rows[j];
194 for (std::size_t c = 0; c < C; ++c) {
196 if (std::isfinite(v) && v > 0.0) scvd(j, c) = v;
199 std::vector<double> Zd(C, 0.0), Nd(C, 0.0);
200 for (std::size_t c = 0; c < C; ++c) {
201 for (std::size_t i : infrows)
207 sjnopt.
tol =
opt.iter_tol;
208 sjnopt.
iter_max =
static_cast<std::size_t
>(
opt.iter_max);
215 bool distinct =
true;
216 for (std::size_t i = 0; i < L.
nclasses && distinct; ++i)
217 for (std::size_t j = i + 1; j < L.
nclasses; ++j)
223 sjnopt.
prio.assign(C, 0);
224 for (std::size_t c = 0; c < C; ++c) sjnopt.
prio[c] = L.
classes[c].prio;
228 double lattice = 1.0;
229 for (std::size_t c = 0; c < C; ++c) lattice *= Nd[c] + 1.0;
231 if (
opt.method ==
"amva" ||
opt.method ==
"bs" ||
opt.method ==
"sjn.amva")
233 else if (
opt.method ==
"exact" ||
opt.method ==
"mva" ||
opt.method ==
"sjn.mva")
243 if (
opt.method !=
"default")
throw;
254 for (std::size_t c = 0; c < C; ++c) Xchain[c] = num_traits<T>::from_double(sjn.
XN[c]);
255 for (std::size_t j = 0; j < Mq; ++j) {
256 const std::size_t i = rows[j];
257 for (std::size_t c = 0; c < C; ++c) {
262 for (std::size_t i = 0; i < M; ++i)
263 for (std::size_t c = 0; c < C; ++c) Tchain(i, c) = T(Xchain[c] * d.
Vchain(i, c));
265 for (std::size_t i : infrows)
266 for (std::size_t c = 0; c < C; ++c) {
267 Qchain(i, c) = T(Tchain(i, c) * d.
STchain(i, c));
268 Uchain(i, c) = Qchain(i, c);
271 for (std::size_t i = 0; i < M; ++i)
272 for (std::size_t c = 0; c < C; ++c)
273 if (Tchain(i, c) != zero) Rchain(i, c) = T(Qchain(i, c) / Tchain(i, c));
277 for (std::size_t c = 0; c < C; ++c) {
278 if (d.
Nchain[c] != 0.0)
continue;
280 for (std::size_t i = 0; i < M; ++i) {
301 out.
sol.method =
opt.method;
302 out.
sol.iter =
static_cast<int>(sjn.
iter);
304 out.
sol.lG = std::numeric_limits<double>::quiet_NaN();
309 "the utilization cap of 0.999 was binding at an SJN station: the station is in the "
310 "starvation regime, where long jobs are held back and the arrival theorem is badly "
311 "violated. The results are stable but their accuracy is not warranted, use SolverCTMC "
312 "or SolverLDES there";
315 out.
warning +=
"the SJN fixed point did not converge in " + std::to_string(sjn.
iter) +
ClassResults< T > sn_deaggregate_chain_results(const qn::NetworkStruct< T > &L, const ChainDemands< T > &d, const Matrix< T > &Qchain, const Matrix< T > &Uchain, const Matrix< T > &Rchain, const Matrix< T > &Tchain, const std::vector< T > &Xchain)
Port of sn_deaggregate_chain_results.
SjnResult pfqn_amvasjn(const Matrix< double > &L, const std::vector< double > &N, const std::vector< double > &Z, const Matrix< double > &scv, const std::vector< std::size_t > &sjnset, const Matrix< double > &V, const SjnOptions &options)
Schweitzer fixed point counterpart of pfqn_mvasjn.
SjnResult pfqn_mvasjn(const Matrix< double > &L, const std::vector< double > &N, const std::vector< double > &Z, const Matrix< double > &scv, const std::vector< std::size_t > &sjnset, const Matrix< double > &V, const SjnOptions &options)
Exact-lattice MVA for closed networks with SJN stations, the unidirectional scheme of Kant 1992.