141 "pfqn_clwjd requires transcendental arithmetic (contour integration of a "
142 "generating function)");
145 const std::size_t R = N.size();
146 const std::size_t M = mu.size();
147 if (!Z.empty() && Z.size() != R)
148 throw InputError(
"pfqn_clwjd: Z and N disagree on the chain count");
149 if (!visits.
empty() && (visits.
rows() != M || visits.
cols() != R))
150 throw InputError(
"pfqn_clwjd: visits must be M x R");
152 throw InputError(
"pfqn_clwjd: lcut must be M x R");
157 for (std::size_t r = 0; r < R; ++r) {
160 res.
lG = T(-std::numeric_limits<T>::infinity());
171 std::vector<int> lfull;
172 std::vector<double> gfull;
173 detail::clw_defaults(R,
opt, lfull, gfull);
177 std::vector<std::size_t> keep;
178 for (std::size_t r = 0; r < R; ++r)
179 if (N[r] > 0) keep.push_back(r);
180 const std::size_t p = keep.size();
181 std::vector<int> Nk(p, 0), l(p, 1);
182 std::vector<T> Zk(p, zero);
183 std::vector<double> gam(p, 0.0);
184 for (std::size_t j = 0; j < p; ++j) {
186 Zk[j] = Z.empty() ? zero : Z[keep[j]];
187 l[j] = lfull[keep[j]];
188 gam[j] = gfull[keep[j]];
192 std::vector<std::vector<int>> Lk(M, std::vector<int>(p, 1));
193 for (std::size_t i = 0; i < M; ++i)
194 for (std::size_t b = 0; b < p; ++b) {
195 int li = lcut.
empty() ? Nk[b] : lcut(i, keep[b]);
197 if (li > Nk[b]) li = Nk[b];
203 std::vector<std::size_t> ntreg(M, 1);
204 std::vector<std::vector<T>> muT(M);
205 std::vector<std::vector<std::vector<std::size_t>>> regDec(M), regSat(M);
206 std::vector<std::vector<std::size_t>> satMask(M);
207 for (std::size_t i = 0; i < M; ++i) {
208 std::vector<std::size_t> st(p, 1);
210 for (std::size_t b = 0; b < p; ++b) {
212 nt *=
static_cast<std::size_t
>(Lk[i][b] + 1);
215 muT[i].assign(nt, one);
216 regDec[i].assign(nt, std::vector<std::size_t>());
217 regSat[i].assign(nt, std::vector<std::size_t>());
218 satMask[i].assign(nt, 0);
219 std::vector<int> t(p, 0);
220 for (std::size_t tl = 0; tl < nt; ++tl) {
221 for (std::size_t b = 0; b < p; ++b)
222 t[b] =
static_cast<int>((tl / st[b]) %
static_cast<std::size_t
>(Lk[i][b] + 1));
223 for (std::size_t b = 0; b < p; ++b) {
225 regDec[i][tl].push_back(b);
226 regDec[i][tl].push_back(tl - st[b]);
228 if (t[b] == Lk[i][b]) {
229 regSat[i][tl].push_back(b);
230 satMask[i][tl] |= (
static_cast<std::size_t
>(1) << b);
233 if (tl > 0) muT[i][tl] = detail::clwjd_region_rate<T>(mu[i], t, keep, R, N, Lk[i]);
239 for (std::size_t i = 0; i < M; ++i)
240 for (std::size_t b = 0; b < p; ++b) V(i, b) = visits.
empty() ? one : visits(i, keep[b]);
242 std::vector<T> r(p, one);
243 for (std::size_t j = 0; j < p; ++j)
244 r[j] = detail::clw_pow_real(
251 const std::size_t nmask =
static_cast<std::size_t
>(1) << p;
252 std::vector<std::vector<T>> muS(M, std::vector<T>(nmask, zero));
253 std::vector<std::vector<bool>> muSet(M, std::vector<bool>(nmask,
false));
254 for (std::size_t i = 0; i < M; ++i)
255 for (std::size_t tl = 0; tl < ntreg[i]; ++tl) {
256 const std::size_t sm = satMask[i][tl];
257 if (sm == 0)
continue;
258 if (!muSet[i][sm] || muT[i][tl] < muS[i][sm]) {
259 muS[i][sm] = muT[i][tl];
266 std::vector<std::vector<T>> rows;
267 for (std::size_t i = 0; i < M; ++i)
268 for (std::size_t mask = 1; mask < nmask; ++mask) {
269 if (!muSet[i][mask])
continue;
270 bool dominated =
false;
271 for (std::size_t mask2 = 1; mask2 < nmask && !dominated; ++mask2)
272 if (mask2 != mask && (mask & mask2) == mask && muSet[i][mask2] &&
275 if (dominated)
continue;
276 std::vector<T> row(p, zero);
277 for (std::size_t b = 0; b < p; ++b)
278 if (mask & (
static_cast<std::size_t
>(1) << b)) row[b] = V(i, b) / muS[i][mask];
281 const std::size_t nrow = rows.size();
283 for (std::size_t i = 0; i < nrow; ++i)
284 for (std::size_t j = 0; j < p; ++j) Lt(i, j) = rows[i][j];
286 const std::vector<long> mult(nrow ? nrow : 1, 1);
287 const std::vector<T> alpha = detail::clw_scaling(Lt, Lt, Nk, Zk, l, r, mult);
289 std::vector<T> arho0(p, zero);
291 for (std::size_t j = 0; j < p; ++j) {
292 arho0[j] = alpha[j] * Zk[j];
293 for (std::size_t i = 0; i < M; ++i) vs(i, j) = V(i, j) * alpha[j];
296 std::size_t ntmax = 1;
297 for (std::size_t i = 0; i < M; ++i) ntmax = std::max(ntmax, ntreg[i]);
298 std::vector<detail::Cx<T>> FT(ntmax, detail::Cx<T>(zero, zero));
299 const auto gbar = [&](
const std::vector<detail::Cx<T>>& w) {
300 detail::Cx<T> expo(zero, zero);
301 for (std::size_t j = 0; j < p; ++j)
302 expo = detail::cx_add(
303 expo, detail::cx_scale(detail::Cx<T>(T(w[j].re - one), w[j].im), arho0[j]));
304 detail::Cx<T> logF(zero, zero);
305 for (std::size_t i = 0; i < M; ++i) {
306 FT[0] = detail::Cx<T>(one, zero);
307 detail::Cx<T> tot(one, zero);
308 for (std::size_t tl = 1; tl < ntreg[i]; ++tl) {
309 detail::Cx<T> num(zero, zero);
310 const std::vector<std::size_t>& dec = regDec[i][tl];
311 for (std::size_t k = 0; k < dec.size(); k += 2)
312 num = detail::cx_add(
313 num, detail::cx_mul(detail::cx_scale(w[dec[k]], vs(i, dec[k])),
315 detail::Cx<T> den(muT[i][tl], zero);
316 const std::vector<std::size_t>& sat = regSat[i][tl];
317 for (std::size_t k = 0; k < sat.size(); ++k)
318 den = detail::cx_sub(den, detail::cx_scale(w[sat[k]], vs(i, sat[k])));
319 FT[tl] = detail::cx_div(num, den);
320 tot = detail::cx_add(tot, FT[tl]);
322 logF = detail::cx_add(logF, detail::cx_log(tot));
324 return detail::cx_exp(detail::cx_add(expo, logF));
327 std::vector<detail::Cx<T>> w(p);
328 const detail::Cx<T> gv = detail::clw_invert(0, w, Nk, l, r, p, gbar);
330 throw NumericError(
"pfqn_clwjd: the inverted generating function is not positive");
333 for (std::size_t j = 0; j < p; ++j)