From e1c15de38cfb1b71ce230787f3280ca0d323065e Mon Sep 17 00:00:00 2001 From: Aki Vehtari Date: Sat, 24 Oct 2026 11:39:30 +0300 Subject: [PATCH 1/2] Do not compute MCSE, ESS, and R-hat for sampler diagnostics in stansummary --- src/cmdstan/stansummary.cpp | 3 ++- src/cmdstan/stansummary_helper.hpp | 13 +++++++++++-- src/test/interface/stansummary_test.cpp | 18 +++++++++--------- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/cmdstan/stansummary.cpp b/src/cmdstan/stansummary.cpp index cf8e41cc96..8889151e4a 100644 --- a/src/cmdstan/stansummary.cpp +++ b/src/cmdstan/stansummary.cpp @@ -201,8 +201,9 @@ Example: stansummary model_chain_1.csv model_chain_2.csv Eigen::MatrixXd model_params(num_model_params, header.size()); get_stats(chains, sampling_times, probs, {0}, lp_param); + // MCSE, ESS, and R_hat are not meaningful for the sampler diagnostics get_stats(chains, sampling_times, probs, sampler_params_idxes, - sampler_params); + sampler_params, false); get_stats(chains, sampling_times, probs, model_param_idxes, model_params); // Console output formatting diff --git a/src/cmdstan/stansummary_helper.hpp b/src/cmdstan/stansummary_helper.hpp index ab0e649fb7..f8834a3799 100644 --- a/src/cmdstan/stansummary_helper.hpp +++ b/src/cmdstan/stansummary_helper.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -393,11 +394,12 @@ std::vector get_header( * @param in vector of model param column incides in chains object * @param in span length * @param in out matrix of model param statistics + * @param in convergence_diagnostics if false, MCSE, ESS, and R_hat are NaN */ void get_stats(const stan::mcmc::chainset &chains, const Eigen::VectorXd &sampling_times, const Eigen::VectorXd &probs, std::vector cols, - Eigen::MatrixXd ¶ms) { + Eigen::MatrixXd ¶ms, bool convergence_diagnostics = true) { params.setZero(); if (params.rows() != cols.size()) { @@ -405,12 +407,13 @@ void get_stats(const stan::mcmc::chainset &chains, } double total_sampling_time = sampling_times.sum(); + constexpr double nan = std::numeric_limits::quiet_NaN(); // Model parameters int i = 0; for (int i_chains : cols) { params(i, 0) = chains.mean(i_chains); - params(i, 1) = chains.mcse_mean(i_chains); + params(i, 1) = convergence_diagnostics ? chains.mcse_mean(i_chains) : nan; params(i, 2) = chains.sd(i_chains); params(i, 3) = chains.med_abs_deviation(i_chains); Eigen::VectorXd quantiles = chains.quantiles(i_chains, probs); @@ -418,6 +421,12 @@ void get_stats(const stan::mcmc::chainset &chains, params(i, 4 + j) = quantiles(j); auto offset = 4 + quantiles.size(); + if (!convergence_diagnostics) { + for (int j = 0; j < 4; ++j) + params(i, offset++) = nan; + i++; + continue; + } auto [ess_bulk, ess_tail] = chains.split_rank_normalized_ess(i_chains); params(i, offset++) = ess_bulk; diff --git a/src/test/interface/stansummary_test.cpp b/src/test/interface/stansummary_test.cpp index f9c595a01c..d7ab2bcc7b 100644 --- a/src/test/interface/stansummary_test.cpp +++ b/src/test/interface/stansummary_test.cpp @@ -433,11 +433,11 @@ TEST(CommandStansummary, check_console_output) { = "theta 0.26 6.1e-03 0.12 0.12 0.080 0.25 0.47 " " 362 396 15718 1.0"; std::string accept_stat - = "accept_stat__ 0.90 4.6e-03 1.5e-01 0.064 0.57 0.96 1.0 " - "1284 941 55805 1.00"; + = "accept_stat__ 0.90 nan 1.5e-01 0.064 0.57 0.96 1.0 " + " nan nan nan nan"; std::string energy - = "energy__ 7.8 5.1e-02 1.0e+00 0.75 6.8 7.5 9.9 " - " 490 486 21299 1.0"; + = "energy__ 7.8 nan 1.0e+00 0.75 6.8 7.5 9.9 " + " nan nan nan nan"; std::string path_separator; path_separator.push_back(get_path_separator()); @@ -488,8 +488,8 @@ TEST(CommandStansummary, check_csv_output) { = "\"lp__\",-7.2719,0.0365168,0.768874,0.303688,-8.98426,-6.97009,-6." "75007,519.29,503.309,22577.8,1.00141"; std::string energy - = "\"energy__\",7.78428,0.0508815,1.0314,0.745859,6.80565,7.46758,9.8864," - "489.874,486.438,21298.9,1.00495"; + = "\"energy__\",7.78428,nan,1.0314,0.745859,6.80565,7.46758,9.8864,nan," + "nan,nan,nan"; std::string theta = "\"theta\",0.256552,0.00610844,0.119654,0.120965,0.0802982,0.24996,0." "47034,361.506,395.736,15717.6,1.00186"; @@ -581,7 +581,7 @@ TEST(CommandStansummary, check_csv_output_sig_figs) { std::string lp = "\"lp__\",-7.3,0.037,0.77,0.3,-9,-7,-6.8,5.2e+02,5e+02,2.3e+04,1"; std::string energy - = "\"energy__\",7.8,0.051,1,0.75,6.8,7.5,9.9,4.9e+02,4.9e+02,2.1e+04,1"; + = "\"energy__\",7.8,nan,1,0.75,6.8,7.5,9.9,nan,nan,nan,nan"; std::string theta = "\"theta\",0.26,0.0061,0.12,0.12,0.08,0.25,0.47,3.6e+02,4e+02,1.6e+04," "1"; @@ -635,8 +635,8 @@ TEST(CommandStansummary, check_csv_output_include_param) { = "\"lp__\",-15.5617,0.97319,6.05585,6.3817,-25.3182,-15.7598,-5.47732," "41.1897,113.537,396.283,1.00153"; std::string energy - = "\"energy__\",20.5888,1.01449,6.43127,6.6161,10.2809,20.8278,30.9921," - "42.5605,140.171,409.472,1.00069"; + = "\"energy__\",20.5888,nan,6.43127,6.6161,10.2809,20.8278,30.9921,nan," + "nan,nan,nan"; // note: skipping theta 1-5 std::string theta6 = "\"theta[6]\",5.001,0.365016,5.76072,5.37947,-4.95375,5.22746,14.1688," From 0264af89e185db2a37788d5d24dbeb871a1040f4 Mon Sep 17 00:00:00 2001 From: Aki Vehtari Date: Sat, 24 Oct 2026 11:39:46 +0300 Subject: [PATCH 2/2] Update stansummary_test MCSE values for split-chain MCSE in Stan --- src/test/interface/stansummary_test.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/interface/stansummary_test.cpp b/src/test/interface/stansummary_test.cpp index d7ab2bcc7b..35e599eda5 100644 --- a/src/test/interface/stansummary_test.cpp +++ b/src/test/interface/stansummary_test.cpp @@ -485,13 +485,13 @@ TEST(CommandStansummary, check_csv_output) { = "name,Mean,MCSE,StdDev,MAD,5%,50%,95%,ESS_bulk,ESS_tail,ESS_bulk/" "s,R_hat"; std::string lp - = "\"lp__\",-7.2719,0.0365168,0.768874,0.303688,-8.98426,-6.97009,-6." + = "\"lp__\",-7.2719,0.0365073,0.768874,0.303688,-8.98426,-6.97009,-6." "75007,519.29,503.309,22577.8,1.00141"; std::string energy = "\"energy__\",7.78428,nan,1.0314,0.745859,6.80565,7.46758,9.8864,nan," "nan,nan,nan"; std::string theta - = "\"theta\",0.256552,0.00610844,0.119654,0.120965,0.0802982,0.24996,0." + = "\"theta\",0.256552,0.00609368,0.119654,0.120965,0.0802982,0.24996,0." "47034,361.506,395.736,15717.6,1.00186"; std::string path_separator; @@ -538,7 +538,7 @@ TEST(CommandStansummary, check_csv_output_no_percentiles) { std::string csv_header = "name,Mean,MCSE,StdDev,MAD,ESS_bulk,ESS_tail,ESS_bulk/s,R_hat"; std::string lp - = "\"lp__\",-7.2719,0.0365168,0.768874,0.303688,519.29,503.309,22577.8,1." + = "\"lp__\",-7.2719,0.0365073,0.768874,0.303688,519.29,503.309,22577.8,1." "00141"; std::string path_separator; @@ -632,17 +632,17 @@ TEST(CommandStansummary, check_csv_output_include_param) { = "name,Mean,MCSE,StdDev,MAD,5%,50%,95%,ESS_bulk,ESS_tail,ESS_bulk/" "s,R_hat"; std::string lp - = "\"lp__\",-15.5617,0.97319,6.05585,6.3817,-25.3182,-15.7598,-5.47732," + = "\"lp__\",-15.5617,0.952577,6.05585,6.3817,-25.3182,-15.7598,-5.47732," "41.1897,113.537,396.283,1.00153"; std::string energy = "\"energy__\",20.5888,nan,6.43127,6.6161,10.2809,20.8278,30.9921,nan," "nan,nan,nan"; // note: skipping theta 1-5 std::string theta6 - = "\"theta[6]\",5.001,0.365016,5.76072,5.37947,-4.95375,5.22746,14.1688," + = "\"theta[6]\",5.001,0.368663,5.76072,5.37947,-4.95375,5.22746,14.1688," "230.645,464.978,2219.02,1.00054"; std::string theta7 - = "\"theta[7]\",8.54125,0.650098,6.22195,5.35785,-0.814388,8.09342,19." + = "\"theta[7]\",8.54125,0.641448,6.22195,5.35785,-0.814388,8.09342,19." "2622,92.3075,241.177,888.084,1.00244"; // note: skipping theta 8 std::string message = "# Inference for Stan model: eight_schools_cp_model";