5#ifndef LINE_API_CACHE_SPM_H
6#define LINE_API_CACHE_SPM_H
99 const std::size_t n = A.
rows();
100 if (A.
cols() != n)
throw InputError(
"cache_spm: determinant of a non-square matrix");
103 for (std::size_t k = 0; k < n; ++k) {
106 for (std::size_t i = k + 1; i < n; ++i) {
113 if (amax == zero)
return zero;
115 for (std::size_t j = 0; j < n; ++j) std::swap(A(k, j), A(p, j));
119 for (std::size_t i = k + 1; i < n; ++i) {
120 const T fct = A(i, k) / A(k, k);
121 for (std::size_t j = k; j < n; ++j) A(i, j) -= fct * A(k, j);
131 std::vector<std::size_t> keep;
132 for (std::size_t i = 0; i < gamma.
rows(); ++i) {
134 for (std::size_t j = 0; j < gamma.
cols(); ++j) s += gamma(i, j);
135 if (s > zero) keep.push_back(i);
137 Matrix<T> g(keep.size(), gamma.
cols());
138 for (std::size_t a = 0; a < keep.size(); ++a)
139 for (std::size_t j = 0; j < gamma.
cols(); ++j) g(a, j) = gamma(keep[a], j);
154 "cache_spm requires transcendental arithmetic");
160 const Matrix<T> gamma = detail::gamma_nonzero_rows(gamma_in);
161 const std::size_t h = m.size();
162 const std::size_t n = gamma.
rows();
163 if (gamma.
cols() != h)
throw InputError(
"cache_spm: gamma and m disagree on the number of lists");
166 for (
int v : m) mt += v;
171 const T half = one / two;
174 if (
static_cast<long>(n) == mt) {
189 std::vector<std::size_t> keep;
190 for (std::size_t l = 0; l < h; ++l)
191 if (m[l] > 0) keep.push_back(l);
192 const std::size_t hk = keep.size();
197 r.
xi.assign(h, zero);
202 std::vector<int> mk(hk);
203 for (std::size_t a = 0; a < hk; ++a) {
205 for (std::size_t k = 0; k < n; ++k) gk(k, a) = gamma(k, keep[a]);
209 std::vector<T> xi(h, zero);
210 for (std::size_t a = 0; a < hk; ++a) xi[keep[a]] = xik[a];
212 std::vector<T> S(n, zero);
213 for (std::size_t k = 0; k < n; ++k)
214 for (std::size_t l = 0; l < hk; ++l) S[k] += gk(k, l) * xik[l];
217 for (std::size_t k = 0; k < n; ++k) phi += log(one + S[k]);
218 for (std::size_t l = 0; l < hk; ++l)
222 for (std::size_t j = 0; j < hk; ++j) {
223 for (std::size_t l = 0; l < hk; ++l) {
224 T C1 = zero, C2 = zero;
225 for (std::size_t k = 0; k < n; ++k) {
226 C1 += gk(k, j) / (one + S[k]);
227 C2 += gk(k, j) * gk(k, l) / ((one + S[k]) * (one + S[k]));
229 C(j, l) = (j == l ? C1 : zero) - xik[j] * C2;
233 const T detC = detail::cache_det(C);
234 if (detC == zero)
throw NumericError(
"cache_spm: the saddle-point Hessian is singular");
237 const T s2pi = sqrt(two * pi);
241 for (std::size_t l = 0; l < hk; ++l)
246 for (std::size_t l = 0; l < hk; ++l) lsqrtxi += half * log(
num_abs(xik[l]));
251 T prodfact = one, prodsqrtxi = one;
252 for (std::size_t l = 0; l < hk; ++l) {
254 prodsqrtxi *= sqrt(
num_abs(xik[l]));
256 r.
Z = exp(phi) *
num_pow_int(one / s2pi,
static_cast<unsigned>(hk)) * prodfact / prodsqrtxi /
Exact recursive normalizing constant of a multi-list cache model.
Lagrange multipliers of a multi-list cache by the Gast-Van Houdt iteration.
NumericError(const std::string &what)
The exception types the port throws.
Dense matrix and non-owning view.
std::vector< T > cache_xi_iter(const Matrix< T > &gamma, const std::vector< int > &m)
Lagrange multipliers of a multi-list cache by the Gast-Van Houdt iteration.
CacheSpmResult< T > cache_spm(const Matrix< T > &gamma_in, const std::vector< int > &m)
Saddle-point approximation of the cache normalizing constant.
T cache_erec(const Matrix< T > &gamma, const std::vector< int > &m)
Exact recursive normalizing constant of a multi-list cache model.
T num_factorial(unsigned n)
Factorial as a value of T.
T num_pow_int(const T &base, unsigned e)
Integer power, valid in any field (no transcendental requirement).
Number-type abstraction for the templated API port.
Return value of cache_spm, mirroring [Z,lZ,xi].
std::vector< T > xi
(h) saddle-point multipliers