183 const std::size_t M = D.
rows();
184 const std::size_t R = D.
cols();
185 if (N.size() != R)
throw InputError(
"pfqn_ncldmx: D and N disagree on the class count");
186 if (lambda.size() != R)
187 throw InputError(
"pfqn_ncldmx: lambda and D disagree on the class count");
188 if (mu.
rows() != M)
throw InputError(
"pfqn_ncldmx: mu and D disagree on the station count");
193 std::vector<std::size_t> openCl, closedCl;
194 for (std::size_t r = 0; r < R; ++r) (N[r] < 0 ? openCl : closedCl).push_back(r);
195 for (std::size_t r : closedCl)
196 if (lambda[r] != zero)
197 throw InputError(
"pfqn_ncldmx: an arrival rate is specified on a closed class");
199 std::vector<int> Nc(closedCl.size(), 0);
201 for (std::size_t a = 0; a < closedCl.size(); ++a) {
202 Nc[a] = N[closedCl[a]];
205 const std::size_t width =
static_cast<std::size_t
>(Kc > 0 ? Kc : 1);
218 const std::size_t padCols = (mu.
cols() > width ? mu.
cols() : width) + 1;
220 for (std::size_t i = 0; i < M; ++i)
221 for (std::size_t k = 0; k < padCols; ++k)
222 mup(i, k) = mu.
cols() == 0 ? one : mu(i, k < mu.
cols() ? k : mu.
cols() - 1);
224 std::vector<T> lambdao(R, zero);
225 for (std::size_t r : openCl) lambdao[r] = lambda[r];
232 for (std::size_t i = 0; i < M; ++i) res.
Gopen *= ec.
E(i, 0);
236 for (std::size_t i = 0; i < M; ++i)
237 for (std::size_t a = 0; a < closedCl.size(); ++a) Dc(i, a) = D(i, closedCl[a]);
239 for (std::size_t i = 0; i < Zc.
rows(); ++i)
240 for (std::size_t a = 0; a < closedCl.size(); ++a) Zc(i, a) = Z(i, closedCl[a]);
243 for (std::size_t i = 0; i < M; ++i)
244 for (std::size_t k = 0; k < width; ++k) {
245 if (ec.
EC(i, k) == zero)
246 throw NumericError(
"pfqn_ncldmx: an effective capacity term is zero");
247 muEff(i, k) = one / ec.
EC(i, k);
260 const std::size_t C = closedCl.size();
261 res.
XN.assign(R, zero);
263 for (std::size_t r : openCl) res.
XN[r] = lambda[r];
265 std::vector<double> lGr(C > 0 ? C : 1, 0.0);
267 for (std::size_t a = 0; a < C; ++a) {
268 if (Nc[a] <= 0)
continue;
269 std::vector<int> Ncr = Nc;
271 lGr[a] = detail::ncldmx_lg(Dc, Ncr, Zc, muEff, method, atol, nopt);
276 for (std::size_t i = 0; i < M; ++i) {
277 bool anyDemand =
false;
278 for (std::size_t a = 0; a < C; ++a)
279 if (Dc(i, a) > zero) { anyDemand =
true;
break; }
280 if (!anyDemand)
continue;
283 for (std::size_t k = 0; k < muhat.
cols(); ++k) muhatRow(0, k) = muhat(i, k);
286 const Matrix<T> Dminus = detail::ncldmx_drop_row(Dc, i);
287 const Matrix<T> muminus = detail::ncldmx_drop_row(muEff, i);
289 for (std::size_t i2 = 0; i2 < M; ++i2)
290 for (std::size_t a = 0; a < C; ++a) DcPlus(i2, a) = Dc(i2, a);
291 for (std::size_t a = 0; a < C; ++a) DcPlus(M, a) = Dc(i, a);
293 for (std::size_t i2 = 0; i2 < M; ++i2)
294 for (std::size_t k = 0; k < muhat.
cols(); ++k) muhatPlus(i2, k) = muhat(i2, k);
295 for (std::size_t k = 0; k < muhat.
cols() && k < fnc.
mu.cols(); ++k)
296 muhatPlus(M, k) = fnc.
mu(0, k);
297 for (std::size_t a = 0; a < C; ++a) {
298 if (Nc[a] <= 0 || !(Dc(i, a) > zero))
continue;
299 std::vector<int> Ncr = Nc;
301 const double lGhat = detail::ncldmx_lg(Dc, Ncr, Zc, muhat, method, atol, nopt);
302 const double lGhatf =
303 detail::ncldmx_lg(DcPlus, Ncr, Zc, muhatPlus, method, atol, nopt);
304 const double lGminus =
305 detail::ncldmx_lg(Dminus, Ncr, Zc, muminus, method, atol, nopt);
307 (std::exp(lGhatf - lGhat) - 1.0) + cshift * (std::exp(lGminus - lGhat) - 1.0);
317 if (!openCl.empty()) {
318 for (std::size_t i = 0; i < M; ++i) {
320 for (std::size_t a = 0; a < C; ++a)
322 const std::size_t b = detail::ncldmx_lld_level(mup, i);
323 const std::size_t bcap = b < ec.
EC.cols() ? b : ec.
EC.cols();
325 double acc = ECinf * (Qtot + 1.0);
327 const Matrix<T> Dminus = detail::ncldmx_drop_row(Dc, i);
328 const Matrix<T> muminus = detail::ncldmx_drop_row(muEff, i);
330 for (std::size_t a = 0; a < C; ++a) Drow(0, a) = Dc(i, a);
331 for (std::size_t k = 0; k < muEff.
cols(); ++k) murow(0, k) = muEff(i, k);
333 for (std::size_t n = 0; n + 2 <= b; ++n) {
335 if (delta == 0.0)
continue;
345 Pn = n == 0 ? 1.0 : 0.0;
347 std::vector<std::vector<int> > ks;
348 std::vector<int> cur(C, 0);
350 detail::ncldmx_compositions(
static_cast<int>(n), Nc, 0, cur, ks);
352 ks.push_back(std::vector<int>());
353 for (std::size_t t = 0; t < ks.size(); ++t) {
354 std::vector<int> rest(C, 0);
355 for (std::size_t a = 0; a < C; ++a) rest[a] = Nc[a] - ks[t][a];
356 const double lF = n == 0 ? 0.0
357 : detail::ncldmx_lg(Drow, ks[t], Zzero, murow,
360 detail::ncldmx_lg(Dminus, rest, Zc, muminus, method, atol, nopt);
361 Pn += std::exp(lF + lGbar - res.
lG);
364 acc +=
static_cast<double>(n + 1) * delta * Pn;
367 for (std::size_t r : openCl)