159 const std::vector<double>& s, std::size_t samples, std::size_t nbatches,
162 "pfqn_mcmc requires transcendental arithmetic: it is a Monte Carlo estimator "
163 "whose value is a random variable and whose batch-means interval needs a "
166 const std::size_t M = L.
empty() ? 0 : L.
rows();
167 const std::size_t R = N.size();
169 throw InputError(
"pfqn_mcmc: L and N disagree on the class count");
170 if (!Z.empty() && Z.size() != R)
throw InputError(
"pfqn_mcmc: Z has the wrong length");
171 if (!s.empty() && s.size() != M)
172 throw InputError(
"pfqn_mcmc: the server count vector has the wrong length");
176 res.
X.assign(R, zero);
177 res.
Xse.assign(R, zero);
178 res.
Xlo.assign(R, zero);
179 res.
Xhi.assign(R, zero);
186 for (std::size_t r = 0; r < R; ++r) {
191 throw InputError(
"pfqn_mcmc requires a closed model, but the population vector "
192 "marks an open class");
195 if (Ntot == 0)
return res;
201 bool hasDelay =
false;
202 for (std::size_t r = 0; r < R && !Z.empty(); ++r)
204 const std::size_t Mx = hasDelay ? M + 1 : M;
207 std::vector<double> svec(Mx, 1.0);
208 for (std::size_t i = 0; i < M; ++i) {
209 svec[i] = s.empty() ? 1.0 : s[i];
210 for (std::size_t r = 0; r < R; ++r) {
212 rho(i, r) = (std::isfinite(v) && v > 0.0) ? L(i, r) : zero;
216 svec[M] = std::numeric_limits<double>::infinity();
217 for (std::size_t r = 0; r < R; ++r) rho(M, r) = Z[r];
220 std::vector<T> rhoTot(R, zero);
221 for (std::size_t r = 0; r < R; ++r) {
222 for (std::size_t i = 0; i < Mx; ++i) rhoTot[r] += rho(i, r);
224 throw InputError(
"pfqn_mcmc: a class has a positive population but no demand "
225 "anywhere in the network");
232 for (std::size_t r = 0; r < R; ++r) {
234 std::numeric_limits<double>::min());
236 for (std::size_t i = 0; i < Mx; ++i) {
241 cumP(Mx - 1, r) = 1.0;
244 if (nbatches == 0) nbatches = 1;
245 if (samples == 0) samples = 1;
246 if (!(burnin >= 0.0)) burnin = 0.0;
247 if (burnin > 0.9) burnin = 0.9;
248 const std::size_t batchLen = std::max<std::size_t>(1, samples / nbatches);
249 samples = batchLen * nbatches;
250 const std::size_t nburn =
static_cast<std::size_t
>(std::llround(burnin * samples));
256 std::vector<std::vector<long> > Y(Mx, std::vector<long>(R, 0));
257 std::vector<double> Ytot(Mx, 0.0);
258 for (std::size_t r = 0; r < R; ++r) {
259 if (N[r] == 0)
continue;
260 std::vector<double> target(Mx, 0.0);
262 for (std::size_t i = 0; i < Mx; ++i) {
263 target[i] = N[r] * Pstar(i, r);
264 Y[i][r] =
static_cast<long>(std::floor(target[i]));
270 for (
long k = 0; k < N[r] - placed; ++k) {
271 std::size_t best = 0;
272 double bestRem = -std::numeric_limits<double>::infinity();
273 for (std::size_t i = 0; i < Mx; ++i) {
274 const double rem = target[i] -
static_cast<double>(Y[i][r]);
283 for (std::size_t i = 0; i < Mx; ++i) {
285 for (std::size_t r = 0; r < R; ++r) tot += static_cast<double>(Y[i][r]);
291 std::vector<Matrix<double> > qnum(nbatches,
Matrix<double>(Mx, R, 0.0));
292 std::vector<double> den(nbatches, 0.0);
293 std::vector<double> Psi(Mx, 0.0), cPsi(Mx, 0.0), rvec(R, 0.0), cY(R, 0.0);
296 const std::size_t horizon = nburn + samples;
297 for (std::size_t t = 1; t <= horizon; ++t) {
301 for (std::size_t i = 0; i < Mx; ++i) {
302 Psi[i] = std::min(svec[i], Ytot[i]);
306 for (std::size_t r = 0; r < R; ++r) rvec[r] = 0.0;
307 for (std::size_t i = 0; i < Mx; ++i) {
308 if (Ytot[i] <= 0.0)
continue;
309 const double rw = Psi[i] / Ytot[i];
310 for (std::size_t r = 0; r < R; ++r)
311 if (Y[i][r] != 0) rvec[r] += rw *
static_cast<double>(Y[i][r]);
317 const std::size_t b = (t - nburn - 1) / batchLen;
319 for (std::size_t r = 0; r < R; ++r) xnum(b, r) += w * rvec[r];
321 for (std::size_t i = 0; i < Mx; ++i)
322 for (std::size_t r = 0; r < R; ++r)
323 if (Y[i][r] != 0) qb(i, r) += w *
static_cast<double>(Y[i][r]);
331 for (std::size_t k = 0; k < Mx; ++k)
337 for (std::size_t k = Mx; k-- > 0;)
344 for (std::size_t r = 0; r < R; ++r) {
345 acc +=
static_cast<double>(Y[i][r]);
351 for (std::size_t k = 0; k < R; ++k)
357 for (std::size_t k = R; k-- > 0;)
368 for (std::size_t k = 0; k < Mx; ++k)
369 if (cumP(k, cls) >= u) {
373 if (m < Mx && m != i) {
386 for (std::size_t b = 0; b < nbatches; ++b) denTot += den[b];
387 for (std::size_t r = 0; r < R; ++r) {
389 for (std::size_t b = 0; b < nbatches; ++b) num += xnum(b, r);
393 for (std::size_t i = 0; i < M; ++i)
394 for (std::size_t r = 0; r < R; ++r) {
396 for (std::size_t b = 0; b < nbatches; ++b) num += qnum[b](i, r);
402 std::vector<double> v(nbatches, 0.0);
403 for (std::size_t r = 0; r < R; ++r) {
405 for (std::size_t b = 0; b < nbatches; ++b) v[b] = (xnum(b, r) / den[b]) / rt;
407 std::sqrt(
static_cast<double>(nbatches)));
409 for (std::size_t i = 0; i < M; ++i)
410 for (std::size_t r = 0; r < R; ++r) {
411 for (std::size_t b = 0; b < nbatches; ++b) v[b] = qnum[b](i, r) / den[b];
413 detail::mcmc_sample_std(v) / std::sqrt(
static_cast<double>(nbatches)));
417 for (std::size_t r = 0; r < R; ++r) {
418 res.
Xlo[r] = T(res.
X[r] - two * res.
Xse[r]);
419 res.
Xhi[r] = T(res.
X[r] + two * res.
Xse[r]);
421 for (std::size_t i = 0; i < M; ++i)
422 for (std::size_t r = 0; r < R; ++r) {
423 res.
Qlo(i, r) = T(res.
Q(i, r) - two * res.
Qse(i, r));
424 res.
Qhi(i, r) = T(res.
Q(i, r) + two * res.
Qse(i, r));