68 const std::vector<long>& c, std::size_t M, std::size_t R) {
71 for (std::size_t i = 0; i < M; ++i) {
72 if (is_is(c, i))
continue;
74 for (std::size_t r = 0; r < R; ++r)
75 if (V(i, r) > zero && mu(i, r) > zero) rho_i += X[r] * V(i, r) / mu(i, r);
76 if (rho_i > maxrho) maxrho = rho_i;
80 const T f = cap / maxrho;
81 for (std::size_t r = 0; r < R; ++r) X[r] *= f;
93PseudoOpen<T> me_cqn_pseudoopen(std::size_t M, std::size_t R,
const Matrix<T>& lambda,
96 const Matrix<T>& selfp,
const std::vector<long>& c,
97 const std::vector<char>& insens,
Matrix<T>& Ca,
104 for (std::size_t i = 0; i < M; ++i)
105 for (std::size_t r = 0; r < R; ++r) lameff(i, r) = lambda(i, r) * (one - selfp(i, r));
109 for (std::size_t i = 0; i < M; ++i)
110 for (std::size_t r = 0; r < R; ++r) {
111 if (!(mu(i, r) > zero))
continue;
112 po.rho(i, r) = is_is(c, i) ? lameff(i, r) / mueff(i, r) : lambda(i, r) / mu(i, r);
116 std::vector<T> lam_a(M, zero), mu_a(M, zero), Cs_a(M, one);
117 for (std::size_t i = 0; i < M; ++i)
118 for (std::size_t r = 0; r < R; ++r) lam_a[i] += lameff(i, r);
119 for (std::size_t i = 0; i < M; ++i) {
120 if (!(lam_a[i] > zero))
continue;
121 T ES = zero, ES2 = zero;
122 for (std::size_t u = 0; u < R; ++u) {
123 if (!(lameff(i, u) > zero && mueff(i, u) > zero))
continue;
124 const T wu = lameff(i, u) / lam_a[i];
125 ES += wu / mueff(i, u);
126 ES2 += wu * (Cseff(i, u) + one) / (mueff(i, u) * mueff(i, u));
130 Cs_a[i] = ES2 / (ES * ES) - one;
134 for (std::size_t j = 0; j < M; ++j) {
135 if (!(lam_a[j] > zero))
continue;
136 for (std::size_t i = 0; i < M; ++i) {
138 for (std::size_t r = 0; r < R; ++r)
139 if (lameff(j, r) > zero) num += lameff(j, r) * Peff[r](j, i);
140 Pa(j, i) = num / lam_a[j];
145 std::vector<T> Ca_a(M, one), Cd_a(M, one), L_a(M, zero);
146 for (std::size_t i = 0; i < M; ++i) {
147 if (!(lam_a[i] > zero))
continue;
148 for (std::size_t r = 0; r < R; ++r)
149 if (lameff(i, r) > zero) {
150 Ca_a[i] = one + (Ca(i, r) - one) * lam_a[i] / lameff(i, r);
154 for (
long it = 1; it <=
opt.maxiter; ++it) {
155 const std::vector<T> Ca_old = Ca_a;
156 for (std::size_t i = 0; i < M; ++i) {
157 if (!(lam_a[i] > zero))
continue;
159 for (std::size_t r = 0; r < R; ++r) rho_i += po.rho(i, r);
161 L_a[i] = lam_a[i] / mu_a[i];
163 }
else if (rho_i < one) {
165 L_a[i] = rho_i / (one - rho_i);
167 L_a[i] = rho_i * (Ca_a[i] + one) / two +
168 rho_i * rho_i * (Ca_a[i] + Cs_a[i]) / (two * (one - rho_i));
169 Cd_a[i] = two * L_a[i] * (one - rho_i) + Ca_a[i] * (one - two * rho_i);
172 for (std::size_t i = 0; i < M; ++i) {
173 if (!(lam_a[i] > zero))
continue;
175 for (std::size_t j = 0; j < M; ++j) {
176 if (!(Pa(j, i) > zero) || !(lam_a[j] > zero))
continue;
177 const T Cdji = one + Pa(j, i) * (Cd_a[j] - one);
178 sum_inv += (lam_a[j] * Pa(j, i) / lam_a[i]) / (Cdji + one);
180 if (sum_inv > zero) Ca_a[i] = -one + one / sum_inv;
183 for (std::size_t i = 0; i < M; ++i) {
184 const T d =
num_abs(T(Ca_a[i] - Ca_old[i]));
185 if (d > delta) delta = d;
187 if (delta < tol)
break;
193 for (std::size_t i = 0; i < M; ++i) {
195 for (std::size_t r = 0; r < R; ++r) rho_i += po.rho(i, r);
196 for (std::size_t r = 0; r < R; ++r) {
197 if (!(lameff(i, r) > zero))
continue;
198 const T pr = lameff(i, r) / lam_a[i];
199 Ca(i, r) = one + pr * (Ca_a[i] - one);
200 po.Cd(i, r) = one + pr * (Cd_a[i] - one);
203 for (std::size_t r = 0; r < R; ++r)
204 if (lameff(i, r) > zero && mueff(i, r) > zero)
205 po.L(i, r) = lameff(i, r) / mueff(i, r);
206 }
else if (rho_i < one) {
208 for (std::size_t r = 0; r < R; ++r)
209 if (lameff(i, r) > zero && mueff(i, r) > zero)
210 po.L(i, r) = po.rho(i, r) / (one - rho_i);
213 for (std::size_t u = 0; u < R; ++u)
214 if (lameff(i, u) > zero && mueff(i, u) > zero)
215 resid += lameff(i, u) * (Cseff(i, u) + Ca(i, u)) /
216 (mueff(i, u) * mueff(i, u));
217 for (std::size_t r = 0; r < R; ++r)
218 if (lameff(i, r) > zero && mueff(i, r) > zero)
219 po.L(i, r) = po.rho(i, r) * (Ca(i, r) + one) / two +
220 lameff(i, r) * resid / (two * (one - rho_i));
228inline std::vector<std::vector<long>> me_cqn_lattice(
const std::vector<long>& N) {
229 std::size_t PIdx = 1;
230 for (std::size_t r = 0; r < N.size(); ++r) PIdx *=
static_cast<std::size_t
>(N[r] + 1);
231 std::vector<std::vector<long>> Dec(PIdx, std::vector<long>(N.size(), 0));
232 for (std::size_t p = 0; p < PIdx; ++p) {
234 for (std::size_t r = 0; r < N.size(); ++r) {
235 const std::size_t sz =
static_cast<std::size_t
>(N[r] + 1);
236 Dec[p][r] =
static_cast<long>(q % sz);
249Matrix<T> me_cqn_coefficients(std::size_t M, std::size_t R,
const std::vector<long>& N,
250 const std::vector<std::vector<long>>& Dec,
const Matrix<T>& Lpo,
253 const std::vector<long>& c,
const Matrix<T>& selfp) {
255 const std::size_t PIdx = Dec.size();
258 for (std::size_t i = 0; i < M; ++i)
259 for (std::size_t r = 0; r < R; ++r) lameff(i, r) = lambda(i, r) * (one - selfp(i, r));
261 for (std::size_t i = 0; i < M; ++i) {
264 std::vector<std::vector<T>> logg(R);
265 std::vector<std::vector<char>> ok(R);
266 for (std::size_t r = 0; r < R; ++r) {
267 logg[r].assign(
static_cast<std::size_t
>(N[r]), zero);
268 ok[r].assign(
static_cast<std::size_t
>(N[r]), 0);
269 for (
long j = 1; j <= N[r]; ++j) {
270 if (!(lameff(i, r) > zero && mueff(i, r) > zero))
continue;
272 (Ca(i, r) + Cseff(i, r));
273 if (!(den > zero))
continue;
274 const T gj = (lameff(i, r) * (one + Cseff(i, r)) +
278 if (!(gj > zero))
continue;
279 logg[r][
static_cast<std::size_t
>(j - 1)] = num_log(gj);
280 ok[r][
static_cast<std::size_t
>(j - 1)] = 1;
283 for (std::size_t p = 0; p < PIdx; ++p) {
286 for (std::size_t r = 0; r < R && good; ++r)
287 for (
long j = 1; j <= Dec[p][r]; ++j) {
288 if (!ok[r][
static_cast<std::size_t
>(j - 1)]) {
292 val += logg[r][
static_cast<std::size_t
>(j - 1)];
294 F(p, i) = good ? num_exp(val) : zero;
300 T rho_i = zero, Li = zero;
301 for (std::size_t r = 0; r < R; ++r) {
302 rho_i += rho_po(i, r);
305 std::vector<T> x(R, zero), gx(R, zero);
306 if (Li > zero && rho_i < one) {
307 for (std::size_t r = 0; r < R; ++r) {
308 if (!(lambda(i, r) > zero))
continue;
309 const T d = Lpo(i, r) - rho_po(i, r);
310 x[r] = d > zero ? d / Li : zero;
311 gx[r] = rho_po(i, r) * rho_i / ((one - rho_i) * Li);
314 for (std::size_t p = 0; p < PIdx; ++p) {
317 for (std::size_t r = 0; r < R; ++r) {
319 if (Dec[p][r] > 0 && !(lambda(i, r) > zero)) absent =
true;
329 T logmult = log_factorial<T>(ntot - 1);
330 for (std::size_t r = 0; r < R; ++r) logmult -= log_factorial<T>(Dec[p][r]);
332 for (std::size_t r = 0; r < R; ++r) {
333 if (!(Dec[p][r] > 0) || !(gx[r] > zero))
continue;
336 for (std::size_t s = 0; s < R; ++s) {
337 const long es = (s == r) ? Dec[p][s] - 1 : Dec[p][s];
338 if (es <= 0)
continue;
339 if (!(x[s] > zero)) {
345 if (good) tot += num_exp(T(logmult + lterm));
351 for (std::size_t p = 0; p < PIdx; ++p)
352 if (F(p, i) > fmax) fmax = F(p, i);
354 for (std::size_t p = 0; p < PIdx; ++p) F(p, i) /= fmax;
362std::vector<T> me_cqn_convpair(
const std::vector<T>& G,
const std::vector<T>& f,
363 const std::vector<std::vector<long>>& Dec,
364 const std::vector<long>& N,
const std::vector<std::size_t>& rad) {
366 const std::size_t PIdx = Dec.size();
367 std::vector<T> G2(PIdx, zero);
368 for (std::size_t p = 0; p < PIdx; ++p) {
369 if (f[p] == zero)
continue;
370 for (std::size_t q = 0; q < PIdx; ++q) {
371 if (G[q] == zero)
continue;
374 for (std::size_t r = 0; r < N.size(); ++r) {
375 const long t = Dec[p][r] + Dec[q][r];
380 idx +=
static_cast<std::size_t
>(t) * rad[r];
382 if (fits) G2[idx] += f[p] * G[q];
400MeCqnConv<T> me_cqn_convolve(std::size_t M, std::size_t R,
const std::vector<long>& N,
401 const std::vector<std::vector<long>>& Dec,
const Matrix<T>& F) {
403 const std::size_t PIdx = Dec.size();
404 std::vector<std::size_t> rad(R, 1);
405 for (std::size_t r = 1; r < R; ++r)
406 rad[r] = rad[r - 1] *
static_cast<std::size_t
>(N[r - 1] + 1);
408 std::vector<std::vector<T>> Fcol(M, std::vector<T>(PIdx, zero));
409 for (std::size_t i = 0; i < M; ++i)
410 for (std::size_t p = 0; p < PIdx; ++p) Fcol[i][p] = F(p, i);
412 std::vector<T> G0(PIdx, zero);
414 std::vector<std::vector<T>> Gpre(M + 1), Gsuf(M + 1);
416 for (std::size_t k = 0; k < M; ++k)
417 Gpre[k + 1] = me_cqn_convpair(Gpre[k], Fcol[k], Dec, N, rad);
419 for (std::size_t k = M; k-- > 0;)
420 Gsuf[k] = me_cqn_convpair(Gsuf[k + 1], Fcol[k], Dec, N, rad);
422 const T Z = Gpre[M][PIdx - 1];
423 if (!(Z > zero))
throw NumericError(
"me_cqn: the normalizing constant vanished");
427 out.U.assign(M, zero);
428 for (std::size_t i = 0; i < M; ++i) {
429 const std::vector<T> Grest = me_cqn_convpair(Gpre[i], Gsuf[i + 1], Dec, N, rad);
430 for (std::size_t p = 0; p < PIdx; ++p) {
431 if (!(F(p, i) > zero))
continue;
433 for (std::size_t r = 0; r < R; ++r)
434 q +=
static_cast<std::size_t
>(N[r] - Dec[p][r]) * rad[r];
435 const T pin = F(p, i) * Grest[q] / Z;
436 if (p > 0) out.U[i] += pin;
437 for (std::size_t r = 0; r < R; ++r)
465 const std::vector<long>& c,
const std::vector<long>& refstat_in,
468 detail::check_dims(M, R, mu, Cs, P, c, insens,
"me_cqn");
469 if (N.size() != R)
throw InputError(
"me_cqn: one population per class");
470 if (refstat_in.size() != R)
throw InputError(
"me_cqn: one reference station per class");
471 for (std::size_t i = 0; i < M; ++i)
472 if (c[i] > 1)
throw InputError(
"me_cqn: only single-server and IS stations are supported");
473 for (std::size_t r = 0; r < R; ++r)
474 if (N[r] < 0)
throw InputError(
"me_cqn: populations must be nonnegative");
481 std::vector<Matrix<T>> Peff = P;
482 Matrix<T> mueff = mu, Cseff = Cs, selfp(M, R, zero);
483 for (std::size_t i = 0; i < M; ++i)
484 for (std::size_t r = 0; r < R; ++r) {
485 const T pii = P[r](i, i);
486 if (!(pii > zero))
continue;
487 if (pii >= one)
throw InputError(
"me_cqn: a self-loop probability of one");
489 mueff(i, r) = mu(i, r) * (one - pii);
490 Cseff(i, r) = pii + (one - pii) * Cs(i, r);
491 for (std::size_t j = 0; j < M; ++j) Peff[r](i, j) = P[r](i, j) / (one - pii);
492 Peff[r](i, i) = zero;
497 std::vector<long> refstat = refstat_in;
498 for (std::size_t r = 0; r < R; ++r) {
500 if (refstat[r] < 0) {
502 while (k < M && !(mu(k, r) > zero)) ++k;
503 if (k == M)
throw InputError(
"me_cqn: a class is not served anywhere");
506 ref =
static_cast<std::size_t
>(refstat[r]);
507 if (ref >= M)
throw InputError(
"me_cqn: the reference station is out of range");
509 refstat[r] =
static_cast<long>(ref);
511 std::vector<T> b(M, zero);
512 for (std::size_t i = 0; i < M; ++i)
513 for (std::size_t j = 0; j < M; ++j) A(i, j) = (i == j ? one : zero) - P[r](j, i);
514 for (std::size_t j = 0; j < M; ++j) A(ref, j) = zero;
517 const std::vector<T> v = detail::linear_solve(A, b);
519 for (std::size_t i = 0; i < M; ++i) V(i, r) =
num_abs(v[i]) < eps ? zero : v[i];
523 std::vector<T> X(R, zero);
524 for (std::size_t r = 0; r < R; ++r) {
527 for (std::size_t i = 0; i < M; ++i) {
528 if (detail::is_is(c, i) || !(V(i, r) > zero) || !(mu(i, r) > zero))
continue;
529 const T cand = mu(i, r) / V(i, r);
530 if (!have || cand < capr) {
535 if (!have) capr = one;
542 detail::PseudoOpen<T> po;
547 const long maxit1 = std::min<long>(
opt.maxiter, 100);
548 for (
long it1 = 1; it1 <= maxit1; ++it1) {
550 detail::me_cqn_capacity_cap(X, V, mu, c, M, R);
551 for (std::size_t i = 0; i < M; ++i)
552 for (std::size_t r = 0; r < R; ++r) lambda(i, r) = V(i, r) * X[r];
553 po = detail::me_cqn_pseudoopen(M, R, lambda, mu, mueff, Cseff, Peff, selfp, c, insens,
556 std::vector<T> Ltot(R, zero);
557 for (std::size_t r = 0; r < R; ++r)
558 for (std::size_t i = 0; i < M; ++i) Ltot[r] += po.L(i, r);
559 for (std::size_t r = 0; r < R; ++r) {
560 if (!(N[r] > 0) || !(Ltot[r] > zero))
continue;
563 if (e > err1) err1 = e;
565 if (err1 < tol)
break;
566 const std::vector<T> Xold = X;
567 for (std::size_t r = 0; r < R; ++r) {
568 if (!(Ltot[r] > zero))
continue;
571 if (fac < lo) fac = lo;
572 if (fac > hi) fac = hi;
573 X[r] = half * X[r] + half * X[r] * fac;
577 std::vector<T> Xc = X;
578 detail::me_cqn_capacity_cap(Xc, V, mu, c, M, R);
580 for (std::size_t r = 0; r < R; ++r) {
584 const T d =
num_abs(T(Xc[r] - Xold[r])) / den;
585 if (d > move) move = d;
587 if (move < tol)
break;
591 const std::vector<std::vector<long>> Dec = detail::me_cqn_lattice(N);
595 for (
long it2 = 1; it2 <=
opt.maxiter; ++it2) {
597 const Matrix<T> F = detail::me_cqn_coefficients(M, R, N, Dec, po.L, po.rho, lambda, mueff,
598 Cseff, out.
Ca, c, selfp);
599 const detail::MeCqnConv<T> conv = detail::me_cqn_convolve(M, R, N, Dec, F);
602 std::vector<T> Xhat(R, zero);
603 for (std::size_t r = 0; r < R; ++r) {
604 T num = zero, den = zero;
605 for (std::size_t i = 0; i < M; ++i) {
606 if (!(lambda(i, r) > zero))
continue;
607 if (detail::is_is(c, i)) {
608 out.
rho(i, r) = out.
L(i, r);
609 num += out.
L(i, r) * mueff(i, r) / (one - selfp(i, r));
612 for (std::size_t u = 0; u < R; ++u) rho_i += po.rho(i, u);
613 if (rho_i > zero) out.
rho(i, r) = conv.U[i] * po.rho(i, r) / rho_i;
614 num += out.
rho(i, r) * mu(i, r);
618 if (den > zero) Xhat[r] = num / den;
621 for (std::size_t r = 0; r < R; ++r) {
622 if (!(X[r] > zero))
continue;
623 const T e =
num_abs(T(Xhat[r] - X[r])) / X[r];
624 if (e > err2) err2 = e;
630 const std::vector<T> Xold = X;
631 for (std::size_t r = 0; r < R; ++r) X[r] = half * X[r] + half * Xhat[r];
632 detail::me_cqn_capacity_cap(X, V, mu, c, M, R);
634 for (std::size_t r = 0; r < R; ++r) {
638 const T d =
num_abs(T(X[r] - Xold[r])) / den;
639 if (d > move) move = d;
641 if (move < tol)
break;
642 for (std::size_t i = 0; i < M; ++i)
643 for (std::size_t r = 0; r < R; ++r) lambda(i, r) = V(i, r) * X[r];
644 po = detail::me_cqn_pseudoopen(M, R, lambda, mu, mueff, Cseff, Peff, selfp, c, insens,
650 for (std::size_t i = 0; i < M; ++i)
651 for (std::size_t r = 0; r < R; ++r) out.
lambda(i, r) = V(i, r) * X[r];
653 for (std::size_t i = 0; i < M; ++i)
654 for (std::size_t r = 0; r < R; ++r)
655 if (out.
lambda(i, r) > zero) out.
W(i, r) = out.
L(i, r) / out.
lambda(i, r);