154 std::size_t dist_size,
unsigned max_arrivals, std::size_t max_levels,
157 "qsys_mapdc requires transcendental arithmetic");
159 if (s <= zero)
throw InputError(
"qsys_mapdc: service time s must be positive");
160 if (c == 0)
throw InputError(
"qsys_mapdc: at least one server is required");
161 if (dist_size == 0)
throw InputError(
"qsys_mapdc: dist_size must be positive");
162 if (max_levels == 0)
throw InputError(
"qsys_mapdc: max_levels must be positive");
163 const std::size_t m = arrival.
D0.rows();
164 if (arrival.
D0.cols() != m || arrival.
D1.rows() != m || arrival.
D1.cols() != m)
165 throw InputError(
"qsys_mapdc: D0 and D1 must be square and of equal order");
170 if (lambda <= zero)
throw InputError(
"qsys_mapdc: non-positive arrival rate");
172 const T rho = lambda * s / cT;
173 if (rho >= one)
throw InputError(
"qsys_mapdc: load rho must be strictly less than 1");
177 for (std::size_t i = 0; i < m; ++i) {
178 const T d = -D0(i, i);
179 if (d > numax) numax = d;
181 const T est = numax * s;
185 const unsigned guess =
static_cast<unsigned>(2.0 * e + 10.0 * std::sqrt(e + 1.0) + 8.0);
186 if (guess > K) K = guess;
188 if (K > max_arrivals) K = max_arrivals;
189 std::vector<Matrix<T>> A = detail::map_counting_at(D0, D1, s, K);
192 for (std::size_t i = 0; i < m; ++i) {
194 for (std::size_t k = 0; k < A.size(); ++k)
195 for (std::size_t j = 0; j < m; ++j) row += A[k](i, j);
196 const T lack = one - row;
197 if (lack > missing) missing = lack;
199 if (missing <= tol || K >= max_arrivals)
break;
200 K = (2u * K < max_arrivals) ? 2u * K : max_arrivals;
201 A = detail::map_counting_at(D0, D1, s, K);
203 const std::size_t Kmax = A.size() - 1;
207 const std::size_t cs =
static_cast<std::size_t
>(c);
208 const std::size_t nb = cs * m;
209 std::size_t Kg = (Kmax + cs - 1) / cs + 1;
211 std::vector<Matrix<T>> Ag(Kg + 1,
Matrix<T>(nb, nb, zero));
212 std::vector<Matrix<T>> Bg(Kg + 1,
Matrix<T>(nb, nb, zero));
213 for (std::size_t i = 0; i <= Kg; ++i) {
214 for (std::size_t u = 0; u < cs; ++u) {
215 for (std::size_t v = 0; v < cs; ++v) {
216 const long ka =
static_cast<long>(i * cs + v) -
static_cast<long>(u);
217 if (ka >= 0 &&
static_cast<std::size_t
>(ka) <= Kmax) {
218 const Matrix<T>& blk = A[
static_cast<std::size_t
>(ka)];
219 for (std::size_t p = 0; p < m; ++p)
220 for (std::size_t q = 0; q < m; ++q)
221 Ag[i](u * m + p, v * m + q) = blk(p, q);
223 const std::size_t kb = i * cs + v;
226 for (std::size_t p = 0; p < m; ++p)
227 for (std::size_t q = 0; q < m; ++q)
228 Bg[i](u * m + p, v * m + q) = blk(p, q);
236 const unsigned gmax = 100000u;
237 for (
unsigned it = 0; it < gmax; ++it) {
240 for (std::size_t i = Kg; i-- > 2;) S = mam::qbd_detail::madd(Ag[i],
matmul(S, G));
245 for (std::size_t i = 0; i < nb; ++i)
246 for (std::size_t j = 0; j < nb; ++j) {
247 const T d =
num_abs(T(Gn(i, j) - G(i, j)));
248 if (d > gap) gap = d;
251 if (gap <= tol)
break;
254 std::vector<Matrix<T>> Ahat(Kg + 2), Bhat(Kg + 2);
257 for (std::size_t i = Kg + 1; i-- > 0;) {
258 Ahat[i] = mam::qbd_detail::madd(Ag[i],
matmul(Ahat[i + 1], G));
259 Bhat[i] = mam::qbd_detail::madd(Bg[i],
matmul(Bhat[i + 1], G));
264 for (std::size_t i = 0; i < nb; ++i) M0(i, i) -= one;
265 std::vector<std::vector<T>> x;
266 x.push_back(mam::qbd_detail::statvec(M0));
269 for (
const T& v : x[0]) mass += v;
270 for (std::size_t lvl = 1; lvl <= max_levels; ++lvl) {
271 std::vector<T> acc(nb, zero);
273 const std::vector<T> t =
vecmul(x[0], Bhat[lvl]);
274 for (std::size_t j = 0; j < nb; ++j) acc[j] += t[j];
276 const std::size_t kmin = (lvl + 1 > Kg) ? (lvl + 1 - Kg) : 1;
277 for (std::size_t k = kmin; k + 1 <= lvl; ++k) {
278 const std::vector<T> t =
vecmul(x[k], Ahat[lvl - k + 1]);
279 for (std::size_t j = 0; j < nb; ++j) acc[j] += t[j];
281 const std::vector<T> xn =
vecmul(acc, W);
283 for (
const T& v : xn) inc += v;
286 if (inc <= tol * mass)
break;
288 for (std::vector<T>& row : x)
289 for (T& v : row) v /= mass;
295 for (std::size_t lvl = 0; lvl < x.size(); ++lvl) {
296 for (std::size_t u = 0; u < cs; ++u) {
298 for (std::size_t j = 0; j < m; ++j) pn += x[lvl][u * m + j];
299 const std::size_t n = lvl * cs + u;
MapDcResult< T > qsys_mapdc(const mam::Map< T > &arrival, const T &s, unsigned c, std::size_t dist_size, unsigned max_arrivals, std::size_t max_levels, const T &tol)
MAP/D/c by Crommelin's exact embedded lattice chain.