107 const std::vector<T>& arrRate,
const std::vector<T>& sf) {
109 const std::size_t p = D0.
rows();
110 const std::size_t Nlev = arrRate.size() - 1;
112 for (std::size_t i = 0; i < p; ++i)
113 for (std::size_t j = 0; j < p; ++j) negD0(i, j) = T(-D0(i, j));
116 std::vector<std::vector<int> > tp(p, std::vector<int>(p, -1));
117 std::vector<std::pair<std::size_t, std::size_t> > pairs;
118 for (std::size_t i = 0; i < p; ++i)
119 for (std::size_t j = 0; j < p; ++j) {
121 for (std::size_t k = 0; k < p; ++k) v += T(Ninv(i, k) * D1(k, j));
125 tp[i][j] =
static_cast<int>(pairs.size());
126 pairs.push_back(std::make_pair(i, j));
129 const std::size_t NT = pairs.size();
130 std::vector<T> done(NT, zero);
131 for (std::size_t t = 0; t < NT; ++t)
132 done[t] = T(D1(pairs[t].first, pairs[t].second) / V(pairs[t].first, pairs[t].second));
134 std::vector<std::vector<std::vector<int> > > cfg(cmax + 1);
135 std::vector<std::map<std::vector<int>, std::size_t> > pos(cmax + 1);
136 std::vector<std::size_t> nCfg(cmax + 1, 0), nk(cmax + 1, 0);
137 for (std::size_t k = 0; k <= cmax; ++k) {
139 for (std::size_t r = 0; r < cfg[k].size(); ++r) pos[k][cfg[k][r]] = r;
140 nCfg[k] = cfg[k].size();
145 "ldqbd_mphc: the exact MAP/c chain with a carried service phase needs " +
146 std::to_string(nk[cmax]) +
" configurations per level for " + std::to_string(cmax) +
147 " servers and " + std::to_string(p) +
" service phases, above the " +
149 " the level-by-level inverses can carry. Use fewer servers or SolverLDES on this model");
151 std::vector<Matrix<T> > LOC(cmax + 1), UP(cmax + 1), DN(cmax + 1);
152 for (std::size_t k = 0; k <= cmax; ++k) {
154 if (k < cmax) UP[k] =
Matrix<T>(nk[k], nk[k + 1], zero);
155 if (k > 0) DN[k] =
Matrix<T>(nk[k], nk[k - 1], zero);
156 for (std::size_t row = 0; row < nCfg[k]; ++row) {
157 const std::vector<int>& m = cfg[k][row];
158 for (std::size_t h = 0; h < p; ++h) {
159 const std::size_t a = row * p + h;
160 for (std::size_t t = 0; t < NT; ++t) {
161 if (m[t] == 0)
continue;
163 const std::size_t i = pairs[t].first, j = pairs[t].second;
164 LOC[k](a, a) += T(mult * D0(i, i));
165 for (std::size_t kk = 0; kk < p; ++kk) {
168 std::vector<int> mm = m;
171 LOC[k](a, pos[k][mm] * p + h) += T(mult * D0(i, kk) * V(kk, j) / V(i, j));
174 std::vector<int> mm = m;
176 DN[k](a, pos[k - 1][mm] * p + h) += T(mult * done[t]);
180 for (std::size_t j = 0; j < p; ++j) {
181 if (tp[h][j] < 0)
continue;
182 std::vector<int> mm = m;
184 UP[k](a, pos[k + 1][mm] * p + j) += V(h, j);
191 Matrix<T> CDEP(nk[cmax], nk[cmax], zero);
192 for (std::size_t row = 0; row < nCfg[cmax]; ++row) {
193 const std::vector<int>& m = cfg[cmax][row];
194 for (std::size_t h = 0; h < p; ++h)
195 for (std::size_t t = 0; t < NT; ++t) {
196 if (m[t] == 0)
continue;
198 for (std::size_t j = 0; j < p; ++j) {
199 if (tp[h][j] < 0)
continue;
200 std::vector<int> mm = m;
203 CDEP(row * p + h, pos[cmax][mm] * p + j) += T(mult * done[t] * V(h, j));
207 std::vector<T> speed(Nlev + 1, one);
209 for (std::size_t n = 1; n <= Nlev; ++n) {
210 const std::size_t b = std::min(n, cmax);
212 if (!(sf[n - 1] == bt)) speed[n] = T(sf[n - 1] / bt);
220 for (std::size_t i = 0; i < p; ++i) out.
Q1[0](i, i) = T(-arrRate[0]);
221 for (std::size_t n = 1; n <= Nlev; ++n) {
222 const std::size_t b = std::min(n, cmax);
224 for (std::size_t i = 0; i < nk[b]; ++i) {
225 for (std::size_t j = 0; j < nk[b]; ++j) B(i, j) = T(speed[n] * LOC[b](i, j));
226 B(i, i) -= arrRate[n];
230 for (std::size_t n = 0; n + 1 <= Nlev; ++n) {
233 for (std::size_t i = 0; i < nk[n]; ++i)
234 for (std::size_t j = 0; j < nk[n + 1]; ++j) B(i, j) = T(arrRate[n] * UP[n](i, j));
238 for (std::size_t i = 0; i < nk[cmax]; ++i) B(i, i) = arrRate[n];
242 for (std::size_t n = 1; n <= Nlev; ++n) {
243 const Matrix<T>& S = (n <= cmax) ? DN[n] : CDEP;
245 for (std::size_t i = 0; i < S.
rows(); ++i)
246 for (std::size_t j = 0; j < S.
cols(); ++j) B(i, j) = T(speed[n] * S(i, j));
273 const std::vector<T>& alpha,
double c,
274 const std::vector<T>& arrRate,
const std::vector<T>& sf,
275 bool carry =
false) {
277 const std::size_t p = D0.
rows();
279 throw InputError(
"ldqbd_mphc: needs at least one level above the empty one");
280 const std::size_t Nlev = arrRate.size() - 1;
282 throw InputError(
"ldqbd_mphc: needs at least one level above the empty one");
283 if (D0.
cols() != p || D1.
rows() != p || D1.
cols() != p || alpha.size() != p)
284 throw InputError(
"ldqbd_mphc: D0, D1 and alpha must all have the same order");
285 if (!sf.empty() && sf.size() < Nlev)
286 throw InputError(
"ldqbd_mphc: sf must give one total-service-rate factor per level");
290 const std::size_t cmax =
291 !std::isfinite(c) ? Nlev
292 : std::min(std::max<std::size_t>(1,
static_cast<std::size_t
>(
297 std::vector<std::vector<std::vector<int> > > cfg(cmax + 1);
298 std::vector<std::map<std::vector<int>, std::size_t> > pos(cmax + 1);
299 std::vector<std::size_t> nCfg(cmax + 1, 0);
300 for (std::size_t k = 0; k <= cmax; ++k) {
302 for (std::size_t r = 0; r < cfg[k].size(); ++r) pos[k][cfg[k][r]] = r;
303 nCfg[k] = cfg[k].size();
308 "ldqbd_mphc: the exact M/PH/c chain needs " + std::to_string(nCfg[cmax]) +
309 " configurations per level for " + std::to_string(cmax) +
" servers and " +
312 " the level-by-level inverses can carry. Use fewer phases (a lower-order fit), "
313 "fewer servers, or SolverCTMC/SolverLDES on this model");
316 std::vector<T> t(p, zero);
317 for (std::size_t i = 0; i < p; ++i)
318 for (std::size_t j = 0; j < p; ++j) t[i] += D1(i, j);
323 std::vector<Matrix<T> > LOC(cmax + 1), UP(cmax + 1), DN(cmax + 1);
324 for (std::size_t k = 0; k <= cmax; ++k) {
325 const std::vector<std::vector<int> >& Ck = cfg[k];
326 LOC[k] =
Matrix<T>(nCfg[k], nCfg[k], zero);
327 for (std::size_t row = 0; row < nCfg[k]; ++row) {
328 const std::vector<int>& m = Ck[row];
329 for (std::size_t i = 0; i < p; ++i) {
330 if (m[i] == 0)
continue;
332 for (std::size_t j = 0; j < p; ++j) {
333 if (j == i)
continue;
334 std::vector<int> mm = m;
337 LOC[k](row, pos[k][mm]) += T(mult * D0(i, j));
340 LOC[k](row, row) += T(mult * D0(i, i));
345 UP[k] =
Matrix<T>(nCfg[k], nCfg[k + 1], zero);
346 for (std::size_t row = 0; row < nCfg[k]; ++row) {
347 const std::vector<int>& m = Ck[row];
348 for (std::size_t j = 0; j < p; ++j) {
349 std::vector<int> mm = m;
351 UP[k](row, pos[k + 1][mm]) += alpha[j];
357 DN[k] =
Matrix<T>(nCfg[k], nCfg[k - 1], zero);
358 for (std::size_t row = 0; row < nCfg[k]; ++row) {
359 const std::vector<int>& m = Ck[row];
360 for (std::size_t i = 0; i < p; ++i) {
361 if (m[i] == 0)
continue;
362 std::vector<int> mm = m;
372 Matrix<T> CDEP(nCfg[cmax], nCfg[cmax], zero);
373 for (std::size_t row = 0; row < nCfg[cmax]; ++row) {
374 const std::vector<int>& m = cfg[cmax][row];
375 for (std::size_t i = 0; i < p; ++i) {
376 if (m[i] == 0)
continue;
378 for (std::size_t j = 0; j < p; ++j) {
379 std::vector<int> mm = m;
382 CDEP(row, pos[cmax][mm]) += T(mult * D1(i, j));
392 std::vector<T> speed(Nlev + 1, one);
394 for (std::size_t n = 1; n <= Nlev; ++n) {
395 const std::size_t b = std::min(n, cmax);
397 if (!(sf[n - 1] == bt)) speed[n] = T(sf[n - 1] / bt);
407 for (std::size_t n = 1; n <= Nlev; ++n) {
408 const std::size_t b = std::min(n, cmax);
410 for (std::size_t i = 0; i < nCfg[b]; ++i) {
411 for (std::size_t j = 0; j < nCfg[b]; ++j) B(i, j) = T(speed[n] * LOC[b](i, j));
412 B(i, i) -= arrRate[n];
417 for (std::size_t n = 0; n + 1 <= Nlev; ++n) {
421 for (std::size_t i = 0; i < nCfg[n]; ++i)
422 for (std::size_t j = 0; j < nCfg[n + 1]; ++j) B(i, j) = T(arrRate[n] * UP[n](i, j));
426 Matrix<T> B(nCfg[cmax], nCfg[cmax], zero);
427 for (std::size_t i = 0; i < nCfg[cmax]; ++i) B(i, i) = arrRate[n];
432 for (std::size_t n = 1; n <= Nlev; ++n) {
435 for (std::size_t i = 0; i < nCfg[n]; ++i)
436 for (std::size_t j = 0; j < nCfg[n - 1]; ++j) B(i, j) = T(speed[n] * DN[n](i, j));
439 Matrix<T> B(nCfg[cmax], nCfg[cmax], zero);
440 for (std::size_t i = 0; i < nCfg[cmax]; ++i)
441 for (std::size_t j = 0; j < nCfg[cmax]; ++j) B(i, j) = T(speed[n] * CDEP(i, j));