91 "solver_qna: the decomposition sweeps stop on a tolerance and the multiserver "
92 "correction takes a real power, so exact rational arithmetic cannot run it");
100 "solver_qna: the reference indexes the stateful-indexed sn.rt with station indices, "
101 "which is only correct when every stateful node is a station; this model has " +
102 std::to_string(L.
nof_stateful()) +
" stateful nodes and " + std::to_string(M) +
106 "solver_qna: the reference reads the class-indexed sn.njobs with a chain index, which "
107 "is only correct when each chain holds exactly one class");
118 Matrix<T> S(M, K, zero), scv(M, K, zero);
119 for (std::size_t i = 0; i < M; ++i)
120 for (std::size_t r = 0; r < K; ++r) {
121 const T mu = L.
rates(i, r);
122 S(i, r) = (mu > zero) ? T(one / mu) : zero;
124 scv(i, r) = std::isnan(v) ? zero : L.
scv(i, r);
129 for (std::size_t c = 0; c < C; ++c)
130 for (std::size_t i = 0; i < M; ++i)
131 for (std::size_t k = 0; k < K; ++k)
135 auto RT = [&](std::size_t i, std::size_t r, std::size_t j, std::size_t s) -> T {
136 return rt(i * K + r, j * K + s);
147 std::vector<bool> is_source(M,
false);
148 for (std::size_t i = 0; i < M; ++i)
149 is_source[i] = (L.
stations[i].nodetype == NodeType::Source);
150 for (std::size_t i = 0; i < M; ++i)
151 for (std::size_t j = 0; j < M; ++j) {
152 if (is_source[j])
continue;
153 for (std::size_t r = 0; r < K; ++r)
154 for (std::size_t s = 0; s < K; ++s)
155 if (RT(i, r, j, s) > zero)
156 f2(i * K + r, j * K + s) =
157 T(one + RT(i, r, j, s) * T(one - kRR(i, r)));
161 std::vector<T> lambda(C, zero), d2c(C, zero);
162 Matrix<T> Tp(M, K, zero), Q(M, K, zero), U(M, K, zero), Rt(M, K, zero);
166 for (std::size_t c = 0; c < C; ++c) {
168 if (std::isfinite(L.
classes[c].population)) {
170 for (std::size_t k = 0; k < K; ++k) ni += n0(ref - 1, k);
171 for (std::size_t k = 0; k < K; ++k) Q(ref - 1, k) = ni;
173 std::vector<T> lam_in, scv_in;
174 for (std::size_t k : L.
inchain[c]) {
175 lam_in.push_back(L.
rates(ref - 1, k - 1));
176 scv_in.push_back(scv(ref - 1, k - 1));
179 for (
const T& x : lam_in)
184 if (!std::isfinite(L.
classes[c].population))
185 for (std::size_t a = 0; a < L.
inchain[c].size(); ++a)
186 Tp(ref - 1, L.
inchain[c][a] - 1) = lam_in[a];
192 std::vector<T> d2(M, zero);
194 T num = zero, den = zero;
195 for (std::size_t c = 0; c < C; ++c) {
196 num += T(d2c[c] * lambda[c]);
199 const T seed = (den > zero) ? T(num / den) : zero;
200 for (std::size_t c = 0; c < C; ++c)
204 Matrix<T> a1(M, K, zero), a2(M, K, zero);
210 auto sweep = [&](
const std::vector<T>& qin,
211 std::size_t itnum) -> std::pair<std::vector<T>, std::vector<T>> {
212 for (std::size_t i = 0; i < M; ++i)
213 for (std::size_t k = 0; k < K; ++k) Q(i, k) = qin[i * K + k];
228 std::vector<T> qref(M * K, zero);
229 for (std::size_t c = 0; c < C; ++c) {
230 const double nc = L.
classes[c].population;
232 for (std::size_t i = 0; i < M; ++i) colsum += Q(i, c);
233 for (std::size_t i = 0; i < M; ++i)
237 for (std::size_t i = 0; i < M; ++i)
238 for (std::size_t k = 0; k < K; ++k) qref[i * K + k] = Q(i, k);
241 for (std::size_t c = 0; c < C; ++c)
242 for (std::size_t m = 0; m < M; ++m)
243 for (std::size_t k : L.
inchain[c])
244 Tp(m, k - 1) = T(V(m, k - 1) * lambda[c]);
247 for (std::size_t i = 0; i < M; ++i) {
249 for (std::size_t k = 0; k < K; ++k) lambda_i += Tp(i, k);
250 for (std::size_t r = 0; r < K; ++r) {
254 for (std::size_t j = 0; j < M; ++j)
255 for (std::size_t r = 0; r < K; ++r)
256 for (std::size_t s = 0; s < K; ++s) {
257 const T p = RT(j, s, i, r);
258 if (!(p > zero))
continue;
259 a1(i, r) = T(a1(i, r) + Tp(j, s) * p);
261 a2(i, r) = T(a2(i, r) + T(one / lambda_i) * f2(j * K + s, i * K + r) *
267 for (std::size_t i = 0; i < M; ++i) {
268 if (L.
stations[i].nodetype == NodeType::Join)
continue;
270 case SchedStrategy::INF: {
275 for (std::size_t k = 0; k < K; ++k) {
277 Q(i, k) = T(Tp(i, k) * S(i, k) * V(i, k));
279 Rt(i, k) = Tp(i, k) > zero ? T(Q(i, k) / Tp(i, k)) : zero;
283 case SchedStrategy::PS: {
284 for (std::size_t c = 0; c < C; ++c) {
285 for (std::size_t k : L.
inchain[c]) {
286 Tp(i, k - 1) = T(lambda[c] * V(i, k - 1));
287 U(i, k - 1) = T(S(i, k - 1) * Tp(i, k - 1));
290 for (std::size_t k = 0; k < K; ++k) usum += U(i, k);
291 const T uden = usum < T(one - tol) ? usum : T(one - tol);
296 for (std::size_t k : L.
inchain[c]) Nc += L.
classes[k - 1].population;
297 for (std::size_t k : L.
inchain[c]) {
299 const T Uk = U(i, k - 1);
300 const T num = std::isfinite(Nc)
303 Q(i, k - 1) = T(one - uden) > zero ? T(num / T(one - uden)) : zero;
305 Tp(i, k - 1) > zero ? T(Q(i, k - 1) / Tp(i, k - 1)) : zero;
310 case SchedStrategy::FCFS: {
314 std::vector<T> mu(K, zero), rho_cls(K, zero);
316 for (std::size_t r = 0; r < K; ++r) {
318 mu[r] = std::isnan(m) ? zero : L.
rates(i, r);
319 const T den = T(ftol + mu[r]);
320 rho_cls[r] = den > zero ? T(a1(i, r) / den) : zero;
322 lambda_i += a1(i, r);
326 for (std::size_t r = 0; r < K; ++r) rho += rho_cls[r];
328 if (rho < T(one - tol)) {
333 const T mubar = rho > zero ? T(lambda_i / rho) : zero;
335 for (std::size_t r = 0; r < K; ++r) {
336 if (!(mu[r] > zero) || !(lambda_i > zero))
continue;
337 const T q = T(mubar / mi / mu[r]);
338 c2 += T(a1(i, r) / lambda_i * q * q * T(scv(i, r) + one));
341 for (std::size_t r = 0; r < K; ++r) a2sum += a2(i, r);
342 const T Wiq = mubar > zero
343 ? T(T(alpha / mubar) * T(one / T(one - rho)) *
346 for (std::size_t k = 0; k < K; ++k)
347 Q(i, k) = mu[k] > zero ? T(a1(i, k) / mu[k] + a1(i, k) * Wiq) : zero;
348 d2[i] = T(one + T(rho * rho * T(c2 - one) / sqrt(mi)) +
349 T(T(one - rho * rho) * T(a2sum - one)));
353 for (std::size_t k = 0; k < K; ++k)
357 for (std::size_t k = 0; k < K; ++k) {
359 U(i, k) = T(Tp(i, k) * S(i, k) / mi);
360 Rt(i, k) = Tp(i, k) > zero ? T(Q(i, k) / Tp(i, k)) : zero;
368 if (L.
stations[i].sched != SchedStrategy::EXT)
370 std::string(
"solver_qna: no isolated-station solution for ") +
377 for (std::size_t i = 0; i < M; ++i)
378 for (std::size_t j = 0; j < M; ++j) {
379 if (is_source[j])
continue;
380 for (std::size_t r = 0; r < K; ++r)
381 for (std::size_t s = 0; s < K; ++s)
382 if (RT(i, r, j, s) > zero)
386 f2(i * K + r, j * K + s) =
387 T(one + RT(i, r, j, s) * T(d2[i] - kRR(i, r)));
390 std::vector<T> qnew(M * K, zero);
391 for (std::size_t i = 0; i < M; ++i)
392 for (std::size_t k = 0; k < K; ++k) qnew[i * K + k] = Q(i, k);
393 return std::make_pair(qnew, qref);
399 fo.
iter_max =
static_cast<std::size_t
>(
opt.iter_max) + 1;
404 std::vector<T> q0(M * K, zero);
405 for (std::size_t i = 0; i < M; ++i)
406 for (std::size_t k = 0; k < K; ++k) q0[i * K + k] = Q(i, k);
408 for (std::size_t i = 0; i < M; ++i)
409 for (std::size_t k = 0; k < K; ++k) Q(i, k) = fr.
x[i * K + k];
412 for (std::size_t c = 0; c < C; ++c) {
413 const double nc = L.
classes[c].population;
414 if (!std::isfinite(
nc))
continue;
416 for (std::size_t i = 0; i < M; ++i) colsum += Q(i, c);
417 for (std::size_t i = 0; i < M; ++i)
422 for (std::size_t i = 0; i < M; ++i)
423 if (L.
stations[i].sched == SchedStrategy::INF)
424 for (std::size_t k = 0; k < K; ++k) U(i, k) = Q(i, k);
431 out.
C.assign(K, zero);
432 out.
X.assign(K, zero);
433 for (std::size_t k = 0; k < K; ++k)
434 for (std::size_t i = 0; i < M; ++i) out.
C[k] += Rt(i, k);
437 for (std::size_t i = 0; i < A.rows(); ++i)
438 for (std::size_t j = 0; j < A.cols(); ++j)
442 for (std::size_t i = 0; i < out.
Q.rows(); ++i)
443 for (std::size_t j = 0; j < out.
Q.cols(); ++j)
444 if (out.
Q(i, j) < zero) out.
Q(i, j) = T(-out.
Q(i, j));
448 for (std::size_t k = 0; k < K; ++k)