1 #ifndef HOPS_EFFECTIVESAMPLESIZE_HPP
2 #define HOPS_EFFECTIVESAMPLESIZE_HPP
11 template <
typename StateType>
13 unsigned long dimension) {
14 unsigned long d = dimension;
15 unsigned long numChains = chains.size();
16 unsigned long numDraws = chains[0]->size();
18 double interChainExpectation = 0;
19 double betweenChainVariance = 0;
20 double withinChainVariance = 0;
21 double varianceEstimate = 0;
23 std::vector<double> rhoHat;
24 std::vector<double> intraChainExpectations = std::vector<double>(numChains, 0);
25 std::vector<double> sampleVariances = std::vector<double>(numChains, 0);
27 std::vector<Eigen::VectorXd> autocorrelations(numChains);
29 for (
size_t m = 0; m < numChains; ++m) {
30 for (
size_t n = 0; n < numDraws; ++n) {
31 intraChainExpectations[m] += (*chains[m])[n](d);
33 interChainExpectation += intraChainExpectations[m];
34 intraChainExpectations[m] /= numDraws;
37 interChainExpectation /= numChains * numDraws;
39 for (
size_t m = 0; m < numChains; ++m) {
40 betweenChainVariance += std::pow(intraChainExpectations[m] - interChainExpectation, 2);
41 for (
size_t n = 0; n < numDraws; ++n) {
42 sampleVariances[m] += std::pow((*chains[m])[n](d) - intraChainExpectations[m], 2);
44 withinChainVariance += sampleVariances[m];
45 sampleVariances[m] /= numDraws - 1;
50 betweenChainVariance *= numDraws;
51 betweenChainVariance /= numChains - 1;
53 betweenChainVariance = 0;
55 withinChainVariance /= (numDraws - 1) * numChains;
56 varianceEstimate = ((numDraws-1) * withinChainVariance + betweenChainVariance) / numDraws;
58 for (
size_t m = 0; m < numChains; ++m) {
62 double rhoHatEven, rhoHatOdd, autocovariance;
63 for (
size_t t = 0; t < numDraws / 2 ; ++t) {
65 for (
size_t m = 0; m < numChains; ++m) {
66 autocovariance += (numDraws - 1) * sampleVariances[m] * autocorrelations[m](2*t);
68 autocovariance /= numChains * numDraws;
73 rhoHatEven = (t == 0 ? 1 : 1 - (withinChainVariance - autocovariance) / varianceEstimate);
76 for (
size_t m = 0; m < numChains; ++m) {
77 autocovariance += (numDraws - 1) * sampleVariances[m] * autocorrelations[m](2*t + 1);
79 autocovariance /= numChains * numDraws;
83 rhoHatOdd = 1 - (withinChainVariance - autocovariance) / varianceEstimate;
86 if (rhoHatEven + rhoHatOdd <= 0) {
90 rhoHat.push_back(rhoHatEven);
91 rhoHat.push_back(rhoHatOdd);
95 rhoHat.push_back(rhoHatEven);
106 for (
size_t t = 1; t < (rhoHat.size() - 2) / 2; ++t) {
107 if (rhoHat[2*t] + rhoHat[2*t+1] > rhoHat[2*t-2] + rhoHat[2*t-1]) {
108 rhoHat[2*t] = (rhoHat[2*t-2] + rhoHat[2*t-1]) / 2;
109 rhoHat[2*t+1] = rhoHat[2*t];
113 for (
size_t t = 0; t < rhoHat.size() / 2; ++t) {
114 tauHat += 2 * (rhoHat[2*t] + rhoHat[2*t + 1]);
118 if (rhoHat.size() % 2) {
119 tauHat += rhoHat.back();
126 return std::min(numDraws * numChains / tauHat, numDraws * numChains * std::log10(numDraws * numChains));
129 template <
typename StateType>
131 std::vector<double> ess;
132 for (
long d = 0; d < (*chains[0])[0].size(); ++d) {
139 template <
typename StateType>
141 std::vector<const std::vector<StateType>*> chainsPtrArray;
142 for (
auto& chain : chains) {
143 chainsPtrArray.push_back(&chain);
145 return computeEffectiveSampleSize<StateType>(chainsPtrArray, dimension);
148 template <
typename StateType>
150 std::vector<const std::vector<StateType>*> chainsPtrArray;
151 for (
auto& chain : chains) {
152 chainsPtrArray.push_back(&chain);
154 return computeEffectiveSampleSize<StateType>(chainsPtrArray);
158 #endif // HOPS_EFFECTIVESAMPLESIZE_HPP