110 const std::size_t M = L.
rows();
111 const std::size_t R = L.
cols();
114 "pfqn_comom: at most one queueing station is supported (repairman models with a "
115 "delay); use pfqn_ca or pfqn_recal for M > 1");
116 if (M == 0 || R == 0)
throw InputError(
"pfqn_comom: empty demand matrix");
117 if (N.size() != R)
throw InputError(
"pfqn_comom: L and N disagree on the class count");
118 if (Z.size() != R)
throw InputError(
"pfqn_comom: L and Z disagree on the class count");
124 std::vector<T> Lmax(R, one);
125 for (std::size_t r = 0; r < R; ++r) {
126 T mx = (L(0, r) < atol) ? Z[r] : L(0, r);
127 for (std::size_t i = 1; i < M; ++i) {
128 const T v = (L(i, r) < atol) ? Z[r] : L(i, r);
134 "pfqn_comom: a populated class has neither service demand nor think time");
140 std::vector<T> Zs(R, zero);
141 for (std::size_t r = 0; r < R; ++r) {
142 for (std::size_t i = 0; i < M; ++i)
Ls(i, r) = L(i, r) / Lmax[r];
143 Zs[r] = Z[r] / Lmax[r];
147 const std::vector<std::vector<int>> Dn =
148 detail::comom_basis(
static_cast<int>(R),
static_cast<int>(M));
149 const std::size_t numDn = Dn.size();
150 const std::size_t dim = numDn * (M + 1);
153 const auto col = [&](
const std::vector<int>& d, std::size_t i) {
155 if (pos < 0)
throw NumericError(
"pfqn_comom: basis vector outside the Dn set");
156 const std::size_t p =
static_cast<std::size_t
>(pos);
157 return (i == 1) ? (numDn * M + p) : (p * M + i - 2);
160 std::vector<int> zeroRow(R, 0);
161 std::vector<T> h(dim, zero);
162 for (std::size_t i = 0; i <= M; ++i) h[col(zeroRow, i + 1)] = one;
165 std::vector<int> nvec(R, 0);
166 Matrix<T> A(dim, dim, zero), B(dim, dim, zero), DA(dim, dim, zero);
167 for (std::size_t r = 0; r < R; ++r) {
168 for (
int Nr = 1; Nr <= N[r]; ++Nr) {
175 for (std::size_t d = 0; d < numDn; ++d) {
176 const std::vector<int>& dv = Dn[d];
178 for (std::size_t c = r; c + 1 < R; ++c) s1 += dv[c];
181 for (std::size_t c = r + 1; c + 1 < R; ++c) s2 += dv[c];
182 for (std::size_t k = 0; k <= M; ++k) {
183 const std::size_t c1 = col(dv, k + 1);
188 std::vector<int> dm = dv;
190 B(row, col(dm, k + 1)) = one;
196 for (std::size_t c = 0; c <= r; ++c) s3 += dv[c];
197 if (s3 <
static_cast<int>(M)) {
198 for (std::size_t k = 1; k <= M; ++k) {
199 A(row, col(dv, k + 1)) = one;
200 A(row, col(dv, 1)) = -one;
201 for (std::size_t s = 0; s < r; ++s) {
202 std::vector<int> dp = dv;
204 A(row, col(dp, k + 1)) = -
Ls(k - 1, s);
206 B(row, col(dv, k + 1)) =
Ls(k - 1, r);
209 for (std::size_t s = 0; s < r; ++s) {
211 std::vector<int> dp = dv;
213 A(row, col(dp, 1)) = -Zs[s];
214 for (std::size_t k = 1; k <= M; ++k)
215 A(row, col(dp, k + 1)) = -
Ls(k - 1, s);
222 for (std::size_t d = 0; d < numDn; ++d) {
223 const std::vector<int>& dv = Dn[d];
225 for (std::size_t c = r; c + 1 < R; ++c) s1 += dv[c];
226 if (s1 > 0)
continue;
227 const std::size_t c0 = col(dv, 1);
231 for (std::size_t k = 1; k <= M; ++k) B(row, col(dv, k + 1)) =
Ls(k - 1, r);
235 throw NumericError(
"pfqn_comom: the CoMoM system is not square");
237 for (std::size_t i = 0; i < dim; ++i)
238 for (std::size_t j = 0; j < dim; ++j) A(i, j) += DA(i, j);
241 for (
int x : nvec) nt += x;
244 std::vector<T> b(dim, zero);
245 for (std::size_t i = 0; i < dim; ++i) {
247 for (std::size_t j = 0; j < dim; ++j) s += B(i, j) * h[j];
256 for (
int x : N) Ntot += x;
257 T fact =
num_factorial<T>(
static_cast<unsigned>(Ntot +
static_cast<long>(M) - 1));
258 for (std::size_t r = 0; r < R; ++r) {
260 fact *=
num_pow_int(Lmax[r],
static_cast<unsigned>(N[r]));
265 res.
G = fact * h[dim - R];
288 throw InputError(
"pfqn_comomrm_orig: the solver accepts at most a single queueing station");
296 const std::size_t R = san.
N.size();
302 res.
basis.assign(1, one);
307 std::vector<T> Lv(R, zero), Zv(R, zero), Lmax(R, one);
308 for (std::size_t r = 0; r < R; ++r) {
309 Lv[r] = san.
L.empty() ? zero : san.
L(0, r);
310 for (std::size_t k = 0; k < san.
Z.rows(); ++k) Zv[r] += san.
Z(k, r);
311 T mx = (Lv[r] < atol) ? Zv[r] : Lv[r];
315 "pfqn_comomrm_orig: a populated class has neither demand nor think time");
320 std::vector<int> Nv(R, 0);
321 for (std::size_t r = 0; r < R; ++r) {
328 std::vector<std::size_t> ord(R);
329 for (std::size_t r = 0; r < R; ++r) ord[r] = r;
330 std::stable_sort(ord.begin(), ord.end(),
331 [&](std::size_t a, std::size_t b) { return Zv[a] < Zv[b]; });
332 std::vector<T> Lp(R, zero), Zp(R, zero);
333 std::vector<int> Np(R, 0);
334 for (std::size_t r = 0; r < R; ++r) {
341 std::vector<int> nvec(R, 0);
342 std::vector<T> h(2, one), hprev(2, one);
344 for (std::size_t r = 0; r < R; ++r) {
345 const std::size_t rr = r + 1;
346 for (
int Nr = 1; Nr <= Np[r]; ++Nr) {
349 for (
int x : nvec) nt += x;
353 const std::size_t p = rr - 1;
356 std::vector<T> hn(2 * rr, zero);
357 for (std::size_t i = 0; i < p; ++i) hn[i] = h[i];
358 for (std::size_t i = 0; i < p; ++i) hn[rr + i] = h[p + i];
359 hn[p] = hprev[0] * w;
360 hn[2 * rr - 1] = hprev[p] * w;
364 Matrix<T> C(rr, rr, zero), A12(rr, rr, zero), B1r(rr, 2 * rr, zero),
365 B2r(rr, 2 * rr, zero);
367 for (std::size_t s = 0; s + 1 < rr; ++s) C(0, 1 + s) = -Lp[s];
370 for (std::size_t s = 0; s + 1 < rr; ++s) {
372 A12(1 + s, 1 + s) = -Zp[s];
373 C(1 + s, 1 + s) = -mT * Lp[s];
375 for (std::size_t i = 0; i < rr; ++i) {
376 B2r(i, i) = mT * Lp[r];
377 B2r(i, rr + i) = Zp[r];
381 const std::vector<std::size_t> piv =
lu_factor(LU);
382 Matrix<T> iCB1(rr, 2 * rr, zero), iCA12(rr, rr, zero);
383 for (std::size_t j = 0; j < 2 * rr; ++j) {
384 std::vector<T> rhs(rr, zero);
385 for (std::size_t i = 0; i < rr; ++i) rhs[i] = B1r(i, j);
387 for (std::size_t i = 0; i < rr; ++i) iCB1(i, j) = rhs[i];
389 for (std::size_t j = 0; j < rr; ++j) {
390 std::vector<T> rhs(rr, zero);
391 for (std::size_t i = 0; i < rr; ++i) rhs[i] = A12(i, j);
393 for (std::size_t i = 0; i < rr; ++i) iCA12(i, j) = rhs[i];
397 for (std::size_t i = 0; i < rr; ++i)
398 for (std::size_t j = 0; j < 2 * rr; ++j) {
399 F1(i, j) = iCB1(i, j);
401 for (std::size_t k = 0; k < rr; ++k) s += iCA12(i, k) * B2r(k, j);
403 F2(rr + i, j) = B2r(i, j);
409 std::vector<T> hn(2 * rr, zero);
410 for (std::size_t i = 0; i < 2 * rr; ++i) {
412 for (std::size_t j = 0; j < 2 * rr; ++j) s += (nr * F1(i, j) + F2(i, j)) * hprev[j];
420 for (std::size_t r = 0; r < R; ++r) Ntot += Np[r];
422 for (std::size_t r = 0; r < R; ++r) {
424 fact *=
num_pow_int(Lmax[r],
static_cast<unsigned>(Nv[r]));
428 res.
G = san.
Gremaind * fact * h[h.size() - R];