From 88173ccc7bd2d4d24f87045d364cf9896503fb56 Mon Sep 17 00:00:00 2001 From: aleksgorica Date: Tue, 30 Jan 2024 11:06:42 +0100 Subject: [PATCH 01/25] newrhat --- .../compute_potential_scale_reduction.hpp | 137 +++++++++++++++--- 1 file changed, 113 insertions(+), 24 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index 5ae43c8205..25675b0e8c 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -16,6 +17,101 @@ namespace stan { namespace analyze { +inline double median( Eigen::MatrixXd d){ + auto r { d.reshaped() }; + std::sort( r.begin(), r.end() ); + return r.size() % 2 == 0 ? + r.segment( (r.size()-2)/2, 2 ).mean() : + r( r.size()/2 ); +} + +Eigen::MatrixXd rankTransform(const Eigen::MatrixXd& matrix) { + int rows = matrix.rows(); + int cols = matrix.cols(); + int size = rows * cols; + Eigen::MatrixXd rankMatrix = Eigen::MatrixXd::Zero(rows, cols); + + // Create a vector of pairs (value, original index) + std::vector> valueWithIndex(size); + + for (int col = 0; col < cols; ++col) { + for (int row = 0; row < rows; ++row) { + int index = col * rows + row; // Calculating linear index in column-major order + valueWithIndex[index] = {matrix(row, col), index}; + } + } + + // Sorting the pairs by value + std::sort(valueWithIndex.begin(), valueWithIndex.end()); + + // Assigning average ranks + for (int i = 0; i < size; ++i) { + // Handle ties by averaging ranks + int j = i; + double sumRanks = 0; + int count = 0; + + while (j < size && valueWithIndex[j].first == valueWithIndex[i].first) { + sumRanks += j + 1; // Rank starts from 1 + ++j; + ++count; + } + + double avgRank = sumRanks / count; + for (int k = i; k < j; ++k) { + int index = valueWithIndex[k].second; + int row = index % rows; // Adjusting row index for column-major order + int col = index / rows; // Adjusting column index for column-major order + rankMatrix(row, col) = (avgRank - 3.0/8.0) / (size - 2.0 * 3.0/8.0 + 1.0); + + } + i = j - 1; // Skip over tied elements + } + + auto ndtri = [](double p) { + boost::math::normal_distribution dist; // Standard normal distribution + return boost::math::quantile(dist, p); // Inverse CDF (quantile function) + }; + + rankMatrix = rankMatrix.unaryExpr(ndtri); + return rankMatrix; +} + + +inline double rhat(const Eigen::MatrixXd& draws) { + using boost::accumulators::accumulator_set; + using boost::accumulators::stats; + using boost::accumulators::tag::mean; + using boost::accumulators::tag::variance; + + int num_chains = draws.cols(); + int num_draws = draws.rows(); + std::cout << num_chains << " " << num_draws << std::endl; + Eigen::VectorXd chain_mean(num_chains); + accumulator_set> acc_chain_mean; + Eigen::VectorXd chain_var(num_chains); + double unbiased_var_scale = num_draws / (num_draws - 1.0); + for (int chain = 0; chain < num_chains; ++chain) { + accumulator_set> acc_draw; + for (int n = 0; n < num_draws; ++n) { + acc_draw(draws(n, chain)); + } + chain_mean(chain) = boost::accumulators::mean(acc_draw); + acc_chain_mean(chain_mean(chain)); + chain_var(chain) = boost::accumulators::variance(acc_draw) * unbiased_var_scale; + } + + double var_between = num_draws * boost::accumulators::variance(acc_chain_mean) + * num_chains / (num_chains - 1); + double var_within = chain_var.mean(); + + // rewrote [(n-1)*W/n + B/n]/W as (n-1+ B/W)/n + return sqrt((var_between / var_within + num_draws - 1) / num_draws); +} + + + + /** * Computes the potential scale reduction (Rhat) for the specified * parameter across all kept samples. @@ -31,8 +127,14 @@ namespace analyze { * @param sizes stores sizes of chains * @return potential scale reduction for the specified parameter */ + + inline double compute_potential_scale_reduction( std::vector draws, std::vector sizes) { + std::cout << "DRAWS POINTERS: " << std::endl; + for (int i = 0; i < draws.size(); ++i) { + std::cout << "Index: " << i << " P: " << draws[i] << " EXPECTED END: " << draws[i] + sizes[i] << std::endl; + } int num_chains = sizes.size(); size_t num_draws = sizes[0]; if (num_draws == 0) { @@ -71,35 +173,22 @@ inline double compute_potential_scale_reduction( } } - using boost::accumulators::accumulator_set; - using boost::accumulators::stats; - using boost::accumulators::tag::mean; - using boost::accumulators::tag::variance; - - Eigen::VectorXd chain_mean(num_chains); - accumulator_set> acc_chain_mean; - Eigen::VectorXd chain_var(num_chains); - double unbiased_var_scale = num_draws / (num_draws - 1.0); + Eigen::MatrixXd matrix(num_draws, num_chains); - for (int chain = 0; chain < num_chains; ++chain) { - accumulator_set> acc_draw; - for (int n = 0; n < num_draws; ++n) { - acc_draw(draws[chain][n]); + // Copy data from arrays to matrix + for (int col = 0; col < num_chains; ++col) { + for (int row = 0; row < num_draws; ++row) { + matrix(row, col) = draws[col][row]; + } } - chain_mean(chain) = boost::accumulators::mean(acc_draw); - acc_chain_mean(chain_mean(chain)); - chain_var(chain) - = boost::accumulators::variance(acc_draw) * unbiased_var_scale; - } + double rhat_bulk = rhat(rankTransform(matrix)); + double rhat_tail = rhat(rankTransform((matrix.array() - median(matrix)).abs())); + return std::max(rhat_bulk, rhat_tail); +} + - double var_between = num_draws * boost::accumulators::variance(acc_chain_mean) - * num_chains / (num_chains - 1); - double var_within = chain_var.mean(); - // rewrote [(n-1)*W/n + B/n]/W as (n-1+ B/W)/n - return sqrt((var_between / var_within + num_draws - 1) / num_draws); -} /** * Computes the potential scale reduction (Rhat) for the specified From 98450d76a1cbb37513dc0cd205649a7e464353be Mon Sep 17 00:00:00 2001 From: aleksgorica Date: Wed, 31 Jan 2024 12:37:11 +0100 Subject: [PATCH 02/25] resolved some of pr1 --- .../compute_potential_scale_reduction.hpp | 82 ++++++++++--------- 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index 25675b0e8c..a908d7f25e 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -17,17 +17,18 @@ namespace stan { namespace analyze { -inline double median( Eigen::MatrixXd d){ - auto r { d.reshaped() }; - std::sort( r.begin(), r.end() ); - return r.size() % 2 == 0 ? - r.segment( (r.size()-2)/2, 2 ).mean() : - r( r.size()/2 ); -} -Eigen::MatrixXd rankTransform(const Eigen::MatrixXd& matrix) { - int rows = matrix.rows(); - int cols = matrix.cols(); +/** + * Computes normalized average ranks for draws. Transforming them to normal scores using inverse normal transformation and a fractional offset. + * Based on paper https://arxiv.org/abs/1903.08008 + * @param draws stores chains in columns + * @return normal scores for average ranks of draws + * + */ + +Eigen::MatrixXd rank_transform(const Eigen::MatrixXd& draws) { + int rows = draws.rows(); + int cols = draws.cols(); int size = rows * cols; Eigen::MatrixXd rankMatrix = Eigen::MatrixXd::Zero(rows, cols); @@ -37,11 +38,10 @@ Eigen::MatrixXd rankTransform(const Eigen::MatrixXd& matrix) { for (int col = 0; col < cols; ++col) { for (int row = 0; row < rows; ++row) { int index = col * rows + row; // Calculating linear index in column-major order - valueWithIndex[index] = {matrix(row, col), index}; + valueWithIndex[index] = {draws(row, col), index}; } } - // Sorting the pairs by value std::sort(valueWithIndex.begin(), valueWithIndex.end()); // Assigning average ranks @@ -58,41 +58,51 @@ Eigen::MatrixXd rankTransform(const Eigen::MatrixXd& matrix) { } double avgRank = sumRanks / count; + boost::math::normal_distribution dist; // Standard normal distribution for (int k = i; k < j; ++k) { int index = valueWithIndex[k].second; int row = index % rows; // Adjusting row index for column-major order int col = index / rows; // Adjusting column index for column-major order - rankMatrix(row, col) = (avgRank - 3.0/8.0) / (size - 2.0 * 3.0/8.0 + 1.0); - + double p = (avgRank - 3.0/8.0) / (size - 2.0 * 3.0/8.0 + 1.0); + rankMatrix(row, col) = boost::math::quantile(dist, p); } i = j - 1; // Skip over tied elements } - auto ndtri = [](double p) { - boost::math::normal_distribution dist; // Standard normal distribution - return boost::math::quantile(dist, p); // Inverse CDF (quantile function) - }; - rankMatrix = rankMatrix.unaryExpr(ndtri); - return rankMatrix; + // Eigen::MatrixXd mat(3, 3); + // mat << 9, 3, 6, + // 4, 7, 2, + // 5, 2, 8; + // // Print the original matrix + // std::cout << "Original matrix:\n" << mat << "\n\n"; + // Eigen::Map vec(mat.data(), mat.size()); + // std::cout << "vec:\n" << vec << std::endl; + // // Use stan::math::sort_indices_asc to get the sorting indices + // std::vector ranks = math::sort_indices_asc(vec); + // Eigen::Map eigen_vec(ranks.data(), ranks.size()); + + // std::cout << "Sorted indices:\n" << eigen_vec << std::endl; + return rankMatrix; } - -inline double rhat(const Eigen::MatrixXd& draws) { - using boost::accumulators::accumulator_set; - using boost::accumulators::stats; - using boost::accumulators::tag::mean; - using boost::accumulators::tag::variance; +/** + * Computes square root of marginal posterior variance of the estimand by weigted average of within-chain variance W and between-chain variance B. + * + * @param draws stores chains in columns + * @return square root of ((N-1)/N)W + B/N + * + */ +inline double rhat(const Eigen::MatrixXd& draws) { int num_chains = draws.cols(); int num_draws = draws.rows(); - std::cout << num_chains << " " << num_draws << std::endl; Eigen::VectorXd chain_mean(num_chains); - accumulator_set> acc_chain_mean; + boost::accumulators::accumulator_set> acc_chain_mean; Eigen::VectorXd chain_var(num_chains); double unbiased_var_scale = num_draws / (num_draws - 1.0); for (int chain = 0; chain < num_chains; ++chain) { - accumulator_set> acc_draw; + boost::accumulators::accumulator_set> acc_draw; for (int n = 0; n < num_draws; ++n) { acc_draw(draws(n, chain)); } @@ -105,7 +115,6 @@ inline double rhat(const Eigen::MatrixXd& draws) { * num_chains / (num_chains - 1); double var_within = chain_var.mean(); - // rewrote [(n-1)*W/n + B/n]/W as (n-1+ B/W)/n return sqrt((var_between / var_within + num_draws - 1) / num_draws); } @@ -128,13 +137,9 @@ inline double rhat(const Eigen::MatrixXd& draws) { * @return potential scale reduction for the specified parameter */ - inline double compute_potential_scale_reduction( std::vector draws, std::vector sizes) { - std::cout << "DRAWS POINTERS: " << std::endl; - for (int i = 0; i < draws.size(); ++i) { - std::cout << "Index: " << i << " P: " << draws[i] << " EXPECTED END: " << draws[i] + sizes[i] << std::endl; - } + int num_chains = sizes.size(); size_t num_draws = sizes[0]; if (num_draws == 0) { @@ -175,15 +180,16 @@ inline double compute_potential_scale_reduction( Eigen::MatrixXd matrix(num_draws, num_chains); - // Copy data from arrays to matrix for (int col = 0; col < num_chains; ++col) { for (int row = 0; row < num_draws; ++row) { matrix(row, col) = draws[col][row]; } } - double rhat_bulk = rhat(rankTransform(matrix)); - double rhat_tail = rhat(rankTransform((matrix.array() - median(matrix)).abs())); + double rhat_bulk = rhat(rank_transform(matrix)); + double rhat_tail = rhat(rank_transform((matrix.array() - math::quantile(matrix.reshaped() , 0.5)).abs())); + + std::cout << "bulk, tail: " << rhat_bulk << " " << rhat_tail << std::endl; return std::max(rhat_bulk, rhat_tail); } From b09f512ababb354ae7afa74f8c523bdff476509e Mon Sep 17 00:00:00 2001 From: aleksgorica Date: Wed, 31 Jan 2024 18:02:00 +0100 Subject: [PATCH 03/25] comments deleted --- .../mcmc/compute_potential_scale_reduction.hpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index a908d7f25e..1081cc1145 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -32,7 +32,6 @@ Eigen::MatrixXd rank_transform(const Eigen::MatrixXd& draws) { int size = rows * cols; Eigen::MatrixXd rankMatrix = Eigen::MatrixXd::Zero(rows, cols); - // Create a vector of pairs (value, original index) std::vector> valueWithIndex(size); for (int col = 0; col < cols; ++col) { @@ -68,21 +67,6 @@ Eigen::MatrixXd rank_transform(const Eigen::MatrixXd& draws) { } i = j - 1; // Skip over tied elements } - - - // Eigen::MatrixXd mat(3, 3); - // mat << 9, 3, 6, - // 4, 7, 2, - // 5, 2, 8; - // // Print the original matrix - // std::cout << "Original matrix:\n" << mat << "\n\n"; - // Eigen::Map vec(mat.data(), mat.size()); - // std::cout << "vec:\n" << vec << std::endl; - // // Use stan::math::sort_indices_asc to get the sorting indices - // std::vector ranks = math::sort_indices_asc(vec); - // Eigen::Map eigen_vec(ranks.data(), ranks.size()); - - // std::cout << "Sorted indices:\n" << eigen_vec << std::endl; return rankMatrix; } From dcd21f2eec34810a43def6626d9fa90e98cf6238 Mon Sep 17 00:00:00 2001 From: aleksgorica Date: Thu, 1 Feb 2024 13:55:07 +0100 Subject: [PATCH 04/25] Test changed --- .../compute_potential_scale_reduction.hpp | 1 - ...compute_potential_scale_reduction_test.cpp | 70 ++++++++----------- 2 files changed, 30 insertions(+), 41 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index 1081cc1145..d2104e45e3 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -173,7 +173,6 @@ inline double compute_potential_scale_reduction( double rhat_bulk = rhat(rank_transform(matrix)); double rhat_tail = rhat(rank_transform((matrix.array() - math::quantile(matrix.reshaped() , 0.5)).abs())); - std::cout << "bulk, tail: " << rhat_bulk << " " << rhat_tail << std::endl; return std::max(rhat_bulk, rhat_tail); } diff --git a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp index 9e4df6d09f..7ea51847ed 100644 --- a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp +++ b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp @@ -32,13 +32,11 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, - 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, - 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, - 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, - 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, - 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, - 1.00735; + rhat << 1.00067, 1.00497, 1.00918, 1.00055, 1.0015, 1.00088, 1.00776, 1.00042, 1.00201, + 0.999558, 0.99984, 1.00054, 1.00403, 1.00516, 1.00591, 1.00627, 1.00134, 1.00895, + 1.00079, 1.00368, 1.00092, 1.00133, 1.01005, 1.00107, 1.00151, 1.00229, 0.999998, + 1.00008, 1.00315, 1.00277, 1.00247, 1.00003, 1.001, 1.01267, 1.00011, 1.00066, 1.00091, + 1.00237, 1.00019, 1.00104, 1.00341, 0.999815, 1.00033, 0.999672, 1.00306, 1.00072, 1.00191, 1.00658; // replicates calls to stan::analyze::compute_effective_sample_size // for any interface *without* access to chains class @@ -54,7 +52,7 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction) { } ASSERT_NEAR(rhat(index - 4), stan::analyze::compute_potential_scale_reduction(draws, sizes), - 1.0) + 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); } @@ -72,13 +70,11 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_convenience) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, - 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, - 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, - 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, - 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, - 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, - 1.00735; + rhat << 1.00067, 1.00497, 1.00918, 1.00055, 1.0015, 1.00088, 1.00776, 1.00042, 1.00201, + 0.999558, 0.99984, 1.00054, 1.00403, 1.00516, 1.00591, 1.00627, 1.00134, 1.00895, + 1.00079, 1.00368, 1.00092, 1.00133, 1.01005, 1.00107, 1.00151, 1.00229, 0.999998, + 1.00008, 1.00315, 1.00277, 1.00247, 1.00003, 1.001, 1.01267, 1.00011, 1.00066, 1.00091, + 1.00237, 1.00019, 1.00104, 1.00341, 0.999815, 1.00033, 0.999672, 1.00306, 1.00072, 1.00191, 1.00658; Eigen::Matrix samples( chains.num_chains()); @@ -92,13 +88,13 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_convenience) { size_t size = samples(0).size(); ASSERT_NEAR(rhat(index - 4), stan::analyze::compute_potential_scale_reduction(draws, size), - 1.0) + 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); } } -TEST_F(ComputeRhat, chains_compute_potential_scale_reduction) { +TEST_F(ComputeRhat, chains_compute_split_potential_scale_reduction) { std::stringstream out; stan::io::stan_csv blocker1 = stan::io::stan_csv_reader::parse(blocker1_stream, &out); @@ -110,13 +106,11 @@ TEST_F(ComputeRhat, chains_compute_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, - 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, - 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, - 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, - 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, - 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, - 1.00735; + rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, 1.00095, 1.00906, + 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, + 1.00303, 1.00976, 1.00295, 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, + 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, 1.00381, 1.00283, 1.00188, + 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; for (int index = 4; index < chains.num_params(); index++) { ASSERT_NEAR(rhat(index - 4), chains.split_potential_scale_reduction(index), @@ -145,13 +139,11 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, - 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, - 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, - 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, - 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, - 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, - 1.00735; + rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, 1.00095, 1.00906, + 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, + 1.00303, 1.00976, 1.00295, 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, + 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, 1.00381, 1.00283, 1.00188, + 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; // replicates calls to stan::analyze::compute_effective_sample_size // for any interface *without* access to chains class @@ -168,7 +160,7 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction) { ASSERT_NEAR( rhat(index - 4), stan::analyze::compute_split_potential_scale_reduction(draws, sizes), - 1.0) + 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); } @@ -186,13 +178,11 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, - 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, - 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, - 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, - 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, - 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, - 1.00735; + rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, 1.00095, 1.00906, + 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, + 1.00303, 1.00976, 1.00295, 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, + 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, 1.00381, 1.00283, 1.00188, + 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; Eigen::Matrix samples( chains.num_chains()); @@ -207,7 +197,7 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience) { ASSERT_NEAR( rhat(index - 4), stan::analyze::compute_split_potential_scale_reduction(draws, size), - 1.0) + 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); } From c20ce616e8d313abb1c38898506cb3a94e2db27f Mon Sep 17 00:00:00 2001 From: aleksgorica Date: Sun, 4 Feb 2024 15:10:53 +0100 Subject: [PATCH 05/25] chains_test modified --- src/test/unit/mcmc/chains_test.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/test/unit/mcmc/chains_test.cpp b/src/test/unit/mcmc/chains_test.cpp index 987279de66..65b3d6d962 100644 --- a/src/test/unit/mcmc/chains_test.cpp +++ b/src/test/unit/mcmc/chains_test.cpp @@ -854,13 +854,11 @@ TEST_F(McmcChains, blocker_split_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, - 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, - 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, - 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, - 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, - 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, - 1.00735; + rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, 1.00095, 1.00906, + 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, + 1.00303, 1.00976, 1.00295, 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, + 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, 1.00381, 1.00283, 1.00188, + 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; for (int index = 4; index < chains.num_params(); index++) { ASSERT_NEAR(rhat(index - 4), chains.split_potential_scale_reduction(index), From 5630c51d0c4e0977ccf8ef003fb3a50af9611dc1 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 6 Feb 2024 16:45:13 -0500 Subject: [PATCH 06/25] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- .../compute_potential_scale_reduction.hpp | 126 +++++++++--------- ...compute_potential_scale_reduction_test.cpp | 55 ++++---- src/test/unit/mcmc/chains_test.cpp | 11 +- 3 files changed, 100 insertions(+), 92 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index d2104e45e3..17a0197104 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -17,82 +17,90 @@ namespace stan { namespace analyze { - /** - * Computes normalized average ranks for draws. Transforming them to normal scores using inverse normal transformation and a fractional offset. - * Based on paper https://arxiv.org/abs/1903.08008 + * Computes normalized average ranks for draws. Transforming them to normal + * scores using inverse normal transformation and a fractional offset. Based on + * paper https://arxiv.org/abs/1903.08008 * @param draws stores chains in columns * @return normal scores for average ranks of draws - * + * */ Eigen::MatrixXd rank_transform(const Eigen::MatrixXd& draws) { - int rows = draws.rows(); - int cols = draws.cols(); - int size = rows * cols; - Eigen::MatrixXd rankMatrix = Eigen::MatrixXd::Zero(rows, cols); - - std::vector> valueWithIndex(size); - - for (int col = 0; col < cols; ++col) { - for (int row = 0; row < rows; ++row) { - int index = col * rows + row; // Calculating linear index in column-major order - valueWithIndex[index] = {draws(row, col), index}; - } + int rows = draws.rows(); + int cols = draws.cols(); + int size = rows * cols; + Eigen::MatrixXd rankMatrix = Eigen::MatrixXd::Zero(rows, cols); + + std::vector> valueWithIndex(size); + + for (int col = 0; col < cols; ++col) { + for (int row = 0; row < rows; ++row) { + int index + = col * rows + row; // Calculating linear index in column-major order + valueWithIndex[index] = {draws(row, col), index}; + } + } + + std::sort(valueWithIndex.begin(), valueWithIndex.end()); + + // Assigning average ranks + for (int i = 0; i < size; ++i) { + // Handle ties by averaging ranks + int j = i; + double sumRanks = 0; + int count = 0; + + while (j < size && valueWithIndex[j].first == valueWithIndex[i].first) { + sumRanks += j + 1; // Rank starts from 1 + ++j; + ++count; } - std::sort(valueWithIndex.begin(), valueWithIndex.end()); - - // Assigning average ranks - for (int i = 0; i < size; ++i) { - // Handle ties by averaging ranks - int j = i; - double sumRanks = 0; - int count = 0; - - while (j < size && valueWithIndex[j].first == valueWithIndex[i].first) { - sumRanks += j + 1; // Rank starts from 1 - ++j; - ++count; - } - - double avgRank = sumRanks / count; - boost::math::normal_distribution dist; // Standard normal distribution - for (int k = i; k < j; ++k) { - int index = valueWithIndex[k].second; - int row = index % rows; // Adjusting row index for column-major order - int col = index / rows; // Adjusting column index for column-major order - double p = (avgRank - 3.0/8.0) / (size - 2.0 * 3.0/8.0 + 1.0); - rankMatrix(row, col) = boost::math::quantile(dist, p); - } - i = j - 1; // Skip over tied elements + double avgRank = sumRanks / count; + boost::math::normal_distribution + dist; // Standard normal distribution + for (int k = i; k < j; ++k) { + int index = valueWithIndex[k].second; + int row = index % rows; // Adjusting row index for column-major order + int col = index / rows; // Adjusting column index for column-major order + double p = (avgRank - 3.0 / 8.0) / (size - 2.0 * 3.0 / 8.0 + 1.0); + rankMatrix(row, col) = boost::math::quantile(dist, p); } - return rankMatrix; + i = j - 1; // Skip over tied elements + } + return rankMatrix; } - /** - * Computes square root of marginal posterior variance of the estimand by weigted average of within-chain variance W and between-chain variance B. - * + * Computes square root of marginal posterior variance of the estimand by + * weigted average of within-chain variance W and between-chain variance B. + * * @param draws stores chains in columns * @return square root of ((N-1)/N)W + B/N - * + * */ inline double rhat(const Eigen::MatrixXd& draws) { int num_chains = draws.cols(); int num_draws = draws.rows(); Eigen::VectorXd chain_mean(num_chains); - boost::accumulators::accumulator_set> acc_chain_mean; + boost::accumulators::accumulator_set< + double, boost::accumulators::stats> + acc_chain_mean; Eigen::VectorXd chain_var(num_chains); double unbiased_var_scale = num_draws / (num_draws - 1.0); for (int chain = 0; chain < num_chains; ++chain) { - boost::accumulators::accumulator_set> acc_draw; + boost::accumulators::accumulator_set< + double, boost::accumulators::stats> + acc_draw; for (int n = 0; n < num_draws; ++n) { acc_draw(draws(n, chain)); } chain_mean(chain) = boost::accumulators::mean(acc_draw); acc_chain_mean(chain_mean(chain)); - chain_var(chain) = boost::accumulators::variance(acc_draw) * unbiased_var_scale; + chain_var(chain) + = boost::accumulators::variance(acc_draw) * unbiased_var_scale; } double var_between = num_draws * boost::accumulators::variance(acc_chain_mean) @@ -102,9 +110,6 @@ inline double rhat(const Eigen::MatrixXd& draws) { return sqrt((var_between / var_within + num_draws - 1) / num_draws); } - - - /** * Computes the potential scale reduction (Rhat) for the specified * parameter across all kept samples. @@ -123,7 +128,6 @@ inline double rhat(const Eigen::MatrixXd& draws) { inline double compute_potential_scale_reduction( std::vector draws, std::vector sizes) { - int num_chains = sizes.size(); size_t num_draws = sizes[0]; if (num_draws == 0) { @@ -164,21 +168,19 @@ inline double compute_potential_scale_reduction( Eigen::MatrixXd matrix(num_draws, num_chains); - for (int col = 0; col < num_chains; ++col) { - for (int row = 0; row < num_draws; ++row) { - matrix(row, col) = draws[col][row]; - } + for (int col = 0; col < num_chains; ++col) { + for (int row = 0; row < num_draws; ++row) { + matrix(row, col) = draws[col][row]; } + } double rhat_bulk = rhat(rank_transform(matrix)); - double rhat_tail = rhat(rank_transform((matrix.array() - math::quantile(matrix.reshaped() , 0.5)).abs())); - + double rhat_tail = rhat(rank_transform( + (matrix.array() - math::quantile(matrix.reshaped(), 0.5)).abs())); + return std::max(rhat_bulk, rhat_tail); } - - - /** * Computes the potential scale reduction (Rhat) for the specified * parameter across all kept samples. diff --git a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp index 7ea51847ed..2f64f659eb 100644 --- a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp +++ b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp @@ -32,11 +32,12 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00067, 1.00497, 1.00918, 1.00055, 1.0015, 1.00088, 1.00776, 1.00042, 1.00201, - 0.999558, 0.99984, 1.00054, 1.00403, 1.00516, 1.00591, 1.00627, 1.00134, 1.00895, - 1.00079, 1.00368, 1.00092, 1.00133, 1.01005, 1.00107, 1.00151, 1.00229, 0.999998, - 1.00008, 1.00315, 1.00277, 1.00247, 1.00003, 1.001, 1.01267, 1.00011, 1.00066, 1.00091, - 1.00237, 1.00019, 1.00104, 1.00341, 0.999815, 1.00033, 0.999672, 1.00306, 1.00072, 1.00191, 1.00658; + rhat << 1.00067, 1.00497, 1.00918, 1.00055, 1.0015, 1.00088, 1.00776, 1.00042, + 1.00201, 0.999558, 0.99984, 1.00054, 1.00403, 1.00516, 1.00591, 1.00627, + 1.00134, 1.00895, 1.00079, 1.00368, 1.00092, 1.00133, 1.01005, 1.00107, + 1.00151, 1.00229, 0.999998, 1.00008, 1.00315, 1.00277, 1.00247, 1.00003, + 1.001, 1.01267, 1.00011, 1.00066, 1.00091, 1.00237, 1.00019, 1.00104, + 1.00341, 0.999815, 1.00033, 0.999672, 1.00306, 1.00072, 1.00191, 1.00658; // replicates calls to stan::analyze::compute_effective_sample_size // for any interface *without* access to chains class @@ -70,11 +71,12 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_convenience) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00067, 1.00497, 1.00918, 1.00055, 1.0015, 1.00088, 1.00776, 1.00042, 1.00201, - 0.999558, 0.99984, 1.00054, 1.00403, 1.00516, 1.00591, 1.00627, 1.00134, 1.00895, - 1.00079, 1.00368, 1.00092, 1.00133, 1.01005, 1.00107, 1.00151, 1.00229, 0.999998, - 1.00008, 1.00315, 1.00277, 1.00247, 1.00003, 1.001, 1.01267, 1.00011, 1.00066, 1.00091, - 1.00237, 1.00019, 1.00104, 1.00341, 0.999815, 1.00033, 0.999672, 1.00306, 1.00072, 1.00191, 1.00658; + rhat << 1.00067, 1.00497, 1.00918, 1.00055, 1.0015, 1.00088, 1.00776, 1.00042, + 1.00201, 0.999558, 0.99984, 1.00054, 1.00403, 1.00516, 1.00591, 1.00627, + 1.00134, 1.00895, 1.00079, 1.00368, 1.00092, 1.00133, 1.01005, 1.00107, + 1.00151, 1.00229, 0.999998, 1.00008, 1.00315, 1.00277, 1.00247, 1.00003, + 1.001, 1.01267, 1.00011, 1.00066, 1.00091, 1.00237, 1.00019, 1.00104, + 1.00341, 0.999815, 1.00033, 0.999672, 1.00306, 1.00072, 1.00191, 1.00658; Eigen::Matrix samples( chains.num_chains()); @@ -106,11 +108,12 @@ TEST_F(ComputeRhat, chains_compute_split_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, 1.00095, 1.00906, - 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, - 1.00303, 1.00976, 1.00295, 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, - 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, 1.00381, 1.00283, 1.00188, - 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; + rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, + 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, + 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, + 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, + 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, + 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; for (int index = 4; index < chains.num_params(); index++) { ASSERT_NEAR(rhat(index - 4), chains.split_potential_scale_reduction(index), @@ -139,11 +142,12 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, 1.00095, 1.00906, - 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, - 1.00303, 1.00976, 1.00295, 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, - 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, 1.00381, 1.00283, 1.00188, - 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; + rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, + 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, + 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, + 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, + 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, + 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; // replicates calls to stan::analyze::compute_effective_sample_size // for any interface *without* access to chains class @@ -178,11 +182,12 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, 1.00095, 1.00906, - 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, - 1.00303, 1.00976, 1.00295, 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, - 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, 1.00381, 1.00283, 1.00188, - 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; + rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, + 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, + 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, + 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, + 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, + 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; Eigen::Matrix samples( chains.num_chains()); diff --git a/src/test/unit/mcmc/chains_test.cpp b/src/test/unit/mcmc/chains_test.cpp index 8eed679d43..41bd645a75 100644 --- a/src/test/unit/mcmc/chains_test.cpp +++ b/src/test/unit/mcmc/chains_test.cpp @@ -853,11 +853,12 @@ TEST_F(McmcChains, blocker_split_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, 1.00095, 1.00906, - 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, - 1.00303, 1.00976, 1.00295, 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, - 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, 1.00381, 1.00283, 1.00188, - 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; + rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, + 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, + 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, + 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, + 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, + 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; for (int index = 4; index < chains.num_params(); index++) { ASSERT_NEAR(rhat(index - 4), chains.split_potential_scale_reduction(index), From 50617bd3600001a0da1abf94f060073ac82ec102 Mon Sep 17 00:00:00 2001 From: aleksgorica Date: Sun, 11 Feb 2024 14:22:47 +0100 Subject: [PATCH 07/25] Eigen::Index; index without calculating rows, cols; removed online way of calculating variance and averages --- .../compute_potential_scale_reduction.hpp | 83 +++++++------------ 1 file changed, 32 insertions(+), 51 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index 17a0197104..fcc3ee41ce 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -27,45 +27,39 @@ namespace analyze { */ Eigen::MatrixXd rank_transform(const Eigen::MatrixXd& draws) { - int rows = draws.rows(); - int cols = draws.cols(); - int size = rows * cols; - Eigen::MatrixXd rankMatrix = Eigen::MatrixXd::Zero(rows, cols); + const Eigen::Index rows = draws.rows(); + const Eigen::Index cols = draws.cols(); + const Eigen::Index size = rows * cols; - std::vector> valueWithIndex(size); + std::vector> value_with_index(size); - for (int col = 0; col < cols; ++col) { - for (int row = 0; row < rows; ++row) { - int index - = col * rows + row; // Calculating linear index in column-major order - valueWithIndex[index] = {draws(row, col), index}; - } + for (Eigen::Index i = 0; i < size; ++i) { + value_with_index[i] = {draws(i), i}; } - std::sort(valueWithIndex.begin(), valueWithIndex.end()); + std::sort(value_with_index.begin(), value_with_index.end()); + + + Eigen::MatrixXd rankMatrix = Eigen::MatrixXd::Zero(rows, cols); // Assigning average ranks - for (int i = 0; i < size; ++i) { + for (Eigen::Index i = 0; i < size; ++i) { // Handle ties by averaging ranks - int j = i; - double sumRanks = 0; - int count = 0; + Eigen::Index j = i+1; + double sumRanks = j; + Eigen::Index count = 1; - while (j < size && valueWithIndex[j].first == valueWithIndex[i].first) { + while (j < size && value_with_index[j].first == value_with_index[i].first) { sumRanks += j + 1; // Rank starts from 1 ++j; ++count; } - double avgRank = sumRanks / count; - boost::math::normal_distribution - dist; // Standard normal distribution - for (int k = i; k < j; ++k) { - int index = valueWithIndex[k].second; - int row = index % rows; // Adjusting row index for column-major order - int col = index / rows; // Adjusting column index for column-major order + boost::math::normal_distribution dist; + for (std::size_t k = i; k < j; ++k) { + Eigen::Index index = value_with_index[k].second; double p = (avgRank - 3.0 / 8.0) / (size - 2.0 * 3.0 / 8.0 + 1.0); - rankMatrix(row, col) = boost::math::quantile(dist, p); + rankMatrix(index) = boost::math::quantile(dist, p); } i = j - 1; // Skip over tied elements } @@ -73,41 +67,28 @@ Eigen::MatrixXd rank_transform(const Eigen::MatrixXd& draws) { } /** - * Computes square root of marginal posterior variance of the estimand by + * Computes square root of marginal posterior variance of the estimand by the * weigted average of within-chain variance W and between-chain variance B. * * @param draws stores chains in columns * @return square root of ((N-1)/N)W + B/N * */ + inline double rhat(const Eigen::MatrixXd& draws) { - int num_chains = draws.cols(); - int num_draws = draws.rows(); + const Eigen::Index num_chains = draws.cols(); + const Eigen::Index num_draws = draws.rows(); + Eigen::VectorXd chain_mean(num_chains); - boost::accumulators::accumulator_set< - double, boost::accumulators::stats> - acc_chain_mean; - Eigen::VectorXd chain_var(num_chains); - double unbiased_var_scale = num_draws / (num_draws - 1.0); - for (int chain = 0; chain < num_chains; ++chain) { - boost::accumulators::accumulator_set< - double, boost::accumulators::stats> - acc_draw; - for (int n = 0; n < num_draws; ++n) { - acc_draw(draws(n, chain)); - } - chain_mean(chain) = boost::accumulators::mean(acc_draw); - acc_chain_mean(chain_mean(chain)); - chain_var(chain) - = boost::accumulators::variance(acc_draw) * unbiased_var_scale; + chain_mean = draws.colwise().mean(); + double total_mean = chain_mean.mean(); + double var_between = num_draws * (chain_mean.array() - total_mean).square().sum() / (num_chains-1); + double var_sum = 0; + for (Eigen::Index col = 0; col < num_chains; ++col) { + var_sum += (draws.col(col).array() - chain_mean(col)).square().sum() / (num_draws - 1); } - - double var_between = num_draws * boost::accumulators::variance(acc_chain_mean) - * num_chains / (num_chains - 1); - double var_within = chain_var.mean(); - - return sqrt((var_between / var_within + num_draws - 1) / num_draws); + double var_within = var_sum / num_chains; + return sqrt((var_between / var_within + num_draws - 1) / num_draws); } /** From dc130f84ab476d648e43c201f713be4707ae3fcc Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 11 Feb 2024 08:24:13 -0500 Subject: [PATCH 08/25] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- .../mcmc/compute_potential_scale_reduction.hpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index fcc3ee41ce..dfce574666 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -39,13 +39,12 @@ Eigen::MatrixXd rank_transform(const Eigen::MatrixXd& draws) { std::sort(value_with_index.begin(), value_with_index.end()); - Eigen::MatrixXd rankMatrix = Eigen::MatrixXd::Zero(rows, cols); // Assigning average ranks for (Eigen::Index i = 0; i < size; ++i) { // Handle ties by averaging ranks - Eigen::Index j = i+1; + Eigen::Index j = i + 1; double sumRanks = j; Eigen::Index count = 1; @@ -55,7 +54,7 @@ Eigen::MatrixXd rank_transform(const Eigen::MatrixXd& draws) { ++count; } double avgRank = sumRanks / count; - boost::math::normal_distribution dist; + boost::math::normal_distribution dist; for (std::size_t k = i; k < j; ++k) { Eigen::Index index = value_with_index[k].second; double p = (avgRank - 3.0 / 8.0) / (size - 2.0 * 3.0 / 8.0 + 1.0); @@ -82,13 +81,16 @@ inline double rhat(const Eigen::MatrixXd& draws) { Eigen::VectorXd chain_mean(num_chains); chain_mean = draws.colwise().mean(); double total_mean = chain_mean.mean(); - double var_between = num_draws * (chain_mean.array() - total_mean).square().sum() / (num_chains-1); + double var_between = num_draws + * (chain_mean.array() - total_mean).square().sum() + / (num_chains - 1); double var_sum = 0; for (Eigen::Index col = 0; col < num_chains; ++col) { - var_sum += (draws.col(col).array() - chain_mean(col)).square().sum() / (num_draws - 1); + var_sum += (draws.col(col).array() - chain_mean(col)).square().sum() + / (num_draws - 1); } double var_within = var_sum / num_chains; - return sqrt((var_between / var_within + num_draws - 1) / num_draws); + return sqrt((var_between / var_within + num_draws - 1) / num_draws); } /** From 3433d9c7dfc91ab364d0c8b4e199812d9c5aaa89 Mon Sep 17 00:00:00 2001 From: aleksgorica Date: Mon, 26 Feb 2024 11:33:55 +0100 Subject: [PATCH 09/25] duplicated functions and test for rank version of compute_potential_scale_reduction --- .../compute_potential_scale_reduction.hpp | 158 +++++++++++- src/stan/mcmc/chains.hpp | 19 ++ ...compute_potential_scale_reduction_test.cpp | 238 +++++++++++++++++- 3 files changed, 404 insertions(+), 11 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index fcc3ee41ce..99afda60dc 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -91,6 +91,75 @@ inline double rhat(const Eigen::MatrixXd& draws) { return sqrt((var_between / var_within + num_draws - 1) / num_draws); } + +/** + * Computes the potential scale reduction (Rhat) using rank based diagnostic for the specified + * parameter across all kept samples. + * Based on paper https://arxiv.org/abs/1903.08008 + * + * Current implementation assumes draws are stored in contiguous + * blocks of memory. Chains are trimmed from the back to match the + * length of the shortest chain. + * + * @param draws stores pointers to arrays of chains + * @param sizes stores sizes of chains + * @return potential scale reduction for the specified parameter + */ +inline double compute_potential_scale_reduction_rank(std::vector draws, std::vector sizes) { +int num_chains = sizes.size(); + size_t num_draws = sizes[0]; + if (num_draws == 0) { + return std::numeric_limits::quiet_NaN(); + } + for (int chain = 1; chain < num_chains; ++chain) { + num_draws = std::min(num_draws, sizes[chain]); + } + + // check if chains are constant; all equal to first draw's value + bool are_all_const = false; + Eigen::VectorXd init_draw = Eigen::VectorXd::Zero(num_chains); + + for (int chain = 0; chain < num_chains; chain++) { + Eigen::Map> draw( + draws[chain], sizes[chain]); + + for (int n = 0; n < num_draws; n++) { + if (!std::isfinite(draw(n))) { + return std::numeric_limits::quiet_NaN(); + } + } + + init_draw(chain) = draw(0); + + if (draw.isApproxToConstant(draw(0))) { + are_all_const |= true; + } + } + + if (are_all_const) { + // If all chains are constant then return NaN + // if they all equal the same constant value + if (init_draw.isApproxToConstant(init_draw(0))) { + return std::numeric_limits::quiet_NaN(); + } + } + + Eigen::MatrixXd matrix(num_draws, num_chains); + + for (int col = 0; col < num_chains; ++col) { + for (int row = 0; row < num_draws; ++row) { + matrix(row, col) = draws[col][row]; + } + } + + double rhat_bulk = rhat(rank_transform(matrix)); + double rhat_tail = rhat(rank_transform( + (matrix.array() - math::quantile(matrix.reshaped(), 0.5)).abs())); + + return std::max(rhat_bulk, rhat_tail); +} + + /** * Computes the potential scale reduction (Rhat) for the specified * parameter across all kept samples. @@ -155,11 +224,31 @@ inline double compute_potential_scale_reduction( } } - double rhat_bulk = rhat(rank_transform(matrix)); - double rhat_tail = rhat(rank_transform( - (matrix.array() - math::quantile(matrix.reshaped(), 0.5)).abs())); + return rhat(matrix); +} - return std::max(rhat_bulk, rhat_tail); +/** + * Computes the potential scale reduction (Rhat) using rank based diagnostic for the specified + * parameter across all kept samples. + * Based on paper https://arxiv.org/abs/1903.08008 + * + * See more details in Stan reference manual section "Potential + * Scale Reduction". http://mc-stan.org/users/documentation + * + * Current implementation assumes draws are stored in contiguous + * blocks of memory. Chains are trimmed from the back to match the + * length of the shortest chain. Argument size will be broadcast to + * same length as draws. + * + * @param draws stores pointers to arrays of chains + * @param size stores sizes of chains + * @return potential scale reduction for the specified parameter + */ +inline double compute_potential_scale_reduction_rank( + std::vector draws, size_t size) { + int num_chains = draws.size(); + std::vector sizes(num_chains, size); + return compute_potential_scale_reduction_rank(draws, sizes); } /** @@ -185,6 +274,41 @@ inline double compute_potential_scale_reduction( return compute_potential_scale_reduction(draws, sizes); } + +/** + * Computes the potential scale reduction (Rhat) using rank based diagnostic for the specified + * parameter across all kept samples. + * Based on paper https://arxiv.org/abs/1903.08008 + * + * When the number of total draws N is odd, the (N+1)/2th draw is ignored. + * + * See more details in Stan reference manual section "Potential + * Scale Reduction". http://mc-stan.org/users/documentation + * + * Current implementation assumes draws are stored in contiguous + * blocks of memory. Chains are trimmed from the back to match the + * length of the shortest chain. + * + * @param draws stores pointers to arrays of chains + * @param sizes stores sizes of chains + * @return potential scale reduction for the specified parameter + */ +inline double compute_split_potential_scale_reduction_rank( + std::vector draws, std::vector sizes) { + int num_chains = sizes.size(); + size_t num_draws = sizes[0]; + for (int chain = 1; chain < num_chains; ++chain) { + num_draws = std::min(num_draws, sizes[chain]); + } + + std::vector split_draws = split_chains(draws, sizes); + + double half = num_draws / 2.0; + std::vector half_sizes(2 * num_chains, std::floor(half)); + + return compute_potential_scale_reduction_rank(split_draws, half_sizes); +} + /** * Computes the split potential scale reduction (Rhat) for the * specified parameter across all kept samples. When the number of @@ -217,6 +341,32 @@ inline double compute_split_potential_scale_reduction( return compute_potential_scale_reduction(split_draws, half_sizes); } +/** + * Computes the potential scale reduction (Rhat) using rank based diagnostic for the specified + * parameter across all kept samples. + * Based on paper https://arxiv.org/abs/1903.08008 + * + * When the number of total draws N is odd, the (N+1)/2th draw is ignored. + * + * See more details in Stan reference manual section "Potential + * Scale Reduction". http://mc-stan.org/users/documentation + * + * Current implementation assumes draws are stored in contiguous + * blocks of memory. Chains are trimmed from the back to match the + * length of the shortest chain. Argument size will be broadcast to + * same length as draws. + * + * @param draws stores pointers to arrays of chains + * @param size stores sizes of chains + * @return potential scale reduction for the specified parameter + */ +inline double compute_split_potential_scale_reduction_rank( + std::vector draws, size_t size) { + int num_chains = draws.size(); + std::vector sizes(num_chains, size); + return compute_split_potential_scale_reduction_rank(draws, sizes); +} + /** * Computes the split potential scale reduction (Rhat) for the * specified parameter across all kept samples. When the number of diff --git a/src/stan/mcmc/chains.hpp b/src/stan/mcmc/chains.hpp index 507a5bc537..820eeb363d 100644 --- a/src/stan/mcmc/chains.hpp +++ b/src/stan/mcmc/chains.hpp @@ -595,6 +595,21 @@ class chains { return split_effective_sample_size(index(name)); } + double split_potential_scale_reduction_rank(const int index) const { + int n_chains = num_chains(); + std::vector draws(n_chains); + std::vector sizes(n_chains); + int n_kept_samples = 0; + for (int chain = 0; chain < n_chains; ++chain) { + n_kept_samples = num_kept_samples(chain); + draws[chain] + = samples_(chain).col(index).bottomRows(n_kept_samples).data(); + sizes[chain] = n_kept_samples; + } + + return analyze::compute_split_potential_scale_reduction_rank(draws, sizes); + } + double split_potential_scale_reduction(const int index) const { int n_chains = num_chains(); std::vector draws(n_chains); @@ -610,6 +625,10 @@ class chains { return analyze::compute_split_potential_scale_reduction(draws, sizes); } + double split_potential_scale_reduction_rank(const std::string& name) const { + return split_potential_scale_reduction_rank(index(name)); + } + double split_potential_scale_reduction(const std::string& name) const { return split_potential_scale_reduction(index(name)); } diff --git a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp index 2f64f659eb..d1b20978c5 100644 --- a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp +++ b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp @@ -27,6 +27,44 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction) { stan::io::stan_csv blocker2 = stan::io::stan_csv_reader::parse(blocker2_stream, &out); EXPECT_EQ("", out.str()); + stan::mcmc::chains<> chains(blocker1); + chains.add(blocker2); + + Eigen::VectorXd rhat(48); + rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, + 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, + 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, + 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, + 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, + 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, + 1.00735; + + // replicates calls to stan::analyze::compute_effective_sample_size + // for any interface *without* access to chains class + Eigen::Matrix samples( + chains.num_chains()); + std::vector draws(chains.num_chains()); + std::vector sizes(chains.num_chains()); + for (int index = 4; index < chains.num_params(); index++) { + for (int chain = 0; chain < chains.num_chains(); ++chain) { + samples(chain) = chains.samples(chain, index); + draws[chain] = &samples(chain)(0); + sizes[chain] = samples(chain).size(); + } + ASSERT_NEAR(rhat(index - 4), + stan::analyze::compute_potential_scale_reduction(draws, sizes), + 1.0) + << "rhat for index: " << index + << ", parameter: " << chains.param_name(index); + } +} +TEST_F(ComputeRhat, compute_potential_scale_reduction_rank) { + std::stringstream out; + stan::io::stan_csv blocker1 + = stan::io::stan_csv_reader::parse(blocker1_stream, &out); + stan::io::stan_csv blocker2 + = stan::io::stan_csv_reader::parse(blocker2_stream, &out); + EXPECT_EQ("", out.str()); stan::mcmc::chains<> chains(blocker1); chains.add(blocker2); @@ -52,13 +90,15 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction) { sizes[chain] = samples(chain).size(); } ASSERT_NEAR(rhat(index - 4), - stan::analyze::compute_potential_scale_reduction(draws, sizes), + stan::analyze::compute_potential_scale_reduction_rank(draws, sizes), 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); } } + + TEST_F(ComputeRhat, compute_potential_scale_reduction_convenience) { std::stringstream out; stan::io::stan_csv blocker1 @@ -70,6 +110,45 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_convenience) { stan::mcmc::chains<> chains(blocker1); chains.add(blocker2); + Eigen::VectorXd rhat(48); + rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, + 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, + 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, + 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, + 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, + 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, + 1.00735; + + Eigen::Matrix samples( + chains.num_chains()); + std::vector draws(chains.num_chains()); + std::vector sizes(chains.num_chains()); + for (int index = 4; index < chains.num_params(); index++) { + for (int chain = 0; chain < chains.num_chains(); ++chain) { + samples(chain) = chains.samples(chain, index); + draws[chain] = &samples(chain)(0); + } + size_t size = samples(0).size(); + ASSERT_NEAR(rhat(index - 4), + stan::analyze::compute_potential_scale_reduction(draws, size), + 1) + << "rhat for index: " << index + << ", parameter: " << chains.param_name(index); + } +} + + +TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_convenience) { + std::stringstream out; + stan::io::stan_csv blocker1 + = stan::io::stan_csv_reader::parse(blocker1_stream, &out); + stan::io::stan_csv blocker2 + = stan::io::stan_csv_reader::parse(blocker2_stream, &out); + EXPECT_EQ("", out.str()); + + stan::mcmc::chains<> chains(blocker1); + chains.add(blocker2); + Eigen::VectorXd rhat(48); rhat << 1.00067, 1.00497, 1.00918, 1.00055, 1.0015, 1.00088, 1.00776, 1.00042, 1.00201, 0.999558, 0.99984, 1.00054, 1.00403, 1.00516, 1.00591, 1.00627, @@ -89,13 +168,14 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_convenience) { } size_t size = samples(0).size(); ASSERT_NEAR(rhat(index - 4), - stan::analyze::compute_potential_scale_reduction(draws, size), + stan::analyze::compute_potential_scale_reduction_rank(draws, size), 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); } } + TEST_F(ComputeRhat, chains_compute_split_potential_scale_reduction) { std::stringstream out; stan::io::stan_csv blocker1 @@ -107,6 +187,40 @@ TEST_F(ComputeRhat, chains_compute_split_potential_scale_reduction) { stan::mcmc::chains<> chains(blocker1); chains.add(blocker2); + Eigen::VectorXd rhat(48); + rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, + 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, + 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, + 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, + 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, + 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, + 1.00735; + + for (int index = 4; index < chains.num_params(); index++) { + ASSERT_NEAR(rhat(index - 4), chains.split_potential_scale_reduction(index), + 1e-4) + << "rhat for index: " << index + << ", parameter: " << chains.param_name(index); + } + + for (int index = 0; index < chains.num_params(); index++) { + std::string name = chains.param_name(index); + ASSERT_EQ(chains.split_potential_scale_reduction(index), + chains.split_potential_scale_reduction(name)); + } +} + +TEST_F(ComputeRhat, chains_compute_split_potential_scale_reduction_rank) { + std::stringstream out; + stan::io::stan_csv blocker1 + = stan::io::stan_csv_reader::parse(blocker1_stream, &out); + stan::io::stan_csv blocker2 + = stan::io::stan_csv_reader::parse(blocker2_stream, &out); + EXPECT_EQ("", out.str()); + + stan::mcmc::chains<> chains(blocker1); + chains.add(blocker2); + Eigen::VectorXd rhat(48); rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, @@ -116,7 +230,7 @@ TEST_F(ComputeRhat, chains_compute_split_potential_scale_reduction) { 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; for (int index = 4; index < chains.num_params(); index++) { - ASSERT_NEAR(rhat(index - 4), chains.split_potential_scale_reduction(index), + ASSERT_NEAR(rhat(index - 4), chains.split_potential_scale_reduction_rank(index), 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); @@ -124,8 +238,8 @@ TEST_F(ComputeRhat, chains_compute_split_potential_scale_reduction) { for (int index = 0; index < chains.num_params(); index++) { std::string name = chains.param_name(index); - ASSERT_EQ(chains.split_potential_scale_reduction(index), - chains.split_potential_scale_reduction(name)); + ASSERT_EQ(chains.split_potential_scale_reduction_rank(index), + chains.split_potential_scale_reduction_rank(name)); } } @@ -141,6 +255,48 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction) { chains.add(blocker2); + Eigen::VectorXd rhat(48); + rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, + 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, + 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, + 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, + 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, + 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, + 1.00735; + + // replicates calls to stan::analyze::compute_effective_sample_size + // for any interface *without* access to chains class + Eigen::Matrix samples( + chains.num_chains()); + std::vector draws(chains.num_chains()); + std::vector sizes(chains.num_chains()); + for (int index = 4; index < chains.num_params(); index++) { + for (int chain = 0; chain < chains.num_chains(); ++chain) { + samples(chain) = chains.samples(chain, index); + draws[chain] = &samples(chain)(0); + sizes[chain] = samples(chain).size(); + } + ASSERT_NEAR( + rhat(index - 4), + stan::analyze::compute_split_potential_scale_reduction(draws, sizes), + 1.0) + << "rhat for index: " << index + << ", parameter: " << chains.param_name(index); + } +} + +TEST_F(ComputeRhat, compute_split_potential_scale_reduction_rank) { + std::stringstream out; + stan::io::stan_csv blocker1 + = stan::io::stan_csv_reader::parse(blocker1_stream, &out); + stan::io::stan_csv blocker2 + = stan::io::stan_csv_reader::parse(blocker2_stream, &out); + EXPECT_EQ("", out.str()); + + stan::mcmc::chains<> chains(blocker1); + + chains.add(blocker2); + Eigen::VectorXd rhat(48); rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, @@ -163,7 +319,7 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction) { } ASSERT_NEAR( rhat(index - 4), - stan::analyze::compute_split_potential_scale_reduction(draws, sizes), + stan::analyze::compute_split_potential_scale_reduction_rank(draws, sizes), 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); @@ -181,6 +337,47 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience) { stan::mcmc::chains<> chains(blocker1); chains.add(blocker2); + Eigen::VectorXd rhat(48); + rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, + 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, + 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, + 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, + 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, + 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, + 1.00735; + + Eigen::Matrix samples( + chains.num_chains()); + std::vector draws(chains.num_chains()); + std::vector sizes(chains.num_chains()); + for (int index = 4; index < chains.num_params(); index++) { + for (int chain = 0; chain < chains.num_chains(); ++chain) { + samples(chain) = chains.samples(chain, index); + draws[chain] = &samples(chain)(0); + } + size_t size = samples(0).size(); + std::cout << "RHAT" << std::endl; + std::cout << stan::analyze::compute_split_potential_scale_reduction(draws, size) << std::endl; + ASSERT_NEAR( + rhat(index - 4), + stan::analyze::compute_split_potential_scale_reduction(draws, size), + 1e-4) + << "rhat for index: " << index + << ", parameter: " << chains.param_name(index); + } +} + +TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience_rank) { + std::stringstream out; + stan::io::stan_csv blocker1 + = stan::io::stan_csv_reader::parse(blocker1_stream, &out); + stan::io::stan_csv blocker2 + = stan::io::stan_csv_reader::parse(blocker2_stream, &out); + EXPECT_EQ("", out.str()); + + stan::mcmc::chains<> chains(blocker1); + chains.add(blocker2); + Eigen::VectorXd rhat(48); rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, @@ -193,6 +390,11 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience) { chains.num_chains()); std::vector draws(chains.num_chains()); std::vector sizes(chains.num_chains()); + std::cout << "SAMPLES: \n"; + for (int i = 0; i < 10; i++) { + std::cout << chains.samples(0, 4)(i) << std::endl; + } + for (int index = 4; index < chains.num_params(); index++) { for (int chain = 0; chain < chains.num_chains(); ++chain) { samples(chain) = chains.samples(chain, index); @@ -201,7 +403,7 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience) { size_t size = samples(0).size(); ASSERT_NEAR( rhat(index - 4), - stan::analyze::compute_split_potential_scale_reduction(draws, size), + stan::analyze::compute_split_potential_scale_reduction_rank(draws, size), 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); @@ -219,6 +421,17 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_constant) { << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); } +TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_constant) { + std::vector param_names{"a"}; + stan::mcmc::chains<> chains(param_names); + Eigen::Matrix draws; + draws << 1.0, 1.0; + chains.add(draws); + + ASSERT_TRUE(std::isnan(chains.split_potential_scale_reduction_rank(0))) + << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); +} + TEST_F(ComputeRhat, compute_potential_scale_reduction_nan) { std::vector param_names{"a"}; stan::mcmc::chains<> chains(param_names); @@ -229,3 +442,14 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_nan) { ASSERT_TRUE(std::isnan(chains.split_potential_scale_reduction(0))) << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); } + +TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_nan) { + std::vector param_names{"a"}; + stan::mcmc::chains<> chains(param_names); + Eigen::Matrix draws; + draws << 1.0, std::numeric_limits::quiet_NaN(); + chains.add(draws); + + ASSERT_TRUE(std::isnan(chains.split_potential_scale_reduction_rank(0))) + << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); +} \ No newline at end of file From 30333ce83ef72749c052f578ac07ca57c5b1b3b7 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 26 Feb 2024 06:05:51 -0500 Subject: [PATCH 10/25] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- .../compute_potential_scale_reduction.hpp | 38 ++++++++--------- ...compute_potential_scale_reduction_test.cpp | 42 +++++++++---------- 2 files changed, 39 insertions(+), 41 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index 45ba1d8647..94295cf749 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -93,11 +93,10 @@ inline double rhat(const Eigen::MatrixXd& draws) { return sqrt((var_between / var_within + num_draws - 1) / num_draws); } - /** - * Computes the potential scale reduction (Rhat) using rank based diagnostic for the specified - * parameter across all kept samples. - * Based on paper https://arxiv.org/abs/1903.08008 + * Computes the potential scale reduction (Rhat) using rank based diagnostic for + * the specified parameter across all kept samples. Based on paper + * https://arxiv.org/abs/1903.08008 * * Current implementation assumes draws are stored in contiguous * blocks of memory. Chains are trimmed from the back to match the @@ -107,8 +106,9 @@ inline double rhat(const Eigen::MatrixXd& draws) { * @param sizes stores sizes of chains * @return potential scale reduction for the specified parameter */ -inline double compute_potential_scale_reduction_rank(std::vector draws, std::vector sizes) { -int num_chains = sizes.size(); +inline double compute_potential_scale_reduction_rank( + std::vector draws, std::vector sizes) { + int num_chains = sizes.size(); size_t num_draws = sizes[0]; if (num_draws == 0) { return std::numeric_limits::quiet_NaN(); @@ -161,7 +161,6 @@ int num_chains = sizes.size(); return std::max(rhat_bulk, rhat_tail); } - /** * Computes the potential scale reduction (Rhat) for the specified * parameter across all kept samples. @@ -230,9 +229,9 @@ inline double compute_potential_scale_reduction( } /** - * Computes the potential scale reduction (Rhat) using rank based diagnostic for the specified - * parameter across all kept samples. - * Based on paper https://arxiv.org/abs/1903.08008 + * Computes the potential scale reduction (Rhat) using rank based diagnostic for + * the specified parameter across all kept samples. Based on paper + * https://arxiv.org/abs/1903.08008 * * See more details in Stan reference manual section "Potential * Scale Reduction". http://mc-stan.org/users/documentation @@ -276,12 +275,11 @@ inline double compute_potential_scale_reduction( return compute_potential_scale_reduction(draws, sizes); } - /** - * Computes the potential scale reduction (Rhat) using rank based diagnostic for the specified - * parameter across all kept samples. - * Based on paper https://arxiv.org/abs/1903.08008 - * + * Computes the potential scale reduction (Rhat) using rank based diagnostic for + * the specified parameter across all kept samples. Based on paper + * https://arxiv.org/abs/1903.08008 + * * When the number of total draws N is odd, the (N+1)/2th draw is ignored. * * See more details in Stan reference manual section "Potential @@ -344,12 +342,12 @@ inline double compute_split_potential_scale_reduction( } /** - * Computes the potential scale reduction (Rhat) using rank based diagnostic for the specified - * parameter across all kept samples. - * Based on paper https://arxiv.org/abs/1903.08008 - * + * Computes the potential scale reduction (Rhat) using rank based diagnostic for + * the specified parameter across all kept samples. Based on paper + * https://arxiv.org/abs/1903.08008 + * * When the number of total draws N is odd, the (N+1)/2th draw is ignored. - * + * * See more details in Stan reference manual section "Potential * Scale Reduction". http://mc-stan.org/users/documentation * diff --git a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp index d1b20978c5..7422e657bd 100644 --- a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp +++ b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp @@ -89,16 +89,15 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank) { draws[chain] = &samples(chain)(0); sizes[chain] = samples(chain).size(); } - ASSERT_NEAR(rhat(index - 4), - stan::analyze::compute_potential_scale_reduction_rank(draws, sizes), - 1e-4) + ASSERT_NEAR( + rhat(index - 4), + stan::analyze::compute_potential_scale_reduction_rank(draws, sizes), + 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); } } - - TEST_F(ComputeRhat, compute_potential_scale_reduction_convenience) { std::stringstream out; stan::io::stan_csv blocker1 @@ -137,7 +136,6 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_convenience) { } } - TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_convenience) { std::stringstream out; stan::io::stan_csv blocker1 @@ -167,15 +165,15 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_convenience) { draws[chain] = &samples(chain)(0); } size_t size = samples(0).size(); - ASSERT_NEAR(rhat(index - 4), - stan::analyze::compute_potential_scale_reduction_rank(draws, size), - 1e-4) + ASSERT_NEAR( + rhat(index - 4), + stan::analyze::compute_potential_scale_reduction_rank(draws, size), + 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); } } - TEST_F(ComputeRhat, chains_compute_split_potential_scale_reduction) { std::stringstream out; stan::io::stan_csv blocker1 @@ -230,8 +228,8 @@ TEST_F(ComputeRhat, chains_compute_split_potential_scale_reduction_rank) { 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; for (int index = 4; index < chains.num_params(); index++) { - ASSERT_NEAR(rhat(index - 4), chains.split_potential_scale_reduction_rank(index), - 1e-4) + ASSERT_NEAR(rhat(index - 4), + chains.split_potential_scale_reduction_rank(index), 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); } @@ -317,10 +315,10 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_rank) { draws[chain] = &samples(chain)(0); sizes[chain] = samples(chain).size(); } - ASSERT_NEAR( - rhat(index - 4), - stan::analyze::compute_split_potential_scale_reduction_rank(draws, sizes), - 1e-4) + ASSERT_NEAR(rhat(index - 4), + stan::analyze::compute_split_potential_scale_reduction_rank( + draws, sizes), + 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); } @@ -357,7 +355,9 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience) { } size_t size = samples(0).size(); std::cout << "RHAT" << std::endl; - std::cout << stan::analyze::compute_split_potential_scale_reduction(draws, size) << std::endl; + std::cout << stan::analyze::compute_split_potential_scale_reduction(draws, + size) + << std::endl; ASSERT_NEAR( rhat(index - 4), stan::analyze::compute_split_potential_scale_reduction(draws, size), @@ -401,10 +401,10 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience_rank) { draws[chain] = &samples(chain)(0); } size_t size = samples(0).size(); - ASSERT_NEAR( - rhat(index - 4), - stan::analyze::compute_split_potential_scale_reduction_rank(draws, size), - 1e-4) + ASSERT_NEAR(rhat(index - 4), + stan::analyze::compute_split_potential_scale_reduction_rank( + draws, size), + 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); } From 77d875fe10638d00a876d44655704e37560a3391 Mon Sep 17 00:00:00 2001 From: aleksgorica Date: Mon, 26 Feb 2024 19:39:04 +0100 Subject: [PATCH 11/25] test chains_test changed --- src/test/unit/mcmc/chains_test.cpp | 43 +++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/src/test/unit/mcmc/chains_test.cpp b/src/test/unit/mcmc/chains_test.cpp index 41bd645a75..f8ca33a852 100644 --- a/src/test/unit/mcmc/chains_test.cpp +++ b/src/test/unit/mcmc/chains_test.cpp @@ -852,6 +852,43 @@ TEST_F(McmcChains, blocker_split_potential_scale_reduction) { stan::mcmc::chains<> chains(blocker1); chains.add(blocker2); + Eigen::VectorXd rhat(48); + rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, + 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, + 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, + 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, + 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, + 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, + 1.00735; + + for (int index = 4; index < chains.num_params(); index++) { + ASSERT_NEAR(rhat(index - 4), chains.split_potential_scale_reduction(index), + 1e-4) + << "rhat for index: " << index + << ", parameter: " << chains.param_name(index); + } + + for (int index = 0; index < chains.num_params(); index++) { + std::string name = chains.param_name(index); + ASSERT_EQ(chains.split_potential_scale_reduction(index), + chains.split_potential_scale_reduction(name)); + } +} + + + + +TEST_F(McmcChains, blocker_split_potential_scale_reduction_rank) { + std::stringstream out; + stan::io::stan_csv blocker1 + = stan::io::stan_csv_reader::parse(blocker1_stream, &out); + stan::io::stan_csv blocker2 + = stan::io::stan_csv_reader::parse(blocker2_stream, &out); + EXPECT_EQ("", out.str()); + + stan::mcmc::chains<> chains(blocker1); + chains.add(blocker2); + Eigen::VectorXd rhat(48); rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, @@ -861,7 +898,7 @@ TEST_F(McmcChains, blocker_split_potential_scale_reduction) { 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; for (int index = 4; index < chains.num_params(); index++) { - ASSERT_NEAR(rhat(index - 4), chains.split_potential_scale_reduction(index), + ASSERT_NEAR(rhat(index - 4), chains.split_potential_scale_reduction_rank(index), 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); @@ -869,7 +906,7 @@ TEST_F(McmcChains, blocker_split_potential_scale_reduction) { for (int index = 0; index < chains.num_params(); index++) { std::string name = chains.param_name(index); - ASSERT_EQ(chains.split_potential_scale_reduction(index), - chains.split_potential_scale_reduction(name)); + ASSERT_EQ(chains.split_potential_scale_reduction_rank(index), + chains.split_potential_scale_reduction_rank(name)); } } From da10f8ffa2cba885844257200681312732317887 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 26 Feb 2024 14:03:06 -0500 Subject: [PATCH 12/25] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- src/test/unit/mcmc/chains_test.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/test/unit/mcmc/chains_test.cpp b/src/test/unit/mcmc/chains_test.cpp index f8ca33a852..d9c8194e43 100644 --- a/src/test/unit/mcmc/chains_test.cpp +++ b/src/test/unit/mcmc/chains_test.cpp @@ -875,9 +875,6 @@ TEST_F(McmcChains, blocker_split_potential_scale_reduction) { } } - - - TEST_F(McmcChains, blocker_split_potential_scale_reduction_rank) { std::stringstream out; stan::io::stan_csv blocker1 @@ -898,8 +895,8 @@ TEST_F(McmcChains, blocker_split_potential_scale_reduction_rank) { 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; for (int index = 4; index < chains.num_params(); index++) { - ASSERT_NEAR(rhat(index - 4), chains.split_potential_scale_reduction_rank(index), - 1e-4) + ASSERT_NEAR(rhat(index - 4), + chains.split_potential_scale_reduction_rank(index), 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); } From c3b11016406f13172789fe18e8023ad011d4e0f1 Mon Sep 17 00:00:00 2001 From: aleksgorica Date: Wed, 28 Feb 2024 19:10:29 +0100 Subject: [PATCH 13/25] added test values from arviz --- .../compute_potential_scale_reduction.hpp | 4 +-- ...compute_potential_scale_reduction_test.cpp | 33 +++++-------------- 2 files changed, 10 insertions(+), 27 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index 94295cf749..082cc28c6d 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -26,7 +26,7 @@ namespace analyze { * */ -Eigen::MatrixXd rank_transform(const Eigen::MatrixXd& draws) { +inline Eigen::MatrixXd rank_transform(const Eigen::MatrixXd& draws) { const Eigen::Index rows = draws.rows(); const Eigen::Index cols = draws.cols(); const Eigen::Index size = rows * cols; @@ -116,7 +116,7 @@ inline double compute_potential_scale_reduction_rank( for (int chain = 1; chain < num_chains; ++chain) { num_draws = std::min(num_draws, sizes[chain]); } - + // check if chains are constant; all equal to first draw's value bool are_all_const = false; Eigen::VectorXd init_draw = Eigen::VectorXd::Zero(num_chains); diff --git a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp index 7422e657bd..04dc5c04bd 100644 --- a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp +++ b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp @@ -31,13 +31,8 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, - 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, - 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, - 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, - 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, - 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, - 1.00735; + rhat << 1.00042,1.00036,0.99955,1.00047,1.00119,1.00089,1.00018,1.00019,1.00226,0.99954,0.9996,0.99951,1.00237,1.00515,1.00566,0.99957,1.00099,1.00853,1.0008,0.99961,1.0006,1.00046,1.01023,0.9996,1.0011,0.99967,0.99973,0.99958,1.00242,1.00213,1.00244,0.99998,0.99969,1.00079,0.99955,1.0009,1.00136,1.00288,1.00036,0.99989,1.00077,0.99997,1.00194,0.99972,1.00257,1.00109,1.00004,0.99955; + // replicates calls to stan::analyze::compute_effective_sample_size // for any interface *without* access to chains class @@ -53,7 +48,7 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction) { } ASSERT_NEAR(rhat(index - 4), stan::analyze::compute_potential_scale_reduction(draws, sizes), - 1.0) + 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); } @@ -110,13 +105,7 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_convenience) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, - 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, - 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, - 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, - 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, - 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, - 1.00735; + rhat << 1.00042,1.00036,0.99955,1.00047,1.00119,1.00089,1.00018,1.00019,1.00226,0.99954,0.9996,0.99951,1.00237,1.00515,1.00566,0.99957,1.00099,1.00853,1.0008,0.99961,1.0006,1.00046,1.01023,0.9996,1.0011,0.99967,0.99973,0.99958,1.00242,1.00213,1.00244,0.99998,0.99969,1.00079,0.99955,1.0009,1.00136,1.00288,1.00036,0.99989,1.00077,0.99997,1.00194,0.99972,1.00257,1.00109,1.00004,0.99955; Eigen::Matrix samples( chains.num_chains()); @@ -127,10 +116,12 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_convenience) { samples(chain) = chains.samples(chain, index); draws[chain] = &samples(chain)(0); } + + size_t size = samples(0).size(); ASSERT_NEAR(rhat(index - 4), stan::analyze::compute_potential_scale_reduction(draws, size), - 1) + 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); } @@ -277,7 +268,7 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction) { ASSERT_NEAR( rhat(index - 4), stan::analyze::compute_split_potential_scale_reduction(draws, sizes), - 1.0) + 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); } @@ -354,10 +345,6 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience) { draws[chain] = &samples(chain)(0); } size_t size = samples(0).size(); - std::cout << "RHAT" << std::endl; - std::cout << stan::analyze::compute_split_potential_scale_reduction(draws, - size) - << std::endl; ASSERT_NEAR( rhat(index - 4), stan::analyze::compute_split_potential_scale_reduction(draws, size), @@ -390,10 +377,6 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience_rank) { chains.num_chains()); std::vector draws(chains.num_chains()); std::vector sizes(chains.num_chains()); - std::cout << "SAMPLES: \n"; - for (int i = 0; i < 10; i++) { - std::cout << chains.samples(0, 4)(i) << std::endl; - } for (int index = 4; index < chains.num_params(); index++) { for (int chain = 0; chain < chains.num_chains(); ++chain) { From 51ad447d6965a59da24c6365c078450bdaebea9b Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 28 Feb 2024 13:16:43 -0500 Subject: [PATCH 14/25] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- .../mcmc/compute_potential_scale_reduction.hpp | 2 +- .../compute_potential_scale_reduction_test.cpp | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index 082cc28c6d..3cd230540a 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -116,7 +116,7 @@ inline double compute_potential_scale_reduction_rank( for (int chain = 1; chain < num_chains; ++chain) { num_draws = std::min(num_draws, sizes[chain]); } - + // check if chains are constant; all equal to first draw's value bool are_all_const = false; Eigen::VectorXd init_draw = Eigen::VectorXd::Zero(num_chains); diff --git a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp index 04dc5c04bd..6faa735f73 100644 --- a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp +++ b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp @@ -31,8 +31,13 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00042,1.00036,0.99955,1.00047,1.00119,1.00089,1.00018,1.00019,1.00226,0.99954,0.9996,0.99951,1.00237,1.00515,1.00566,0.99957,1.00099,1.00853,1.0008,0.99961,1.0006,1.00046,1.01023,0.9996,1.0011,0.99967,0.99973,0.99958,1.00242,1.00213,1.00244,0.99998,0.99969,1.00079,0.99955,1.0009,1.00136,1.00288,1.00036,0.99989,1.00077,0.99997,1.00194,0.99972,1.00257,1.00109,1.00004,0.99955; - + rhat << 1.00042, 1.00036, 0.99955, 1.00047, 1.00119, 1.00089, 1.00018, + 1.00019, 1.00226, 0.99954, 0.9996, 0.99951, 1.00237, 1.00515, 1.00566, + 0.99957, 1.00099, 1.00853, 1.0008, 0.99961, 1.0006, 1.00046, 1.01023, + 0.9996, 1.0011, 0.99967, 0.99973, 0.99958, 1.00242, 1.00213, 1.00244, + 0.99998, 0.99969, 1.00079, 0.99955, 1.0009, 1.00136, 1.00288, 1.00036, + 0.99989, 1.00077, 0.99997, 1.00194, 0.99972, 1.00257, 1.00109, 1.00004, + 0.99955; // replicates calls to stan::analyze::compute_effective_sample_size // for any interface *without* access to chains class @@ -105,7 +110,13 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_convenience) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00042,1.00036,0.99955,1.00047,1.00119,1.00089,1.00018,1.00019,1.00226,0.99954,0.9996,0.99951,1.00237,1.00515,1.00566,0.99957,1.00099,1.00853,1.0008,0.99961,1.0006,1.00046,1.01023,0.9996,1.0011,0.99967,0.99973,0.99958,1.00242,1.00213,1.00244,0.99998,0.99969,1.00079,0.99955,1.0009,1.00136,1.00288,1.00036,0.99989,1.00077,0.99997,1.00194,0.99972,1.00257,1.00109,1.00004,0.99955; + rhat << 1.00042, 1.00036, 0.99955, 1.00047, 1.00119, 1.00089, 1.00018, + 1.00019, 1.00226, 0.99954, 0.9996, 0.99951, 1.00237, 1.00515, 1.00566, + 0.99957, 1.00099, 1.00853, 1.0008, 0.99961, 1.0006, 1.00046, 1.01023, + 0.9996, 1.0011, 0.99967, 0.99973, 0.99958, 1.00242, 1.00213, 1.00244, + 0.99998, 0.99969, 1.00079, 0.99955, 1.0009, 1.00136, 1.00288, 1.00036, + 0.99989, 1.00077, 0.99997, 1.00194, 0.99972, 1.00257, 1.00109, 1.00004, + 0.99955; Eigen::Matrix samples( chains.num_chains()); @@ -117,7 +128,6 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_convenience) { draws[chain] = &samples(chain)(0); } - size_t size = samples(0).size(); ASSERT_NEAR(rhat(index - 4), stan::analyze::compute_potential_scale_reduction(draws, size), From 71bfbcf2185f95e904fb03b304cd6cb8570daafb Mon Sep 17 00:00:00 2001 From: aleksgorica Date: Mon, 25 Mar 2024 14:35:42 +0100 Subject: [PATCH 15/25] smaller changes for comments in pull request --- .../compute_potential_scale_reduction.hpp | 272 +++++++++--------- ...compute_potential_scale_reduction_test.cpp | 39 ++- 2 files changed, 163 insertions(+), 148 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index 3cd230540a..4082f8ec0b 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -21,76 +21,76 @@ namespace analyze { * Computes normalized average ranks for draws. Transforming them to normal * scores using inverse normal transformation and a fractional offset. Based on * paper https://arxiv.org/abs/1903.08008 - * @param draws stores chains in columns + * @param chains stores chains in columns * @return normal scores for average ranks of draws - * */ - -inline Eigen::MatrixXd rank_transform(const Eigen::MatrixXd& draws) { - const Eigen::Index rows = draws.rows(); - const Eigen::Index cols = draws.cols(); +inline Eigen::MatrixXd rank_transform(const Eigen::MatrixXd& chains) { + const Eigen::Index rows = chains.rows(); + const Eigen::Index cols = chains.cols(); const Eigen::Index size = rows * cols; std::vector> value_with_index(size); for (Eigen::Index i = 0; i < size; ++i) { - value_with_index[i] = {draws(i), i}; + value_with_index[i] = {chains(i), i}; } std::sort(value_with_index.begin(), value_with_index.end()); - Eigen::MatrixXd rankMatrix = Eigen::MatrixXd::Zero(rows, cols); + Eigen::MatrixXd rank_matrix = Eigen::MatrixXd::Zero(rows, cols); // Assigning average ranks for (Eigen::Index i = 0; i < size; ++i) { // Handle ties by averaging ranks Eigen::Index j = i + 1; - double sumRanks = j; + double sum_ranks = j; Eigen::Index count = 1; while (j < size && value_with_index[j].first == value_with_index[i].first) { - sumRanks += j + 1; // Rank starts from 1 + sum_ranks += j + 1; // Rank starts from 1 ++j; ++count; } - double avgRank = sumRanks / count; + double avg_rank = sum_ranks / count; boost::math::normal_distribution dist; for (std::size_t k = i; k < j; ++k) { - Eigen::Index index = value_with_index[k].second; - double p = (avgRank - 3.0 / 8.0) / (size - 2.0 * 3.0 / 8.0 + 1.0); - rankMatrix(index) = boost::math::quantile(dist, p); + double p = (avg_rank - 3.0 / 8.0) / (size - 2.0 * 3.0 / 8.0 + 1.0); + const Eigen::Index index = value_with_index[k].second; + rank_matrix(index) = boost::math::quantile(dist, p); } i = j - 1; // Skip over tied elements } - return rankMatrix; + return rank_matrix; } /** * Computes square root of marginal posterior variance of the estimand by the * weigted average of within-chain variance W and between-chain variance B. * - * @param draws stores chains in columns + * @param chains stores chains in columns * @return square root of ((N-1)/N)W + B/N - * */ - -inline double rhat(const Eigen::MatrixXd& draws) { - const Eigen::Index num_chains = draws.cols(); - const Eigen::Index num_draws = draws.rows(); - - Eigen::VectorXd chain_mean(num_chains); - chain_mean = draws.colwise().mean(); - double total_mean = chain_mean.mean(); - double var_between = num_draws - * (chain_mean.array() - total_mean).square().sum() +inline double rhat(const Eigen::MatrixXd& chains) { + const Eigen::Index num_chains = chains.cols(); + const Eigen::Index num_draws = chains.rows(); + + Eigen::RowVectorXd within_chain_means = chains.colwise().mean(); + double across_chain_mean = within_chain_means.mean(); + double between_variance = num_draws + * (within_chain_means.array() - across_chain_mean).square().sum() / (num_chains - 1); - double var_sum = 0; - for (Eigen::Index col = 0; col < num_chains; ++col) { - var_sum += (draws.col(col).array() - chain_mean(col)).square().sum() - / (num_draws - 1); - } - double var_within = var_sum / num_chains; - return sqrt((var_between / var_within + num_draws - 1) / num_draws); + double within_variance = + // Divide each row by chains and get sum of squares for each chain (getting a vector back) + ((chains.rowwise() - within_chain_means) + .array() + .square() + .colwise() + // divide each sum of square by num_draws, sum the sum of squares, and divide by num chains + .sum() / (num_draws - 1.0)) + .sum() / num_chains; + + return sqrt((between_variance / within_variance + num_draws - 1) / num_draws); + } /** @@ -102,43 +102,51 @@ inline double rhat(const Eigen::MatrixXd& draws) { * blocks of memory. Chains are trimmed from the back to match the * length of the shortest chain. * - * @param draws stores pointers to arrays of chains + * @param chain_begin stores pointers to arrays of chains * @param sizes stores sizes of chains * @return potential scale reduction for the specified parameter */ inline double compute_potential_scale_reduction_rank( - std::vector draws, std::vector sizes) { - int num_chains = sizes.size(); - size_t num_draws = sizes[0]; - if (num_draws == 0) { - return std::numeric_limits::quiet_NaN(); - } - for (int chain = 1; chain < num_chains; ++chain) { - num_draws = std::min(num_draws, sizes[chain]); + const std::vector& chain_begins, const std::vector& chain_sizes) { + std::vector nonzero_chain_begins; + std::vector nonzero_chain_sizes; + for (size_t i = 0; i < chain_sizes.size(); ++i) { + if (chain_sizes[i]) { + nonzero_chain_begins.push_back(chain_begins[i]); + nonzero_chain_sizes.push_back(chain_sizes[i]); + } + } + if (!nonzero_chain_sizes.size()) { + return std::numeric_limits::quiet_NaN(); + } + std::size_t num_nonzero_chains = nonzero_chain_sizes.size(); + std::size_t min_num_draws = nonzero_chain_sizes[0]; + for (std::size_t chain = 1; chain < num_nonzero_chains; ++chain) { + min_num_draws = std::min(min_num_draws, nonzero_chain_sizes[chain]); } // check if chains are constant; all equal to first draw's value bool are_all_const = false; - Eigen::VectorXd init_draw = Eigen::VectorXd::Zero(num_chains); + Eigen::VectorXd init_draw = Eigen::VectorXd::Zero(num_nonzero_chains); + Eigen::MatrixXd draws_matrix(min_num_draws, num_nonzero_chains); - for (int chain = 0; chain < num_chains; chain++) { - Eigen::Map> draw( - draws[chain], sizes[chain]); + for (std::size_t chain = 0; chain < num_nonzero_chains; chain++) { + Eigen::Map> draws( + nonzero_chain_begins[chain], nonzero_chain_sizes[chain]); - for (int n = 0; n < num_draws; n++) { - if (!std::isfinite(draw(n))) { + for (std::size_t n = 0; n < min_num_draws; n++) { + if (!std::isfinite(draws(n))) { return std::numeric_limits::quiet_NaN(); } + draws_matrix(n, chain) = draws(n); } - init_draw(chain) = draw(0); - - if (draw.isApproxToConstant(draw(0))) { + init_draw(chain) = draws(0); + if (!draws.isApproxToConstant(draws(0))) { are_all_const |= true; } } - - if (are_all_const) { + if (are_all_const) { // If all chains are constant then return NaN // if they all equal the same constant value if (init_draw.isApproxToConstant(init_draw(0))) { @@ -146,18 +154,11 @@ inline double compute_potential_scale_reduction_rank( } } - Eigen::MatrixXd matrix(num_draws, num_chains); - - for (int col = 0; col < num_chains; ++col) { - for (int row = 0; row < num_draws; ++row) { - matrix(row, col) = draws[col][row]; - } - } - - double rhat_bulk = rhat(rank_transform(matrix)); + double rhat_bulk = rhat(rank_transform(draws_matrix)); double rhat_tail = rhat(rank_transform( - (matrix.array() - math::quantile(matrix.reshaped(), 0.5)).abs())); + (draws_matrix.array() - math::quantile(draws_matrix.reshaped(), 0.5)).abs())); + // return std::make_pair(rhat_bulk, rhat_tail); return std::max(rhat_bulk, rhat_tail); } @@ -169,47 +170,54 @@ inline double compute_potential_scale_reduction_rank( * Scale Reduction". http://mc-stan.org/users/documentation * * Current implementation assumes draws are stored in contiguous - * blocks of memory. Chains are trimmed from the back to match the + * blocks of memory. Chains are trimmed from the back to match the * length of the shortest chain. * - * @param draws stores pointers to arrays of chains - * @param sizes stores sizes of chains + * @param chain_begins stores pointers to arrays of chains + * @param chain_sizes stores sizes of chains * @return potential scale reduction for the specified parameter */ - inline double compute_potential_scale_reduction( - std::vector draws, std::vector sizes) { - int num_chains = sizes.size(); - size_t num_draws = sizes[0]; - if (num_draws == 0) { - return std::numeric_limits::quiet_NaN(); - } - for (int chain = 1; chain < num_chains; ++chain) { - num_draws = std::min(num_draws, sizes[chain]); + const std::vector& chain_begins, const std::vector& chain_sizes) { + std::vector nonzero_chain_begins; + std::vector nonzero_chain_sizes; + for (size_t i = 0; i < chain_sizes.size(); ++i) { + if (chain_sizes[i]) { + nonzero_chain_begins.push_back(chain_begins[i]); + nonzero_chain_sizes.push_back(chain_sizes[i]); + } + } + if (!nonzero_chain_sizes.size()) { + return std::numeric_limits::quiet_NaN(); + } + std::size_t num_nonzero_chains = nonzero_chain_sizes.size(); + std::size_t min_num_draws = nonzero_chain_sizes[0]; + for (std::size_t chain = 1; chain < num_nonzero_chains; ++chain) { + min_num_draws = std::min(min_num_draws, nonzero_chain_sizes[chain]); } // check if chains are constant; all equal to first draw's value bool are_all_const = false; - Eigen::VectorXd init_draw = Eigen::VectorXd::Zero(num_chains); + Eigen::VectorXd init_draw = Eigen::VectorXd::Zero(num_nonzero_chains); + Eigen::MatrixXd draws_matrix(min_num_draws, num_nonzero_chains); - for (int chain = 0; chain < num_chains; chain++) { - Eigen::Map> draw( - draws[chain], sizes[chain]); + for (std::size_t chain = 0; chain < num_nonzero_chains; chain++) { + Eigen::Map> draws( + nonzero_chain_begins[chain], nonzero_chain_sizes[chain]); - for (int n = 0; n < num_draws; n++) { - if (!std::isfinite(draw(n))) { + for (std::size_t n = 0; n < min_num_draws; n++) { + if (!std::isfinite(draws(n))) { return std::numeric_limits::quiet_NaN(); } + draws_matrix(n, chain) = draws(n); } - init_draw(chain) = draw(0); - - if (draw.isApproxToConstant(draw(0))) { + init_draw(chain) = draws(0); + if (!draws.isApproxToConstant(draws(0))) { are_all_const |= true; } } - - if (are_all_const) { + if (are_all_const) { // If all chains are constant then return NaN // if they all equal the same constant value if (init_draw.isApproxToConstant(init_draw(0))) { @@ -217,15 +225,7 @@ inline double compute_potential_scale_reduction( } } - Eigen::MatrixXd matrix(num_draws, num_chains); - - for (int col = 0; col < num_chains; ++col) { - for (int row = 0; row < num_draws; ++row) { - matrix(row, col) = draws[col][row]; - } - } - - return rhat(matrix); + return rhat(draws_matrix); } /** @@ -237,19 +237,19 @@ inline double compute_potential_scale_reduction( * Scale Reduction". http://mc-stan.org/users/documentation * * Current implementation assumes draws are stored in contiguous - * blocks of memory. Chains are trimmed from the back to match the - * length of the shortest chain. Argument size will be broadcast to + * blocks of memory. Chains are trimmed from the back to match the + * length of the shortest chain. Argument size will be broadcast to * same length as draws. * - * @param draws stores pointers to arrays of chains + * @param chain_begins stores pointers to arrays of chains * @param size stores sizes of chains * @return potential scale reduction for the specified parameter */ inline double compute_potential_scale_reduction_rank( - std::vector draws, size_t size) { - int num_chains = draws.size(); + const std::vector& chain_begins, size_t size) { + size_t num_chains = chain_begins.size(); std::vector sizes(num_chains, size); - return compute_potential_scale_reduction_rank(draws, sizes); + return compute_potential_scale_reduction_rank(chain_begins, sizes); } /** @@ -259,20 +259,20 @@ inline double compute_potential_scale_reduction_rank( * See more details in Stan reference manual section "Potential * Scale Reduction". http://mc-stan.org/users/documentation * - * Current implementation assumes draws are stored in contiguous - * blocks of memory. Chains are trimmed from the back to match the - * length of the shortest chain. Argument size will be broadcast to + * Current implementation assumes draws are stored in contiguousdereck lively ii height weight + * blocks of memory. Chains are trimmed from the back to match the + * length of the shortest chain. Argument size will be broadcast to * same length as draws. * - * @param draws stores pointers to arrays of chains + * @param chain_begins stores pointers to arrays of chains * @param size stores sizes of chains * @return potential scale reduction for the specified parameter */ inline double compute_potential_scale_reduction( - std::vector draws, size_t size) { - int num_chains = draws.size(); + const std::vector& chain_begins, size_t size) { + size_t num_chains = chain_begins.size(); std::vector sizes(num_chains, size); - return compute_potential_scale_reduction(draws, sizes); + return compute_potential_scale_reduction(chain_begins, sizes); } /** @@ -286,25 +286,25 @@ inline double compute_potential_scale_reduction( * Scale Reduction". http://mc-stan.org/users/documentation * * Current implementation assumes draws are stored in contiguous - * blocks of memory. Chains are trimmed from the back to match the + * blocks of memory. Chains are trimmed from the back to match the * length of the shortest chain. * - * @param draws stores pointers to arrays of chains - * @param sizes stores sizes of chains + * @param chain_begins stores pointers to arrays of chains + * @param chain_sizes stores sizes of chains * @return potential scale reduction for the specified parameter */ inline double compute_split_potential_scale_reduction_rank( - std::vector draws, std::vector sizes) { - int num_chains = sizes.size(); - size_t num_draws = sizes[0]; - for (int chain = 1; chain < num_chains; ++chain) { - num_draws = std::min(num_draws, sizes[chain]); + const std::vector& chain_begins, const std::vector& chain_sizes) { + size_t num_chains = chain_sizes.size(); + size_t num_draws = chain_sizes[0]; + for (size_t chain = 1; chain < num_chains; ++chain) { + num_draws = std::min(num_draws, chain_sizes[chain]); } - std::vector split_draws = split_chains(draws, sizes); + std::vector split_draws = split_chains(chain_begins, chain_sizes); - double half = num_draws / 2.0; - std::vector half_sizes(2 * num_chains, std::floor(half)); + size_t half = std::floor(num_draws / 2.0); + std::vector half_sizes(2 * num_chains, half); return compute_potential_scale_reduction_rank(split_draws, half_sizes); } @@ -321,19 +321,19 @@ inline double compute_split_potential_scale_reduction_rank( * blocks of memory. Chains are trimmed from the back to match the * length of the shortest chain. * - * @param draws stores pointers to arrays of chains - * @param sizes stores sizes of chains + * @param chain_begins stores pointers to arrays of chains + * @param chain_sizes stores sizes of chains * @return potential scale reduction for the specified parameter */ inline double compute_split_potential_scale_reduction( - std::vector draws, std::vector sizes) { - int num_chains = sizes.size(); - size_t num_draws = sizes[0]; - for (int chain = 1; chain < num_chains; ++chain) { - num_draws = std::min(num_draws, sizes[chain]); + const std::vector& chain_begins, const std::vector& chain_sizes) { + size_t num_chains = chain_sizes.size(); + size_t num_draws = chain_sizes[0]; + for (size_t chain = 1; chain < num_chains; ++chain) { + num_draws = std::min(num_draws, chain_sizes[chain]); } - std::vector split_draws = split_chains(draws, sizes); + std::vector split_draws = split_chains(chain_begins, chain_sizes); double half = num_draws / 2.0; std::vector half_sizes(2 * num_chains, std::floor(half)); @@ -356,15 +356,15 @@ inline double compute_split_potential_scale_reduction( * length of the shortest chain. Argument size will be broadcast to * same length as draws. * - * @param draws stores pointers to arrays of chains + * @param chain_begins stores pointers to arrays of chains * @param size stores sizes of chains * @return potential scale reduction for the specified parameter */ inline double compute_split_potential_scale_reduction_rank( - std::vector draws, size_t size) { - int num_chains = draws.size(); + const std::vector& chain_begins, size_t size) { + size_t num_chains = chain_begins.size(); std::vector sizes(num_chains, size); - return compute_split_potential_scale_reduction_rank(draws, sizes); + return compute_split_potential_scale_reduction_rank(chain_begins, sizes); } /** @@ -380,15 +380,15 @@ inline double compute_split_potential_scale_reduction_rank( * length of the shortest chain. Argument size will be broadcast to * same length as draws. * - * @param draws stores pointers to arrays of chains + * @param chain_begins stores pointers to arrays of chains * @param size stores sizes of chains * @return potential scale reduction for the specified parameter */ inline double compute_split_potential_scale_reduction( - std::vector draws, size_t size) { - int num_chains = draws.size(); + const std::vector& chain_begins, size_t size) { + size_t num_chains = chain_begins.size(); std::vector sizes(num_chains, size); - return compute_split_potential_scale_reduction(draws, sizes); + return compute_split_potential_scale_reduction(chain_begins, sizes); } } // namespace analyze diff --git a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp index 6faa735f73..0d69d57ae8 100644 --- a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp +++ b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp @@ -70,12 +70,12 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00067, 1.00497, 1.00918, 1.00055, 1.0015, 1.00088, 1.00776, 1.00042, - 1.00201, 0.999558, 0.99984, 1.00054, 1.00403, 1.00516, 1.00591, 1.00627, - 1.00134, 1.00895, 1.00079, 1.00368, 1.00092, 1.00133, 1.01005, 1.00107, - 1.00151, 1.00229, 0.999998, 1.00008, 1.00315, 1.00277, 1.00247, 1.00003, - 1.001, 1.01267, 1.00011, 1.00066, 1.00091, 1.00237, 1.00019, 1.00104, - 1.00341, 0.999815, 1.00033, 0.999672, 1.00306, 1.00072, 1.00191, 1.00658; + rhat << 1.00067,1.00497,1.00918,1.00055,1.0015,1.00088,1.00776,1.00042,1.00201,0.99956,0.99984,1.00054,1.00403,1.00516,1.00591,1.00627,1.00134,1.00895,1.00079,1.00368,1.00092,1.00133,1.01005,1.00107,1.00151,1.00229,1.0,1.00008,1.00315,1.00277,1.00247,1.00003,1.001,1.01267,1.00011,1.00066,1.00091,1.00237,1.00019,1.00104,1.00341,0.99981,1.00033,0.99967,1.00306,1.00072,1.00191,1.00658; + + // Eigen::VectorXd rhat_bulk(48); + // rhat_bulk << 1.00067,0.99979,0.99966,1.00055,1.0011,1.00088,1.00032,0.99997,1.00201,0.99956,0.99956,0.9995,1.00292,1.00516,1.00591,0.99975,1.00088,1.00895,1.00079,0.99953,1.00092,1.00044,1.01005,0.9996,1.00151,0.99966,0.99965,0.99963,1.00315,1.00277,1.00247,1.00003,0.99994,1.00116,0.99952,1.0005,1.00091,1.00213,1.00019,0.99977,1.0003,0.99981,1.00003,0.99967,1.00306,1.00072,0.9996,0.99979; + // Eigen::VectorXd rhat_tail(48); + // rhat_tail << 1.00063,1.00497,1.00918,0.99965,1.0015,0.99962,1.00776,1.00042,0.99963,0.99951,0.99984,1.00054,1.00403,1.00107,1.00287,1.00627,1.00134,0.99957,0.99997,1.00368,1.00053,1.00133,1.00589,1.00107,1.00031,1.00229,1.0,1.00008,1.0001,1.00116,1.00219,0.99992,1.001,1.01267,1.00011,1.00066,1.00065,1.00237,0.9995,1.00104,1.00341,0.99958,1.00033,0.9996,0.99957,1.00058,1.00191,1.00658; // replicates calls to stan::analyze::compute_effective_sample_size // for any interface *without* access to chains class @@ -89,6 +89,15 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank) { draws[chain] = &samples(chain)(0); sizes[chain] = samples(chain).size(); } + + // double [computed_bulk_rhat, computed_tail_rhat] = stan::analyze::compute_potential_scale_reduction_rank(draws, sizes); + // double expected_bulk_rhat = rhat_bulk(index - 4); + // double expected_tail_rhat = rhat_tail(index - 4); + + // ASSERT_NEAR(expected_bulk_rhat, computed_bulk_rhat, 1e-4) + // << "Bulk Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + // ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) + // << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); ASSERT_NEAR( rhat(index - 4), stan::analyze::compute_potential_scale_reduction_rank(draws, sizes), @@ -234,7 +243,6 @@ TEST_F(ComputeRhat, chains_compute_split_potential_scale_reduction_rank) { << "rhat for index: " << index << ", parameter: " << chains.param_name(index); } - for (int index = 0; index < chains.num_params(); index++) { std::string name = chains.param_name(index); ASSERT_EQ(chains.split_potential_scale_reduction_rank(index), @@ -406,9 +414,14 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience_rank) { TEST_F(ComputeRhat, compute_potential_scale_reduction_constant) { std::vector param_names{"a"}; stan::mcmc::chains<> chains(param_names); - Eigen::Matrix draws; - draws << 1.0, 1.0; - chains.add(draws); + Eigen::Matrix draws1; + draws1 << 1.0, 1.0, 2.0; + chains.add(draws1); + Eigen::Matrix draws2; + draws2 << 4.0, 4.0, 4.0; + chains.add(draws2); + + std::cout << "SOMETHING" << std::endl; ASSERT_TRUE(std::isnan(chains.split_potential_scale_reduction(0))) << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); @@ -442,7 +455,9 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_nan) { Eigen::Matrix draws; draws << 1.0, std::numeric_limits::quiet_NaN(); chains.add(draws); - ASSERT_TRUE(std::isnan(chains.split_potential_scale_reduction_rank(0))) << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); -} \ No newline at end of file +} + + + From 385c80bbd4f0de9e1e2be50683ed9d8ab9bbbe09 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 25 Mar 2024 09:36:24 -0400 Subject: [PATCH 16/25] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- .../compute_potential_scale_reduction.hpp | 105 ++++++++++-------- ...compute_potential_scale_reduction_test.cpp | 27 +++-- 2 files changed, 75 insertions(+), 57 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index 4082f8ec0b..111e2a796c 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -74,23 +74,27 @@ inline double rhat(const Eigen::MatrixXd& chains) { const Eigen::Index num_chains = chains.cols(); const Eigen::Index num_draws = chains.rows(); - Eigen::RowVectorXd within_chain_means = chains.colwise().mean(); + Eigen::RowVectorXd within_chain_means = chains.colwise().mean(); double across_chain_mean = within_chain_means.mean(); - double between_variance = num_draws - * (within_chain_means.array() - across_chain_mean).square().sum() - / (num_chains - 1); + double between_variance + = num_draws + * (within_chain_means.array() - across_chain_mean).square().sum() + / (num_chains - 1); double within_variance = - // Divide each row by chains and get sum of squares for each chain (getting a vector back) + // Divide each row by chains and get sum of squares for each chain + // (getting a vector back) ((chains.rowwise() - within_chain_means) - .array() - .square() - .colwise() - // divide each sum of square by num_draws, sum the sum of squares, and divide by num chains - .sum() / (num_draws - 1.0)) - .sum() / num_chains; - - return sqrt((between_variance / within_variance + num_draws - 1) / num_draws); - + .array() + .square() + .colwise() + // divide each sum of square by num_draws, sum the sum of squares, + // and divide by num chains + .sum() + / (num_draws - 1.0)) + .sum() + / num_chains; + + return sqrt((between_variance / within_variance + num_draws - 1) / num_draws); } /** @@ -107,18 +111,19 @@ inline double rhat(const Eigen::MatrixXd& chains) { * @return potential scale reduction for the specified parameter */ inline double compute_potential_scale_reduction_rank( - const std::vector& chain_begins, const std::vector& chain_sizes) { - std::vector nonzero_chain_begins; - std::vector nonzero_chain_sizes; - for (size_t i = 0; i < chain_sizes.size(); ++i) { - if (chain_sizes[i]) { - nonzero_chain_begins.push_back(chain_begins[i]); - nonzero_chain_sizes.push_back(chain_sizes[i]); - } - } - if (!nonzero_chain_sizes.size()) { - return std::numeric_limits::quiet_NaN(); - } + const std::vector& chain_begins, + const std::vector& chain_sizes) { + std::vector nonzero_chain_begins; + std::vector nonzero_chain_sizes; + for (size_t i = 0; i < chain_sizes.size(); ++i) { + if (chain_sizes[i]) { + nonzero_chain_begins.push_back(chain_begins[i]); + nonzero_chain_sizes.push_back(chain_sizes[i]); + } + } + if (!nonzero_chain_sizes.size()) { + return std::numeric_limits::quiet_NaN(); + } std::size_t num_nonzero_chains = nonzero_chain_sizes.size(); std::size_t min_num_draws = nonzero_chain_sizes[0]; for (std::size_t chain = 1; chain < num_nonzero_chains; ++chain) { @@ -146,7 +151,7 @@ inline double compute_potential_scale_reduction_rank( are_all_const |= true; } } - if (are_all_const) { + if (are_all_const) { // If all chains are constant then return NaN // if they all equal the same constant value if (init_draw.isApproxToConstant(init_draw(0))) { @@ -156,7 +161,8 @@ inline double compute_potential_scale_reduction_rank( double rhat_bulk = rhat(rank_transform(draws_matrix)); double rhat_tail = rhat(rank_transform( - (draws_matrix.array() - math::quantile(draws_matrix.reshaped(), 0.5)).abs())); + (draws_matrix.array() - math::quantile(draws_matrix.reshaped(), 0.5)) + .abs())); // return std::make_pair(rhat_bulk, rhat_tail); return std::max(rhat_bulk, rhat_tail); @@ -178,18 +184,19 @@ inline double compute_potential_scale_reduction_rank( * @return potential scale reduction for the specified parameter */ inline double compute_potential_scale_reduction( - const std::vector& chain_begins, const std::vector& chain_sizes) { - std::vector nonzero_chain_begins; - std::vector nonzero_chain_sizes; - for (size_t i = 0; i < chain_sizes.size(); ++i) { - if (chain_sizes[i]) { - nonzero_chain_begins.push_back(chain_begins[i]); - nonzero_chain_sizes.push_back(chain_sizes[i]); - } - } - if (!nonzero_chain_sizes.size()) { - return std::numeric_limits::quiet_NaN(); - } + const std::vector& chain_begins, + const std::vector& chain_sizes) { + std::vector nonzero_chain_begins; + std::vector nonzero_chain_sizes; + for (size_t i = 0; i < chain_sizes.size(); ++i) { + if (chain_sizes[i]) { + nonzero_chain_begins.push_back(chain_begins[i]); + nonzero_chain_sizes.push_back(chain_sizes[i]); + } + } + if (!nonzero_chain_sizes.size()) { + return std::numeric_limits::quiet_NaN(); + } std::size_t num_nonzero_chains = nonzero_chain_sizes.size(); std::size_t min_num_draws = nonzero_chain_sizes[0]; for (std::size_t chain = 1; chain < num_nonzero_chains; ++chain) { @@ -217,7 +224,7 @@ inline double compute_potential_scale_reduction( are_all_const |= true; } } - if (are_all_const) { + if (are_all_const) { // If all chains are constant then return NaN // if they all equal the same constant value if (init_draw.isApproxToConstant(init_draw(0))) { @@ -259,8 +266,8 @@ inline double compute_potential_scale_reduction_rank( * See more details in Stan reference manual section "Potential * Scale Reduction". http://mc-stan.org/users/documentation * - * Current implementation assumes draws are stored in contiguousdereck lively ii height weight - * blocks of memory. Chains are trimmed from the back to match the + * Current implementation assumes draws are stored in contiguousdereck lively ii + * height weight blocks of memory. Chains are trimmed from the back to match the * length of the shortest chain. Argument size will be broadcast to * same length as draws. * @@ -294,14 +301,16 @@ inline double compute_potential_scale_reduction( * @return potential scale reduction for the specified parameter */ inline double compute_split_potential_scale_reduction_rank( - const std::vector& chain_begins, const std::vector& chain_sizes) { + const std::vector& chain_begins, + const std::vector& chain_sizes) { size_t num_chains = chain_sizes.size(); size_t num_draws = chain_sizes[0]; for (size_t chain = 1; chain < num_chains; ++chain) { num_draws = std::min(num_draws, chain_sizes[chain]); } - std::vector split_draws = split_chains(chain_begins, chain_sizes); + std::vector split_draws + = split_chains(chain_begins, chain_sizes); size_t half = std::floor(num_draws / 2.0); std::vector half_sizes(2 * num_chains, half); @@ -326,14 +335,16 @@ inline double compute_split_potential_scale_reduction_rank( * @return potential scale reduction for the specified parameter */ inline double compute_split_potential_scale_reduction( - const std::vector& chain_begins, const std::vector& chain_sizes) { + const std::vector& chain_begins, + const std::vector& chain_sizes) { size_t num_chains = chain_sizes.size(); size_t num_draws = chain_sizes[0]; for (size_t chain = 1; chain < num_chains; ++chain) { num_draws = std::min(num_draws, chain_sizes[chain]); } - std::vector split_draws = split_chains(chain_begins, chain_sizes); + std::vector split_draws + = split_chains(chain_begins, chain_sizes); double half = num_draws / 2.0; std::vector half_sizes(2 * num_chains, std::floor(half)); diff --git a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp index 0d69d57ae8..a682e168e8 100644 --- a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp +++ b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp @@ -70,12 +70,19 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00067,1.00497,1.00918,1.00055,1.0015,1.00088,1.00776,1.00042,1.00201,0.99956,0.99984,1.00054,1.00403,1.00516,1.00591,1.00627,1.00134,1.00895,1.00079,1.00368,1.00092,1.00133,1.01005,1.00107,1.00151,1.00229,1.0,1.00008,1.00315,1.00277,1.00247,1.00003,1.001,1.01267,1.00011,1.00066,1.00091,1.00237,1.00019,1.00104,1.00341,0.99981,1.00033,0.99967,1.00306,1.00072,1.00191,1.00658; + rhat << 1.00067, 1.00497, 1.00918, 1.00055, 1.0015, 1.00088, 1.00776, 1.00042, + 1.00201, 0.99956, 0.99984, 1.00054, 1.00403, 1.00516, 1.00591, 1.00627, + 1.00134, 1.00895, 1.00079, 1.00368, 1.00092, 1.00133, 1.01005, 1.00107, + 1.00151, 1.00229, 1.0, 1.00008, 1.00315, 1.00277, 1.00247, 1.00003, 1.001, + 1.01267, 1.00011, 1.00066, 1.00091, 1.00237, 1.00019, 1.00104, 1.00341, + 0.99981, 1.00033, 0.99967, 1.00306, 1.00072, 1.00191, 1.00658; // Eigen::VectorXd rhat_bulk(48); - // rhat_bulk << 1.00067,0.99979,0.99966,1.00055,1.0011,1.00088,1.00032,0.99997,1.00201,0.99956,0.99956,0.9995,1.00292,1.00516,1.00591,0.99975,1.00088,1.00895,1.00079,0.99953,1.00092,1.00044,1.01005,0.9996,1.00151,0.99966,0.99965,0.99963,1.00315,1.00277,1.00247,1.00003,0.99994,1.00116,0.99952,1.0005,1.00091,1.00213,1.00019,0.99977,1.0003,0.99981,1.00003,0.99967,1.00306,1.00072,0.9996,0.99979; + // rhat_bulk + // << 1.00067,0.99979,0.99966,1.00055,1.0011,1.00088,1.00032,0.99997,1.00201,0.99956,0.99956,0.9995,1.00292,1.00516,1.00591,0.99975,1.00088,1.00895,1.00079,0.99953,1.00092,1.00044,1.01005,0.9996,1.00151,0.99966,0.99965,0.99963,1.00315,1.00277,1.00247,1.00003,0.99994,1.00116,0.99952,1.0005,1.00091,1.00213,1.00019,0.99977,1.0003,0.99981,1.00003,0.99967,1.00306,1.00072,0.9996,0.99979; // Eigen::VectorXd rhat_tail(48); - // rhat_tail << 1.00063,1.00497,1.00918,0.99965,1.0015,0.99962,1.00776,1.00042,0.99963,0.99951,0.99984,1.00054,1.00403,1.00107,1.00287,1.00627,1.00134,0.99957,0.99997,1.00368,1.00053,1.00133,1.00589,1.00107,1.00031,1.00229,1.0,1.00008,1.0001,1.00116,1.00219,0.99992,1.001,1.01267,1.00011,1.00066,1.00065,1.00237,0.9995,1.00104,1.00341,0.99958,1.00033,0.9996,0.99957,1.00058,1.00191,1.00658; + // rhat_tail + // << 1.00063,1.00497,1.00918,0.99965,1.0015,0.99962,1.00776,1.00042,0.99963,0.99951,0.99984,1.00054,1.00403,1.00107,1.00287,1.00627,1.00134,0.99957,0.99997,1.00368,1.00053,1.00133,1.00589,1.00107,1.00031,1.00229,1.0,1.00008,1.0001,1.00116,1.00219,0.99992,1.001,1.01267,1.00011,1.00066,1.00065,1.00237,0.9995,1.00104,1.00341,0.99958,1.00033,0.9996,0.99957,1.00058,1.00191,1.00658; // replicates calls to stan::analyze::compute_effective_sample_size // for any interface *without* access to chains class @@ -90,14 +97,17 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank) { sizes[chain] = samples(chain).size(); } - // double [computed_bulk_rhat, computed_tail_rhat] = stan::analyze::compute_potential_scale_reduction_rank(draws, sizes); + // double [computed_bulk_rhat, computed_tail_rhat] = + // stan::analyze::compute_potential_scale_reduction_rank(draws, sizes); // double expected_bulk_rhat = rhat_bulk(index - 4); // double expected_tail_rhat = rhat_tail(index - 4); // ASSERT_NEAR(expected_bulk_rhat, computed_bulk_rhat, 1e-4) - // << "Bulk Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + // << "Bulk Rhat mismatch for index: " << index << ", parameter: " << + // chains.param_name(index); // ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) - // << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + // << "Tail Rhat mismatch for index: " << index << ", parameter: " << + // chains.param_name(index); ASSERT_NEAR( rhat(index - 4), stan::analyze::compute_potential_scale_reduction_rank(draws, sizes), @@ -417,7 +427,7 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_constant) { Eigen::Matrix draws1; draws1 << 1.0, 1.0, 2.0; chains.add(draws1); - Eigen::Matrix draws2; + Eigen::Matrix draws2; draws2 << 4.0, 4.0, 4.0; chains.add(draws2); @@ -458,6 +468,3 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_nan) { ASSERT_TRUE(std::isnan(chains.split_potential_scale_reduction_rank(0))) << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); } - - - From 51a2504724a37fabb11fcd98b18eded545f631d6 Mon Sep 17 00:00:00 2001 From: aleksgorica Date: Tue, 26 Mar 2024 16:15:48 +0100 Subject: [PATCH 17/25] returning pair for rank rhat --- .../compute_potential_scale_reduction.hpp | 64 ++--- src/stan/mcmc/chains.hpp | 4 +- ...compute_potential_scale_reduction_test.cpp | 253 +++++++++++------- src/test/unit/mcmc/chains_test.cpp | 37 ++- 4 files changed, 218 insertions(+), 140 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index 111e2a796c..8c024a96dc 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -110,20 +110,19 @@ inline double rhat(const Eigen::MatrixXd& chains) { * @param sizes stores sizes of chains * @return potential scale reduction for the specified parameter */ -inline double compute_potential_scale_reduction_rank( - const std::vector& chain_begins, - const std::vector& chain_sizes) { - std::vector nonzero_chain_begins; - std::vector nonzero_chain_sizes; - for (size_t i = 0; i < chain_sizes.size(); ++i) { - if (chain_sizes[i]) { - nonzero_chain_begins.push_back(chain_begins[i]); - nonzero_chain_sizes.push_back(chain_sizes[i]); - } - } - if (!nonzero_chain_sizes.size()) { - return std::numeric_limits::quiet_NaN(); - } +inline std::pair compute_potential_scale_reduction_rank( + const std::vector& chain_begins, const std::vector& chain_sizes) { + std::vector nonzero_chain_begins; + std::vector nonzero_chain_sizes; + for (size_t i = 0; i < chain_sizes.size(); ++i) { + if (chain_sizes[i]) { + nonzero_chain_begins.push_back(chain_begins[i]); + nonzero_chain_sizes.push_back(chain_sizes[i]); + } + } + if (!nonzero_chain_sizes.size()) { + return {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}; + } std::size_t num_nonzero_chains = nonzero_chain_sizes.size(); std::size_t min_num_draws = nonzero_chain_sizes[0]; for (std::size_t chain = 1; chain < num_nonzero_chains; ++chain) { @@ -141,21 +140,20 @@ inline double compute_potential_scale_reduction_rank( for (std::size_t n = 0; n < min_num_draws; n++) { if (!std::isfinite(draws(n))) { - return std::numeric_limits::quiet_NaN(); + return {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}; } draws_matrix(n, chain) = draws(n); } init_draw(chain) = draws(0); - if (!draws.isApproxToConstant(draws(0))) { - are_all_const |= true; - } + are_all_const |= !draws.isApproxToConstant(draws(0)); + } if (are_all_const) { // If all chains are constant then return NaN // if they all equal the same constant value if (init_draw.isApproxToConstant(init_draw(0))) { - return std::numeric_limits::quiet_NaN(); + return {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}; } } @@ -164,8 +162,8 @@ inline double compute_potential_scale_reduction_rank( (draws_matrix.array() - math::quantile(draws_matrix.reshaped(), 0.5)) .abs())); - // return std::make_pair(rhat_bulk, rhat_tail); - return std::max(rhat_bulk, rhat_tail); + return std::make_pair(rhat_bulk, rhat_tail); + //return std::max(rhat_bulk, rhat_tail); } /** @@ -220,17 +218,14 @@ inline double compute_potential_scale_reduction( } init_draw(chain) = draws(0); - if (!draws.isApproxToConstant(draws(0))) { - are_all_const |= true; - } + + are_all_const |= !draws.isApproxToConstant(draws(0)); } - if (are_all_const) { - // If all chains are constant then return NaN - // if they all equal the same constant value - if (init_draw.isApproxToConstant(init_draw(0))) { - return std::numeric_limits::quiet_NaN(); - } + // if they all equal the same constant value + if (init_draw.isApproxToConstant(init_draw(0))) { + return std::numeric_limits::quiet_NaN(); } + return rhat(draws_matrix); } @@ -252,7 +247,7 @@ inline double compute_potential_scale_reduction( * @param size stores sizes of chains * @return potential scale reduction for the specified parameter */ -inline double compute_potential_scale_reduction_rank( +inline std::pair compute_potential_scale_reduction_rank( const std::vector& chain_begins, size_t size) { size_t num_chains = chain_begins.size(); std::vector sizes(num_chains, size); @@ -300,9 +295,8 @@ inline double compute_potential_scale_reduction( * @param chain_sizes stores sizes of chains * @return potential scale reduction for the specified parameter */ -inline double compute_split_potential_scale_reduction_rank( - const std::vector& chain_begins, - const std::vector& chain_sizes) { +inline std::pair compute_split_potential_scale_reduction_rank( + const std::vector& chain_begins, const std::vector& chain_sizes) { size_t num_chains = chain_sizes.size(); size_t num_draws = chain_sizes[0]; for (size_t chain = 1; chain < num_chains; ++chain) { @@ -371,7 +365,7 @@ inline double compute_split_potential_scale_reduction( * @param size stores sizes of chains * @return potential scale reduction for the specified parameter */ -inline double compute_split_potential_scale_reduction_rank( +inline std::pair compute_split_potential_scale_reduction_rank( const std::vector& chain_begins, size_t size) { size_t num_chains = chain_begins.size(); std::vector sizes(num_chains, size); diff --git a/src/stan/mcmc/chains.hpp b/src/stan/mcmc/chains.hpp index 820eeb363d..18b93c504c 100644 --- a/src/stan/mcmc/chains.hpp +++ b/src/stan/mcmc/chains.hpp @@ -595,7 +595,7 @@ class chains { return split_effective_sample_size(index(name)); } - double split_potential_scale_reduction_rank(const int index) const { + std::pair split_potential_scale_reduction_rank(const int index) const { int n_chains = num_chains(); std::vector draws(n_chains); std::vector sizes(n_chains); @@ -625,7 +625,7 @@ class chains { return analyze::compute_split_potential_scale_reduction(draws, sizes); } - double split_potential_scale_reduction_rank(const std::string& name) const { + std::pair split_potential_scale_reduction_rank(const std::string& name) const { return split_potential_scale_reduction_rank(index(name)); } diff --git a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp index a682e168e8..9fe188c19e 100644 --- a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp +++ b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp @@ -69,20 +69,13 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank) { stan::mcmc::chains<> chains(blocker1); chains.add(blocker2); - Eigen::VectorXd rhat(48); - rhat << 1.00067, 1.00497, 1.00918, 1.00055, 1.0015, 1.00088, 1.00776, 1.00042, - 1.00201, 0.99956, 0.99984, 1.00054, 1.00403, 1.00516, 1.00591, 1.00627, - 1.00134, 1.00895, 1.00079, 1.00368, 1.00092, 1.00133, 1.01005, 1.00107, - 1.00151, 1.00229, 1.0, 1.00008, 1.00315, 1.00277, 1.00247, 1.00003, 1.001, - 1.01267, 1.00011, 1.00066, 1.00091, 1.00237, 1.00019, 1.00104, 1.00341, - 0.99981, 1.00033, 0.99967, 1.00306, 1.00072, 1.00191, 1.00658; - - // Eigen::VectorXd rhat_bulk(48); - // rhat_bulk - // << 1.00067,0.99979,0.99966,1.00055,1.0011,1.00088,1.00032,0.99997,1.00201,0.99956,0.99956,0.9995,1.00292,1.00516,1.00591,0.99975,1.00088,1.00895,1.00079,0.99953,1.00092,1.00044,1.01005,0.9996,1.00151,0.99966,0.99965,0.99963,1.00315,1.00277,1.00247,1.00003,0.99994,1.00116,0.99952,1.0005,1.00091,1.00213,1.00019,0.99977,1.0003,0.99981,1.00003,0.99967,1.00306,1.00072,0.9996,0.99979; - // Eigen::VectorXd rhat_tail(48); - // rhat_tail - // << 1.00063,1.00497,1.00918,0.99965,1.0015,0.99962,1.00776,1.00042,0.99963,0.99951,0.99984,1.00054,1.00403,1.00107,1.00287,1.00627,1.00134,0.99957,0.99997,1.00368,1.00053,1.00133,1.00589,1.00107,1.00031,1.00229,1.0,1.00008,1.0001,1.00116,1.00219,0.99992,1.001,1.01267,1.00011,1.00066,1.00065,1.00237,0.9995,1.00104,1.00341,0.99958,1.00033,0.9996,0.99957,1.00058,1.00191,1.00658; + // Eigen::VectorXd rhat(48); + // rhat << 1.00067,1.00497,1.00918,1.00055,1.0015,1.00088,1.00776,1.00042,1.00201,0.99956,0.99984,1.00054,1.00403,1.00516,1.00591,1.00627,1.00134,1.00895,1.00079,1.00368,1.00092,1.00133,1.01005,1.00107,1.00151,1.00229,1.0,1.00008,1.00315,1.00277,1.00247,1.00003,1.001,1.01267,1.00011,1.00066,1.00091,1.00237,1.00019,1.00104,1.00341,0.99981,1.00033,0.99967,1.00306,1.00072,1.00191,1.00658; + + Eigen::VectorXd rhat_bulk(48); + rhat_bulk << 1.00067,0.99979,0.99966,1.00055,1.0011,1.00088,1.00032,0.99997,1.00201,0.99956,0.99956,0.9995,1.00292,1.00516,1.00591,0.99975,1.00088,1.00895,1.00079,0.99953,1.00092,1.00044,1.01005,0.9996,1.00151,0.99966,0.99965,0.99963,1.00315,1.00277,1.00247,1.00003,0.99994,1.00116,0.99952,1.0005,1.00091,1.00213,1.00019,0.99977,1.0003,0.99981,1.00003,0.99967,1.00306,1.00072,0.9996,0.99979; + Eigen::VectorXd rhat_tail(48); + rhat_tail << 1.00063,1.00497,1.00918,0.99965,1.0015,0.99962,1.00776,1.00042,0.99963,0.99951,0.99984,1.00054,1.00403,1.00107,1.00287,1.00627,1.00134,0.99957,0.99997,1.00368,1.00053,1.00133,1.00589,1.00107,1.00031,1.00229,1.0,1.00008,1.0001,1.00116,1.00219,0.99992,1.001,1.01267,1.00011,1.00066,1.00065,1.00237,0.9995,1.00104,1.00341,0.99958,1.00033,0.9996,0.99957,1.00058,1.00191,1.00658; // replicates calls to stan::analyze::compute_effective_sample_size // for any interface *without* access to chains class @@ -96,24 +89,21 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank) { draws[chain] = &samples(chain)(0); sizes[chain] = samples(chain).size(); } - - // double [computed_bulk_rhat, computed_tail_rhat] = - // stan::analyze::compute_potential_scale_reduction_rank(draws, sizes); - // double expected_bulk_rhat = rhat_bulk(index - 4); - // double expected_tail_rhat = rhat_tail(index - 4); - - // ASSERT_NEAR(expected_bulk_rhat, computed_bulk_rhat, 1e-4) - // << "Bulk Rhat mismatch for index: " << index << ", parameter: " << - // chains.param_name(index); - // ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) - // << "Tail Rhat mismatch for index: " << index << ", parameter: " << - // chains.param_name(index); - ASSERT_NEAR( - rhat(index - 4), - stan::analyze::compute_potential_scale_reduction_rank(draws, sizes), - 1e-4) - << "rhat for index: " << index - << ", parameter: " << chains.param_name(index); + double computed_bulk_rhat, computed_tail_rhat; + std::tie(computed_bulk_rhat, computed_tail_rhat) = stan::analyze::compute_potential_scale_reduction_rank(draws, sizes); + double expected_bulk_rhat = rhat_bulk(index - 4); + double expected_tail_rhat = rhat_tail(index - 4); + + ASSERT_NEAR(expected_bulk_rhat, computed_bulk_rhat, 1e-4) + << "Bulk Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) + << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + // ASSERT_NEAR( + // rhat(index - 4), + // stan::analyze::compute_potential_scale_reduction_rank(draws, sizes), + // 1e-4) + // << "rhat for index: " << index + // << ", parameter: " << chains.param_name(index); } } @@ -167,13 +157,20 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_convenience) { stan::mcmc::chains<> chains(blocker1); chains.add(blocker2); - Eigen::VectorXd rhat(48); - rhat << 1.00067, 1.00497, 1.00918, 1.00055, 1.0015, 1.00088, 1.00776, 1.00042, - 1.00201, 0.999558, 0.99984, 1.00054, 1.00403, 1.00516, 1.00591, 1.00627, - 1.00134, 1.00895, 1.00079, 1.00368, 1.00092, 1.00133, 1.01005, 1.00107, - 1.00151, 1.00229, 0.999998, 1.00008, 1.00315, 1.00277, 1.00247, 1.00003, - 1.001, 1.01267, 1.00011, 1.00066, 1.00091, 1.00237, 1.00019, 1.00104, - 1.00341, 0.999815, 1.00033, 0.999672, 1.00306, 1.00072, 1.00191, 1.00658; + // Eigen::VectorXd rhat(48); + // rhat << 1.00067, 1.00497, 1.00918, 1.00055, 1.0015, 1.00088, 1.00776, 1.00042, + // 1.00201, 0.999558, 0.99984, 1.00054, 1.00403, 1.00516, 1.00591, 1.00627, + // 1.00134, 1.00895, 1.00079, 1.00368, 1.00092, 1.00133, 1.01005, 1.00107, + // 1.00151, 1.00229, 0.999998, 1.00008, 1.00315, 1.00277, 1.00247, 1.00003, + // 1.001, 1.01267, 1.00011, 1.00066, 1.00091, 1.00237, 1.00019, 1.00104, + // 1.00341, 0.999815, 1.00033, 0.999672, 1.00306, 1.00072, 1.00191, 1.00658; + + + Eigen::VectorXd rhat_bulk(48); + rhat_bulk << 1.00067,0.99979,0.99966,1.00055,1.0011,1.00088,1.00032,0.99997,1.00201,0.99956,0.99956,0.9995,1.00292,1.00516,1.00591,0.99975,1.00088,1.00895,1.00079,0.99953,1.00092,1.00044,1.01005,0.9996,1.00151,0.99966,0.99965,0.99963,1.00315,1.00277,1.00247,1.00003,0.99994,1.00116,0.99952,1.0005,1.00091,1.00213,1.00019,0.99977,1.0003,0.99981,1.00003,0.99967,1.00306,1.00072,0.9996,0.99979; + Eigen::VectorXd rhat_tail(48); + rhat_tail << 1.00063,1.00497,1.00918,0.99965,1.0015,0.99962,1.00776,1.00042,0.99963,0.99951,0.99984,1.00054,1.00403,1.00107,1.00287,1.00627,1.00134,0.99957,0.99997,1.00368,1.00053,1.00133,1.00589,1.00107,1.00031,1.00229,1.0,1.00008,1.0001,1.00116,1.00219,0.99992,1.001,1.01267,1.00011,1.00066,1.00065,1.00237,0.9995,1.00104,1.00341,0.99958,1.00033,0.9996,0.99957,1.00058,1.00191,1.00658; + Eigen::Matrix samples( chains.num_chains()); @@ -185,12 +182,22 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_convenience) { draws[chain] = &samples(chain)(0); } size_t size = samples(0).size(); - ASSERT_NEAR( - rhat(index - 4), - stan::analyze::compute_potential_scale_reduction_rank(draws, size), - 1e-4) - << "rhat for index: " << index - << ", parameter: " << chains.param_name(index); + + double computed_bulk_rhat, computed_tail_rhat; + std::tie(computed_bulk_rhat, computed_tail_rhat) = stan::analyze::compute_potential_scale_reduction_rank(draws, size); + double expected_bulk_rhat = rhat_bulk(index - 4); + double expected_tail_rhat = rhat_tail(index - 4); + + ASSERT_NEAR(expected_bulk_rhat, computed_bulk_rhat, 1e-4) + << "Bulk Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) + << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + // ASSERT_NEAR( + // rhat(index - 4), + // stan::analyze::compute_potential_scale_reduction_rank(draws, size), + // 1e-4) + // << "rhat for index: " << index + // << ", parameter: " << chains.param_name(index); } } @@ -239,19 +246,35 @@ TEST_F(ComputeRhat, chains_compute_split_potential_scale_reduction_rank) { stan::mcmc::chains<> chains(blocker1); chains.add(blocker2); - Eigen::VectorXd rhat(48); - rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, - 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, - 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, - 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, - 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, - 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; + // Eigen::VectorXd rhat(48); + // rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, + // 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, + // 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, + // 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, + // 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, + // 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; + + Eigen::VectorXd rhat_bulk(48); + rhat_bulk << 1.0078,1.0109,0.99919,1.001,1.00401,1.00992,1.00182,1.00519,1.00095,1.00351,1.00554,1.00075,1.00595,1.00473,1.00546,1.01304,1.00166,1.0074,1.00178,1.00588,1.00406,1.00129,1.00976,1.0013,1.00193,1.00104,0.99938,1.00025,1.01082,1.0019,1.00354,1.0043,1.00111,1.00281,1.00436,1.00515,1.00325,1.0089,1.00222,1.00118,1.00191,1.00283,1.0003,1.00216,1.00335,1.00133,1.00023,1.0109; + Eigen::VectorXd rhat_tail(48); + rhat_tail << 1.00097,1.00422,1.00731,1.00333,1.00337,0.99917,1.00734,1.00633,1.00074,1.00906,1.01019,1.00074,1.00447,1.00383,1.00895,1.00389,1.00052,1.00188,1.00236,1.00284,1.00414,1.00303,1.00327,1.00295,1.00037,1.0044,1.00488,1.00178,1.00475,1.00082,1.00413,1.01303,1.0024,1.01148,1.00098,1.00078,1.00712,1.00595,1.00124,1.00112,1.00381,1.0006,1.00188,1.00225,1.0026,1.0009,1.00209,1.00464; + for (int index = 4; index < chains.num_params(); index++) { - ASSERT_NEAR(rhat(index - 4), - chains.split_potential_scale_reduction_rank(index), 1e-4) - << "rhat for index: " << index - << ", parameter: " << chains.param_name(index); + double computed_bulk_rhat, computed_tail_rhat; + std::tie(computed_bulk_rhat, computed_tail_rhat) = chains.split_potential_scale_reduction_rank(index); + double expected_bulk_rhat = rhat_bulk(index - 4); + double expected_tail_rhat = rhat_tail(index - 4); + + ASSERT_NEAR(expected_bulk_rhat, computed_bulk_rhat, 1e-4) + << "Bulk Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) + << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + + // ASSERT_NEAR(rhat(index - 4), + // chains.split_potential_scale_reduction_rank(index), 1e-4) + // << "rhat for index: " << index + // << ", parameter: " << chains.param_name(index); } for (int index = 0; index < chains.num_params(); index++) { std::string name = chains.param_name(index); @@ -314,13 +337,18 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_rank) { chains.add(blocker2); - Eigen::VectorXd rhat(48); - rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, - 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, - 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, - 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, - 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, - 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; + // Eigen::VectorXd rhat(48); + // rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, + // 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, + // 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, + // 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, + // 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, + // 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; + + Eigen::VectorXd rhat_bulk(48); + rhat_bulk << 1.0078,1.0109,0.99919,1.001,1.00401,1.00992,1.00182,1.00519,1.00095,1.00351,1.00554,1.00075,1.00595,1.00473,1.00546,1.01304,1.00166,1.0074,1.00178,1.00588,1.00406,1.00129,1.00976,1.0013,1.00193,1.00104,0.99938,1.00025,1.01082,1.0019,1.00354,1.0043,1.00111,1.00281,1.00436,1.00515,1.00325,1.0089,1.00222,1.00118,1.00191,1.00283,1.0003,1.00216,1.00335,1.00133,1.00023,1.0109; + Eigen::VectorXd rhat_tail(48); + rhat_tail << 1.00097,1.00422,1.00731,1.00333,1.00337,0.99917,1.00734,1.00633,1.00074,1.00906,1.01019,1.00074,1.00447,1.00383,1.00895,1.00389,1.00052,1.00188,1.00236,1.00284,1.00414,1.00303,1.00327,1.00295,1.00037,1.0044,1.00488,1.00178,1.00475,1.00082,1.00413,1.01303,1.0024,1.01148,1.00098,1.00078,1.00712,1.00595,1.00124,1.00112,1.00381,1.0006,1.00188,1.00225,1.0026,1.0009,1.00209,1.00464; // replicates calls to stan::analyze::compute_effective_sample_size // for any interface *without* access to chains class @@ -334,12 +362,24 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_rank) { draws[chain] = &samples(chain)(0); sizes[chain] = samples(chain).size(); } - ASSERT_NEAR(rhat(index - 4), - stan::analyze::compute_split_potential_scale_reduction_rank( - draws, sizes), - 1e-4) - << "rhat for index: " << index - << ", parameter: " << chains.param_name(index); + + double computed_bulk_rhat, computed_tail_rhat; + std::tie(computed_bulk_rhat, computed_tail_rhat) = stan::analyze::compute_split_potential_scale_reduction_rank(draws, sizes); + double expected_bulk_rhat = rhat_bulk(index - 4); + double expected_tail_rhat = rhat_tail(index - 4); + + ASSERT_NEAR(expected_bulk_rhat, computed_bulk_rhat, 1e-4) + << "Bulk Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) + << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + + + // ASSERT_NEAR(rhat(index - 4), + // stan::analyze::compute_split_potential_scale_reduction_rank( + // draws, sizes), + // 1e-4) + // << "rhat for index: " << index + // << ", parameter: " << chains.param_name(index); } } @@ -393,13 +433,20 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience_rank) { stan::mcmc::chains<> chains(blocker1); chains.add(blocker2); - Eigen::VectorXd rhat(48); - rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, - 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, - 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, - 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, - 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, - 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; + // Eigen::VectorXd rhat(48); + // rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, + // 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, + // 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, + // 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, + // 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, + // 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; + + + Eigen::VectorXd rhat_bulk(48); + rhat_bulk << 1.0078,1.0109,0.99919,1.001,1.00401,1.00992,1.00182,1.00519,1.00095,1.00351,1.00554,1.00075,1.00595,1.00473,1.00546,1.01304,1.00166,1.0074,1.00178,1.00588,1.00406,1.00129,1.00976,1.0013,1.00193,1.00104,0.99938,1.00025,1.01082,1.0019,1.00354,1.0043,1.00111,1.00281,1.00436,1.00515,1.00325,1.0089,1.00222,1.00118,1.00191,1.00283,1.0003,1.00216,1.00335,1.00133,1.00023,1.0109; + Eigen::VectorXd rhat_tail(48); + rhat_tail << 1.00097,1.00422,1.00731,1.00333,1.00337,0.99917,1.00734,1.00633,1.00074,1.00906,1.01019,1.00074,1.00447,1.00383,1.00895,1.00389,1.00052,1.00188,1.00236,1.00284,1.00414,1.00303,1.00327,1.00295,1.00037,1.0044,1.00488,1.00178,1.00475,1.00082,1.00413,1.01303,1.0024,1.01148,1.00098,1.00078,1.00712,1.00595,1.00124,1.00112,1.00381,1.0006,1.00188,1.00225,1.0026,1.0009,1.00209,1.00464; + Eigen::Matrix samples( chains.num_chains()); @@ -412,26 +459,31 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience_rank) { draws[chain] = &samples(chain)(0); } size_t size = samples(0).size(); - ASSERT_NEAR(rhat(index - 4), - stan::analyze::compute_split_potential_scale_reduction_rank( - draws, size), - 1e-4) - << "rhat for index: " << index - << ", parameter: " << chains.param_name(index); + + double computed_bulk_rhat, computed_tail_rhat; + std::tie(computed_bulk_rhat, computed_tail_rhat) = stan::analyze::compute_split_potential_scale_reduction_rank(draws, size); + double expected_bulk_rhat = rhat_bulk(index - 4); + double expected_tail_rhat = rhat_tail(index - 4); + + ASSERT_NEAR(expected_bulk_rhat, computed_bulk_rhat, 1e-4) + << "Bulk Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) + << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + // ASSERT_NEAR(rhat(index - 4), + // stan::analyze::compute_split_potential_scale_reduction_rank( + // draws, size), + // 1e-4) + // << "rhat for index: " << index + // << ", parameter: " << chains.param_name(index); } } TEST_F(ComputeRhat, compute_potential_scale_reduction_constant) { std::vector param_names{"a"}; stan::mcmc::chains<> chains(param_names); - Eigen::Matrix draws1; - draws1 << 1.0, 1.0, 2.0; - chains.add(draws1); - Eigen::Matrix draws2; - draws2 << 4.0, 4.0, 4.0; - chains.add(draws2); - - std::cout << "SOMETHING" << std::endl; + Eigen::Matrix draws; + draws << 1.0, 1.0; + chains.add(draws); ASSERT_TRUE(std::isnan(chains.split_potential_scale_reduction(0))) << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); @@ -444,8 +496,15 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_constant) { draws << 1.0, 1.0; chains.add(draws); - ASSERT_TRUE(std::isnan(chains.split_potential_scale_reduction_rank(0))) + double computed_bulk_rhat, computed_tail_rhat; + std::tie(computed_bulk_rhat, computed_tail_rhat) = chains.split_potential_scale_reduction_rank(0); + + ASSERT_TRUE(std::isnan(computed_bulk_rhat)) + << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); + ASSERT_TRUE(std::isnan(computed_tail_rhat)) << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); + // ASSERT_TRUE(std::isnan(chains.split_potential_scale_reduction_rank(0))) + // << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); } TEST_F(ComputeRhat, compute_potential_scale_reduction_nan) { @@ -465,6 +524,16 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_nan) { Eigen::Matrix draws; draws << 1.0, std::numeric_limits::quiet_NaN(); chains.add(draws); - ASSERT_TRUE(std::isnan(chains.split_potential_scale_reduction_rank(0))) + + double computed_bulk_rhat, computed_tail_rhat; + std::tie(computed_bulk_rhat, computed_tail_rhat) = chains.split_potential_scale_reduction_rank(0); + + ASSERT_TRUE(std::isnan(computed_bulk_rhat)) << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); + ASSERT_TRUE(std::isnan(computed_tail_rhat)) + << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); + + + // ASSERT_TRUE(std::isnan(chains.split_potential_scale_reduction_rank(0))) + // << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); } diff --git a/src/test/unit/mcmc/chains_test.cpp b/src/test/unit/mcmc/chains_test.cpp index d9c8194e43..26ca3dbea6 100644 --- a/src/test/unit/mcmc/chains_test.cpp +++ b/src/test/unit/mcmc/chains_test.cpp @@ -886,19 +886,34 @@ TEST_F(McmcChains, blocker_split_potential_scale_reduction_rank) { stan::mcmc::chains<> chains(blocker1); chains.add(blocker2); - Eigen::VectorXd rhat(48); - rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, - 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, - 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, - 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, - 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, - 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; + // Eigen::VectorXd rhat(48); + // rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, + // 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, + // 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, + // 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, + // 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, + // 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; + + Eigen::VectorXd rhat_bulk(48); + rhat_bulk << 1.0078,1.0109,0.99919,1.001,1.00401,1.00992,1.00182,1.00519,1.00095,1.00351,1.00554,1.00075,1.00595,1.00473,1.00546,1.01304,1.00166,1.0074,1.00178,1.00588,1.00406,1.00129,1.00976,1.0013,1.00193,1.00104,0.99938,1.00025,1.01082,1.0019,1.00354,1.0043,1.00111,1.00281,1.00436,1.00515,1.00325,1.0089,1.00222,1.00118,1.00191,1.00283,1.0003,1.00216,1.00335,1.00133,1.00023,1.0109; + Eigen::VectorXd rhat_tail(48); + rhat_tail << 1.00097,1.00422,1.00731,1.00333,1.00337,0.99917,1.00734,1.00633,1.00074,1.00906,1.01019,1.00074,1.00447,1.00383,1.00895,1.00389,1.00052,1.00188,1.00236,1.00284,1.00414,1.00303,1.00327,1.00295,1.00037,1.0044,1.00488,1.00178,1.00475,1.00082,1.00413,1.01303,1.0024,1.01148,1.00098,1.00078,1.00712,1.00595,1.00124,1.00112,1.00381,1.0006,1.00188,1.00225,1.0026,1.0009,1.00209,1.00464; for (int index = 4; index < chains.num_params(); index++) { - ASSERT_NEAR(rhat(index - 4), - chains.split_potential_scale_reduction_rank(index), 1e-4) - << "rhat for index: " << index - << ", parameter: " << chains.param_name(index); + double computed_bulk_rhat, computed_tail_rhat; + std::tie(computed_bulk_rhat, computed_tail_rhat) = chains.split_potential_scale_reduction_rank(index); + double expected_bulk_rhat = rhat_bulk(index - 4); + double expected_tail_rhat = rhat_tail(index - 4); + + ASSERT_NEAR(expected_bulk_rhat, computed_bulk_rhat, 1e-4) + << "Bulk Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) + << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + + // ASSERT_NEAR(rhat(index - 4), + // chains.split_potential_scale_reduction_rank(index), 1e-4) + // << "rhat for index: " << index + // << ", parameter: " << chains.param_name(index); } for (int index = 0; index < chains.num_params(); index++) { From ba2b6f5a4ea4fe145acc86f7f29a4d3560568932 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 27 Mar 2024 10:36:34 -0400 Subject: [PATCH 18/25] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- .../compute_potential_scale_reduction.hpp | 41 +++-- src/stan/mcmc/chains.hpp | 6 +- ...compute_potential_scale_reduction_test.cpp | 170 +++++++++++++----- src/test/unit/mcmc/chains_test.cpp | 28 ++- 4 files changed, 173 insertions(+), 72 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index 8c024a96dc..e9daa6f8a6 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -111,18 +111,20 @@ inline double rhat(const Eigen::MatrixXd& chains) { * @return potential scale reduction for the specified parameter */ inline std::pair compute_potential_scale_reduction_rank( - const std::vector& chain_begins, const std::vector& chain_sizes) { - std::vector nonzero_chain_begins; - std::vector nonzero_chain_sizes; - for (size_t i = 0; i < chain_sizes.size(); ++i) { - if (chain_sizes[i]) { - nonzero_chain_begins.push_back(chain_begins[i]); - nonzero_chain_sizes.push_back(chain_sizes[i]); - } - } - if (!nonzero_chain_sizes.size()) { - return {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}; - } + const std::vector& chain_begins, + const std::vector& chain_sizes) { + std::vector nonzero_chain_begins; + std::vector nonzero_chain_sizes; + for (size_t i = 0; i < chain_sizes.size(); ++i) { + if (chain_sizes[i]) { + nonzero_chain_begins.push_back(chain_begins[i]); + nonzero_chain_sizes.push_back(chain_sizes[i]); + } + } + if (!nonzero_chain_sizes.size()) { + return {std::numeric_limits::quiet_NaN(), + std::numeric_limits::quiet_NaN()}; + } std::size_t num_nonzero_chains = nonzero_chain_sizes.size(); std::size_t min_num_draws = nonzero_chain_sizes[0]; for (std::size_t chain = 1; chain < num_nonzero_chains; ++chain) { @@ -140,20 +142,21 @@ inline std::pair compute_potential_scale_reduction_rank( for (std::size_t n = 0; n < min_num_draws; n++) { if (!std::isfinite(draws(n))) { - return {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}; + return {std::numeric_limits::quiet_NaN(), + std::numeric_limits::quiet_NaN()}; } draws_matrix(n, chain) = draws(n); } init_draw(chain) = draws(0); are_all_const |= !draws.isApproxToConstant(draws(0)); - } if (are_all_const) { // If all chains are constant then return NaN // if they all equal the same constant value if (init_draw.isApproxToConstant(init_draw(0))) { - return {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}; + return {std::numeric_limits::quiet_NaN(), + std::numeric_limits::quiet_NaN()}; } } @@ -163,7 +166,7 @@ inline std::pair compute_potential_scale_reduction_rank( .abs())); return std::make_pair(rhat_bulk, rhat_tail); - //return std::max(rhat_bulk, rhat_tail); + // return std::max(rhat_bulk, rhat_tail); } /** @@ -218,14 +221,13 @@ inline double compute_potential_scale_reduction( } init_draw(chain) = draws(0); - + are_all_const |= !draws.isApproxToConstant(draws(0)); } // if they all equal the same constant value if (init_draw.isApproxToConstant(init_draw(0))) { return std::numeric_limits::quiet_NaN(); } - return rhat(draws_matrix); } @@ -296,7 +298,8 @@ inline double compute_potential_scale_reduction( * @return potential scale reduction for the specified parameter */ inline std::pair compute_split_potential_scale_reduction_rank( - const std::vector& chain_begins, const std::vector& chain_sizes) { + const std::vector& chain_begins, + const std::vector& chain_sizes) { size_t num_chains = chain_sizes.size(); size_t num_draws = chain_sizes[0]; for (size_t chain = 1; chain < num_chains; ++chain) { diff --git a/src/stan/mcmc/chains.hpp b/src/stan/mcmc/chains.hpp index 18b93c504c..a553fd36cd 100644 --- a/src/stan/mcmc/chains.hpp +++ b/src/stan/mcmc/chains.hpp @@ -595,7 +595,8 @@ class chains { return split_effective_sample_size(index(name)); } - std::pair split_potential_scale_reduction_rank(const int index) const { + std::pair split_potential_scale_reduction_rank( + const int index) const { int n_chains = num_chains(); std::vector draws(n_chains); std::vector sizes(n_chains); @@ -625,7 +626,8 @@ class chains { return analyze::compute_split_potential_scale_reduction(draws, sizes); } - std::pair split_potential_scale_reduction_rank(const std::string& name) const { + std::pair split_potential_scale_reduction_rank( + const std::string& name) const { return split_potential_scale_reduction_rank(index(name)); } diff --git a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp index 9fe188c19e..4625bb37b7 100644 --- a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp +++ b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp @@ -70,12 +70,25 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank) { chains.add(blocker2); // Eigen::VectorXd rhat(48); - // rhat << 1.00067,1.00497,1.00918,1.00055,1.0015,1.00088,1.00776,1.00042,1.00201,0.99956,0.99984,1.00054,1.00403,1.00516,1.00591,1.00627,1.00134,1.00895,1.00079,1.00368,1.00092,1.00133,1.01005,1.00107,1.00151,1.00229,1.0,1.00008,1.00315,1.00277,1.00247,1.00003,1.001,1.01267,1.00011,1.00066,1.00091,1.00237,1.00019,1.00104,1.00341,0.99981,1.00033,0.99967,1.00306,1.00072,1.00191,1.00658; + // rhat + // << 1.00067,1.00497,1.00918,1.00055,1.0015,1.00088,1.00776,1.00042,1.00201,0.99956,0.99984,1.00054,1.00403,1.00516,1.00591,1.00627,1.00134,1.00895,1.00079,1.00368,1.00092,1.00133,1.01005,1.00107,1.00151,1.00229,1.0,1.00008,1.00315,1.00277,1.00247,1.00003,1.001,1.01267,1.00011,1.00066,1.00091,1.00237,1.00019,1.00104,1.00341,0.99981,1.00033,0.99967,1.00306,1.00072,1.00191,1.00658; Eigen::VectorXd rhat_bulk(48); - rhat_bulk << 1.00067,0.99979,0.99966,1.00055,1.0011,1.00088,1.00032,0.99997,1.00201,0.99956,0.99956,0.9995,1.00292,1.00516,1.00591,0.99975,1.00088,1.00895,1.00079,0.99953,1.00092,1.00044,1.01005,0.9996,1.00151,0.99966,0.99965,0.99963,1.00315,1.00277,1.00247,1.00003,0.99994,1.00116,0.99952,1.0005,1.00091,1.00213,1.00019,0.99977,1.0003,0.99981,1.00003,0.99967,1.00306,1.00072,0.9996,0.99979; + rhat_bulk << 1.00067, 0.99979, 0.99966, 1.00055, 1.0011, 1.00088, 1.00032, + 0.99997, 1.00201, 0.99956, 0.99956, 0.9995, 1.00292, 1.00516, 1.00591, + 0.99975, 1.00088, 1.00895, 1.00079, 0.99953, 1.00092, 1.00044, 1.01005, + 0.9996, 1.00151, 0.99966, 0.99965, 0.99963, 1.00315, 1.00277, 1.00247, + 1.00003, 0.99994, 1.00116, 0.99952, 1.0005, 1.00091, 1.00213, 1.00019, + 0.99977, 1.0003, 0.99981, 1.00003, 0.99967, 1.00306, 1.00072, 0.9996, + 0.99979; Eigen::VectorXd rhat_tail(48); - rhat_tail << 1.00063,1.00497,1.00918,0.99965,1.0015,0.99962,1.00776,1.00042,0.99963,0.99951,0.99984,1.00054,1.00403,1.00107,1.00287,1.00627,1.00134,0.99957,0.99997,1.00368,1.00053,1.00133,1.00589,1.00107,1.00031,1.00229,1.0,1.00008,1.0001,1.00116,1.00219,0.99992,1.001,1.01267,1.00011,1.00066,1.00065,1.00237,0.9995,1.00104,1.00341,0.99958,1.00033,0.9996,0.99957,1.00058,1.00191,1.00658; + rhat_tail << 1.00063, 1.00497, 1.00918, 0.99965, 1.0015, 0.99962, 1.00776, + 1.00042, 0.99963, 0.99951, 0.99984, 1.00054, 1.00403, 1.00107, 1.00287, + 1.00627, 1.00134, 0.99957, 0.99997, 1.00368, 1.00053, 1.00133, 1.00589, + 1.00107, 1.00031, 1.00229, 1.0, 1.00008, 1.0001, 1.00116, 1.00219, + 0.99992, 1.001, 1.01267, 1.00011, 1.00066, 1.00065, 1.00237, 0.9995, + 1.00104, 1.00341, 0.99958, 1.00033, 0.9996, 0.99957, 1.00058, 1.00191, + 1.00658; // replicates calls to stan::analyze::compute_effective_sample_size // for any interface *without* access to chains class @@ -90,14 +103,17 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank) { sizes[chain] = samples(chain).size(); } double computed_bulk_rhat, computed_tail_rhat; - std::tie(computed_bulk_rhat, computed_tail_rhat) = stan::analyze::compute_potential_scale_reduction_rank(draws, sizes); + std::tie(computed_bulk_rhat, computed_tail_rhat) + = stan::analyze::compute_potential_scale_reduction_rank(draws, sizes); double expected_bulk_rhat = rhat_bulk(index - 4); double expected_tail_rhat = rhat_tail(index - 4); ASSERT_NEAR(expected_bulk_rhat, computed_bulk_rhat, 1e-4) - << "Bulk Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + << "Bulk Rhat mismatch for index: " << index + << ", parameter: " << chains.param_name(index); ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) - << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + << "Tail Rhat mismatch for index: " << index + << ", parameter: " << chains.param_name(index); // ASSERT_NEAR( // rhat(index - 4), // stan::analyze::compute_potential_scale_reduction_rank(draws, sizes), @@ -158,19 +174,33 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_convenience) { chains.add(blocker2); // Eigen::VectorXd rhat(48); - // rhat << 1.00067, 1.00497, 1.00918, 1.00055, 1.0015, 1.00088, 1.00776, 1.00042, - // 1.00201, 0.999558, 0.99984, 1.00054, 1.00403, 1.00516, 1.00591, 1.00627, + // rhat + // << 1.00067, 1.00497, 1.00918, 1.00055, 1.0015, 1.00088, 1.00776, 1.00042, + // 1.00201, 0.999558, + // 0.99984, 1.00054, 1.00403, 1.00516, 1.00591, 1.00627, // 1.00134, 1.00895, 1.00079, 1.00368, 1.00092, 1.00133, 1.01005, 1.00107, - // 1.00151, 1.00229, 0.999998, 1.00008, 1.00315, 1.00277, 1.00247, 1.00003, + // 1.00151, 1.00229, + // 0.999998, 1.00008, 1.00315, 1.00277, 1.00247, 1.00003, // 1.001, 1.01267, 1.00011, 1.00066, 1.00091, 1.00237, 1.00019, 1.00104, - // 1.00341, 0.999815, 1.00033, 0.999672, 1.00306, 1.00072, 1.00191, 1.00658; - + // 1.00341, 0.999815, 1.00033, + // 0.999672, 1.00306, 1.00072, 1.00191, 1.00658; Eigen::VectorXd rhat_bulk(48); - rhat_bulk << 1.00067,0.99979,0.99966,1.00055,1.0011,1.00088,1.00032,0.99997,1.00201,0.99956,0.99956,0.9995,1.00292,1.00516,1.00591,0.99975,1.00088,1.00895,1.00079,0.99953,1.00092,1.00044,1.01005,0.9996,1.00151,0.99966,0.99965,0.99963,1.00315,1.00277,1.00247,1.00003,0.99994,1.00116,0.99952,1.0005,1.00091,1.00213,1.00019,0.99977,1.0003,0.99981,1.00003,0.99967,1.00306,1.00072,0.9996,0.99979; + rhat_bulk << 1.00067, 0.99979, 0.99966, 1.00055, 1.0011, 1.00088, 1.00032, + 0.99997, 1.00201, 0.99956, 0.99956, 0.9995, 1.00292, 1.00516, 1.00591, + 0.99975, 1.00088, 1.00895, 1.00079, 0.99953, 1.00092, 1.00044, 1.01005, + 0.9996, 1.00151, 0.99966, 0.99965, 0.99963, 1.00315, 1.00277, 1.00247, + 1.00003, 0.99994, 1.00116, 0.99952, 1.0005, 1.00091, 1.00213, 1.00019, + 0.99977, 1.0003, 0.99981, 1.00003, 0.99967, 1.00306, 1.00072, 0.9996, + 0.99979; Eigen::VectorXd rhat_tail(48); - rhat_tail << 1.00063,1.00497,1.00918,0.99965,1.0015,0.99962,1.00776,1.00042,0.99963,0.99951,0.99984,1.00054,1.00403,1.00107,1.00287,1.00627,1.00134,0.99957,0.99997,1.00368,1.00053,1.00133,1.00589,1.00107,1.00031,1.00229,1.0,1.00008,1.0001,1.00116,1.00219,0.99992,1.001,1.01267,1.00011,1.00066,1.00065,1.00237,0.9995,1.00104,1.00341,0.99958,1.00033,0.9996,0.99957,1.00058,1.00191,1.00658; - + rhat_tail << 1.00063, 1.00497, 1.00918, 0.99965, 1.0015, 0.99962, 1.00776, + 1.00042, 0.99963, 0.99951, 0.99984, 1.00054, 1.00403, 1.00107, 1.00287, + 1.00627, 1.00134, 0.99957, 0.99997, 1.00368, 1.00053, 1.00133, 1.00589, + 1.00107, 1.00031, 1.00229, 1.0, 1.00008, 1.0001, 1.00116, 1.00219, + 0.99992, 1.001, 1.01267, 1.00011, 1.00066, 1.00065, 1.00237, 0.9995, + 1.00104, 1.00341, 0.99958, 1.00033, 0.9996, 0.99957, 1.00058, 1.00191, + 1.00658; Eigen::Matrix samples( chains.num_chains()); @@ -184,14 +214,17 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_convenience) { size_t size = samples(0).size(); double computed_bulk_rhat, computed_tail_rhat; - std::tie(computed_bulk_rhat, computed_tail_rhat) = stan::analyze::compute_potential_scale_reduction_rank(draws, size); + std::tie(computed_bulk_rhat, computed_tail_rhat) + = stan::analyze::compute_potential_scale_reduction_rank(draws, size); double expected_bulk_rhat = rhat_bulk(index - 4); double expected_tail_rhat = rhat_tail(index - 4); ASSERT_NEAR(expected_bulk_rhat, computed_bulk_rhat, 1e-4) - << "Bulk Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + << "Bulk Rhat mismatch for index: " << index + << ", parameter: " << chains.param_name(index); ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) - << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + << "Tail Rhat mismatch for index: " << index + << ", parameter: " << chains.param_name(index); // ASSERT_NEAR( // rhat(index - 4), // stan::analyze::compute_potential_scale_reduction_rank(draws, size), @@ -247,7 +280,8 @@ TEST_F(ComputeRhat, chains_compute_split_potential_scale_reduction_rank) { chains.add(blocker2); // Eigen::VectorXd rhat(48); - // rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, + // rhat + // << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, // 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, // 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, // 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, @@ -255,21 +289,35 @@ TEST_F(ComputeRhat, chains_compute_split_potential_scale_reduction_rank) { // 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; Eigen::VectorXd rhat_bulk(48); - rhat_bulk << 1.0078,1.0109,0.99919,1.001,1.00401,1.00992,1.00182,1.00519,1.00095,1.00351,1.00554,1.00075,1.00595,1.00473,1.00546,1.01304,1.00166,1.0074,1.00178,1.00588,1.00406,1.00129,1.00976,1.0013,1.00193,1.00104,0.99938,1.00025,1.01082,1.0019,1.00354,1.0043,1.00111,1.00281,1.00436,1.00515,1.00325,1.0089,1.00222,1.00118,1.00191,1.00283,1.0003,1.00216,1.00335,1.00133,1.00023,1.0109; + rhat_bulk << 1.0078, 1.0109, 0.99919, 1.001, 1.00401, 1.00992, 1.00182, + 1.00519, 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, + 1.01304, 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, + 1.0013, 1.00193, 1.00104, 0.99938, 1.00025, 1.01082, 1.0019, 1.00354, + 1.0043, 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, + 1.00118, 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, + 1.0109; Eigen::VectorXd rhat_tail(48); - rhat_tail << 1.00097,1.00422,1.00731,1.00333,1.00337,0.99917,1.00734,1.00633,1.00074,1.00906,1.01019,1.00074,1.00447,1.00383,1.00895,1.00389,1.00052,1.00188,1.00236,1.00284,1.00414,1.00303,1.00327,1.00295,1.00037,1.0044,1.00488,1.00178,1.00475,1.00082,1.00413,1.01303,1.0024,1.01148,1.00098,1.00078,1.00712,1.00595,1.00124,1.00112,1.00381,1.0006,1.00188,1.00225,1.0026,1.0009,1.00209,1.00464; - + rhat_tail << 1.00097, 1.00422, 1.00731, 1.00333, 1.00337, 0.99917, 1.00734, + 1.00633, 1.00074, 1.00906, 1.01019, 1.00074, 1.00447, 1.00383, 1.00895, + 1.00389, 1.00052, 1.00188, 1.00236, 1.00284, 1.00414, 1.00303, 1.00327, + 1.00295, 1.00037, 1.0044, 1.00488, 1.00178, 1.00475, 1.00082, 1.00413, + 1.01303, 1.0024, 1.01148, 1.00098, 1.00078, 1.00712, 1.00595, 1.00124, + 1.00112, 1.00381, 1.0006, 1.00188, 1.00225, 1.0026, 1.0009, 1.00209, + 1.00464; for (int index = 4; index < chains.num_params(); index++) { double computed_bulk_rhat, computed_tail_rhat; - std::tie(computed_bulk_rhat, computed_tail_rhat) = chains.split_potential_scale_reduction_rank(index); + std::tie(computed_bulk_rhat, computed_tail_rhat) + = chains.split_potential_scale_reduction_rank(index); double expected_bulk_rhat = rhat_bulk(index - 4); double expected_tail_rhat = rhat_tail(index - 4); ASSERT_NEAR(expected_bulk_rhat, computed_bulk_rhat, 1e-4) - << "Bulk Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + << "Bulk Rhat mismatch for index: " << index + << ", parameter: " << chains.param_name(index); ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) - << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + << "Tail Rhat mismatch for index: " << index + << ", parameter: " << chains.param_name(index); // ASSERT_NEAR(rhat(index - 4), // chains.split_potential_scale_reduction_rank(index), 1e-4) @@ -338,7 +386,8 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_rank) { chains.add(blocker2); // Eigen::VectorXd rhat(48); - // rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, + // rhat + // << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, // 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, // 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, // 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, @@ -346,9 +395,21 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_rank) { // 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; Eigen::VectorXd rhat_bulk(48); - rhat_bulk << 1.0078,1.0109,0.99919,1.001,1.00401,1.00992,1.00182,1.00519,1.00095,1.00351,1.00554,1.00075,1.00595,1.00473,1.00546,1.01304,1.00166,1.0074,1.00178,1.00588,1.00406,1.00129,1.00976,1.0013,1.00193,1.00104,0.99938,1.00025,1.01082,1.0019,1.00354,1.0043,1.00111,1.00281,1.00436,1.00515,1.00325,1.0089,1.00222,1.00118,1.00191,1.00283,1.0003,1.00216,1.00335,1.00133,1.00023,1.0109; + rhat_bulk << 1.0078, 1.0109, 0.99919, 1.001, 1.00401, 1.00992, 1.00182, + 1.00519, 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, + 1.01304, 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, + 1.0013, 1.00193, 1.00104, 0.99938, 1.00025, 1.01082, 1.0019, 1.00354, + 1.0043, 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, + 1.00118, 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, + 1.0109; Eigen::VectorXd rhat_tail(48); - rhat_tail << 1.00097,1.00422,1.00731,1.00333,1.00337,0.99917,1.00734,1.00633,1.00074,1.00906,1.01019,1.00074,1.00447,1.00383,1.00895,1.00389,1.00052,1.00188,1.00236,1.00284,1.00414,1.00303,1.00327,1.00295,1.00037,1.0044,1.00488,1.00178,1.00475,1.00082,1.00413,1.01303,1.0024,1.01148,1.00098,1.00078,1.00712,1.00595,1.00124,1.00112,1.00381,1.0006,1.00188,1.00225,1.0026,1.0009,1.00209,1.00464; + rhat_tail << 1.00097, 1.00422, 1.00731, 1.00333, 1.00337, 0.99917, 1.00734, + 1.00633, 1.00074, 1.00906, 1.01019, 1.00074, 1.00447, 1.00383, 1.00895, + 1.00389, 1.00052, 1.00188, 1.00236, 1.00284, 1.00414, 1.00303, 1.00327, + 1.00295, 1.00037, 1.0044, 1.00488, 1.00178, 1.00475, 1.00082, 1.00413, + 1.01303, 1.0024, 1.01148, 1.00098, 1.00078, 1.00712, 1.00595, 1.00124, + 1.00112, 1.00381, 1.0006, 1.00188, 1.00225, 1.0026, 1.0009, 1.00209, + 1.00464; // replicates calls to stan::analyze::compute_effective_sample_size // for any interface *without* access to chains class @@ -362,17 +423,20 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_rank) { draws[chain] = &samples(chain)(0); sizes[chain] = samples(chain).size(); } - + double computed_bulk_rhat, computed_tail_rhat; - std::tie(computed_bulk_rhat, computed_tail_rhat) = stan::analyze::compute_split_potential_scale_reduction_rank(draws, sizes); + std::tie(computed_bulk_rhat, computed_tail_rhat) + = stan::analyze::compute_split_potential_scale_reduction_rank(draws, + sizes); double expected_bulk_rhat = rhat_bulk(index - 4); double expected_tail_rhat = rhat_tail(index - 4); ASSERT_NEAR(expected_bulk_rhat, computed_bulk_rhat, 1e-4) - << "Bulk Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + << "Bulk Rhat mismatch for index: " << index + << ", parameter: " << chains.param_name(index); ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) - << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); - + << "Tail Rhat mismatch for index: " << index + << ", parameter: " << chains.param_name(index); // ASSERT_NEAR(rhat(index - 4), // stan::analyze::compute_split_potential_scale_reduction_rank( @@ -434,19 +498,30 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience_rank) { chains.add(blocker2); // Eigen::VectorXd rhat(48); - // rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, + // rhat + // << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, // 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, // 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, // 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, // 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, // 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; - Eigen::VectorXd rhat_bulk(48); - rhat_bulk << 1.0078,1.0109,0.99919,1.001,1.00401,1.00992,1.00182,1.00519,1.00095,1.00351,1.00554,1.00075,1.00595,1.00473,1.00546,1.01304,1.00166,1.0074,1.00178,1.00588,1.00406,1.00129,1.00976,1.0013,1.00193,1.00104,0.99938,1.00025,1.01082,1.0019,1.00354,1.0043,1.00111,1.00281,1.00436,1.00515,1.00325,1.0089,1.00222,1.00118,1.00191,1.00283,1.0003,1.00216,1.00335,1.00133,1.00023,1.0109; + rhat_bulk << 1.0078, 1.0109, 0.99919, 1.001, 1.00401, 1.00992, 1.00182, + 1.00519, 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, + 1.01304, 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, + 1.0013, 1.00193, 1.00104, 0.99938, 1.00025, 1.01082, 1.0019, 1.00354, + 1.0043, 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, + 1.00118, 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, + 1.0109; Eigen::VectorXd rhat_tail(48); - rhat_tail << 1.00097,1.00422,1.00731,1.00333,1.00337,0.99917,1.00734,1.00633,1.00074,1.00906,1.01019,1.00074,1.00447,1.00383,1.00895,1.00389,1.00052,1.00188,1.00236,1.00284,1.00414,1.00303,1.00327,1.00295,1.00037,1.0044,1.00488,1.00178,1.00475,1.00082,1.00413,1.01303,1.0024,1.01148,1.00098,1.00078,1.00712,1.00595,1.00124,1.00112,1.00381,1.0006,1.00188,1.00225,1.0026,1.0009,1.00209,1.00464; - + rhat_tail << 1.00097, 1.00422, 1.00731, 1.00333, 1.00337, 0.99917, 1.00734, + 1.00633, 1.00074, 1.00906, 1.01019, 1.00074, 1.00447, 1.00383, 1.00895, + 1.00389, 1.00052, 1.00188, 1.00236, 1.00284, 1.00414, 1.00303, 1.00327, + 1.00295, 1.00037, 1.0044, 1.00488, 1.00178, 1.00475, 1.00082, 1.00413, + 1.01303, 1.0024, 1.01148, 1.00098, 1.00078, 1.00712, 1.00595, 1.00124, + 1.00112, 1.00381, 1.0006, 1.00188, 1.00225, 1.0026, 1.0009, 1.00209, + 1.00464; Eigen::Matrix samples( chains.num_chains()); @@ -461,14 +536,18 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience_rank) { size_t size = samples(0).size(); double computed_bulk_rhat, computed_tail_rhat; - std::tie(computed_bulk_rhat, computed_tail_rhat) = stan::analyze::compute_split_potential_scale_reduction_rank(draws, size); + std::tie(computed_bulk_rhat, computed_tail_rhat) + = stan::analyze::compute_split_potential_scale_reduction_rank(draws, + size); double expected_bulk_rhat = rhat_bulk(index - 4); double expected_tail_rhat = rhat_tail(index - 4); ASSERT_NEAR(expected_bulk_rhat, computed_bulk_rhat, 1e-4) - << "Bulk Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + << "Bulk Rhat mismatch for index: " << index + << ", parameter: " << chains.param_name(index); ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) - << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + << "Tail Rhat mismatch for index: " << index + << ", parameter: " << chains.param_name(index); // ASSERT_NEAR(rhat(index - 4), // stan::analyze::compute_split_potential_scale_reduction_rank( // draws, size), @@ -481,7 +560,7 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience_rank) { TEST_F(ComputeRhat, compute_potential_scale_reduction_constant) { std::vector param_names{"a"}; stan::mcmc::chains<> chains(param_names); - Eigen::Matrix draws; + Eigen::Matrix draws; draws << 1.0, 1.0; chains.add(draws); @@ -497,7 +576,8 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_constant) { chains.add(draws); double computed_bulk_rhat, computed_tail_rhat; - std::tie(computed_bulk_rhat, computed_tail_rhat) = chains.split_potential_scale_reduction_rank(0); + std::tie(computed_bulk_rhat, computed_tail_rhat) + = chains.split_potential_scale_reduction_rank(0); ASSERT_TRUE(std::isnan(computed_bulk_rhat)) << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); @@ -526,14 +606,14 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_nan) { chains.add(draws); double computed_bulk_rhat, computed_tail_rhat; - std::tie(computed_bulk_rhat, computed_tail_rhat) = chains.split_potential_scale_reduction_rank(0); - + std::tie(computed_bulk_rhat, computed_tail_rhat) + = chains.split_potential_scale_reduction_rank(0); + ASSERT_TRUE(std::isnan(computed_bulk_rhat)) << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); ASSERT_TRUE(std::isnan(computed_tail_rhat)) << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); - // ASSERT_TRUE(std::isnan(chains.split_potential_scale_reduction_rank(0))) // << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); } diff --git a/src/test/unit/mcmc/chains_test.cpp b/src/test/unit/mcmc/chains_test.cpp index 26ca3dbea6..f2d90aaf0d 100644 --- a/src/test/unit/mcmc/chains_test.cpp +++ b/src/test/unit/mcmc/chains_test.cpp @@ -887,7 +887,8 @@ TEST_F(McmcChains, blocker_split_potential_scale_reduction_rank) { chains.add(blocker2); // Eigen::VectorXd rhat(48); - // rhat << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, + // rhat + // << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, // 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, // 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, // 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, @@ -895,20 +896,35 @@ TEST_F(McmcChains, blocker_split_potential_scale_reduction_rank) { // 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; Eigen::VectorXd rhat_bulk(48); - rhat_bulk << 1.0078,1.0109,0.99919,1.001,1.00401,1.00992,1.00182,1.00519,1.00095,1.00351,1.00554,1.00075,1.00595,1.00473,1.00546,1.01304,1.00166,1.0074,1.00178,1.00588,1.00406,1.00129,1.00976,1.0013,1.00193,1.00104,0.99938,1.00025,1.01082,1.0019,1.00354,1.0043,1.00111,1.00281,1.00436,1.00515,1.00325,1.0089,1.00222,1.00118,1.00191,1.00283,1.0003,1.00216,1.00335,1.00133,1.00023,1.0109; + rhat_bulk << 1.0078, 1.0109, 0.99919, 1.001, 1.00401, 1.00992, 1.00182, + 1.00519, 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, + 1.01304, 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, + 1.0013, 1.00193, 1.00104, 0.99938, 1.00025, 1.01082, 1.0019, 1.00354, + 1.0043, 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, + 1.00118, 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, + 1.0109; Eigen::VectorXd rhat_tail(48); - rhat_tail << 1.00097,1.00422,1.00731,1.00333,1.00337,0.99917,1.00734,1.00633,1.00074,1.00906,1.01019,1.00074,1.00447,1.00383,1.00895,1.00389,1.00052,1.00188,1.00236,1.00284,1.00414,1.00303,1.00327,1.00295,1.00037,1.0044,1.00488,1.00178,1.00475,1.00082,1.00413,1.01303,1.0024,1.01148,1.00098,1.00078,1.00712,1.00595,1.00124,1.00112,1.00381,1.0006,1.00188,1.00225,1.0026,1.0009,1.00209,1.00464; + rhat_tail << 1.00097, 1.00422, 1.00731, 1.00333, 1.00337, 0.99917, 1.00734, + 1.00633, 1.00074, 1.00906, 1.01019, 1.00074, 1.00447, 1.00383, 1.00895, + 1.00389, 1.00052, 1.00188, 1.00236, 1.00284, 1.00414, 1.00303, 1.00327, + 1.00295, 1.00037, 1.0044, 1.00488, 1.00178, 1.00475, 1.00082, 1.00413, + 1.01303, 1.0024, 1.01148, 1.00098, 1.00078, 1.00712, 1.00595, 1.00124, + 1.00112, 1.00381, 1.0006, 1.00188, 1.00225, 1.0026, 1.0009, 1.00209, + 1.00464; for (int index = 4; index < chains.num_params(); index++) { double computed_bulk_rhat, computed_tail_rhat; - std::tie(computed_bulk_rhat, computed_tail_rhat) = chains.split_potential_scale_reduction_rank(index); + std::tie(computed_bulk_rhat, computed_tail_rhat) + = chains.split_potential_scale_reduction_rank(index); double expected_bulk_rhat = rhat_bulk(index - 4); double expected_tail_rhat = rhat_tail(index - 4); ASSERT_NEAR(expected_bulk_rhat, computed_bulk_rhat, 1e-4) - << "Bulk Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + << "Bulk Rhat mismatch for index: " << index + << ", parameter: " << chains.param_name(index); ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) - << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + << "Tail Rhat mismatch for index: " << index + << ", parameter: " << chains.param_name(index); // ASSERT_NEAR(rhat(index - 4), // chains.split_potential_scale_reduction_rank(index), 1e-4) From 981eedc1472445df9dac0a5a60956e6ae5adb7f5 Mon Sep 17 00:00:00 2001 From: aleksgorica Date: Sun, 7 Apr 2024 14:11:21 +0200 Subject: [PATCH 19/25] small fixes, removed comments in tests --- .../compute_potential_scale_reduction.hpp | 52 ++++++------ ...compute_potential_scale_reduction_test.cpp | 80 +------------------ 2 files changed, 26 insertions(+), 106 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index e9daa6f8a6..2a150e0e76 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -111,20 +111,20 @@ inline double rhat(const Eigen::MatrixXd& chains) { * @return potential scale reduction for the specified parameter */ inline std::pair compute_potential_scale_reduction_rank( - const std::vector& chain_begins, - const std::vector& chain_sizes) { - std::vector nonzero_chain_begins; - std::vector nonzero_chain_sizes; - for (size_t i = 0; i < chain_sizes.size(); ++i) { - if (chain_sizes[i]) { - nonzero_chain_begins.push_back(chain_begins[i]); - nonzero_chain_sizes.push_back(chain_sizes[i]); - } - } - if (!nonzero_chain_sizes.size()) { - return {std::numeric_limits::quiet_NaN(), - std::numeric_limits::quiet_NaN()}; - } + const std::vector& chain_begins, const std::vector& chain_sizes) { + std::vector nonzero_chain_begins; + std::vector nonzero_chain_sizes; + nonzero_chain_begins.reserve(chain_begins.size()); + nonzero_chain_sizes.reserve(chain_sizes.size()); + for (size_t i = 0; i < chain_sizes.size(); ++i) { + if (chain_sizes[i]) { + nonzero_chain_begins.push_back(chain_begins[i]); + nonzero_chain_sizes.push_back(chain_sizes[i]); + } + } + if (!nonzero_chain_sizes.size()) { + return {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}; + } std::size_t num_nonzero_chains = nonzero_chain_sizes.size(); std::size_t min_num_draws = nonzero_chain_sizes[0]; for (std::size_t chain = 1; chain < num_nonzero_chains; ++chain) { @@ -151,14 +151,11 @@ inline std::pair compute_potential_scale_reduction_rank( init_draw(chain) = draws(0); are_all_const |= !draws.isApproxToConstant(draws(0)); } - if (are_all_const) { - // If all chains are constant then return NaN - // if they all equal the same constant value - if (init_draw.isApproxToConstant(init_draw(0))) { - return {std::numeric_limits::quiet_NaN(), - std::numeric_limits::quiet_NaN()}; + // If all chains are constant then return NaN + if (are_all_const && init_draw.isApproxToConstant(init_draw(0))) { + return {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}; } - } + double rhat_bulk = rhat(rank_transform(draws_matrix)); double rhat_tail = rhat(rank_transform( @@ -166,7 +163,6 @@ inline std::pair compute_potential_scale_reduction_rank( .abs())); return std::make_pair(rhat_bulk, rhat_tail); - // return std::max(rhat_bulk, rhat_tail); } /** @@ -189,6 +185,8 @@ inline double compute_potential_scale_reduction( const std::vector& chain_sizes) { std::vector nonzero_chain_begins; std::vector nonzero_chain_sizes; + nonzero_chain_begins.reserve(chain_begins.size()); + nonzero_chain_sizes.reserve(chain_sizes.size()); for (size_t i = 0; i < chain_sizes.size(); ++i) { if (chain_sizes[i]) { nonzero_chain_begins.push_back(chain_begins[i]); @@ -251,8 +249,7 @@ inline double compute_potential_scale_reduction( */ inline std::pair compute_potential_scale_reduction_rank( const std::vector& chain_begins, size_t size) { - size_t num_chains = chain_begins.size(); - std::vector sizes(num_chains, size); + std::vector sizes(chain_begins.size(), size); return compute_potential_scale_reduction_rank(chain_begins, sizes); } @@ -263,8 +260,8 @@ inline std::pair compute_potential_scale_reduction_rank( * See more details in Stan reference manual section "Potential * Scale Reduction". http://mc-stan.org/users/documentation * - * Current implementation assumes draws are stored in contiguousdereck lively ii - * height weight blocks of memory. Chains are trimmed from the back to match the + * Current implementation assumes draws are stored in contiguous + * blocks of memory. Chains are trimmed from the back to match the * length of the shortest chain. Argument size will be broadcast to * same length as draws. * @@ -274,8 +271,7 @@ inline std::pair compute_potential_scale_reduction_rank( */ inline double compute_potential_scale_reduction( const std::vector& chain_begins, size_t size) { - size_t num_chains = chain_begins.size(); - std::vector sizes(num_chains, size); + std::vector sizes(chain_begins.size(), size); return compute_potential_scale_reduction(chain_begins, sizes); } diff --git a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp index 4625bb37b7..0962b7f510 100644 --- a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp +++ b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp @@ -114,12 +114,6 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank) { ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); - // ASSERT_NEAR( - // rhat(index - 4), - // stan::analyze::compute_potential_scale_reduction_rank(draws, sizes), - // 1e-4) - // << "rhat for index: " << index - // << ", parameter: " << chains.param_name(index); } } @@ -173,18 +167,6 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_convenience) { stan::mcmc::chains<> chains(blocker1); chains.add(blocker2); - // Eigen::VectorXd rhat(48); - // rhat - // << 1.00067, 1.00497, 1.00918, 1.00055, 1.0015, 1.00088, 1.00776, 1.00042, - // 1.00201, 0.999558, - // 0.99984, 1.00054, 1.00403, 1.00516, 1.00591, 1.00627, - // 1.00134, 1.00895, 1.00079, 1.00368, 1.00092, 1.00133, 1.01005, 1.00107, - // 1.00151, 1.00229, - // 0.999998, 1.00008, 1.00315, 1.00277, 1.00247, 1.00003, - // 1.001, 1.01267, 1.00011, 1.00066, 1.00091, 1.00237, 1.00019, 1.00104, - // 1.00341, 0.999815, 1.00033, - // 0.999672, 1.00306, 1.00072, 1.00191, 1.00658; - Eigen::VectorXd rhat_bulk(48); rhat_bulk << 1.00067, 0.99979, 0.99966, 1.00055, 1.0011, 1.00088, 1.00032, 0.99997, 1.00201, 0.99956, 0.99956, 0.9995, 1.00292, 1.00516, 1.00591, @@ -223,14 +205,7 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_convenience) { << "Bulk Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) - << "Tail Rhat mismatch for index: " << index - << ", parameter: " << chains.param_name(index); - // ASSERT_NEAR( - // rhat(index - 4), - // stan::analyze::compute_potential_scale_reduction_rank(draws, size), - // 1e-4) - // << "rhat for index: " << index - // << ", parameter: " << chains.param_name(index); + << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); } } @@ -279,15 +254,6 @@ TEST_F(ComputeRhat, chains_compute_split_potential_scale_reduction_rank) { stan::mcmc::chains<> chains(blocker1); chains.add(blocker2); - // Eigen::VectorXd rhat(48); - // rhat - // << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, - // 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, - // 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, - // 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, - // 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, - // 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; - Eigen::VectorXd rhat_bulk(48); rhat_bulk << 1.0078, 1.0109, 0.99919, 1.001, 1.00401, 1.00992, 1.00182, 1.00519, 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, @@ -318,11 +284,6 @@ TEST_F(ComputeRhat, chains_compute_split_potential_scale_reduction_rank) { ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); - - // ASSERT_NEAR(rhat(index - 4), - // chains.split_potential_scale_reduction_rank(index), 1e-4) - // << "rhat for index: " << index - // << ", parameter: " << chains.param_name(index); } for (int index = 0; index < chains.num_params(); index++) { std::string name = chains.param_name(index); @@ -385,15 +346,6 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_rank) { chains.add(blocker2); - // Eigen::VectorXd rhat(48); - // rhat - // << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, - // 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, - // 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, - // 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, - // 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, - // 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; - Eigen::VectorXd rhat_bulk(48); rhat_bulk << 1.0078, 1.0109, 0.99919, 1.001, 1.00401, 1.00992, 1.00182, 1.00519, 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, @@ -437,13 +389,6 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_rank) { ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); - - // ASSERT_NEAR(rhat(index - 4), - // stan::analyze::compute_split_potential_scale_reduction_rank( - // draws, sizes), - // 1e-4) - // << "rhat for index: " << index - // << ", parameter: " << chains.param_name(index); } } @@ -497,15 +442,6 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience_rank) { stan::mcmc::chains<> chains(blocker1); chains.add(blocker2); - // Eigen::VectorXd rhat(48); - // rhat - // << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, - // 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, - // 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, - // 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, - // 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, - // 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; - Eigen::VectorXd rhat_bulk(48); rhat_bulk << 1.0078, 1.0109, 0.99919, 1.001, 1.00401, 1.00992, 1.00182, 1.00519, 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, @@ -537,8 +473,7 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience_rank) { double computed_bulk_rhat, computed_tail_rhat; std::tie(computed_bulk_rhat, computed_tail_rhat) - = stan::analyze::compute_split_potential_scale_reduction_rank(draws, - size); + = stan::analyze::compute_split_potential_scale_reduction_rank(draws, size); double expected_bulk_rhat = rhat_bulk(index - 4); double expected_tail_rhat = rhat_tail(index - 4); @@ -548,12 +483,6 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience_rank) { ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); - // ASSERT_NEAR(rhat(index - 4), - // stan::analyze::compute_split_potential_scale_reduction_rank( - // draws, size), - // 1e-4) - // << "rhat for index: " << index - // << ", parameter: " << chains.param_name(index); } } @@ -583,8 +512,6 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_constant) { << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); ASSERT_TRUE(std::isnan(computed_tail_rhat)) << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); - // ASSERT_TRUE(std::isnan(chains.split_potential_scale_reduction_rank(0))) - // << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); } TEST_F(ComputeRhat, compute_potential_scale_reduction_nan) { @@ -613,7 +540,4 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_nan) { << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); ASSERT_TRUE(std::isnan(computed_tail_rhat)) << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); - - // ASSERT_TRUE(std::isnan(chains.split_potential_scale_reduction_rank(0))) - // << "rhat for index: " << 1 << ", parameter: " << chains.param_name(1); } From 971aed70bd8bfd4813c1b86e76ba63c923436393 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 7 Apr 2024 08:47:19 -0400 Subject: [PATCH 20/25] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- .../compute_potential_scale_reduction.hpp | 32 ++++++++++--------- ...compute_potential_scale_reduction_test.cpp | 6 ++-- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index 2a150e0e76..0afaaa2517 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -111,20 +111,22 @@ inline double rhat(const Eigen::MatrixXd& chains) { * @return potential scale reduction for the specified parameter */ inline std::pair compute_potential_scale_reduction_rank( - const std::vector& chain_begins, const std::vector& chain_sizes) { - std::vector nonzero_chain_begins; - std::vector nonzero_chain_sizes; + const std::vector& chain_begins, + const std::vector& chain_sizes) { + std::vector nonzero_chain_begins; + std::vector nonzero_chain_sizes; nonzero_chain_begins.reserve(chain_begins.size()); nonzero_chain_sizes.reserve(chain_sizes.size()); - for (size_t i = 0; i < chain_sizes.size(); ++i) { - if (chain_sizes[i]) { - nonzero_chain_begins.push_back(chain_begins[i]); - nonzero_chain_sizes.push_back(chain_sizes[i]); - } - } - if (!nonzero_chain_sizes.size()) { - return {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}; - } + for (size_t i = 0; i < chain_sizes.size(); ++i) { + if (chain_sizes[i]) { + nonzero_chain_begins.push_back(chain_begins[i]); + nonzero_chain_sizes.push_back(chain_sizes[i]); + } + } + if (!nonzero_chain_sizes.size()) { + return {std::numeric_limits::quiet_NaN(), + std::numeric_limits::quiet_NaN()}; + } std::size_t num_nonzero_chains = nonzero_chain_sizes.size(); std::size_t min_num_draws = nonzero_chain_sizes[0]; for (std::size_t chain = 1; chain < num_nonzero_chains; ++chain) { @@ -153,9 +155,9 @@ inline std::pair compute_potential_scale_reduction_rank( } // If all chains are constant then return NaN if (are_all_const && init_draw.isApproxToConstant(init_draw(0))) { - return {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}; - } - + return {std::numeric_limits::quiet_NaN(), + std::numeric_limits::quiet_NaN()}; + } double rhat_bulk = rhat(rank_transform(draws_matrix)); double rhat_tail = rhat(rank_transform( diff --git a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp index 0962b7f510..41a102e51d 100644 --- a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp +++ b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp @@ -205,7 +205,8 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_rank_convenience) { << "Bulk Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); ASSERT_NEAR(expected_tail_rhat, computed_tail_rhat, 1e-4) - << "Tail Rhat mismatch for index: " << index << ", parameter: " << chains.param_name(index); + << "Tail Rhat mismatch for index: " << index + << ", parameter: " << chains.param_name(index); } } @@ -473,7 +474,8 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience_rank) { double computed_bulk_rhat, computed_tail_rhat; std::tie(computed_bulk_rhat, computed_tail_rhat) - = stan::analyze::compute_split_potential_scale_reduction_rank(draws, size); + = stan::analyze::compute_split_potential_scale_reduction_rank(draws, + size); double expected_bulk_rhat = rhat_bulk(index - 4); double expected_tail_rhat = rhat_tail(index - 4); From 61c4c6cdbf8eb4907858168c1990f1ee28843482 Mon Sep 17 00:00:00 2001 From: aleksgorica Date: Wed, 17 Apr 2024 16:26:08 +0200 Subject: [PATCH 21/25] reverting nonrank functions --- .../compute_potential_scale_reduction.hpp | 129 ++++++++++-------- 1 file changed, 75 insertions(+), 54 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index 0afaaa2517..ee28995aa9 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -175,63 +175,84 @@ inline std::pair compute_potential_scale_reduction_rank( * Scale Reduction". http://mc-stan.org/users/documentation * * Current implementation assumes draws are stored in contiguous - * blocks of memory. Chains are trimmed from the back to match the + * blocks of memory. Chains are trimmed from the back to match the * length of the shortest chain. * - * @param chain_begins stores pointers to arrays of chains - * @param chain_sizes stores sizes of chains + * @param draws stores pointers to arrays of chains + * @param sizes stores sizes of chains * @return potential scale reduction for the specified parameter */ inline double compute_potential_scale_reduction( - const std::vector& chain_begins, - const std::vector& chain_sizes) { - std::vector nonzero_chain_begins; - std::vector nonzero_chain_sizes; - nonzero_chain_begins.reserve(chain_begins.size()); - nonzero_chain_sizes.reserve(chain_sizes.size()); - for (size_t i = 0; i < chain_sizes.size(); ++i) { - if (chain_sizes[i]) { - nonzero_chain_begins.push_back(chain_begins[i]); - nonzero_chain_sizes.push_back(chain_sizes[i]); - } - } - if (!nonzero_chain_sizes.size()) { + std::vector draws, std::vector sizes) { + int num_chains = sizes.size(); + size_t num_draws = sizes[0]; + if (num_draws == 0) { return std::numeric_limits::quiet_NaN(); } - std::size_t num_nonzero_chains = nonzero_chain_sizes.size(); - std::size_t min_num_draws = nonzero_chain_sizes[0]; - for (std::size_t chain = 1; chain < num_nonzero_chains; ++chain) { - min_num_draws = std::min(min_num_draws, nonzero_chain_sizes[chain]); + for (int chain = 1; chain < num_chains; ++chain) { + num_draws = std::min(num_draws, sizes[chain]); } // check if chains are constant; all equal to first draw's value bool are_all_const = false; - Eigen::VectorXd init_draw = Eigen::VectorXd::Zero(num_nonzero_chains); - Eigen::MatrixXd draws_matrix(min_num_draws, num_nonzero_chains); + Eigen::VectorXd init_draw = Eigen::VectorXd::Zero(num_chains); - for (std::size_t chain = 0; chain < num_nonzero_chains; chain++) { - Eigen::Map> draws( - nonzero_chain_begins[chain], nonzero_chain_sizes[chain]); + for (int chain = 0; chain < num_chains; chain++) { + Eigen::Map> draw( + draws[chain], sizes[chain]); - for (std::size_t n = 0; n < min_num_draws; n++) { - if (!std::isfinite(draws(n))) { + for (int n = 0; n < num_draws; n++) { + if (!std::isfinite(draw(n))) { return std::numeric_limits::quiet_NaN(); } - draws_matrix(n, chain) = draws(n); } - init_draw(chain) = draws(0); + init_draw(chain) = draw(0); - are_all_const |= !draws.isApproxToConstant(draws(0)); + if (draw.isApproxToConstant(draw(0))) { + are_all_const |= true; + } } - // if they all equal the same constant value - if (init_draw.isApproxToConstant(init_draw(0))) { - return std::numeric_limits::quiet_NaN(); + + if (are_all_const) { + // If all chains are constant then return NaN + // if they all equal the same constant value + if (init_draw.isApproxToConstant(init_draw(0))) { + return std::numeric_limits::quiet_NaN(); + } } - return rhat(draws_matrix); + using boost::accumulators::accumulator_set; + using boost::accumulators::stats; + using boost::accumulators::tag::mean; + using boost::accumulators::tag::variance; + + Eigen::VectorXd chain_mean(num_chains); + accumulator_set> acc_chain_mean; + Eigen::VectorXd chain_var(num_chains); + double unbiased_var_scale = num_draws / (num_draws - 1.0); + + for (int chain = 0; chain < num_chains; ++chain) { + accumulator_set> acc_draw; + for (int n = 0; n < num_draws; ++n) { + acc_draw(draws[chain][n]); + } + + chain_mean(chain) = boost::accumulators::mean(acc_draw); + acc_chain_mean(chain_mean(chain)); + chain_var(chain) + = boost::accumulators::variance(acc_draw) * unbiased_var_scale; + } + + double var_between = num_draws * boost::accumulators::variance(acc_chain_mean) + * num_chains / (num_chains - 1); + double var_within = chain_var.mean(); + + // rewrote [(n-1)*W/n + B/n]/W as (n-1+ B/W)/n + return sqrt((var_between / var_within + num_draws - 1) / num_draws); } + /** * Computes the potential scale reduction (Rhat) using rank based diagnostic for * the specified parameter across all kept samples. Based on paper @@ -263,20 +284,22 @@ inline std::pair compute_potential_scale_reduction_rank( * Scale Reduction". http://mc-stan.org/users/documentation * * Current implementation assumes draws are stored in contiguous - * blocks of memory. Chains are trimmed from the back to match the - * length of the shortest chain. Argument size will be broadcast to + * blocks of memory. Chains are trimmed from the back to match the + * length of the shortest chain. Argument size will be broadcast to * same length as draws. * - * @param chain_begins stores pointers to arrays of chains + * @param draws stores pointers to arrays of chains * @param size stores sizes of chains * @return potential scale reduction for the specified parameter */ inline double compute_potential_scale_reduction( - const std::vector& chain_begins, size_t size) { - std::vector sizes(chain_begins.size(), size); - return compute_potential_scale_reduction(chain_begins, sizes); + std::vector draws, size_t size) { + int num_chains = draws.size(); + std::vector sizes(num_chains, size); + return compute_potential_scale_reduction(draws, sizes); } + /** * Computes the potential scale reduction (Rhat) using rank based diagnostic for * the specified parameter across all kept samples. Based on paper @@ -325,21 +348,19 @@ inline std::pair compute_split_potential_scale_reduction_rank( * blocks of memory. Chains are trimmed from the back to match the * length of the shortest chain. * - * @param chain_begins stores pointers to arrays of chains - * @param chain_sizes stores sizes of chains + * @param draws stores pointers to arrays of chains + * @param sizes stores sizes of chains * @return potential scale reduction for the specified parameter */ inline double compute_split_potential_scale_reduction( - const std::vector& chain_begins, - const std::vector& chain_sizes) { - size_t num_chains = chain_sizes.size(); - size_t num_draws = chain_sizes[0]; - for (size_t chain = 1; chain < num_chains; ++chain) { - num_draws = std::min(num_draws, chain_sizes[chain]); + std::vector draws, std::vector sizes) { + int num_chains = sizes.size(); + size_t num_draws = sizes[0]; + for (int chain = 1; chain < num_chains; ++chain) { + num_draws = std::min(num_draws, sizes[chain]); } - std::vector split_draws - = split_chains(chain_begins, chain_sizes); + std::vector split_draws = split_chains(draws, sizes); double half = num_draws / 2.0; std::vector half_sizes(2 * num_chains, std::floor(half)); @@ -386,15 +407,15 @@ inline std::pair compute_split_potential_scale_reduction_rank( * length of the shortest chain. Argument size will be broadcast to * same length as draws. * - * @param chain_begins stores pointers to arrays of chains + * @param draws stores pointers to arrays of chains * @param size stores sizes of chains * @return potential scale reduction for the specified parameter */ inline double compute_split_potential_scale_reduction( - const std::vector& chain_begins, size_t size) { - size_t num_chains = chain_begins.size(); + std::vector draws, size_t size) { + int num_chains = draws.size(); std::vector sizes(num_chains, size); - return compute_split_potential_scale_reduction(chain_begins, sizes); + return compute_split_potential_scale_reduction(draws, sizes); } } // namespace analyze From 51db135cbedb9f4371438297243f2d57275259f8 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 17 Apr 2024 10:27:18 -0400 Subject: [PATCH 22/25] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index ee28995aa9..93813775ca 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -252,7 +252,6 @@ inline double compute_potential_scale_reduction( return sqrt((var_between / var_within + num_draws - 1) / num_draws); } - /** * Computes the potential scale reduction (Rhat) using rank based diagnostic for * the specified parameter across all kept samples. Based on paper @@ -299,7 +298,6 @@ inline double compute_potential_scale_reduction( return compute_potential_scale_reduction(draws, sizes); } - /** * Computes the potential scale reduction (Rhat) using rank based diagnostic for * the specified parameter across all kept samples. Based on paper From f12f2591348c30e3849bb9c964ce67f248fcf6ab Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Fri, 19 Apr 2024 12:40:20 -0400 Subject: [PATCH 23/25] update so scale_reduction calls scale_reduction_rank --- .../compute_potential_scale_reduction.hpp | 73 +------------------ src/stan/mcmc/chains.hpp | 6 +- ...compute_potential_scale_reduction_test.cpp | 45 ++---------- src/test/unit/mcmc/chains_test.cpp | 23 ++---- 4 files changed, 21 insertions(+), 126 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index 93813775ca..b187cb14c7 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -183,73 +183,8 @@ inline std::pair compute_potential_scale_reduction_rank( * @return potential scale reduction for the specified parameter */ inline double compute_potential_scale_reduction( - std::vector draws, std::vector sizes) { - int num_chains = sizes.size(); - size_t num_draws = sizes[0]; - if (num_draws == 0) { - return std::numeric_limits::quiet_NaN(); - } - for (int chain = 1; chain < num_chains; ++chain) { - num_draws = std::min(num_draws, sizes[chain]); - } - - // check if chains are constant; all equal to first draw's value - bool are_all_const = false; - Eigen::VectorXd init_draw = Eigen::VectorXd::Zero(num_chains); - - for (int chain = 0; chain < num_chains; chain++) { - Eigen::Map> draw( - draws[chain], sizes[chain]); - - for (int n = 0; n < num_draws; n++) { - if (!std::isfinite(draw(n))) { - return std::numeric_limits::quiet_NaN(); - } - } - - init_draw(chain) = draw(0); - - if (draw.isApproxToConstant(draw(0))) { - are_all_const |= true; - } - } - - if (are_all_const) { - // If all chains are constant then return NaN - // if they all equal the same constant value - if (init_draw.isApproxToConstant(init_draw(0))) { - return std::numeric_limits::quiet_NaN(); - } - } - - using boost::accumulators::accumulator_set; - using boost::accumulators::stats; - using boost::accumulators::tag::mean; - using boost::accumulators::tag::variance; - - Eigen::VectorXd chain_mean(num_chains); - accumulator_set> acc_chain_mean; - Eigen::VectorXd chain_var(num_chains); - double unbiased_var_scale = num_draws / (num_draws - 1.0); - - for (int chain = 0; chain < num_chains; ++chain) { - accumulator_set> acc_draw; - for (int n = 0; n < num_draws; ++n) { - acc_draw(draws[chain][n]); - } - - chain_mean(chain) = boost::accumulators::mean(acc_draw); - acc_chain_mean(chain_mean(chain)); - chain_var(chain) - = boost::accumulators::variance(acc_draw) * unbiased_var_scale; - } - - double var_between = num_draws * boost::accumulators::variance(acc_chain_mean) - * num_chains / (num_chains - 1); - double var_within = chain_var.mean(); - - // rewrote [(n-1)*W/n + B/n]/W as (n-1+ B/W)/n - return sqrt((var_between / var_within + num_draws - 1) / num_draws); + const std::vector& draws, const std::vector& sizes) { + return compute_potential_scale_reduction_rank(draws, sizes).first; } /** @@ -295,7 +230,7 @@ inline double compute_potential_scale_reduction( std::vector draws, size_t size) { int num_chains = draws.size(); std::vector sizes(num_chains, size); - return compute_potential_scale_reduction(draws, sizes); + return compute_potential_scale_reduction_rank(draws, sizes).first; } /** @@ -363,7 +298,7 @@ inline double compute_split_potential_scale_reduction( double half = num_draws / 2.0; std::vector half_sizes(2 * num_chains, std::floor(half)); - return compute_potential_scale_reduction(split_draws, half_sizes); + return compute_potential_scale_reduction_rank(split_draws, half_sizes).first; } /** diff --git a/src/stan/mcmc/chains.hpp b/src/stan/mcmc/chains.hpp index a553fd36cd..1e763d0414 100644 --- a/src/stan/mcmc/chains.hpp +++ b/src/stan/mcmc/chains.hpp @@ -623,16 +623,16 @@ class chains { sizes[chain] = n_kept_samples; } - return analyze::compute_split_potential_scale_reduction(draws, sizes); + return analyze::compute_split_potential_scale_reduction_rank(draws, sizes).first; } std::pair split_potential_scale_reduction_rank( const std::string& name) const { - return split_potential_scale_reduction_rank(index(name)); + return this->split_potential_scale_reduction_rank(index(name)); } double split_potential_scale_reduction(const std::string& name) const { - return split_potential_scale_reduction(index(name)); + return this->split_potential_scale_reduction_rank(index(name)).first; } }; diff --git a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp index 41a102e51d..2d7d25afc6 100644 --- a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp +++ b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp @@ -31,13 +31,7 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00042, 1.00036, 0.99955, 1.00047, 1.00119, 1.00089, 1.00018, - 1.00019, 1.00226, 0.99954, 0.9996, 0.99951, 1.00237, 1.00515, 1.00566, - 0.99957, 1.00099, 1.00853, 1.0008, 0.99961, 1.0006, 1.00046, 1.01023, - 0.9996, 1.0011, 0.99967, 0.99973, 0.99958, 1.00242, 1.00213, 1.00244, - 0.99998, 0.99969, 1.00079, 0.99955, 1.0009, 1.00136, 1.00288, 1.00036, - 0.99989, 1.00077, 0.99997, 1.00194, 0.99972, 1.00257, 1.00109, 1.00004, - 0.99955; + rhat << 1.00067, 0.999789, 0.999656, 1.00055, 1.0011, 1.00088, 1.00032, 0.999969, 1.00201, 0.999558, 0.999555, 0.9995, 1.00292, 1.00516, 1.00591, 0.999753, 1.00088, 1.00895, 1.00079, 0.99953, 1.00092, 1.00044, 1.01005, 0.999598, 1.00151, 0.999659, 0.999648, 0.999627, 1.00315, 1.00277, 1.00247, 1.00003, 0.999937, 1.00116, 0.999521, 1.0005, 1.00091, 1.00213, 1.00019, 0.999767, 1.0003, 0.999815, 1.00003, 0.999672, 1.00306, 1.00072, 0.999602, 0.999789; // replicates calls to stan::analyze::compute_effective_sample_size // for any interface *without* access to chains class @@ -52,8 +46,7 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction) { sizes[chain] = samples(chain).size(); } ASSERT_NEAR(rhat(index - 4), - stan::analyze::compute_potential_scale_reduction(draws, sizes), - 1e-4) + stan::analyze::compute_potential_scale_reduction(draws, sizes), 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); } @@ -129,13 +122,7 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_convenience) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00042, 1.00036, 0.99955, 1.00047, 1.00119, 1.00089, 1.00018, - 1.00019, 1.00226, 0.99954, 0.9996, 0.99951, 1.00237, 1.00515, 1.00566, - 0.99957, 1.00099, 1.00853, 1.0008, 0.99961, 1.0006, 1.00046, 1.01023, - 0.9996, 1.0011, 0.99967, 0.99973, 0.99958, 1.00242, 1.00213, 1.00244, - 0.99998, 0.99969, 1.00079, 0.99955, 1.0009, 1.00136, 1.00288, 1.00036, - 0.99989, 1.00077, 0.99997, 1.00194, 0.99972, 1.00257, 1.00109, 1.00004, - 0.99955; + rhat << 1.00067, 0.999789, 0.999656, 1.00055, 1.0011, 1.00088, 1.00032, 0.999969, 1.00201, 0.999558, 0.999555, 0.9995, 1.00292, 1.00516, 1.00591, 0.999753, 1.00088, 1.00895, 1.00079, 0.99953, 1.00092, 1.00044, 1.01005, 0.999598, 1.00151, 0.999659, 0.999648, 0.999627, 1.00315, 1.00277, 1.00247, 1.00003, 0.999937, 1.00116, 0.999521, 1.0005, 1.00091, 1.00213, 1.00019, 0.999767, 1.0003, 0.999815, 1.00003, 0.999672, 1.00306, 1.00072, 0.999602, 0.999789; Eigen::Matrix samples( chains.num_chains()); @@ -222,14 +209,7 @@ TEST_F(ComputeRhat, chains_compute_split_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, - 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, - 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, - 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, - 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, - 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, - 1.00735; - + rhat << 1.0078, 1.0109, 0.999187, 1.001, 1.00401, 1.00992, 1.00182, 1.00519, 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, 1.01304, 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, 1.0013, 1.00193, 1.00104, 0.999383, 1.00025, 1.01082, 1.0019, 1.00354, 1.0043, 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, 1.00118, 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, 1.0109; for (int index = 4; index < chains.num_params(); index++) { ASSERT_NEAR(rhat(index - 4), chains.split_potential_scale_reduction(index), 1e-4) @@ -306,13 +286,7 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, - 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, - 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, - 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, - 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, - 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, - 1.00735; + rhat << 1.0078, 1.0109, 0.999187, 1.001, 1.00401, 1.00992, 1.00182, 1.00519, 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, 1.01304, 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, 1.0013, 1.00193, 1.00104, 0.999383, 1.00025, 1.01082, 1.0019, 1.00354, 1.0043, 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, 1.00118, 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, 1.0109; // replicates calls to stan::analyze::compute_effective_sample_size // for any interface *without* access to chains class @@ -405,13 +379,7 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, - 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, - 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, - 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, - 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, - 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, - 1.00735; + rhat << 1.0078, 1.0109, 0.999187, 1.001, 1.00401, 1.00992, 1.00182, 1.00519, 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, 1.01304, 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, 1.0013, 1.00193, 1.00104, 0.999383, 1.00025, 1.01082, 1.0019, 1.00354, 1.0043, 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, 1.00118, 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, 1.0109; Eigen::Matrix samples( chains.num_chains()); @@ -429,6 +397,7 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience) { 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); + } } diff --git a/src/test/unit/mcmc/chains_test.cpp b/src/test/unit/mcmc/chains_test.cpp index f2d90aaf0d..7bf581ab31 100644 --- a/src/test/unit/mcmc/chains_test.cpp +++ b/src/test/unit/mcmc/chains_test.cpp @@ -853,13 +853,13 @@ TEST_F(McmcChains, blocker_split_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, - 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, - 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, - 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, - 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, - 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, - 1.00735; + rhat << 1.0078, 1.0109, 0.99919, 1.001, 1.00401, 1.00992, 1.00182, + 1.00519, 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, + 1.01304, 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, + 1.0013, 1.00193, 1.00104, 0.99938, 1.00025, 1.01082, 1.0019, 1.00354, + 1.0043, 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, + 1.00118, 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, + 1.0109; for (int index = 4; index < chains.num_params(); index++) { ASSERT_NEAR(rhat(index - 4), chains.split_potential_scale_reduction(index), @@ -886,15 +886,6 @@ TEST_F(McmcChains, blocker_split_potential_scale_reduction_rank) { stan::mcmc::chains<> chains(blocker1); chains.add(blocker2); - // Eigen::VectorXd rhat(48); - // rhat - // << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, - // 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, - // 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, - // 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, - // 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, - // 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; - Eigen::VectorXd rhat_bulk(48); rhat_bulk << 1.0078, 1.0109, 0.99919, 1.001, 1.00401, 1.00992, 1.00182, 1.00519, 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, From da5bb8d0c07bae4fca06763faf8bf074f44d1765 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Fri, 19 Apr 2024 12:42:10 -0400 Subject: [PATCH 24/25] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- .../compute_potential_scale_reduction.hpp | 2 +- src/stan/mcmc/chains.hpp | 3 +- ...compute_potential_scale_reduction_test.cpp | 41 +++++++++++++++---- src/test/unit/mcmc/chains_test.cpp | 13 +++--- 4 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index b187cb14c7..47d0769573 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -184,7 +184,7 @@ inline std::pair compute_potential_scale_reduction_rank( */ inline double compute_potential_scale_reduction( const std::vector& draws, const std::vector& sizes) { - return compute_potential_scale_reduction_rank(draws, sizes).first; + return compute_potential_scale_reduction_rank(draws, sizes).first; } /** diff --git a/src/stan/mcmc/chains.hpp b/src/stan/mcmc/chains.hpp index 1e763d0414..69ae7669f8 100644 --- a/src/stan/mcmc/chains.hpp +++ b/src/stan/mcmc/chains.hpp @@ -623,7 +623,8 @@ class chains { sizes[chain] = n_kept_samples; } - return analyze::compute_split_potential_scale_reduction_rank(draws, sizes).first; + return analyze::compute_split_potential_scale_reduction_rank(draws, sizes) + .first; } std::pair split_potential_scale_reduction_rank( diff --git a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp index 2d7d25afc6..84f6efbe81 100644 --- a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp +++ b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp @@ -31,7 +31,13 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00067, 0.999789, 0.999656, 1.00055, 1.0011, 1.00088, 1.00032, 0.999969, 1.00201, 0.999558, 0.999555, 0.9995, 1.00292, 1.00516, 1.00591, 0.999753, 1.00088, 1.00895, 1.00079, 0.99953, 1.00092, 1.00044, 1.01005, 0.999598, 1.00151, 0.999659, 0.999648, 0.999627, 1.00315, 1.00277, 1.00247, 1.00003, 0.999937, 1.00116, 0.999521, 1.0005, 1.00091, 1.00213, 1.00019, 0.999767, 1.0003, 0.999815, 1.00003, 0.999672, 1.00306, 1.00072, 0.999602, 0.999789; + rhat << 1.00067, 0.999789, 0.999656, 1.00055, 1.0011, 1.00088, 1.00032, + 0.999969, 1.00201, 0.999558, 0.999555, 0.9995, 1.00292, 1.00516, 1.00591, + 0.999753, 1.00088, 1.00895, 1.00079, 0.99953, 1.00092, 1.00044, 1.01005, + 0.999598, 1.00151, 0.999659, 0.999648, 0.999627, 1.00315, 1.00277, + 1.00247, 1.00003, 0.999937, 1.00116, 0.999521, 1.0005, 1.00091, 1.00213, + 1.00019, 0.999767, 1.0003, 0.999815, 1.00003, 0.999672, 1.00306, 1.00072, + 0.999602, 0.999789; // replicates calls to stan::analyze::compute_effective_sample_size // for any interface *without* access to chains class @@ -46,7 +52,8 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction) { sizes[chain] = samples(chain).size(); } ASSERT_NEAR(rhat(index - 4), - stan::analyze::compute_potential_scale_reduction(draws, sizes), 1e-4) + stan::analyze::compute_potential_scale_reduction(draws, sizes), + 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); } @@ -122,7 +129,13 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_convenience) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00067, 0.999789, 0.999656, 1.00055, 1.0011, 1.00088, 1.00032, 0.999969, 1.00201, 0.999558, 0.999555, 0.9995, 1.00292, 1.00516, 1.00591, 0.999753, 1.00088, 1.00895, 1.00079, 0.99953, 1.00092, 1.00044, 1.01005, 0.999598, 1.00151, 0.999659, 0.999648, 0.999627, 1.00315, 1.00277, 1.00247, 1.00003, 0.999937, 1.00116, 0.999521, 1.0005, 1.00091, 1.00213, 1.00019, 0.999767, 1.0003, 0.999815, 1.00003, 0.999672, 1.00306, 1.00072, 0.999602, 0.999789; + rhat << 1.00067, 0.999789, 0.999656, 1.00055, 1.0011, 1.00088, 1.00032, + 0.999969, 1.00201, 0.999558, 0.999555, 0.9995, 1.00292, 1.00516, 1.00591, + 0.999753, 1.00088, 1.00895, 1.00079, 0.99953, 1.00092, 1.00044, 1.01005, + 0.999598, 1.00151, 0.999659, 0.999648, 0.999627, 1.00315, 1.00277, + 1.00247, 1.00003, 0.999937, 1.00116, 0.999521, 1.0005, 1.00091, 1.00213, + 1.00019, 0.999767, 1.0003, 0.999815, 1.00003, 0.999672, 1.00306, 1.00072, + 0.999602, 0.999789; Eigen::Matrix samples( chains.num_chains()); @@ -209,7 +222,12 @@ TEST_F(ComputeRhat, chains_compute_split_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.0078, 1.0109, 0.999187, 1.001, 1.00401, 1.00992, 1.00182, 1.00519, 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, 1.01304, 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, 1.0013, 1.00193, 1.00104, 0.999383, 1.00025, 1.01082, 1.0019, 1.00354, 1.0043, 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, 1.00118, 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, 1.0109; + rhat << 1.0078, 1.0109, 0.999187, 1.001, 1.00401, 1.00992, 1.00182, 1.00519, + 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, 1.01304, + 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, 1.0013, + 1.00193, 1.00104, 0.999383, 1.00025, 1.01082, 1.0019, 1.00354, 1.0043, + 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, 1.00118, + 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, 1.0109; for (int index = 4; index < chains.num_params(); index++) { ASSERT_NEAR(rhat(index - 4), chains.split_potential_scale_reduction(index), 1e-4) @@ -286,7 +304,12 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.0078, 1.0109, 0.999187, 1.001, 1.00401, 1.00992, 1.00182, 1.00519, 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, 1.01304, 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, 1.0013, 1.00193, 1.00104, 0.999383, 1.00025, 1.01082, 1.0019, 1.00354, 1.0043, 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, 1.00118, 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, 1.0109; + rhat << 1.0078, 1.0109, 0.999187, 1.001, 1.00401, 1.00992, 1.00182, 1.00519, + 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, 1.01304, + 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, 1.0013, + 1.00193, 1.00104, 0.999383, 1.00025, 1.01082, 1.0019, 1.00354, 1.0043, + 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, 1.00118, + 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, 1.0109; // replicates calls to stan::analyze::compute_effective_sample_size // for any interface *without* access to chains class @@ -379,7 +402,12 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.0078, 1.0109, 0.999187, 1.001, 1.00401, 1.00992, 1.00182, 1.00519, 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, 1.01304, 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, 1.0013, 1.00193, 1.00104, 0.999383, 1.00025, 1.01082, 1.0019, 1.00354, 1.0043, 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, 1.00118, 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, 1.0109; + rhat << 1.0078, 1.0109, 0.999187, 1.001, 1.00401, 1.00992, 1.00182, 1.00519, + 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, 1.01304, + 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, 1.0013, + 1.00193, 1.00104, 0.999383, 1.00025, 1.01082, 1.0019, 1.00354, 1.0043, + 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, 1.00118, + 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, 1.0109; Eigen::Matrix samples( chains.num_chains()); @@ -397,7 +425,6 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience) { 1e-4) << "rhat for index: " << index << ", parameter: " << chains.param_name(index); - } } diff --git a/src/test/unit/mcmc/chains_test.cpp b/src/test/unit/mcmc/chains_test.cpp index 7bf581ab31..b0d0db1d24 100644 --- a/src/test/unit/mcmc/chains_test.cpp +++ b/src/test/unit/mcmc/chains_test.cpp @@ -853,13 +853,12 @@ TEST_F(McmcChains, blocker_split_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.0078, 1.0109, 0.99919, 1.001, 1.00401, 1.00992, 1.00182, - 1.00519, 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, - 1.01304, 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, - 1.0013, 1.00193, 1.00104, 0.99938, 1.00025, 1.01082, 1.0019, 1.00354, - 1.0043, 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, - 1.00118, 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, - 1.0109; + rhat << 1.0078, 1.0109, 0.99919, 1.001, 1.00401, 1.00992, 1.00182, 1.00519, + 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, 1.01304, + 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, 1.0013, + 1.00193, 1.00104, 0.99938, 1.00025, 1.01082, 1.0019, 1.00354, 1.0043, + 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, 1.00118, + 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, 1.0109; for (int index = 4; index < chains.num_params(); index++) { ASSERT_NEAR(rhat(index - 4), chains.split_potential_scale_reduction(index), From b3631beaefae57c43b3629f70ae161a2653dd334 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 22 Apr 2024 11:03:57 -0400 Subject: [PATCH 25/25] Revert "update so scale_reduction calls scale_reduction_rank" This reverts commit f12f2591348c30e3849bb9c964ce67f248fcf6ab. --- .../compute_potential_scale_reduction.hpp | 73 ++++++++++++++++++- src/stan/mcmc/chains.hpp | 7 +- ...compute_potential_scale_reduction_test.cpp | 68 +++++++++-------- src/test/unit/mcmc/chains_test.cpp | 22 ++++-- 4 files changed, 124 insertions(+), 46 deletions(-) diff --git a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp index 47d0769573..93813775ca 100644 --- a/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp +++ b/src/stan/analyze/mcmc/compute_potential_scale_reduction.hpp @@ -183,8 +183,73 @@ inline std::pair compute_potential_scale_reduction_rank( * @return potential scale reduction for the specified parameter */ inline double compute_potential_scale_reduction( - const std::vector& draws, const std::vector& sizes) { - return compute_potential_scale_reduction_rank(draws, sizes).first; + std::vector draws, std::vector sizes) { + int num_chains = sizes.size(); + size_t num_draws = sizes[0]; + if (num_draws == 0) { + return std::numeric_limits::quiet_NaN(); + } + for (int chain = 1; chain < num_chains; ++chain) { + num_draws = std::min(num_draws, sizes[chain]); + } + + // check if chains are constant; all equal to first draw's value + bool are_all_const = false; + Eigen::VectorXd init_draw = Eigen::VectorXd::Zero(num_chains); + + for (int chain = 0; chain < num_chains; chain++) { + Eigen::Map> draw( + draws[chain], sizes[chain]); + + for (int n = 0; n < num_draws; n++) { + if (!std::isfinite(draw(n))) { + return std::numeric_limits::quiet_NaN(); + } + } + + init_draw(chain) = draw(0); + + if (draw.isApproxToConstant(draw(0))) { + are_all_const |= true; + } + } + + if (are_all_const) { + // If all chains are constant then return NaN + // if they all equal the same constant value + if (init_draw.isApproxToConstant(init_draw(0))) { + return std::numeric_limits::quiet_NaN(); + } + } + + using boost::accumulators::accumulator_set; + using boost::accumulators::stats; + using boost::accumulators::tag::mean; + using boost::accumulators::tag::variance; + + Eigen::VectorXd chain_mean(num_chains); + accumulator_set> acc_chain_mean; + Eigen::VectorXd chain_var(num_chains); + double unbiased_var_scale = num_draws / (num_draws - 1.0); + + for (int chain = 0; chain < num_chains; ++chain) { + accumulator_set> acc_draw; + for (int n = 0; n < num_draws; ++n) { + acc_draw(draws[chain][n]); + } + + chain_mean(chain) = boost::accumulators::mean(acc_draw); + acc_chain_mean(chain_mean(chain)); + chain_var(chain) + = boost::accumulators::variance(acc_draw) * unbiased_var_scale; + } + + double var_between = num_draws * boost::accumulators::variance(acc_chain_mean) + * num_chains / (num_chains - 1); + double var_within = chain_var.mean(); + + // rewrote [(n-1)*W/n + B/n]/W as (n-1+ B/W)/n + return sqrt((var_between / var_within + num_draws - 1) / num_draws); } /** @@ -230,7 +295,7 @@ inline double compute_potential_scale_reduction( std::vector draws, size_t size) { int num_chains = draws.size(); std::vector sizes(num_chains, size); - return compute_potential_scale_reduction_rank(draws, sizes).first; + return compute_potential_scale_reduction(draws, sizes); } /** @@ -298,7 +363,7 @@ inline double compute_split_potential_scale_reduction( double half = num_draws / 2.0; std::vector half_sizes(2 * num_chains, std::floor(half)); - return compute_potential_scale_reduction_rank(split_draws, half_sizes).first; + return compute_potential_scale_reduction(split_draws, half_sizes); } /** diff --git a/src/stan/mcmc/chains.hpp b/src/stan/mcmc/chains.hpp index 69ae7669f8..a553fd36cd 100644 --- a/src/stan/mcmc/chains.hpp +++ b/src/stan/mcmc/chains.hpp @@ -623,17 +623,16 @@ class chains { sizes[chain] = n_kept_samples; } - return analyze::compute_split_potential_scale_reduction_rank(draws, sizes) - .first; + return analyze::compute_split_potential_scale_reduction(draws, sizes); } std::pair split_potential_scale_reduction_rank( const std::string& name) const { - return this->split_potential_scale_reduction_rank(index(name)); + return split_potential_scale_reduction_rank(index(name)); } double split_potential_scale_reduction(const std::string& name) const { - return this->split_potential_scale_reduction_rank(index(name)).first; + return split_potential_scale_reduction(index(name)); } }; diff --git a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp index 84f6efbe81..41a102e51d 100644 --- a/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp +++ b/src/test/unit/analyze/mcmc/compute_potential_scale_reduction_test.cpp @@ -31,13 +31,13 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00067, 0.999789, 0.999656, 1.00055, 1.0011, 1.00088, 1.00032, - 0.999969, 1.00201, 0.999558, 0.999555, 0.9995, 1.00292, 1.00516, 1.00591, - 0.999753, 1.00088, 1.00895, 1.00079, 0.99953, 1.00092, 1.00044, 1.01005, - 0.999598, 1.00151, 0.999659, 0.999648, 0.999627, 1.00315, 1.00277, - 1.00247, 1.00003, 0.999937, 1.00116, 0.999521, 1.0005, 1.00091, 1.00213, - 1.00019, 0.999767, 1.0003, 0.999815, 1.00003, 0.999672, 1.00306, 1.00072, - 0.999602, 0.999789; + rhat << 1.00042, 1.00036, 0.99955, 1.00047, 1.00119, 1.00089, 1.00018, + 1.00019, 1.00226, 0.99954, 0.9996, 0.99951, 1.00237, 1.00515, 1.00566, + 0.99957, 1.00099, 1.00853, 1.0008, 0.99961, 1.0006, 1.00046, 1.01023, + 0.9996, 1.0011, 0.99967, 0.99973, 0.99958, 1.00242, 1.00213, 1.00244, + 0.99998, 0.99969, 1.00079, 0.99955, 1.0009, 1.00136, 1.00288, 1.00036, + 0.99989, 1.00077, 0.99997, 1.00194, 0.99972, 1.00257, 1.00109, 1.00004, + 0.99955; // replicates calls to stan::analyze::compute_effective_sample_size // for any interface *without* access to chains class @@ -129,13 +129,13 @@ TEST_F(ComputeRhat, compute_potential_scale_reduction_convenience) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.00067, 0.999789, 0.999656, 1.00055, 1.0011, 1.00088, 1.00032, - 0.999969, 1.00201, 0.999558, 0.999555, 0.9995, 1.00292, 1.00516, 1.00591, - 0.999753, 1.00088, 1.00895, 1.00079, 0.99953, 1.00092, 1.00044, 1.01005, - 0.999598, 1.00151, 0.999659, 0.999648, 0.999627, 1.00315, 1.00277, - 1.00247, 1.00003, 0.999937, 1.00116, 0.999521, 1.0005, 1.00091, 1.00213, - 1.00019, 0.999767, 1.0003, 0.999815, 1.00003, 0.999672, 1.00306, 1.00072, - 0.999602, 0.999789; + rhat << 1.00042, 1.00036, 0.99955, 1.00047, 1.00119, 1.00089, 1.00018, + 1.00019, 1.00226, 0.99954, 0.9996, 0.99951, 1.00237, 1.00515, 1.00566, + 0.99957, 1.00099, 1.00853, 1.0008, 0.99961, 1.0006, 1.00046, 1.01023, + 0.9996, 1.0011, 0.99967, 0.99973, 0.99958, 1.00242, 1.00213, 1.00244, + 0.99998, 0.99969, 1.00079, 0.99955, 1.0009, 1.00136, 1.00288, 1.00036, + 0.99989, 1.00077, 0.99997, 1.00194, 0.99972, 1.00257, 1.00109, 1.00004, + 0.99955; Eigen::Matrix samples( chains.num_chains()); @@ -222,12 +222,14 @@ TEST_F(ComputeRhat, chains_compute_split_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.0078, 1.0109, 0.999187, 1.001, 1.00401, 1.00992, 1.00182, 1.00519, - 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, 1.01304, - 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, 1.0013, - 1.00193, 1.00104, 0.999383, 1.00025, 1.01082, 1.0019, 1.00354, 1.0043, - 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, 1.00118, - 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, 1.0109; + rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, + 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, + 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, + 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, + 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, + 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, + 1.00735; + for (int index = 4; index < chains.num_params(); index++) { ASSERT_NEAR(rhat(index - 4), chains.split_potential_scale_reduction(index), 1e-4) @@ -304,12 +306,13 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.0078, 1.0109, 0.999187, 1.001, 1.00401, 1.00992, 1.00182, 1.00519, - 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, 1.01304, - 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, 1.0013, - 1.00193, 1.00104, 0.999383, 1.00025, 1.01082, 1.0019, 1.00354, 1.0043, - 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, 1.00118, - 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, 1.0109; + rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, + 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, + 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, + 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, + 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, + 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, + 1.00735; // replicates calls to stan::analyze::compute_effective_sample_size // for any interface *without* access to chains class @@ -402,12 +405,13 @@ TEST_F(ComputeRhat, compute_split_potential_scale_reduction_convenience) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.0078, 1.0109, 0.999187, 1.001, 1.00401, 1.00992, 1.00182, 1.00519, - 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, 1.01304, - 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, 1.0013, - 1.00193, 1.00104, 0.999383, 1.00025, 1.01082, 1.0019, 1.00354, 1.0043, - 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, 1.00118, - 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, 1.0109; + rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, + 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, + 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, + 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, + 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, + 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, + 1.00735; Eigen::Matrix samples( chains.num_chains()); diff --git a/src/test/unit/mcmc/chains_test.cpp b/src/test/unit/mcmc/chains_test.cpp index b0d0db1d24..f2d90aaf0d 100644 --- a/src/test/unit/mcmc/chains_test.cpp +++ b/src/test/unit/mcmc/chains_test.cpp @@ -853,12 +853,13 @@ TEST_F(McmcChains, blocker_split_potential_scale_reduction) { chains.add(blocker2); Eigen::VectorXd rhat(48); - rhat << 1.0078, 1.0109, 0.99919, 1.001, 1.00401, 1.00992, 1.00182, 1.00519, - 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546, 1.01304, - 1.00166, 1.0074, 1.00178, 1.00588, 1.00406, 1.00129, 1.00976, 1.0013, - 1.00193, 1.00104, 0.99938, 1.00025, 1.01082, 1.0019, 1.00354, 1.0043, - 1.00111, 1.00281, 1.00436, 1.00515, 1.00325, 1.0089, 1.00222, 1.00118, - 1.00191, 1.00283, 1.0003, 1.00216, 1.00335, 1.00133, 1.00023, 1.0109; + rhat << 1.00718, 1.00473, 0.999203, 1.00061, 1.00378, 1.01031, 1.00173, + 1.0045, 1.00111, 1.00337, 1.00546, 1.00105, 1.00558, 1.00463, 1.00534, + 1.01244, 1.00174, 1.00718, 1.00186, 1.00554, 1.00436, 1.00147, 1.01017, + 1.00162, 1.00143, 1.00058, 0.999221, 1.00012, 1.01028, 1.001, 1.00305, + 1.00435, 1.00055, 1.00246, 1.00447, 1.0048, 1.00209, 1.01159, 1.00202, + 1.00077, 1.0021, 1.00262, 1.00308, 1.00197, 1.00246, 1.00085, 1.00047, + 1.00735; for (int index = 4; index < chains.num_params(); index++) { ASSERT_NEAR(rhat(index - 4), chains.split_potential_scale_reduction(index), @@ -885,6 +886,15 @@ TEST_F(McmcChains, blocker_split_potential_scale_reduction_rank) { stan::mcmc::chains<> chains(blocker1); chains.add(blocker2); + // Eigen::VectorXd rhat(48); + // rhat + // << 1.0078, 1.0109, 1.00731, 1.00333, 1.00401, 1.00992, 1.00734, 1.00633, + // 1.00095, 1.00906, 1.01019, 1.00075, 1.00595, 1.00473, 1.00895, 1.01304, + // 1.00166, 1.0074, 1.00236, 1.00588, 1.00414, 1.00303, 1.00976, 1.00295, + // 1.00193, 1.0044, 1.00488, 1.00178, 1.01082, 1.0019, 1.00413, 1.01303, + // 1.0024, 1.01148, 1.00436, 1.00515, 1.00712, 1.0089, 1.00222, 1.00118, + // 1.00381, 1.00283, 1.00188, 1.00225, 1.00335, 1.00133, 1.00209, 1.0109; + Eigen::VectorXd rhat_bulk(48); rhat_bulk << 1.0078, 1.0109, 0.99919, 1.001, 1.00401, 1.00992, 1.00182, 1.00519, 1.00095, 1.00351, 1.00554, 1.00075, 1.00595, 1.00473, 1.00546,