158 std::size_t dist_size,
unsigned max_arrivals, std::size_t max_levels,
159 const T& tol, std::size_t num_steps) {
161 "qsys_mapdc requires transcendental arithmetic");
163 if (s <= zero)
throw InputError(
"qsys_mapdc: service time s must be positive");
164 if (c == 0)
throw InputError(
"qsys_mapdc: at least one server is required");
165 if (dist_size == 0)
throw InputError(
"qsys_mapdc: dist_size must be positive");
166 if (max_levels == 0)
throw InputError(
"qsys_mapdc: max_levels must be positive");
167 const std::size_t m = arrival.
D0.rows();
168 if (arrival.
D0.cols() != m || arrival.
D1.rows() != m || arrival.
D1.cols() != m)
169 throw InputError(
"qsys_mapdc: D0 and D1 must be square and of equal order");
174 if (lambda <= zero)
throw InputError(
"qsys_mapdc: non-positive arrival rate");
176 const T rho = lambda * s / cT;
177 if (rho >= one)
throw InputError(
"qsys_mapdc: load rho must be strictly less than 1");
181 for (std::size_t i = 0; i < m; ++i) {
182 const T d = -D0(i, i);
183 if (d > numax) numax = d;
185 const T est = numax * s;
189 const unsigned guess =
static_cast<unsigned>(2.0 * e + 10.0 * std::sqrt(e + 1.0) + 8.0);
190 if (guess > K) K = guess;
192 if (K > max_arrivals) K = max_arrivals;
193 std::vector<Matrix<T>> A = detail::map_counting_at(D0, D1, s, K);
196 for (std::size_t i = 0; i < m; ++i) {
198 for (std::size_t k = 0; k < A.size(); ++k)
199 for (std::size_t j = 0; j < m; ++j) row += A[k](i, j);
200 const T lack = one - row;
201 if (lack > missing) missing = lack;
203 if (missing <= tol || K >= max_arrivals)
break;
204 K = (2u * K < max_arrivals) ? 2u * K : max_arrivals;
205 A = detail::map_counting_at(D0, D1, s, K);
207 const std::size_t Kmax = A.size() - 1;
211 const std::size_t cs =
static_cast<std::size_t
>(c);
212 const std::size_t nb = cs * m;
213 std::size_t Kg = (Kmax + cs - 1) / cs + 1;
215 std::vector<Matrix<T>> Ag(Kg + 1,
Matrix<T>(nb, nb, zero));
216 std::vector<Matrix<T>> Bg(Kg + 1,
Matrix<T>(nb, nb, zero));
217 for (std::size_t i = 0; i <= Kg; ++i) {
218 for (std::size_t u = 0; u < cs; ++u) {
219 for (std::size_t v = 0; v < cs; ++v) {
220 const long ka =
static_cast<long>(i * cs + v) -
static_cast<long>(u);
221 if (ka >= 0 &&
static_cast<std::size_t
>(ka) <= Kmax) {
222 const Matrix<T>& blk = A[
static_cast<std::size_t
>(ka)];
223 for (std::size_t p = 0; p < m; ++p)
224 for (std::size_t q = 0; q < m; ++q)
225 Ag[i](u * m + p, v * m + q) = blk(p, q);
227 const std::size_t kb = i * cs + v;
230 for (std::size_t p = 0; p < m; ++p)
231 for (std::size_t q = 0; q < m; ++q)
232 Bg[i](u * m + p, v * m + q) = blk(p, q);
240 const unsigned gmax = 100000u;
241 for (
unsigned it = 0; it < gmax; ++it) {
244 for (std::size_t i = Kg; i-- > 2;) S = mam::qbd_detail::madd(Ag[i],
matmul(S, G));
249 for (std::size_t i = 0; i < nb; ++i)
250 for (std::size_t j = 0; j < nb; ++j) {
251 const T d =
num_abs(T(Gn(i, j) - G(i, j)));
252 if (d > gap) gap = d;
255 if (gap <= tol)
break;
258 std::vector<Matrix<T>> Ahat(Kg + 2), Bhat(Kg + 2);
261 for (std::size_t i = Kg + 1; i-- > 0;) {
262 Ahat[i] = mam::qbd_detail::madd(Ag[i],
matmul(Ahat[i + 1], G));
263 Bhat[i] = mam::qbd_detail::madd(Bg[i],
matmul(Bhat[i + 1], G));
268 for (std::size_t i = 0; i < nb; ++i) M0(i, i) -= one;
269 std::vector<std::vector<T>> x;
270 x.push_back(mam::qbd_detail::statvec(M0));
273 for (
const T& v : x[0]) mass += v;
274 for (std::size_t lvl = 1; lvl <= max_levels; ++lvl) {
275 std::vector<T> acc(nb, zero);
277 const std::vector<T> t =
vecmul(x[0], Bhat[lvl]);
278 for (std::size_t j = 0; j < nb; ++j) acc[j] += t[j];
280 const std::size_t kmin = (lvl + 1 > Kg) ? (lvl + 1 - Kg) : 1;
281 for (std::size_t k = kmin; k + 1 <= lvl; ++k) {
282 const std::vector<T> t =
vecmul(x[k], Ahat[lvl - k + 1]);
283 for (std::size_t j = 0; j < nb; ++j) acc[j] += t[j];
285 const std::vector<T> xn =
vecmul(acc, W);
287 for (
const T& v : xn) inc += v;
290 if (inc <= tol * mass)
break;
292 for (std::vector<T>& row : x)
293 for (T& v : row) v /= mass;
299 for (std::size_t lvl = 0; lvl < x.size(); ++lvl) {
300 for (std::size_t u = 0; u < cs; ++u) {
302 for (std::size_t j = 0; j < m; ++j) pn += x[lvl][u * m + j];
303 const std::size_t n = lvl * cs + u;
319 std::vector<std::vector<T>> pi(x.size() * cs, std::vector<T>(m, zero));
320 for (std::size_t lvl = 0; lvl < x.size(); ++lvl)
321 for (std::size_t u = 0; u < cs; ++u)
322 for (std::size_t j = 0; j < m; ++j) pi[lvl * cs + u][j] = x[lvl][u * m + j];
325 num_steps == 0 ? 1 : num_steps, thetaA,
328 r.
analyzer =
"Q-MAM:MAP/D/" + std::to_string(c);