72 const std::size_t M = mu.
rows();
73 const std::size_t Nt = mu.
cols();
74 if (M == 0 || Nt == 0)
throw InputError(
"pfqn_ldmx_ec: the rate lattice is empty");
75 if (D.
rows() != M)
throw InputError(
"pfqn_ldmx_ec: D and mu disagree on the station count");
76 if (lambda.size() != D.
cols())
77 throw InputError(
"pfqn_ldmx_ec: lambda and D disagree on the class count");
83 res.
Lo.assign(M, zero);
84 for (std::size_t i = 0; i < M; ++i)
85 for (std::size_t r = 0; r < lambda.size(); ++r) res.
Lo[i] += lambda[r] * D(i, r);
88 std::vector<std::size_t> b(M, 1);
89 for (std::size_t i = 0; i < M; ++i) {
90 const T& last = mu(i, Nt - 1);
92 while (k < Nt && mu(i, k - 1) != last) ++k;
96 for (std::size_t i = 0; i < M; ++i) bmax = b[i] > bmax ? b[i] : bmax;
100 const std::size_t Cw = Nt + bmax + 2;
102 for (std::size_t i = 0; i < M; ++i) {
103 for (std::size_t k = 0; k < Cw; ++k) {
104 const T& rate = k < Nt ? mu(i, k) : mu(i, Nt - 1);
105 if (rate == zero)
throw NumericError(
"pfqn_ldmx_ec: a load-dependent rate is zero");
106 C(i, k) = one / rate;
110 const auto Cq = [&](std::size_t i, std::size_t k) ->
const T& {
return C(i, k - 1); };
116 for (std::size_t i = 0; i < M; ++i) {
117 const T Cb = Cq(i, b[i]);
118 const T denom = one - res.
Lo[i] * Cb;
121 "pfqn_ldmx_ec: the station is saturated by the open classes (Lo * C(b) = 1), the "
122 "effective capacity is unbounded");
123 const T geo = one / denom;
125 const std::size_t nhead = b[i] >= 2 ? b[i] - 1 : 0;
127 std::vector<T> E1(Nt + 1, zero);
128 for (std::size_t n = 0; n <= Nt; ++n) {
130 res.
E(i, n) =
num_pow_int(geo,
static_cast<unsigned>(n + 1));
131 res.
Eprime(i, n) = Cb * res.
E(i, n);
137 for (std::size_t j = 1; j + 1 <= b[i]; ++j) E1[0] *= Cq(i, j) / Cb;
139 E1[n] = geo * Cb / Cq(i, n) * E1[n - 1];
142 T E2 = zero, E2p = zero;
145 T F2p = Cq(i, n + 1);
146 for (std::size_t n0 = 0; n0 < nhead; ++n0) {
150 F2 = w * res.
Lo[i] * Cq(i, n + n0) * F2;
151 F2p = w * res.
Lo[i] * Cq(i, n + n0 + 1) * F2p;
163 for (std::size_t j = 1; j + 1 <= b[i]; ++j) F3 *= Cq(i, j) / Cb;
164 for (std::size_t k = 1; k <= n; ++k) F3 = Cb / Cq(i, k) * F3;
165 for (std::size_t n0 = 0; n0 < nhead; ++n0) {
169 F3 = w * res.
Lo[i] * Cb * F3;
174 res.
E(i, n) = E1[n] + E2 - E3;
176 res.
Eprime(i, n) = Cb * E1[n] + E2p - Cb * E3;
178 res.
Eprime(i, n) = Cb * res.
E(i, n);
181 for (std::size_t n = 1; n <= Nt; ++n) {
182 if (res.
E(i, n - 1) == zero)
throw NumericError(
"pfqn_ldmx_ec: E vanishes");
183 res.
EC(i, n - 1) = Cq(i, n) * res.
E(i, n) / res.
E(i, n - 1);
LdmxEcResult< T > pfqn_ldmx_ec(const std::vector< T > &lambda, const Matrix< T > &D, const Matrix< T > &mu)
Bruell-Balbo-Afshari effective-capacity terms for a MIXED open/closed network with limited load depen...