189 "solver_mva_oi_analyzer: the OI solver requires at least one order-independent "
190 "station (PAS or OI scheduling, a service-rate function, and an all-zero swap graph)");
196 for (std::size_t c = 0; c < L.
nchains; ++c)
199 "solver_mva_oi: requires one class per chain (no class switching)");
201 std::vector<int> N(R, 0);
202 for (std::size_t r = 0; r < R; ++r) {
203 const double nr = L.
classes[r].population;
204 if (!std::isfinite(nr))
206 "solver_mva_oi_analyzer: the CMVA recursion is over a closed lattice; this model "
207 "has an open class");
208 N[r] =
static_cast<int>(std::llround(nr));
211 std::vector<bool> isOI(M,
false), isDelay(M,
false);
212 for (std::size_t i : oi_list) isOI[i - 1] =
true;
213 for (std::size_t i = 0; i < M; ++i) isDelay[i] = (L.
stations[i].sched == SchedStrategy::INF);
217 for (std::size_t c = 0; c < L.
nchains; ++c)
218 for (std::size_t i = 0; i < M; ++i)
219 for (std::size_t r = 0; r < R; ++r)
221 for (std::size_t i = 0; i < M; ++i)
222 for (std::size_t r = 0; r < R; ++r) {
223 const T mu = L.
rates(i, r);
225 D(i, r) = T(V(i, r) / mu);
230 std::vector<T> Z(R, zero);
231 std::vector<std::size_t> li_list, ms_list;
232 for (std::size_t i = 0; i < M; ++i) {
233 if (isOI[i])
continue;
235 for (std::size_t r = 0; r < R; ++r) Z[r] += D(i, r);
236 }
else if (std::isfinite(L.
stations[i].nservers) && L.
stations[i].nservers > 1.0) {
237 ms_list.push_back(i + 1);
239 li_list.push_back(i + 1);
243 for (std::size_t a = 0; a < li_list.size(); ++a)
244 for (std::size_t r = 0; r < R; ++r) Dli(a, r) = D(li_list[a] - 1, r);
246 std::vector<std::function<T(
const std::vector<int>&)>> mu;
247 mu.reserve(oi_list.size() + ms_list.size());
248 for (std::size_t o = 0; o < oi_list.size(); ++o) {
249 const std::function<T(
const std::vector<std::size_t>&)> f =
250 L.
stations[oi_list[o] - 1].svc_rate_fun;
251 mu.push_back([f, R](
const std::vector<int>& n) {
return detail::oi_rate<T>(f, n, R); });
253 for (std::size_t j = 0; j < ms_list.size(); ++j) {
254 std::vector<T> Dq(R, zero);
255 for (std::size_t r = 0; r < R; ++r) Dq[r] = D(ms_list[j] - 1, r);
256 const double c = L.
stations[ms_list[j] - 1].nservers;
257 mu.push_back([Dq, c](
const std::vector<int>& n) {
return detail::ms_oi_rate<T>(n, Dq, c); });
262 Matrix<T> QN(M, R, zero), TN(M, R, zero), RN(M, R, zero), UN(M, R, zero);
263 for (std::size_t o = 0; o < oi_list.size(); ++o)
264 for (std::size_t r = 0; r < R; ++r) QN(oi_list[o] - 1, r) = res.
Qoi(o, r);
265 for (std::size_t j = 0; j < ms_list.size(); ++j)
266 for (std::size_t r = 0; r < R; ++r)
267 QN(ms_list[j] - 1, r) = res.
Qoi(oi_list.size() + j, r);
268 for (std::size_t a = 0; a < li_list.size(); ++a)
269 for (std::size_t r = 0; r < R; ++r) QN(li_list[a] - 1, r) = res.
Qli(a, r);
271 for (std::size_t i = 0; i < M; ++i)
273 for (std::size_t r = 0; r < R; ++r) QN(i, r) = T(res.
X[r] * D(i, r));
276 std::vector<std::size_t> oiRow(M, 0);
277 for (std::size_t o = 0; o < oi_list.size(); ++o) oiRow[oi_list[o] - 1] = o + 1;
279 for (std::size_t i = 0; i < M; ++i)
280 for (std::size_t r = 0; r < R; ++r) {
281 TN(i, r) = T(res.
X[r] * V(i, r));
282 if (res.
X[r] > zero) RN(i, r) = T(QN(i, r) / res.
X[r]);
283 const double sv_raw = L.
stations[i].nservers;
284 const double sv = (std::isfinite(sv_raw) && sv_raw > 0.0) ? sv_raw : 1.0;
291 }
else if (isDelay[i]) {
306 out.
C.assign(R, zero);
307 for (std::size_t r = 0; r < R; ++r)
308 for (std::size_t i = 0; i < M; ++i) out.
C[r] += RN(i, r);
311 for (
int v : N) iter += v;
MvaoiResult< T > pfqn_mvaoi(const std::vector< T > &Z, const std::vector< int > &N, const std::vector< std::function< T(const std::vector< int > &)> > &mu, const Matrix< T > &Dli, const Matrix< T > &visits, bool want_soi)
Mean-value analysis of a closed network with order-independent (OI) stations, the composition-depende...