215 const std::vector<double>& N,
216 const std::vector<std::size_t>& subnet,
217 const std::vector<std::size_t>& n,
219 const std::vector<bool>& isdelay = std::vector<bool>(),
220 const std::string& method =
"clw") {
221 const std::size_t J = alpha.
rows(), R = alpha.
cols();
222 bool is_closed =
true, is_open =
true;
223 for (std::size_t r = 0; r < R; ++r) {
224 if (std::isinf(N[r]))
229 if (!is_closed && !is_open)
231 "pfqn_busyp_clw: a mixed model needs the lattice routine pfqn_busyp_multiclass");
232 std::vector<bool> delay = isdelay.empty() ? std::vector<bool>(J,
false) : isdelay;
234 std::vector<std::size_t> target = subnet;
235 std::sort(target.begin(), target.end());
236 target.erase(std::unique(target.begin(), target.end()), target.end());
237 if (target.empty())
throw InputError(
"pfqn_busyp_clw: the subnetwork must be non-empty");
238 if (is_closed && target.size() >= J)
240 "pfqn_busyp_clw: in a closed network the subnetwork must be a proper subset");
241 std::vector<bool> in_subnet(J,
false);
242 for (std::size_t i = 0; i < target.size(); ++i) in_subnet[target[i]] =
true;
243 std::vector<std::size_t> compl_nodes, all_nodes;
244 for (std::size_t j = 0; j < J; ++j) {
245 all_nodes.push_back(j);
246 if (!in_subnet[j]) compl_nodes.push_back(j);
250 std::vector<std::vector<double>> L(J, std::vector<double>(R, 0.0));
251 for (std::size_t i = 0; i < J; ++i)
252 for (std::size_t r = 0; r < R; ++r) {
255 L[i][r] = (a > 0 && m > 0) ? a / m : 0.0;
259 std::vector<double> A(R, 0.0);
261 for (std::size_t r = 0; r < R; ++r) {
262 const Matrix<T>& Pr = (P.size() == 1) ? P[0] : P[r];
263 for (std::size_t i = 0; i < compl_nodes.size(); ++i)
264 for (std::size_t j = 0; j < target.size(); ++j)
267 if (gamma.rows() == J)
268 for (std::size_t j = 0; j < target.size(); ++j)
274 "pfqn_busyp_clw: no job ever enters the subnetwork, its busy period is undefined");
276 std::size_t nmax = 1;
277 for (std::size_t t = 0; t < n.size(); ++t) nmax = std::max(nmax, n[t]);
281 std::vector<double> rho(target.size(), 0.0);
282 std::vector<bool> delayI(target.size(),
false);
284 for (std::size_t t = 0; t < target.size(); ++t) {
285 for (std::size_t r = 0; r < R; ++r) rho[t] += L[target[t]][r];
286 delayI[t] = delay[target[t]];
292 "pfqn_busyp_clw: the subnetwork is not stable, its busy period is infinite");
293 lg1 += -std::log1p(-rho[t]);
296 const std::vector<double> lseq = detail::busyp_clw_open(rho, delayI, nmax);
297 std::vector<double> b(n.size(), 0.0);
298 for (std::size_t t = 0; t < n.size(); ++t) {
299 const std::vector<double> head(lseq.begin(),
300 lseq.begin() +
static_cast<std::ptrdiff_t
>(n[t]));
301 const double tail = lg1 + std::log1p(-std::exp(detail::busyp_lse(head) - lg1));
302 b[t] = std::exp(tail - lseq[n[t] - 1] - std::log(inflow));
307 std::vector<int> pop(R, 0);
308 std::vector<std::size_t> bound(R, 0);
309 for (std::size_t r = 0; r < R; ++r) {
310 pop[r] =
static_cast<int>(std::llround(N[r]));
311 bound[r] = std::min<std::size_t>(
static_cast<std::size_t
>(pop[r]), nmax - 1);
313 std::vector<std::size_t> stride(R, 1);
314 for (std::size_t r = 1; r < R; ++r) stride[r] = stride[r - 1] * (bound[r - 1] + 1);
315 std::size_t size = 1;
316 for (std::size_t r = 0; r < R; ++r) size *= bound[r] + 1;
317 std::vector<std::vector<std::size_t>> mvec(size, std::vector<std::size_t>(R, 0));
318 for (std::size_t idx = 0; idx < size; ++idx)
319 for (std::size_t r = 0; r < R; ++r) mvec[idx][r] = (idx / stride[r]) % (bound[r] + 1);
322 std::vector<double> lGlow(size, 0.0);
323 for (std::size_t idx = 0; idx < size; ++idx)
324 lGlow[idx] = detail::busyp_clw_station(L, delay, target, 0, mvec[idx]);
326 const double lGfull = detail::busyp_clw_lognc(L, delay, all_nodes, pop, method);
328 std::vector<double> b(n.size(), 0.0);
329 for (std::size_t t = 0; t < n.size(); ++t) {
330 std::vector<double> corr, den;
331 for (std::size_t idx = 0; idx < size; ++idx) {
332 std::size_t level = 0;
333 for (std::size_t r = 0; r < R; ++r) level += mvec[idx][r];
334 if (level + 1 <= n[t]) {
336 std::vector<int> left(R, 0);
337 for (std::size_t r = 0; r < R; ++r)
338 left[r] = pop[r] -
static_cast<int>(mvec[idx][r]);
339 corr.push_back(lGlow[idx] +
340 detail::busyp_clw_lognc(L, delay, compl_nodes, left, method));
342 if (level + 1 != n[t])
continue;
344 std::vector<double> terms;
345 for (std::size_t r = 0; r < R; ++r) {
346 if (A[r] <= 0)
continue;
347 std::vector<int> left(R, 0);
349 for (std::size_t s = 0; s < R; ++s) {
350 left[s] = pop[s] -
static_cast<int>(mvec[idx][s]) - (s == r ? 1 : 0);
351 if (left[s] < 0) ok =
false;
354 terms.push_back(std::log(A[r]) +
355 detail::busyp_clw_lognc(L, delay, compl_nodes, left, method));
357 if (!terms.empty()) den.push_back(lGlow[idx] + detail::busyp_lse(terms));
359 const double num = lGfull + std::log1p(-std::exp(detail::busyp_lse(corr) - lGfull));
360 b[t] = std::exp(num - detail::busyp_lse(den));