164 const std::vector<double>& init_sol,
double pstar) {
165 const std::size_t M =
sn.nstations, K =
sn.nclasses;
173 const std::size_t S =
sn.nof_stateful();
174 std::vector<std::size_t> keep_idx;
175 keep_idx.reserve(M * K);
176 for (std::size_t i = 0; i < M; ++i) {
177 const std::size_t isf =
sn.stateful_of_station(i + 1) - 1;
178 for (std::size_t r = 0; r < K; ++r) keep_idx.push_back(isf * K + r);
181 if (
sn.rt.rows() == S * K)
182 for (std::size_t a = 0; a < S * K; ++a)
183 for (std::size_t b = 0; b < S * K; ++b)
190 for (std::size_t i = 0; i < M; ++i) {
192 for (std::size_t r = 0; r < K; ++r) {
193 if (!L.
enabled[i][r])
continue;
195 const std::size_t nn =
sn.service[i][r].D0.rows();
198 for (std::size_t a = 0; a < nn; ++a)
199 for (std::size_t b = 0; b < nn; ++b) {
204 if (mean > 0.0) src_arrival(i, r) = 1.0 / mean;
205 if (src_arrival(i, r) > 0.0)
206 for (std::size_t j = 0; j < M; ++j) {
207 if (j == i)
continue;
208 for (std::size_t q = 0; q < K; ++q) P(j * K + q, i * K + r) = 0.0;
216 std::vector<std::size_t> blk_state;
217 std::vector<std::size_t> blk_len;
218 std::size_t nfull = 0;
219 for (std::size_t i = 0; i < M; ++i)
220 for (std::size_t r = 0; r < K; ++r) {
221 blk_state.push_back(nfull);
222 const std::size_t p = L.
kic[i][r];
223 blk_len.push_back(p);
224 nfull += (p == 0) ? 1 : p;
228 std::vector<double> pie_full(nfull, 0.0), brate(nfull, 0.0);
229 std::vector<bool> disabled_state(nfull,
false);
230 for (std::size_t i = 0; i < M; ++i)
231 for (std::size_t r = 0; r < K; ++r) {
232 const std::size_t b = blk_state[i * K + r], p = blk_len[i * K + r];
234 disabled_state[b] =
true;
238 const std::vector<double> pie = detail::fluid_pie(d);
239 for (std::size_t a = 0; a < p; ++a) {
240 pie_full[b + a] = a < pie.size() ? pie[a] : 0.0;
241 for (std::size_t c = 0; c < p; ++c)
244 for (std::size_t c = 0; c < d.
D1.cols(); ++c)
250 for (std::size_t ir = 0; ir < M * K; ++ir) {
251 const std::size_t bi = blk_state[ir], pi = blk_len[ir];
252 if (pi == 0)
continue;
253 for (std::size_t jl = 0; jl < M * K; ++jl) {
254 const double p = P(ir, jl);
255 if (!(p > 0.0))
continue;
256 const std::size_t bj = blk_state[jl], pj = blk_len[jl];
257 if (pj == 0)
continue;
258 for (std::size_t a = 0; a < pi; ++a)
259 for (std::size_t c = 0; c < pj; ++c)
260 Wfull(bi + a, bj + c) += brate[bi + a] * p * pie_full[bj + c];
265 std::vector<double> alam_full(nfull, 0.0);
266 for (std::size_t i = 0; i < M; ++i) {
268 for (std::size_t r = 0; r < K; ++r) {
269 const std::size_t b = blk_state[i * K + r], p = blk_len[i * K + r];
270 if (p == 0)
continue;
272 for (std::size_t sidx = 0; sidx < M; ++sidx)
273 if (src_arrival(sidx, r) > 0.0)
274 rate += src_arrival(sidx, r) * P(sidx * K + r, i * K + r);
275 if (!(rate > 0.0))
continue;
276 for (std::size_t a = 0; a < p; ++a) alam_full[b + a] = pie_full[b + a] * rate;
281 std::vector<std::size_t> keep;
282 for (std::size_t i = 0; i < nfull; ++i)
283 if (!disabled_state[i]) keep.push_back(i);
284 const std::size_t n = keep.size();
287 for (std::size_t a = 0; a < n; ++a)
288 for (std::size_t b = 0; b < n; ++b) s.
W(a, b) = Wfull(keep[a], keep[b]);
294 s.
is_inf.assign(n,
false);
305 double closed_pop = 0.0;
306 for (std::size_t r = 0; r < K; ++r)
307 if (std::isfinite(
sn.classes[r].population)) closed_pop +=
sn.classes[r].population;
310 std::vector<std::size_t> st_of(nfull, 0), cl_of(nfull, 0), ph_of(nfull, 0);
311 for (std::size_t i = 0; i < M; ++i)
312 for (std::size_t r = 0; r < K; ++r) {
313 const std::size_t b = blk_state[i * K + r], p = blk_len[i * K + r];
314 for (std::size_t a = 0; a < (p == 0 ? 1u : p); ++a) {
321 for (std::size_t a = 0; a < n; ++a) {
322 const std::size_t f = keep[a], i = st_of[f], r = cl_of[f], k = ph_of[f];
323 const double c =
sn.stations[i].nservers;
324 const double servers = std::isfinite(c) ? c : closed_pop;
329 s.
is_inf[a] = !std::isfinite(c);
330 s.
sqc(i * K + r, a) = 1.0;
331 s.
suc(i * K + r, a) = (servers > 0.0) ? 1.0 / servers : 0.0;
333 for (std::size_t cc = 0; cc <
sn.service[i][r].D1.cols(); ++cc)
335 s.
stc(i * K + r, a) = row;
337 s.
x0[a] = s.
is_source[a] ? 0.0 : (f < init_sol.size() ? 0.0 : 0.0);
342 if (!init_sol.empty()) {
343 for (std::size_t a = 0; a < n; ++a) {
344 const std::size_t f = keep[a], i = st_of[f], r = cl_of[f], k = ph_of[f];
346 const std::size_t src = L.
qidx[i][r] + k;
347 if (src < init_sol.size()) s.
x0[a] = init_sol[src];
352 double mr = std::numeric_limits<double>::infinity();
353 for (std::size_t a = 0; a < n; ++a)
354 for (std::size_t b = 0; b < n; ++b) {
355 const double v = std::fabs(s.
W(a, b));
356 if (v > 0.0) mr = std::min(mr, v);
358 s.
min_rate = std::isfinite(mr) ? mr : 1.0;
397 const std::function<
void(
double,
const double*,
double*)>& drift,
398 const std::vector<double>& x, std::size_t K) {
399 const std::size_t n = s.
nstates;
400 if (x.size() != n || n == 0 || K == 0)
return false;
401 double max_abs_x = 1.0;
402 for (std::size_t i = 0; i < n; ++i) max_abs_x = std::max(max_abs_x, std::fabs(x[i]));
403 std::vector<double> d0(n, 0.0);
404 drift(0.0, x.data(), d0.data());
406 for (std::size_t i = 0; i < n; ++i) max_d0 = std::max(max_d0, std::fabs(d0[i]));
407 if (max_d0 > 1e-6 * max_abs_x)
return false;
408 if (s.
sqc.
rows() % K != 0)
return false;
409 const std::size_t M = s.
sqc.
rows() / K;
411 double rate_scale = 0.0;
412 for (std::size_t a = 0; a < n; ++a)
413 for (std::size_t b = 0; b < n; ++b)
414 rate_scale = std::max(rate_scale, std::fabs(s.
W(a, b)));
415 rate_scale = std::max(rate_scale, 1e-12);
417 const double step = 1e-3 * max_abs_x;
418 std::vector<double> xp(n, 0.0), dp(n, 0.0);
419 for (std::size_t r = 0; r < K; ++r) {
424 std::vector<std::vector<std::size_t> > groups;
425 for (std::size_t i = 0; i < M; ++i) {
426 std::vector<std::size_t> members;
427 for (std::size_t a = 0; a < n; ++a)
429 members.push_back(a);
430 if (!members.empty()) groups.push_back(members);
432 if (groups.size() < 2)
continue;
433 std::vector<double> mass(groups.size(), 0.0);
434 for (std::size_t a = 0; a < groups.size(); ++a)
435 for (std::size_t idx : groups[a]) mass[a] += x[idx];
436 for (std::size_t a = 0; a < groups.size(); ++a) {
437 if (mass[a] <= step)
continue;
438 for (std::size_t b = 0; b < groups.size(); ++b) {
439 if (a == b)
continue;
441 for (std::size_t idx : groups[a]) xp[idx] -= step * x[idx] / mass[a];
442 for (std::size_t idx : groups[b])
443 xp[idx] += (mass[b] > 0.0) ? step * x[idx] / mass[b]
444 : step /
static_cast<double>(groups[b].size());
445 drift(0.0, xp.data(), dp.data());
447 for (std::size_t i = 0; i < n; ++i)
448 max_dd = std::max(max_dd, std::fabs(dp[i] - d0[i]));
449 if (max_dd / step <= 1e-4 * rate_scale)
return true;