114 const std::vector<T>& Ca0,
const std::vector<T>& mu,
115 const std::vector<T>& Cs,
const Matrix<T>& P,
116 const std::vector<long>& c,
const std::vector<long>& N,
117 const std::vector<int>& blockrule,
120 "me_oqn_blk requires transcendental arithmetic: its building blocks assemble "
121 "the censored state law in logarithms");
126 if (lambda0.size() != M || Ca0.size() != M || mu.size() != M || Cs.size() != M ||
127 c.size() != M || N.size() != M || blockrule.size() != M)
128 throw InputError(
"me_oqn_blk: every per-station vector must have M entries");
130 throw InputError(
"me_oqn_blk: the routing matrix must be M x M");
134 std::vector<char> finiteBuf(M, 0), bas(M, 0);
135 for (std::size_t i = 0; i < M; ++i) {
136 finiteBuf[i] = (N[i] > 0 && c[i] > 0) ? 1 : 0;
137 bas[i] = (finiteBuf[i] && blockrule[i] == 1) ? 1 : 0;
140 "me_oqn_blk: a finite buffer requires a service scv of at least 1 at station " +
141 std::to_string(i + 1) +
": the GE distribution is not defined for scv < 1.");
144 "me_oqn_blk: a finite buffer requires an external interarrival scv of at least 1 "
145 "at station " + std::to_string(i + 1) +
".");
151 std::vector<T> muf = mu, Csf = Cs;
152 for (std::size_t i = 0; i < M; ++i) {
153 const T pii = P(i, i);
155 const T q = T(one - pii);
156 muf[i] = T(mu[i] * q);
157 Csf[i] = T(pii + q * Cs[i]);
158 for (std::size_t j = 0; j < M; ++j) Pf(i, j) = T(P(i, j) / q);
167 std::vector<T> sigmaS(M, one), muRes(M, zero);
168 for (std::size_t i = 0; i < M; ++i) {
169 sigmaS[i] = T(two / (Csf[i] + one));
174 res.
Ca.assign(M, one);
176 res.
Q.assign(M, zero);
177 res.
U.assign(M, zero);
178 res.
T_.assign(M, zero);
179 res.
lambda.assign(M, zero);
180 res.
PBa.assign(M, zero);
181 Matrix<T> PBs(M, M, zero), PBh(M, M, zero);
182 std::vector<T> PBe(M, zero);
184 double delta = std::numeric_limits<double>::infinity();
186 for (it = 1; it <=
opt.maxiter; ++it) {
187 const std::vector<T> Ca_old = res.
Ca;
189 const std::vector<T> PBe_old = PBe;
193 std::vector<T> PBf(M, zero);
194 for (std::size_t i = 0; i < M; ++i)
195 for (std::size_t j = 0; j < M; ++j)
196 if (Pf(i, j) > zero && bas[j]) PBf[i] += T(Pf(i, j) * PBs(i, j));
197 for (std::size_t i = 0; i < M; ++i)
200 "me_oqn_blk: the transfer-blocking fixed point saturates, a station is blocked "
201 "with probability one. The network has no stable operating point under BAS.");
202 std::vector<T> muEff(M, zero), CsEff(M, one);
203 for (std::size_t i = 0; i < M; ++i) {
204 muEff[i] = T(muf[i] * (one - PBf[i]));
205 CsEff[i] = T(PBf[i] + Csf[i] * (one - PBf[i]));
212 std::vector<T> b(M, zero);
213 for (std::size_t j = 0; j < M; ++j) {
214 b[j] = T(lambda0[j] * (one - PBe[j]));
215 for (std::size_t i = 0; i < M; ++i)
217 A(i, j) = (finiteBuf[j] && !bas[j]) ? T(Pf(i, j) * (one - PBs(i, j)))
222 for (std::size_t r = 0; r < M; ++r) {
223 for (std::size_t k = 0; k < M; ++k) S(r, k) = T(-A(k, r));
224 S(r, r) = T(S(r, r) + one);
228 if (v < zero) v = zero;
232 std::vector<T> attExt(M, zero);
235 for (std::size_t j = 0; j < M; ++j) {
236 attExt[j] = lambda0[j];
237 for (std::size_t i = 0; i < M; ++i)
238 if (Pf(i, j) > zero) {
239 if (finiteBuf[j] && bas[j]) {
240 T den = T(one - PBs(i, j));
241 if (den < tiny) den = tiny;
242 attInt(i, j) = T(res.
T_[i] * Pf(i, j) / den);
244 attInt(i, j) = T(res.
T_[i] * Pf(i, j));
248 for (std::size_t j = 0; j < M; ++j) {
250 for (std::size_t i = 0; i < M; ++i) tot += attInt(i, j);
253 T acc = T(attExt[j] * PBe[j]);
254 for (std::size_t i = 0; i < M; ++i) acc += T(attInt(i, j) * PBs(i, j));
255 res.
PBa[j] = T(acc / tot);
265 for (std::size_t j = 0; j < M; ++j) {
266 if (!(res.
lambda[j] > zero))
continue;
268 if (attExt[j] > zero)
269 sum_inv += T((attExt[j] / res.
lambda[j]) / (Ca0[j] + one));
270 for (std::size_t i = 0; i < M; ++i)
271 if (attInt(i, j) > zero) {
272 CaStreamInt(i, j) = T(one - Pf(i, j) + Pf(i, j) * res.
Cd[i]);
273 sum_inv += T((attInt(i, j) / res.
lambda[j]) / (CaStreamInt(i, j) + one));
275 if (sum_inv > zero) res.
Ca[j] = T(-one + one / sum_inv);
280 std::vector<T> PBe_new(M, zero);
281 Matrix<T> PBs_new(M, M, zero), PBh_new(M, M, zero);
282 for (std::size_t j = 0; j < M; ++j) {
285 res.
Q[j] = (muEff[j] > zero) ? T(res.
lambda[j] / muEff[j]) : zero;
287 res.
Cd[j] = res.
Ca[j];
294 if (muEff[j] > zero) rho = T(res.
lambda[j] / (cT * muEff[j]));
297 std::numeric_limits<double>::infinity());
299 res.
Cd[j] = CsEff[j];
300 }
else if (c[j] == 1) {
301 res.
Q[j] = T(rho * (res.
Ca[j] + one) / two +
302 rho * rho * (CsEff[j] + res.
Ca[j]) / (two * (one - rho)));
304 res.
Cd[j] = T(rho * rho * CsEff[j] + (one - rho) * res.
Ca[j] +
309 res.
Cd[j] = T(rho * rho * CsEff[j] + (one - rho) * res.
Ca[j] +
320 res.
Cd[j] = T(gj.
U * gj.
U * CsEff[j] + (one - gj.
U) * res.
Ca[j] +
321 gj.
U * (one - gj.
U));
322 if (attExt[j] > zero)
323 PBe_new[j] =
me_gegecn_pb(gj.
p, 0L, N[j], c[j], CsEff[j], Ca0[j]);
324 for (std::size_t i = 0; i < M; ++i)
325 if (attInt(i, j) > zero) {
327 me_gegecn_pb(gj.
p, 0L, N[j], c[j], CsEff[j], CaStreamInt(i, j));
333 const T q = T(Pf(i, j) * PBs(i, j));
334 const T CaH = T(one - q + q * res.
Cd[i]);
335 PBh_new(i, j) =
me_gegecn_pb(gj.
p, 0L, N[j], c[j], CsEff[j], CaH);
342 const T w1 = T(one - w);
343 for (std::size_t j = 0; j < M; ++j) PBe[j] = T(w1 * PBe[j] + w * PBe_new[j]);
344 for (std::size_t i = 0; i < M; ++i)
345 for (std::size_t j = 0; j < M; ++j) {
346 PBs(i, j) = T(w1 * PBs(i, j) + w * PBs_new(i, j));
347 PBh(i, j) = T(w1 * PBh(i, j) + w * PBh_new(i, j));
351 for (std::size_t j = 0; j < M; ++j) {
356 for (std::size_t i = 0; i < M; ++i)
360 if (delta <
opt.tol) {
365 res.
iter = std::min(it,
opt.maxiter);
370 for (std::size_t i = 0; i < M; ++i) {
372 for (std::size_t j = 0; j < M; ++j)
373 if (bas[j] && Pf(i, j) > zero && PBs(i, j) > zero) {
374 const T rateH = T(res.
T_[i] * Pf(i, j) * PBs(i, j));
375 const T muH = T(muRes[j] * (one - PBh(i, j)));
376 if (muH > zero) held += T(rateH / muH);
385 for (std::size_t i = 0; i < M; ++i) {
387 res.
U[i] = (c[i] <= 0) ? T(res.
T_[i] / muf[i])
393 res.
W.assign(M, zero);
394 for (std::size_t i = 0; i < M; ++i)
395 if (res.
T_[i] > zero) res.
W[i] = T(res.
Q[i] / res.
T_[i]);