114 "pfqn_mci requires transcendental arithmetic: it is a Monte Carlo estimator over "
115 "an exponential proposal, its integrand is evaluated in the log domain, and its "
116 "proposal rates come from a tolerance-stopped Bard-Schweitzer solve");
118 const std::size_t M = D.
empty() ? 0 : D.
rows();
119 const std::size_t R = N.size();
121 throw InputError(
"pfqn_mci: D and N disagree on the class count");
122 if (!Z.empty() && Z.size() != R)
throw InputError(
"pfqn_mci: Z has the wrong length");
124 if (n < 0)
throw InputError(
"pfqn_mci: negative population");
125 if (samples == 0)
throw InputError(
"pfqn_mci: at least one sample is required");
128 std::vector<T> Zv(R, zero);
129 for (std::size_t r = 0; r < Z.size(); ++r) Zv[r] = Z[r];
133 for (std::size_t i = 0; i < M; ++i)
134 for (std::size_t r = 0; r < R; ++r) dsum += D(i, r);
137 for (std::size_t r = 0; r < R; ++r) {
145 std::vector<double> gamma(M);
151 if (n > Nmax) Nmax = n;
153 std::vector<T> tput(R, zero);
154 for (std::size_t r = 0; r < R; ++r) {
157 for (std::size_t i = 0; i < M; ++i) {
159 if (D(i, r) > dmax) dmax = D(i, r);
162 if (den == zero)
throw NumericError(
ErrorKind{
"Degenerate"},
"pfqn_mci: zero denominator in the 'rm' bound");
165 for (std::size_t i = 0; i < M; ++i) {
167 for (std::size_t r = 0; r < R; ++r)
util += D(i, r) * tput[r];
169 gamma[i] = u > 0.9 ? 1.0 / std::sqrt(
static_cast<double>(Nmax)) : 1.0 - u;
172 std::vector<T> Nt(R), Zt(R);
173 for (std::size_t r = 0; r < R; ++r) {
180 if (n > Nmax) Nmax = n;
181 for (std::size_t i = 0; i < M; ++i) {
183 for (std::size_t r = 0; r < R; ++r)
util += D(i, r) * bs.
XN[r];
186 gamma[i] = 1.0 - u > 0.01 ? 1.0 - u : 0.01;
188 gamma[i] = u > 0.9 ? 1.0 / std::sqrt(
static_cast<double>(Nmax)) : 1.0 - u;
192 for (std::size_t i = 0; i < M; ++i)
193 if (!(gamma[i] > 0.0))
195 "pfqn_mci: a proposal rate is non-positive, the station is saturated beyond what "
196 "the variant's clamp covers");
200 for (std::size_t i = 0; i < M; ++i) lconst -= std::log(gamma[i]);
204 const double tiny = 1.0 / 9007199254740992.0;
205 std::vector<double> Vd(samples * M);
207 const std::size_t Ih = (samples + 1) / 2;
208 for (std::size_t i = 0; i < M; ++i) {
209 for (std::size_t s = 0; s < Ih; ++s) {
211 if (u <= 0.0) u = tiny;
212 Vd[s * M + i] = -std::log(u) / gamma[i];
213 if (Ih + s < samples) Vd[(Ih + s) * M + i] = -std::log(1.0 - u) / gamma[i];
217 std::vector<std::size_t>
perm(samples);
218 for (std::size_t i = 0; i < M; ++i) {
219 for (std::size_t s = 0; s < samples; ++s)
perm[s] = s;
220 for (std::size_t s = samples - 1; s > 0; --s) {
222 const std::size_t t =
perm[s];
226 for (std::size_t s = 0; s < samples; ++s) {
228 static_cast<double>(samples);
229 if (u <= 0.0) u = tiny;
230 Vd[s * M + i] = -std::log(u) / gamma[i];
234 for (std::size_t s = 0; s < samples; ++s) {
235 for (std::size_t i = 0; i < M; ++i) {
237 if (u <= 0.0) u = tiny;
238 Vd[s * M + i] = -std::log(u) / gamma[i];
243 std::vector<double> lZ(samples);
245 for (std::size_t s = 0; s < samples; ++s) {
247 for (std::size_t i = 0; i < M; ++i) {
248 const double v = Vd[s * M + i];
250 lz -= (1.0 - gamma[i]) * v;
252 for (std::size_t r = 0; r < R; ++r) {
253 if (N[r] == 0)
continue;
255 for (std::size_t i = 0; i < M; ++i) inner += V[i] * D(i, r);
262 if (!std::isfinite(lG)) {
265 double m = -std::numeric_limits<double>::infinity();
NcResult< T > pfqn_mci(const Matrix< T > &D, const std::vector< int > &N, const std::vector< T > &Z, std::size_t samples, MciVariant variant, McRng &rng)
Monte Carlo Integration estimate of the normalizing constant of a closed product-form network (Ross,...
AmvaResult< T > pfqn_bs(const Matrix< T > &L, const std::vector< T > &N, const std::vector< T > &Z, const std::vector< AmvaSched > &type, double tol=1e-6, std::size_t maxiter=1000, const Matrix< T > &QN0=Matrix< T >())
Bard-Schweitzer approximate MVA.