215 const std::vector<T>& Z,
const Matrix<T>& alpha0,
216 const std::vector<T>& vfix) {
218 "pfqn_nre requires transcendental arithmetic (a saddlepoint expansion of a "
219 "coefficient-extraction integral)");
222 const std::size_t M0 = L0.
rows(), R = L0.
cols();
223 if (N.size() != R)
throw InputError(
"pfqn_nre: L and N disagree on the class count");
226 T Ntsum = zero, Zsum = zero;
227 for (std::size_t r = 0; r < R; ++r) Ntsum += N[r];
228 for (std::size_t r = 0; r < Z.size(); ++r) Zsum += Z[r];
229 if (Ntsum < zero)
throw InputError(
"pfqn_nre: negative population");
232 const std::size_t Ntot =
static_cast<std::size_t
>(Nt);
236 const std::size_t M = M0 + (Zsum > zero ? 1 : 0);
238 for (std::size_t i = 0; i < M0; ++i)
239 for (std::size_t r = 0; r < R; ++r) L(i, r) = L0(i, r);
241 for (std::size_t i = 0; i < M0 && i < alpha0.
rows(); ++i)
242 for (std::size_t k = 0; k < Ntot; ++k)
243 alpha(i, k) = k < alpha0.
cols() ? alpha0(i, k) : one;
245 if (Z.size() != R)
throw InputError(
"pfqn_nre: Z has the wrong length");
246 for (std::size_t r = 0; r < R; ++r) L(M0, r) = Z[r];
247 for (std::size_t k = 0; k < Ntot; ++k)
252 std::vector<int> Ni(R, 0);
253 for (std::size_t r = 0; r < R; ++r)
262 for (std::size_t r = 0; r < R; ++r) {
264 for (std::size_t i = 0; i < M; ++i)
265 if (L(i, r) > m) m = L(i, r);
266 if (!(m > zero)) m = one;
267 for (std::size_t i = 0; i < M; ++i) L(i, r) = L(i, r) / m;
268 lGscale += N[r] * log(m);
277 const std::size_t d = R - 1;
278 if (d > detail::nre_max_dim())
280 "pfqn_nre: pfqn_nre is limited to 8 classes, use nrl or clw beyond that");
282 std::vector<T> Nd(d);
283 for (std::size_t a = 0; a < d; ++a) Nd[a] = N[a];
284 detail::NreCgf<T> cgf(L, Nt, alpha, d);
285 const T h = detail::nre_hstep<T>();
286 const std::vector<int> origin(d, 0);
291 std::vector<T> vbase(d, zero);
293 bool converged =
false;
294 const bool tilt_given = !vfix.empty();
298 "pfqn_nre: the supplied tilt must have one entry per quotient dimension (R-1)");
299 for (std::size_t a = 0; a < d; ++a) vbase[a] = vfix[a];
302 for (
int it = 0; !tilt_given && it < 100; ++it) {
304 std::vector<T> grad(d);
306 for (std::size_t a = 0; a < d; ++a)
307 grad[a] = (cgf.at(detail::nre_unitoff(d, a, 1)) - cgf.at(detail::nre_unitoff(d, a, -1))) /
310 for (std::size_t a = 0; a < d; ++a)
311 for (std::size_t b = 0; b < d; ++b) hess(a, b) = detail::nre_second_diff(cgf, d, a, b);
312 std::vector<T> step =
solve(hess, grad);
313 for (std::size_t a = 0; a < d; ++a) step[a] = -step[a];
315 T F0 = cgf.at(origin);
316 for (std::size_t a = 0; a < d; ++a) F0 -= Nd[a] * vbase[a];
318 std::vector<T> vtry(d);
321 for (std::size_t a = 0; a < d; ++a) vtry[a] = vbase[a] + tau * step[a];
322 obj = cgf.at_point(vtry);
323 for (std::size_t a = 0; a < d; ++a) obj -= Nd[a] * vtry[a];
324 if (obj <= F0)
break;
328 for (std::size_t a = 0; a < d; ++a) {
329 const T delta = tau * step[a];
331 stepNorm += delta * delta;
335 if (sqrt(stepNorm) < tol) {
346 const T K0 = cgf.at(origin);
348 for (std::size_t a = 0; a < d; ++a)
349 for (std::size_t b = 0; b < d; ++b) Sigma(a, b) = detail::nre_second_diff(cgf, d, a, b);
350 for (std::size_t a = 0; a < d; ++a)
351 for (std::size_t b = a + 1; b < d; ++b) {
357 if (!detail::nre_chol(Sigma, chol))
359 "pfqn_nre: the tilted covariance is singular, a class has no demand at any station");
361 for (std::size_t a = 0; a < d; ++a) logdet += num_traits<T>::from_int(2) * log(chol(a, a));
363 std::vector<T> k3(d * d * d, zero);
364 for (std::size_t a = 0; a < d; ++a)
365 for (std::size_t b = 0; b < d; ++b)
366 for (std::size_t c = 0; c < d; ++c) {
368 for (
int s = 0; s < 8; ++s) {
369 const int s1 = 1 - 2 * ((s >> 0) & 1);
370 const int s2 = 1 - 2 * ((s >> 1) & 1);
371 const int s3 = 1 - 2 * ((s >> 2) & 1);
372 std::vector<int> off(d, 0);
381 std::vector<T> k4(d * d * d * d, zero);
382 for (std::size_t a = 0; a < d; ++a)
383 for (std::size_t b = 0; b < d; ++b)
384 for (std::size_t c = 0; c < d; ++c)
385 for (std::size_t e = 0; e < d; ++e) {
387 for (
int s = 0; s < 16; ++s) {
388 const int s1 = 1 - 2 * ((s >> 0) & 1);
389 const int s2 = 1 - 2 * ((s >> 1) & 1);
390 const int s3 = 1 - 2 * ((s >> 2) & 1);
391 const int s4 = 1 - 2 * ((s >> 3) & 1);
392 std::vector<int> off(d, 0);
399 k4[((a * d + b) * d + c) * d + e] =
406 for (std::size_t a = 0; a < d; ++a)
407 for (std::size_t b = 0; b < d; ++b)
408 for (std::size_t c = 0; c < d; ++c)
409 for (std::size_t e = 0; e < d; ++e)
410 rho4 += k4[((a * d + b) * d + c) * d + e] * S(a, b) * S(c, e);
411 std::vector<T> u(d, zero);
412 for (std::size_t c = 0; c < d; ++c)
413 for (std::size_t a = 0; a < d; ++a)
414 for (std::size_t b = 0; b < d; ++b) u[c] += S(a, b) * k3[(a * d + b) * d + c];
416 for (std::size_t c = 0; c < d; ++c)
417 for (std::size_t e = 0; e < d; ++e) rhoA += u[c] * S(c, e) * u[e];
419 std::vector<T> T1(d * d * d, zero), T2(d * d * d, zero);
420 for (std::size_t i = 0; i < d; ++i)
421 for (std::size_t b = 0; b < d; ++b)
422 for (std::size_t c = 0; c < d; ++c) {
424 for (std::size_t a = 0; a < d; ++a) acc += S(i, a) * k3[(a * d + b) * d + c];
425 T1[(i * d + b) * d + c] = acc;
427 for (std::size_t i = 0; i < d; ++i)
428 for (std::size_t j = 0; j < d; ++j)
429 for (std::size_t c = 0; c < d; ++c) {
431 for (std::size_t b = 0; b < d; ++b) acc += S(j, b) * T1[(i * d + b) * d + c];
432 T2[(i * d + j) * d + c] = acc;
435 for (std::size_t i = 0; i < d; ++i)
436 for (std::size_t j = 0; j < d; ++j)
437 for (std::size_t k = 0; k < d; ++k) {
439 for (std::size_t c = 0; c < d; ++c) acc += S(k, c) * T2[(i * d + j) * d + c];
440 rhoB += k3[(i * d + j) * d + k] * acc;
447 if (!(corr > zero)) corr = one;
450 std::log(2.0 * 3.14159265358979323846)) -
452 for (std::size_t a = 0; a < d; ++a) lGs -= Nd[a] * vbase[a];