151 const std::vector<double>& init_sol,
double pstar) {
152 const std::size_t M =
sn.nstations, K =
sn.nclasses;
160 const std::size_t S =
sn.nof_stateful();
161 std::vector<std::size_t> keep_idx;
162 keep_idx.reserve(M * K);
163 for (std::size_t i = 0; i < M; ++i) {
164 const std::size_t isf =
sn.stateful_of_station(i + 1) - 1;
165 for (std::size_t r = 0; r < K; ++r) keep_idx.push_back(isf * K + r);
168 if (
sn.rt.rows() == S * K)
169 for (std::size_t a = 0; a < S * K; ++a)
170 for (std::size_t b = 0; b < S * K; ++b)
177 for (std::size_t i = 0; i < M; ++i) {
179 for (std::size_t r = 0; r < K; ++r) {
180 if (!L.
enabled[i][r])
continue;
182 const std::size_t nn =
sn.service[i][r].D0.rows();
185 for (std::size_t a = 0; a < nn; ++a)
186 for (std::size_t b = 0; b < nn; ++b) {
191 if (mean > 0.0) src_arrival(i, r) = 1.0 / mean;
192 if (src_arrival(i, r) > 0.0)
193 for (std::size_t j = 0; j < M; ++j) {
194 if (j == i)
continue;
195 for (std::size_t q = 0; q < K; ++q) P(j * K + q, i * K + r) = 0.0;
203 std::vector<std::size_t> blk_state;
204 std::vector<std::size_t> blk_len;
205 std::size_t nfull = 0;
206 for (std::size_t i = 0; i < M; ++i)
207 for (std::size_t r = 0; r < K; ++r) {
208 blk_state.push_back(nfull);
209 const std::size_t p = L.
kic[i][r];
210 blk_len.push_back(p);
211 nfull += (p == 0) ? 1 : p;
215 std::vector<double> pie_full(nfull, 0.0), brate(nfull, 0.0);
216 std::vector<bool> disabled_state(nfull,
false);
217 for (std::size_t i = 0; i < M; ++i)
218 for (std::size_t r = 0; r < K; ++r) {
219 const std::size_t b = blk_state[i * K + r], p = blk_len[i * K + r];
221 disabled_state[b] =
true;
225 const std::vector<double> pie = detail::fluid_pie(d);
226 for (std::size_t a = 0; a < p; ++a) {
227 pie_full[b + a] = a < pie.size() ? pie[a] : 0.0;
228 for (std::size_t c = 0; c < p; ++c)
231 for (std::size_t c = 0; c < d.
D1.cols(); ++c)
237 for (std::size_t ir = 0; ir < M * K; ++ir) {
238 const std::size_t bi = blk_state[ir], pi = blk_len[ir];
239 if (pi == 0)
continue;
240 for (std::size_t jl = 0; jl < M * K; ++jl) {
241 const double p = P(ir, jl);
242 if (!(p > 0.0))
continue;
243 const std::size_t bj = blk_state[jl], pj = blk_len[jl];
244 if (pj == 0)
continue;
245 for (std::size_t a = 0; a < pi; ++a)
246 for (std::size_t c = 0; c < pj; ++c)
247 Wfull(bi + a, bj + c) += brate[bi + a] * p * pie_full[bj + c];
252 std::vector<double> alam_full(nfull, 0.0);
253 for (std::size_t i = 0; i < M; ++i) {
255 for (std::size_t r = 0; r < K; ++r) {
256 const std::size_t b = blk_state[i * K + r], p = blk_len[i * K + r];
257 if (p == 0)
continue;
259 for (std::size_t sidx = 0; sidx < M; ++sidx)
260 if (src_arrival(sidx, r) > 0.0)
261 rate += src_arrival(sidx, r) * P(sidx * K + r, i * K + r);
262 if (!(rate > 0.0))
continue;
263 for (std::size_t a = 0; a < p; ++a) alam_full[b + a] = pie_full[b + a] * rate;
268 std::vector<std::size_t> keep;
269 for (std::size_t i = 0; i < nfull; ++i)
270 if (!disabled_state[i]) keep.push_back(i);
271 const std::size_t n = keep.size();
274 for (std::size_t a = 0; a < n; ++a)
275 for (std::size_t b = 0; b < n; ++b) s.
W(a, b) = Wfull(keep[a], keep[b]);
281 s.
is_inf.assign(n,
false);
286 double closed_pop = 0.0;
287 for (std::size_t r = 0; r < K; ++r)
288 if (std::isfinite(
sn.classes[r].population)) closed_pop +=
sn.classes[r].population;
291 std::vector<std::size_t> st_of(nfull, 0), cl_of(nfull, 0), ph_of(nfull, 0);
292 for (std::size_t i = 0; i < M; ++i)
293 for (std::size_t r = 0; r < K; ++r) {
294 const std::size_t b = blk_state[i * K + r], p = blk_len[i * K + r];
295 for (std::size_t a = 0; a < (p == 0 ? 1u : p); ++a) {
302 for (std::size_t a = 0; a < n; ++a) {
303 const std::size_t f = keep[a], i = st_of[f], r = cl_of[f], k = ph_of[f];
304 const double c =
sn.stations[i].nservers;
305 const double servers = std::isfinite(c) ? c : closed_pop;
310 s.
is_inf[a] = !std::isfinite(c);
311 s.
sqc(i * K + r, a) = 1.0;
312 s.
suc(i * K + r, a) = (servers > 0.0) ? 1.0 / servers : 0.0;
314 for (std::size_t cc = 0; cc <
sn.service[i][r].D1.cols(); ++cc)
316 s.
stc(i * K + r, a) = row;
318 s.
x0[a] = s.
is_source[a] ? 0.0 : (f < init_sol.size() ? 0.0 : 0.0);
323 if (!init_sol.empty()) {
324 for (std::size_t a = 0; a < n; ++a) {
325 const std::size_t f = keep[a], i = st_of[f], r = cl_of[f], k = ph_of[f];
327 const std::size_t src = L.
qidx[i][r] + k;
328 if (src < init_sol.size()) s.
x0[a] = init_sol[src];
333 double mr = std::numeric_limits<double>::infinity();
334 for (std::size_t a = 0; a < n; ++a)
335 for (std::size_t b = 0; b < n; ++b) {
336 const double v = std::fabs(s.
W(a, b));
337 if (v > 0.0) mr = std::min(mr, v);
339 s.
min_rate = std::isfinite(mr) ? mr : 1.0;
378 const std::function<
void(
double,
const double*,
double*)>& drift,
379 const std::vector<double>& x, std::size_t K) {
380 const std::size_t n = s.
nstates;
381 if (x.size() != n || n == 0 || K == 0)
return false;
382 double max_abs_x = 1.0;
383 for (std::size_t i = 0; i < n; ++i) max_abs_x = std::max(max_abs_x, std::fabs(x[i]));
384 std::vector<double> d0(n, 0.0);
385 drift(0.0, x.data(), d0.data());
387 for (std::size_t i = 0; i < n; ++i) max_d0 = std::max(max_d0, std::fabs(d0[i]));
388 if (max_d0 > 1e-6 * max_abs_x)
return false;
389 if (s.
sqc.
rows() % K != 0)
return false;
390 const std::size_t M = s.
sqc.
rows() / K;
392 double rate_scale = 0.0;
393 for (std::size_t a = 0; a < n; ++a)
394 for (std::size_t b = 0; b < n; ++b)
395 rate_scale = std::max(rate_scale, std::fabs(s.
W(a, b)));
396 rate_scale = std::max(rate_scale, 1e-12);
398 const double step = 1e-3 * max_abs_x;
399 std::vector<double> xp(n, 0.0), dp(n, 0.0);
400 for (std::size_t r = 0; r < K; ++r) {
405 std::vector<std::vector<std::size_t> > groups;
406 for (std::size_t i = 0; i < M; ++i) {
407 std::vector<std::size_t> members;
408 for (std::size_t a = 0; a < n; ++a)
410 members.push_back(a);
411 if (!members.empty()) groups.push_back(members);
413 if (groups.size() < 2)
continue;
414 std::vector<double> mass(groups.size(), 0.0);
415 for (std::size_t a = 0; a < groups.size(); ++a)
416 for (std::size_t idx : groups[a]) mass[a] += x[idx];
417 for (std::size_t a = 0; a < groups.size(); ++a) {
418 if (mass[a] <= step)
continue;
419 for (std::size_t b = 0; b < groups.size(); ++b) {
420 if (a == b)
continue;
422 for (std::size_t idx : groups[a]) xp[idx] -= step * x[idx] / mass[a];
423 for (std::size_t idx : groups[b])
424 xp[idx] += (mass[b] > 0.0) ? step * x[idx] / mass[b]
425 : step /
static_cast<double>(groups[b].size());
426 drift(0.0, xp.data(), dp.data());
428 for (std::size_t i = 0; i < n; ++i)
429 max_dd = std::max(max_dd, std::fabs(dp[i] - d0[i]));
430 if (max_dd / step <= 1e-4 * rate_scale)
return true;