202 unsigned max_arrivals, std::size_t max_levels,
const T& tol) {
204 "qsys_mapd1 requires transcendental arithmetic");
206 if (s <= zero)
throw InputError(
"qsys_mapd1: service time s must be positive");
207 if (dist_size == 0)
throw InputError(
"qsys_mapd1: dist_size must be positive");
208 if (max_levels == 0)
throw InputError(
"qsys_mapd1: max_levels must be positive");
209 const std::size_t n = arrival.
D0.rows();
210 if (arrival.
D0.cols() != n || arrival.
D1.rows() != n || arrival.
D1.cols() != n)
211 throw InputError(
"qsys_mapd1: D0 and D1 must be square and of equal order");
216 if (lambda <= zero)
throw InputError(
"qsys_mapd1: non-positive arrival rate");
217 const T rho = lambda * s;
218 if (rho >= one)
throw InputError(
"qsys_mapd1: load rho must be strictly less than 1");
222 for (std::size_t i = 0; i < n; ++i) {
223 const T d = -D0(i, i);
224 if (d > numax) numax = d;
226 const T est = numax * s;
230 const unsigned guess =
static_cast<unsigned>(2.0 * e + 10.0 * std::sqrt(e + 1.0) + 8.0);
231 if (guess > K) K = guess;
233 if (K > max_arrivals) K = max_arrivals;
234 std::vector<Matrix<T>> A = detail::map_counting_at(D0, D1, s, K);
237 for (std::size_t i = 0; i < n; ++i) {
239 for (std::size_t k = 0; k < A.size(); ++k)
240 for (std::size_t j = 0; j < n; ++j) row += A[k](i, j);
241 const T lack = one - row;
242 if (lack > missing) missing = lack;
244 if (missing <= tol || K >= max_arrivals)
break;
245 K = (2u * K < max_arrivals) ? 2u * K : max_arrivals;
246 A = detail::map_counting_at(D0, D1, s, K);
251 std::vector<Matrix<T>> I(A.size());
254 for (std::size_t i = 0; i < n; ++i) C(i, i) -= one;
255 I[0] = detail::rdivide(C, invD0);
256 for (std::size_t k = 1; k < A.size(); ++k) {
259 for (std::size_t i = 0; i < n; ++i)
260 for (std::size_t j = 0; j < n; ++j) Ck(i, j) -= prev(i, j);
261 I[k] = detail::rdivide(Ck, invD0);
267 for (std::size_t i = 0; i < n; ++i)
268 for (std::size_t j = 0; j < n; ++j) negD0inv(i, j) = -invD0(i, j);
270 std::vector<Matrix<T>> B(A.size());
271 for (std::size_t k = 0; k < A.size(); ++k) B[k] =
matmul(Pa, A[k]);
275 const unsigned gmax = 100000u;
276 const std::size_t ktop = A.size() - 1;
277 for (
unsigned it = 0; it < gmax; ++it) {
280 for (std::size_t k = ktop; k-- > 2;) S = mam::qbd_detail::madd(A[k],
matmul(S, G));
285 for (std::size_t i = 0; i < n; ++i)
286 for (std::size_t j = 0; j < n; ++j) {
287 const T d =
num_abs(T(Gn(i, j) - G(i, j)));
288 if (d > gap) gap = d;
291 if (gap <= tol)
break;
295 const std::size_t K1 = A.size() - 1;
296 std::vector<Matrix<T>> Ahat(K1 + 2), Bhat(K1 + 2);
299 for (std::size_t i = K1 + 1; i-- > 0;) {
300 Ahat[i] = mam::qbd_detail::madd(A[i],
matmul(Ahat[i + 1], G));
301 Bhat[i] = mam::qbd_detail::madd(B[i],
matmul(Bhat[i + 1], G));
307 for (std::size_t i = 0; i < n; ++i) M0(i, i) -= one;
308 std::vector<std::vector<T>> x;
309 x.push_back(mam::qbd_detail::statvec(M0));
312 for (
const T& v : x[0]) mass += v;
313 for (std::size_t lvl = 1; lvl <= max_levels; ++lvl) {
314 std::vector<T> acc(n, zero);
316 const std::vector<T> t =
vecmul(x[0], Bhat[lvl]);
317 for (std::size_t j = 0; j < n; ++j) acc[j] += t[j];
319 const std::size_t kmin = (lvl + 1 > K1) ? (lvl + 1 - K1) : 1;
320 for (std::size_t k = kmin; k + 1 <= lvl; ++k) {
321 const std::vector<T> t =
vecmul(x[k], Ahat[lvl - k + 1]);
322 for (std::size_t j = 0; j < n; ++j) acc[j] += t[j];
324 const std::vector<T> xn =
vecmul(acc, W);
326 for (
const T& v : xn) inc += v;
329 if (inc <= tol * mass)
break;
331 for (std::vector<T>& row : x)
332 for (T& v : row) v /= mass;
335 const std::vector<T> e =
ones<T>(n);
336 const std::vector<T> y0 =
vecmul(x[0], Pa);
337 std::vector<std::vector<T>> Ie(I.size());
338 for (std::size_t k = 0; k < I.size(); ++k) Ie[k] =
mulvec(I[k], e);
339 std::vector<T> Isum_e(n, zero), Iw_e(n, zero);
340 for (std::size_t k = 0; k < I.size(); ++k)
341 for (std::size_t j = 0; j < n; ++j) {
342 Isum_e[j] += Ie[k][j];
347 for (std::size_t m = 1; m < x.size(); ++m) {
348 T a = zero, b = zero;
349 for (std::size_t j = 0; j < n; ++j) {
350 a += x[m][j] * Isum_e[j];
351 b += x[m][j] * Iw_e[j];
355 for (std::size_t j = 0; j < n; ++j) L += y0[j] * (Isum_e[j] + Iw_e[j]);
366 const std::vector<T> idle =
mulvec(negD0inv, e);
368 for (std::size_t j = 0; j < n; ++j) p0 += x[0][j] * idle[j];
370 for (std::size_t lvl = 1; lvl < dist_size; ++lvl) {
372 if (lvl - 1 < Ie.size())
373 for (std::size_t j = 0; j < n; ++j) acc += y0[j] * Ie[lvl - 1][j];
374 for (std::size_t m = 1; m <= lvl && m < x.size(); ++m) {
375 const std::size_t kk = lvl - m;
376 if (kk >= Ie.size())
continue;
377 for (std::size_t j = 0; j < n; ++j) acc += x[m][j] * Ie[kk][j];