78inline void sample_without_replacement(std::size_t n, std::size_t mt, std::mt19937_64& rng,
114 std::size_t samples, std::uint64_t seed,
115 const std::vector<int>& sigma_in,
const std::vector<int>& k) {
117 "cache_is requires transcendental arithmetic: the estimator is a Monte Carlo "
118 "average formed in the log domain");
119 if (gamma_in.
cols() != m.size())
120 throw InputError(
"cache_is: gamma and m disagree on the number of lists");
121 if (samples == 0)
throw InputError(
"cache_is: at least one sample is required");
127 const bool capped = !sigma_in.empty() && !k.empty();
128 const Matrix<T> gamma = detail::gamma_drop_zero_rows(gamma_in);
129 std::vector<int> sigma;
132 for (std::size_t i = 0; i < gamma_in.
rows(); ++i) {
134 for (std::size_t j = 0; j < gamma_in.
cols(); ++j) rs += gamma_in(i, j);
138 const std::size_t n = gamma.
rows();
139 const std::size_t h = m.size();
142 if (v < 0)
throw InputError(
"cache_is: negative list capacity");
147 if (n == 0 || mt == 0) {
152 if (
static_cast<long>(n) < mt) {
156 res.
lE = -T(std::numeric_limits<T>::infinity());
159 if (
static_cast<long>(n) == mt) {
168 for (std::size_t i = 0; i < n; ++i)
169 for (std::size_t j = 0; j < h; ++j) lgam(i, j) = log(T(gamma(i, j) + floorv));
172 for (std::size_t j = 0; j < h; ++j)
173 logMFact += pfqn::detail::num_logfact_int<T>(
static_cast<long>(m[j]));
174 const T logComb = pfqn::detail::num_logfact_int<T>(
static_cast<long>(n)) -
175 pfqn::detail::num_logfact_int<T>(mt) -
176 pfqn::detail::num_logfact_int<T>(
static_cast<long>(n) - mt);
177 const T logMultinom = pfqn::detail::num_logfact_int<T>(mt) - logMFact;
178 const T logProposal = -logComb - logMultinom;
180 std::mt19937_64
rng(seed);
181 std::vector<std::size_t>
perm, sel;
182 std::vector<T> lZ(samples, zero);
183 for (std::size_t s = 0; s < samples; ++s) {
184 detail::sample_without_replacement(n,
static_cast<std::size_t
>(mt),
rng,
perm, sel);
185 T logState = logMFact;
187 bool feasible =
true;
188 for (std::size_t j = 0; j < h && feasible; ++j) {
191 for (
int c = 0; c < m[j]; ++c) listCost += sigma[sel[idx + c]];
192 if (listCost > k[j]) {
197 for (
int c = 0; c < m[j]; ++c) logState += lgam(sel[idx++], j);
200 lZ[s] = -T(std::numeric_limits<T>::infinity());
203 lZ[s] = logState - logProposal;
CacheIsResult< T > cache_is(const Matrix< T > &gamma_in, const std::vector< int > &m, std::size_t samples, std::uint64_t seed, const std::vector< int > &sigma_in, const std::vector< int > &k)
Importance-sampling estimate of the cache normalizing constant.