11 std::reference_wrapper<const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>> >;
37 using vec_t = Eigen::Matrix<value_t, Eigen::Dynamic, 1>;
38 using mat_t = Eigen::Matrix<value_t, Eigen::Dynamic, Eigen::Dynamic>;
42 size_t M = samples.size();
44 if (M == 0)
return tau_hat;
46 size_t dim = samples[0].get().cols();
47 size_t N = samples[0].get().rows();
49 if (N <= 1 || dim == 0)
return tau_hat;
51 tau_hat = vec_t::Zero(dim);
53 auto var = [N](
const auto&
mat) {
54 return (
mat.rowwise() -
55 mat.colwise().mean()).colwise()
56 .squaredNorm() / (N-1);
61 mat_t sample_vars(dim, M);
62 for (
size_t i = 0; i < M; ++i) {
63 sample_vars.col(i) = var(samples[i].
get());
67 vec_t W = sample_vars.rowwise().mean();
70 vec_t var_est =
static_cast<T
>(N-1) / N * W;
75 mat_t sample_mean(dim, M);
76 for (
size_t i = 0; i < M; ++i) {
77 sample_mean.col(i) = samples[i].get().colwise().mean();
79 var_est += var(sample_mean.transpose());
84 mat_t acov_mean(N, dim);
87 for (
size_t m = 1; m <= M; ++m) {
89 for (
int j = 0; j < next_acov.cols(); ++j) {
90 next_acov.col(j) *= sample_vars(j,m-1);
93 acov_mean = m_inv * next_acov + (m-1) * m_inv * acov_mean;
97 auto rho_hat = [&](
size_t t,
size_t d) {
98 return 1. - (W(d) - acov_mean(t,d))/var_est(d);
102 for (
size_t d = 0; d < dim; ++d) {
105 value_t curr_rho_hat_even = rho_hat(0,d);
106 value_t curr_p_hat = curr_rho_hat_even + rho_hat(1,d);
107 value_t curr_min = curr_p_hat;
108 tau_hat(d) = curr_min;
113 for (; t < (N-3) && curr_p_hat > 0; t += 2) {
114 curr_rho_hat_even = rho_hat(t,d);
115 curr_p_hat = curr_rho_hat_even + rho_hat(t+1,d);
120 if (curr_p_hat >= 0) {
121 curr_min = std::min(curr_min, curr_p_hat);
122 tau_hat(d) += curr_min;
127 value_t correction = (curr_rho_hat_even > 0) ?
128 curr_rho_hat_even : rho_hat(t,d);
132 tau_hat(d) += correction;
135 vec_t n_eff = N*M*(1./tau_hat.array()).min(std::log10(N)).matrix();
152 inline auto ess(
const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& samples)
155 v.emplace_back(samples);