88 const std::size_t R = H.
rows();
89 if (H.
cols() != R)
throw InputError(
"pas_placement: H must be square");
91 for (std::size_t i = 0; i < R; ++i)
92 for (std::size_t j = 0; j < R; ++j) P(i, j) = H(i, j) != 0 ? 1 : 0;
93 for (std::size_t it = 0; it < R; ++it) {
96 for (std::size_t i = 0; i < R; ++i)
97 for (std::size_t j = 0; j < R; ++j) {
100 for (std::size_t k = 0; k < R && !v; ++k)
101 if (P(i, k) && H(k, j) != 0) v = 1;
103 if (v != P(i, j)) changed =
true;
134 bool want_qlen =
true) {
136 "pfqn_pas_is requires transcendental arithmetic: it is a Monte Carlo estimator, "
137 "inexact by construction, and reports the log of its own estimate");
139 const std::size_t R = N.size();
142 "pfqn_pas_is models a two-station pass-and-swap tandem: mu must have exactly two rate "
145 if (n < 0)
throw InputError(
"pfqn_pas_is: negative population");
147 throw InputError(
"pfqn_pas_is: H must be a (R x R) swap-graph adjacency matrix");
148 if (samples == 0)
throw InputError(
"pfqn_pas_is: at least one sample is required");
156 for (
int n : N) ell_l += n;
162 const std::size_t ell =
static_cast<std::size_t
>(ell_l);
169 std::vector<T> accum(want_qlen ? R + 1 : 1, zero);
170 std::vector<int> x(R), occ(R), occ2(R), avail(R);
171 std::vector<std::size_t> c(ell);
172 std::vector<T> Phi1(ell + 1), Phi2cut(ell + 1);
173 Matrix<T> cnt1(want_qlen ? ell + 1 : 0, want_qlen ? R : 0, zero);
175 for (std::size_t s = 0; s < samples; ++s) {
179 for (std::size_t p = 0; p < ell; ++p) {
181 for (std::size_t j = 0; j < R; ++j) {
182 if (x[j] <= 0)
continue;
183 bool blocked =
false;
185 for (std::size_t i = 0; i < R && !blocked; ++i)
186 if (x[i] > 0 && P(i, j)) blocked =
true;
187 if (!blocked) avail[na++] = j;
191 "pfqn_pas_is: swap graph induces no feasible ordering (cyclic placement "
203 for (std::size_t r = 0; r < R; ++r) cnt1(0, r) = zero;
205 for (std::size_t k = 0; k < ell; ++k) {
206 const std::size_t cls = c[k];
208 const T rate = mu[0](occ);
209 if (rate == zero)
throw NumericError(
"pfqn_pas_is: zero rank rate at station 1");
213 for (std::size_t r = 0; r < R; ++r)
221 for (std::size_t k = ell; k >= 1; --k) {
223 const T rate = mu[1](occ2);
224 if (rate == zero)
throw NumericError(
"pfqn_pas_is: zero rank rate at station 2");
226 Phi2cut[k - 1] = phi;
230 for (std::size_t k = 0; k <= ell; ++k) {
231 const T w2 = k >= ell ? one : Phi2cut[k];
232 const T w = Phi1[k] * w2;
233 accum[0] += w * invp;
234 if (want_qlen && k > 0)
235 for (std::size_t r = 0; r < R; ++r) accum[1 + r] += w * cnt1(k, r) * invp;
240 res.
G = accum[0] / ns;
243 for (std::size_t r = 0; r < R; ++r) {
244 const T q1 = res.
G > zero ? (accum[1 + r] / ns) / res.
G : zero;
PasIsResult< T > pfqn_pas_is(const std::vector< int > &N, const std::vector< OiRateFun< T > > &mu, const Matrix< int > &H, std::size_t samples, McRng &rng, bool want_qlen=true)
Importance-sampling estimate of the normalizing constant of a single communicating class of a cyclic ...