121 "pfqn_ls requires transcendental arithmetic: it importance-samples a Gaussian "
122 "proposal centred on a tolerance-stopped fixed point and averages log-weights");
128 const std::size_t R = N.size();
130 throw InputError(
"pfqn_ls: L and N disagree on the class count");
131 if (!Z.empty() && Z.size() != R)
throw InputError(
"pfqn_ls: Z has the wrong length");
132 if (I == 0)
throw InputError(
"pfqn_ls: at least one sample is required");
135 std::vector<std::size_t> keep;
136 for (std::size_t i = 0; i < L0.
rows(); ++i) {
138 for (std::size_t r = 0; r < R; ++r) s += L0(i, r);
142 for (std::size_t i = 0; i < keep.size(); ++i)
143 for (std::size_t r = 0; r < R; ++r) L(i, r) = L0(keep[i], r);
144 const std::size_t M = L.
rows();
146 T Ntot = zero, Lsum = zero, Zsum = zero;
147 for (
const T& x : N) Ntot += x;
148 for (std::size_t i = 0; i < M; ++i)
149 for (std::size_t r = 0; r < R; ++r) Lsum += L(i, r);
150 for (
const T& x : Z) Zsum += x;
156 for (std::size_t r = 0; r < R; ++r) {
157 lG -= detail::num_factln<T>(N[r]);
158 if (!Z.empty() && Z[r] > zero) lG += N[r] * log(Z[r]);
166 "pfqn_ls: at least two loaded stations are required; the logistic transform maps the "
167 "simplex to R^{M-1}, which is empty for a single station");
170 const bool zeroZ = Z.empty() || Zsum == zero;
183 for (std::size_t i = 0; i < d; ++i) x0[i] = log(T(umax[i] / umax[M - 1]));
189 for (std::size_t i = 0; i + 1 < M; ++i) x0[i] = log(T(umax[i] / umax[M - 1]));
190 x0[M - 1] = log(vmax);
194 for (std::size_t i = 0; i < d; ++i)
195 for (std::size_t j = i + 1; j < d; ++j) {
196 const T m = T(A(i, j) + A(j, i)) * half;
205 if (detail::ls_chol_upper(A,
Ca)) {
206 for (std::size_t i = 0; i < d; ++i) logdetA += log(
Ca(i, i));
209 const T det = detail::pfqn_det(A);
210 logdetA = log(T(det < zero ? T(-det) : det));
214 if (!detail::ls_chol_upper(iA, Ci))
216 "pfqn_ls: the proposal covariance (inverse Hessian at the mode) is not positive "
217 "definite, so no Gaussian proposal exists there");
220 std::vector<double> lr(I);
221 std::vector<T> xs(d), z(d), diff(d);
225 for (std::size_t s = 0; s < I; ++s) {
226 for (std::size_t i = 0; i < d; ++i) z[i] = num_traits<T>::from_double(
mc_normal01(
rng));
228 for (std::size_t j = 0; j < d; ++j) {
230 for (std::size_t i = 0; i <= j; ++i) acc += z[i] * Ci(i, j);
239 std::vector<T> vv(M, one);
240 for (std::size_t i = 0; i < d; ++i) {
244 for (std::size_t r = 0; r < R; ++r) {
246 for (std::size_t i = 0; i < M; ++i) vl += vv[i] * L(i, r);
247 lT += N[r] * log(vl);
249 for (std::size_t i = 0; i < d; ++i) lT += xs[i];
252 const T v = exp(xs[M - 1]);
254 std::vector<T> e(M - 1, zero);
255 for (std::size_t i = 0; i + 1 < M; ++i) {
261 for (std::size_t r = 0; r < R; ++r) {
262 T inner = T(L(M - 1, r) * v + Z[r]);
263 for (std::size_t i = 0; i + 1 < M; ++i) inner += e[i] * T(L(i, r) * v + Z[r]);
264 lT += N[r] * log(inner);
266 for (std::size_t i = 0; i + 1 < M; ++i) lT += xs[i];
267 lT -= eta * log(T(one + esum));
271 for (std::size_t i = 0; i < d; ++i) diff[i] = T(xs[i] - x0[i]);
273 for (std::size_t i = 0; i < d; ++i) {
275 for (std::size_t j = 0; j < d; ++j) row += diff[j] * A(j, i);
290 for (std::size_t r = 0; r < R; ++r) lG -= detail::num_factln<T>(N[r]);
292 for (std::size_t r = 0; r < R; ++r) lG -= detail::num_factln<T>(N[r]);