83 "solver_qna: the decomposition sweeps stop on a tolerance and the multiserver "
84 "correction takes a real power, so exact rational arithmetic cannot run it");
91 if (std::isfinite(c.population))
93 "solver_qna: QNA is an open-network decomposition; a closed chain needs the "
94 "state-encoding layer the reference seeds it from, which is not ported");
97 "solver_qna: the reference indexes the stateful-indexed sn.rt with station indices, "
98 "which is only correct when every stateful node is a station; this model has " +
99 std::to_string(L.
nof_stateful()) +
" stateful nodes and " + std::to_string(M) +
103 "solver_qna: the reference reads the class-indexed sn.njobs with a chain index, which "
104 "is only correct when each chain holds exactly one class");
115 Matrix<T> S(M, K, zero), scv(M, K, zero);
116 for (std::size_t i = 0; i < M; ++i)
117 for (std::size_t r = 0; r < K; ++r) {
118 const T mu = L.
rates(i, r);
119 S(i, r) = (mu > zero) ? T(one / mu) : zero;
121 scv(i, r) = std::isnan(v) ? zero : L.
scv(i, r);
126 for (std::size_t c = 0; c < C; ++c)
127 for (std::size_t i = 0; i < M; ++i)
128 for (std::size_t k = 0; k < K; ++k)
132 auto RT = [&](std::size_t i, std::size_t r, std::size_t j, std::size_t s) -> T {
133 return rt(i * K + r, j * K + s);
144 std::vector<bool> is_source(M,
false);
145 for (std::size_t i = 0; i < M; ++i)
146 is_source[i] = (L.
stations[i].nodetype == NodeType::Source);
147 for (std::size_t i = 0; i < M; ++i)
148 for (std::size_t j = 0; j < M; ++j) {
149 if (is_source[j])
continue;
150 for (std::size_t r = 0; r < K; ++r)
151 for (std::size_t s = 0; s < K; ++s)
152 if (RT(i, r, j, s) > zero)
153 f2(i * K + r, j * K + s) =
154 T(one + RT(i, r, j, s) * T(one - kRR(i, r)));
158 std::vector<T> lambda(C, zero), d2c(C, zero);
159 Matrix<T> Tp(M, K, zero), Q(M, K, zero), U(M, K, zero), Rt(M, K, zero);
160 for (std::size_t c = 0; c < C; ++c) {
162 std::vector<T> lam_in, scv_in;
163 for (std::size_t k : L.
inchain[c]) {
164 lam_in.push_back(L.
rates(ref - 1, k - 1));
165 scv_in.push_back(scv(ref - 1, k - 1));
168 for (
const T& x : lam_in)
172 for (std::size_t a = 0; a < L.
inchain[c].size(); ++a)
173 Tp(ref - 1, L.
inchain[c][a] - 1) = lam_in[a];
179 std::vector<T> d2(M, zero);
181 T num = zero, den = zero;
182 for (std::size_t c = 0; c < C; ++c) {
183 num += T(d2c[c] * lambda[c]);
186 const T seed = (den > zero) ? T(num / den) : zero;
187 for (std::size_t c = 0; c < C; ++c)
191 Matrix<T> a1(M, K, zero), a2(M, K, zero);
197 auto sweep = [&](
const std::vector<T>& qin,
198 std::size_t itnum) -> std::pair<std::vector<T>, std::vector<T>> {
199 for (std::size_t i = 0; i < M; ++i)
200 for (std::size_t k = 0; k < K; ++k) Q(i, k) = qin[i * K + k];
215 std::vector<T> qref(M * K, zero);
216 for (std::size_t c = 0; c < C; ++c) {
217 const double nc = L.
classes[c].population;
219 for (std::size_t i = 0; i < M; ++i) colsum += Q(i, c);
220 for (std::size_t i = 0; i < M; ++i)
224 for (std::size_t i = 0; i < M; ++i)
225 for (std::size_t k = 0; k < K; ++k) qref[i * K + k] = Q(i, k);
228 for (std::size_t c = 0; c < C; ++c)
229 for (std::size_t m = 0; m < M; ++m)
230 for (std::size_t k : L.
inchain[c])
231 Tp(m, k - 1) = T(V(m, k - 1) * lambda[c]);
234 for (std::size_t i = 0; i < M; ++i) {
236 for (std::size_t k = 0; k < K; ++k) lambda_i += Tp(i, k);
237 for (std::size_t r = 0; r < K; ++r) {
241 for (std::size_t j = 0; j < M; ++j)
242 for (std::size_t r = 0; r < K; ++r)
243 for (std::size_t s = 0; s < K; ++s) {
244 const T p = RT(j, s, i, r);
245 if (!(p > zero))
continue;
246 a1(i, r) = T(a1(i, r) + Tp(j, s) * p);
248 a2(i, r) = T(a2(i, r) + T(one / lambda_i) * f2(j * K + s, i * K + r) *
254 for (std::size_t i = 0; i < M; ++i) {
255 if (L.
stations[i].nodetype == NodeType::Join)
continue;
257 case SchedStrategy::INF: {
262 for (std::size_t k = 0; k < K; ++k) {
264 Q(i, k) = T(Tp(i, k) * S(i, k) * V(i, k));
266 Rt(i, k) = Tp(i, k) > zero ? T(Q(i, k) / Tp(i, k)) : zero;
270 case SchedStrategy::PS: {
271 for (std::size_t c = 0; c < C; ++c) {
272 for (std::size_t k : L.
inchain[c]) {
273 Tp(i, k - 1) = T(lambda[c] * V(i, k - 1));
274 U(i, k - 1) = T(S(i, k - 1) * Tp(i, k - 1));
277 for (std::size_t k = 0; k < K; ++k) usum += U(i, k);
278 const T uden = usum < T(one - tol) ? usum : T(one - tol);
283 for (std::size_t k : L.
inchain[c]) {
284 Q(i, k - 1) = T(one - uden) > zero
285 ? T(U(i, k - 1) / T(one - uden))
288 Tp(i, k - 1) > zero ? T(Q(i, k - 1) / Tp(i, k - 1)) : zero;
293 case SchedStrategy::FCFS: {
297 std::vector<T> mu(K, zero), rho_cls(K, zero);
299 for (std::size_t r = 0; r < K; ++r) {
301 mu[r] = std::isnan(m) ? zero : L.
rates(i, r);
302 const T den = T(ftol + mu[r]);
303 rho_cls[r] = den > zero ? T(a1(i, r) / den) : zero;
305 lambda_i += a1(i, r);
309 for (std::size_t r = 0; r < K; ++r) rho += rho_cls[r];
311 if (rho < T(one - tol)) {
316 const T mubar = rho > zero ? T(lambda_i / rho) : zero;
318 for (std::size_t r = 0; r < K; ++r) {
319 if (!(mu[r] > zero) || !(lambda_i > zero))
continue;
320 const T q = T(mubar / mi / mu[r]);
321 c2 += T(a1(i, r) / lambda_i * q * q * T(scv(i, r) + one));
324 for (std::size_t r = 0; r < K; ++r) a2sum += a2(i, r);
325 const T Wiq = mubar > zero
326 ? T(T(alpha / mubar) * T(one / T(one - rho)) *
329 for (std::size_t k = 0; k < K; ++k)
330 Q(i, k) = mu[k] > zero ? T(a1(i, k) / mu[k] + a1(i, k) * Wiq) : zero;
331 d2[i] = T(one + T(rho * rho * T(c2 - one) / sqrt(mi)) +
332 T(T(one - rho * rho) * T(a2sum - one)));
336 for (std::size_t k = 0; k < K; ++k)
340 for (std::size_t k = 0; k < K; ++k) {
342 U(i, k) = T(Tp(i, k) * S(i, k) / mi);
343 Rt(i, k) = Tp(i, k) > zero ? T(Q(i, k) / Tp(i, k)) : zero;
351 if (L.
stations[i].sched != SchedStrategy::EXT)
353 std::string(
"solver_qna: no isolated-station solution for ") +
360 for (std::size_t i = 0; i < M; ++i)
361 for (std::size_t j = 0; j < M; ++j) {
362 if (is_source[j])
continue;
363 for (std::size_t r = 0; r < K; ++r)
364 for (std::size_t s = 0; s < K; ++s)
365 if (RT(i, r, j, s) > zero)
369 f2(i * K + r, j * K + s) =
370 T(one + RT(i, r, j, s) * T(d2[i] - kRR(i, r)));
373 std::vector<T> qnew(M * K, zero);
374 for (std::size_t i = 0; i < M; ++i)
375 for (std::size_t k = 0; k < K; ++k) qnew[i * K + k] = Q(i, k);
376 return std::make_pair(qnew, qref);
382 fo.
iter_max =
static_cast<std::size_t
>(
opt.iter_max) + 1;
386 for (std::size_t i = 0; i < M; ++i)
387 for (std::size_t k = 0; k < K; ++k) Q(i, k) = fr.
x[i * K + k];
390 for (std::size_t i = 0; i < M; ++i)
391 if (L.
stations[i].sched == SchedStrategy::INF)
392 for (std::size_t k = 0; k < K; ++k) U(i, k) = Q(i, k);
399 out.
C.assign(K, zero);
400 out.
X.assign(K, zero);
401 for (std::size_t k = 0; k < K; ++k)
402 for (std::size_t i = 0; i < M; ++i) out.
C[k] += Rt(i, k);
405 for (std::size_t i = 0; i < A.rows(); ++i)
406 for (std::size_t j = 0; j < A.cols(); ++j)
410 for (std::size_t i = 0; i < out.
Q.rows(); ++i)
411 for (std::size_t j = 0; j < out.
Q.cols(); ++j)
412 if (out.
Q(i, j) < zero) out.
Q(i, j) = T(-out.
Q(i, j));
416 for (std::size_t k = 0; k < K; ++k)