5#ifndef LINE_API_CACHE_EREC_H
6#define LINE_API_CACHE_EREC_H
57Matrix<T> gamma_without_row(
const Matrix<T>& gamma, std::size_t i) {
58 if (gamma.rows() == 0)
return gamma;
59 Matrix<T> g(gamma.rows() - 1, gamma.cols());
61 for (std::size_t a = 0; a < gamma.rows(); ++a) {
63 for (std::size_t b = 0; b < gamma.cols(); ++b) g(r, b) = gamma(a, b);
71T cache_erec_aux(
const Matrix<T>& gamma,
const std::vector<int>& m,
int k) {
77 if (first || v < mmin) mmin = v;
80 if (mt == 0)
return num_traits<T>::from_int(1);
81 if (mt > k || mmin < 0)
return num_traits<T>::from_int(0);
83 const std::size_t h = m.size();
84 if (k == 1 && mt == 1) {
85 for (std::size_t j = 0; j < h; ++j)
86 if (m[j] != 0)
return gamma(0, j);
87 return num_traits<T>::from_int(0);
90 T E = cache_erec_aux(gamma, m, k - 1);
91 for (std::size_t j = 0; j < h; ++j) {
93 std::vector<int> mj = m;
95 E += gamma(
static_cast<std::size_t
>(k - 1), j) *
96 num_traits<T>::from_int(
static_cast<long>(m[j])) *
97 cache_erec_aux(gamma, mj, k - 1);
117T cache_erec_cost(
const Matrix<T>& gamma,
const std::vector<int>& m,
118 const std::vector<int>& sigma,
const std::vector<int>& k) {
119 const std::size_t n = gamma.rows();
120 const std::size_t h = m.size();
121 if (sigma.size() != n)
122 throw InputError(
"cache_erec: the item size vector must have one entry per item");
124 throw InputError(
"cache_erec: the cost cap vector must have one entry per cache list");
126 for (std::size_t j = 0; j < h; ++j) {
127 if (m[j] < 0 || k[j] < 0)
return num_traits<T>::from_int(0);
130 for (std::size_t i = 0; i < n; ++i)
132 throw InputError(
"cache_erec: item sizes must be positive integers");
133 if (mt >
static_cast<long>(n))
return num_traits<T>::from_int(0);
134 if (mt == 0)
return num_traits<T>::from_int(1);
136 std::vector<std::size_t> dims(2 * h), stride(2 * h);
137 for (std::size_t j = 0; j < h; ++j) {
138 dims[j] =
static_cast<std::size_t
>(m[j]) + 1;
139 dims[h + j] =
static_cast<std::size_t
>(k[j]) + 1;
141 std::size_t size = 1;
142 for (std::size_t d = 0; d < 2 * h; ++d) {
145 if (size > 10000000u)
147 "cache_erec: the cost-constrained lattice exceeds the exact method "
148 "limit; use the sampling method");
150 std::vector<T> F(size, num_traits<T>::from_int(0));
151 std::vector<T> Fprev(size, num_traits<T>::from_int(0));
152 std::vector<std::size_t> sub(2 * h, 0);
153 for (std::size_t idx = 0; idx < size; ++idx) {
154 std::size_t rem = idx, mc = 0;
155 for (std::size_t d = 2 * h; d-- > 0;) {
156 sub[d] = rem / stride[d];
157 rem -= sub[d] * stride[d];
159 for (std::size_t j = 0; j < h; ++j) mc += sub[j];
160 if (mc == 0) F[idx] = num_traits<T>::from_int(1);
162 for (std::size_t t = 0; t < n; ++t) {
164 for (std::size_t idx = 0; idx < size; ++idx) {
165 std::size_t rem = idx, mc = 0;
166 for (std::size_t d = 2 * h; d-- > 0;) {
167 sub[d] = rem / stride[d];
168 rem -= sub[d] * stride[d];
170 for (std::size_t j = 0; j < h; ++j) mc += sub[j];
172 F[idx] = num_traits<T>::from_int(0);
176 for (std::size_t j = 0; j < h; ++j) {
177 const std::size_t mj = sub[j];
178 const std::size_t kj = sub[h + j];
179 const std::size_t si =
static_cast<std::size_t
>(sigma[t]);
180 if (mj > 0 && kj >= si && !(gamma(t, j) == num_traits<T>::from_int(0))) {
181 val += gamma(t, j) * num_traits<T>::from_int(
static_cast<long>(mj)) *
182 Fprev[idx - stride[j] - si * stride[h + j]];
204 return detail::cache_erec_aux(gamma, m, 0);
206 if (gamma.
cols() != m.size())
207 throw InputError(
"cache_erec: gamma and m disagree on the number of lists");
208 return detail::cache_erec_aux(gamma, m,
static_cast<int>(gamma.
rows()));
224 const std::vector<int>& sigma,
const std::vector<int>& k) {
225 if (sigma.empty() || k.empty())
return cache_erec(gamma, m);
226 if (gamma.
cols() != m.size())
227 throw InputError(
"cache_erec: gamma and m disagree on the number of lists");
228 return detail::cache_erec_cost(gamma, m, sigma, k);
The exception types the port throws.
Dense matrix and non-owning view.
T cache_erec(const Matrix< T > &gamma, const std::vector< int > &m)
Exact recursive normalizing constant of a multi-list cache model.
Number-type abstraction for the templated API port.