120 const std::size_t M = L.
rows(), R = L.
cols();
121 if (N.size() != R)
throw InputError(
"pfqn_dac: L and N disagree on the class count");
125 if (v < 0)
throw InputError(
"pfqn_dac: the population vector must be non-negative");
128 const std::size_t mucols =
static_cast<std::size_t
>(Nt > 0 ? Nt : 1);
130 if (mu.
rows() != M)
throw InputError(
"pfqn_dac: mu must have one row per station");
131 if (Nt > 0 && mu.
cols() <
static_cast<std::size_t
>(Nt))
132 throw InputError(
"pfqn_dac: mu must have at least sum(N) columns");
135 std::vector<T> Zv = Z;
136 if (Zv.empty()) Zv.assign(R, zero);
138 for (
const T& v : Zv) Zsum += v;
139 const bool hasZ = Zsum > zero;
140 const std::size_t J = M + (hasZ ? 1 : 0);
143 for (std::size_t i = 0; i < M; ++i) {
144 for (std::size_t r = 0; r < R; ++r) Lx(i, r) = L(i, r);
145 for (std::size_t k = 0; k < mucols; ++k)
146 mux(i, k) = mu.
empty() ? one : mu(i, k);
149 for (std::size_t r = 0; r < R; ++r) Lx(M, r) = Zv[r];
150 for (std::size_t k = 0; k < mucols; ++k)
156 res.
states.assign(1, std::vector<int>(J, 0));
157 res.
Pjoint.assign(1, one);
158 res.
XN.assign(R, zero);
160 res.
UN.assign(M, zero);
161 res.
CN.assign(R, zero);
166 std::vector<std::size_t> active;
167 for (std::size_t r = 0; r < R; ++r)
168 if (N[r] > 0) active.push_back(r);
169 for (std::size_t idx = 0; idx < active.size(); ++idx) {
171 for (std::size_t j = 0; j < J; ++j)
172 if (Lx(j, active[idx]) > zero) any =
true;
173 if (!any)
throw InputError(
"pfqn_dac: a chain has null demand at every center");
177 std::vector<std::vector<std::vector<int>>> lv(
static_cast<std::size_t
>(Nt) + 1);
178 for (
int k = 0; k <= Nt; ++k) detail::dac_compositions(J, k, lv[static_cast<std::size_t>(k)]);
179 std::vector<std::vector<double>> C(
180 static_cast<std::size_t
>(Nt) + J + 1, std::vector<double>(J + 2, 0.0));
181 for (std::size_t a = 0; a + 1 <=
static_cast<std::size_t
>(Nt) + J; ++a)
182 for (std::size_t b = 0; b <= (a < J ? a : J); ++b)
183 C[a][b] = (b == 0) ? 1.0 : (C[a - 1][b - 1] + C[a - 1][b]);
184 std::vector<std::vector<std::vector<std::size_t>>> succ(
static_cast<std::size_t
>(Nt) + 1);
185 for (
int k = 0; k < Nt; ++k) {
186 const std::vector<std::vector<int>>& Sv = lv[
static_cast<std::size_t
>(k)];
187 succ[
static_cast<std::size_t
>(k)].assign(Sv.size(), std::vector<std::size_t>(J, 0));
188 for (std::size_t i = 0; i < Sv.size(); ++i)
189 for (std::size_t j = 0; j < J; ++j) {
190 std::vector<int> t = Sv[i];
192 succ[
static_cast<std::size_t
>(k)][i][j] = detail::dac_rank(t, k + 1, J, C) - 1;
197 const auto dac_step = [&](
const std::vector<T>& p,
const std::vector<T>& r,
int k,
198 std::vector<T>& pn, T& lam, std::vector<T>& Lq) {
199 const std::vector<std::vector<int>>& Sv = lv[
static_cast<std::size_t
>(k)];
200 Matrix<T> marg(J,
static_cast<std::size_t
>(k) + 1, zero);
201 for (std::size_t i = 0; i < Sv.size(); ++i)
202 for (std::size_t j = 0; j < J; ++j)
203 marg(j,
static_cast<std::size_t
>(Sv[i][j])) += p[i];
204 std::vector<T> c(J, zero);
205 for (std::size_t j = 0; j < J; ++j)
206 for (
int n = 1; n <= k + 1; ++n) {
207 const T mur = mux(j,
static_cast<std::size_t
>(n) - 1);
208 if (mur == zero)
throw NumericError(
"pfqn_dac: zero load-dependent rate");
210 marg(j,
static_cast<std::size_t
>(n) - 1);
213 for (std::size_t j = 0; j < J; ++j) den += r[j] * c[j];
214 if (den == zero)
throw NumericError(
"pfqn_dac: zero cycle time for the added customer");
217 for (std::size_t j = 0; j < J; ++j) Lq[j] = T(lam * r[j] * c[j]);
219 pn.assign(lv[
static_cast<std::size_t
>(k) + 1].size(), zero);
220 for (std::size_t j = 0; j < J; ++j) {
221 if (!(r[j] > zero))
continue;
222 for (std::size_t i = 0; i < Sv.size(); ++i) {
223 const int nj = Sv[i][j] + 1;
224 const T mur = mux(j,
static_cast<std::size_t
>(nj) - 1);
226 pn[succ[
static_cast<std::size_t
>(k)][i][j]] += w;
232 const std::size_t D = active.size();
233 std::vector<std::size_t> prefix;
234 for (std::size_t idx = 0; idx < D; ++idx)
235 for (
int t = 0; t + 1 < N[active[idx]]; ++t) prefix.push_back(active[idx]);
237 std::vector<T> p(1, one);
239 std::vector<T> pn, Lq;
241 const auto column = [&](std::size_t r) {
242 std::vector<T> col(J);
243 for (std::size_t j = 0; j < J; ++j) col[j] = Lx(j, r);
246 for (std::size_t idx = 0; idx < prefix.size(); ++idx) {
247 dac_step(p, column(prefix[idx]), k, pn, lam, Lq);
252 std::vector<std::vector<T>> Sp(D);
254 std::vector<T> pb = p;
256 for (std::size_t idx = 0; idx < D; ++idx) {
257 dac_step(pb, column(active[idx]), kb, pn, lam, Lq);
260 if (idx + 1 < D) Sp[idx + 1] = pb;
263 res.
states = lv[
static_cast<std::size_t
>(Nt)];
265 res.
XN.assign(R, zero);
268 const std::size_t r = active[D - 1];
270 for (std::size_t i = 0; i < M; ++i)
273 for (std::size_t idx = 0; idx + 1 < D; ++idx) {
274 std::vector<T> pc = Sp[idx];
275 int kc = k +
static_cast<int>(idx);
276 std::vector<std::size_t> order;
277 for (std::size_t t = idx + 1; t < D; ++t) order.push_back(active[t]);
278 order.push_back(active[idx]);
279 for (std::size_t t = 0; t < order.size(); ++t) {
280 dac_step(pc, column(order[t]), kc, pn, lam, Lq);
284 const std::size_t r = active[idx];
286 for (std::size_t i = 0; i < M; ++i)
290 res.
PI =
Matrix<T>(M,
static_cast<std::size_t
>(Nt) + 1, zero);
291 for (std::size_t i = 0; i < res.
states.size(); ++i)
292 for (std::size_t j = 0; j < M; ++j)
293 res.
PI(j,
static_cast<std::size_t
>(res.
states[i][j])) += res.
Pjoint[i];
294 res.
UN.assign(M, zero);
295 for (std::size_t j = 0; j < M; ++j) res.
UN[j] = T(one - res.
PI(j, 0));
296 res.
CN.assign(R, zero);
297 for (std::size_t idx = 0; idx < D; ++idx) {
298 const std::size_t r = active[idx];
299 if (res.
XN[r] == zero)
throw NumericError(
"pfqn_dac: zero chain throughput");