101 "retrieval_fpi requires transcendental arithmetic: it is a successive "
102 "substitution stopped on a relative tolerance, so its answer is the fixed "
103 "point only to within tol whatever the arithmetic");
104 const std::size_t n = lambda.size();
105 const std::size_t h = m.size();
106 if (eta.
rows() != n || gamma.
rows() != n)
107 throw InputError(
"retrieval_fpi: eta/gamma and lambda disagree on the item count");
108 if (gamma.
cols() != h)
109 throw InputError(
"retrieval_fpi: gamma and m disagree on the number of lists");
110 if (eta.
cols() == 0)
throw InputError(
"retrieval_fpi: eta has no columns");
111 const std::size_t r = eta.
cols() - 1;
123 std::vector<T> pi0(n, init_phi);
126 for (std::size_t t = 1; t <= options.max_iter; ++t) {
131 for (std::size_t s = 0; s < r; ++s) {
133 for (std::size_t i = 0; i < n; ++i) tot += phi(s + 1, i);
134 for (std::size_t i = 0; i < n; ++i) F(s, i) = one + (tot - phi(s + 1, i));
138 for (std::size_t i = 0; i < n; ++i) {
139 D[i] = one + lambda[i] * eta(i, 0);
140 for (std::size_t s = 0; s < r; ++s) D[i] += lambda[i] * eta(i, s + 1) * F(s, i);
144 for (std::size_t i = 0; i < n; ++i)
145 for (std::size_t j = 0; j < h; ++j) theta(i, j) = gamma(i, j) / D[i];
148 std::vector<T> oneminus(n);
149 for (std::size_t k = 0; k < n; ++k) {
151 for (std::size_t j = 0; j < h; ++j) s += pij(j, k);
152 oneminus[k] = one - s;
155 std::vector<T> xi(h);
156 for (std::size_t j = 0; j < h; ++j) {
158 for (std::size_t k = 0; k < n; ++k) den += theta(k, j) * oneminus[k];
163 std::vector<T> pi0_new(n);
165 for (std::size_t i = 0; i < n; ++i) {
167 for (std::size_t l = 0; l < h; ++l) denom += theta(i, l) * xi[l];
169 for (std::size_t j = 0; j < h; ++j) {
170 pij_new(j, i) = theta(i, j) * xi[j] / denom;
171 sum_pij += pij_new(j, i);
173 pi0_new[i] = (one - sum_pij) / D[i];
174 phi_new(0, i) = lambda[i] * eta(i, 0) * pi0_new[i];
175 for (std::size_t s = 0; s < r; ++s)
176 phi_new(s + 1, i) = lambda[i] * eta(i, s + 1) * F(s, i) * pi0_new[i];
179 const std::vector<T> pij_flat(pij_new.
data(), pij_new.
data() + pij_new.
size());
180 const std::vector<T> pij_old(pij.
data(), pij.
data() + pij.
size());
181 const std::vector<T> phi_flat(phi_new.
data(), phi_new.
data() + phi_new.
size());
182 const std::vector<T> phi_old(phi.
data(), phi.
data() + phi.
size());
183 double delta = detail::fpi_reldiff(pi0_new, pi0);
184 const double d2 = detail::fpi_reldiff(pij_flat, pij_old);
185 const double d3 = detail::fpi_reldiff(phi_flat, phi_old);
186 if (d2 > delta) delta = d2;
187 if (d3 > delta) delta = d3;
193 if (!std::isfinite(delta)) {
197 if (delta < options.tol) {
RetrievalFpiResult< T > retrieval_fpi(const std::vector< int > &m, const std::vector< T > &lambda, const Matrix< T > &eta, const Matrix< T > &gamma, const FpiOptions &options=FpiOptions())
Fixed-point heuristic for a delayed-hit (list-based) cache.