From dd40e699078e083684b3ac14798e5ba01fc6109d Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 19 Mar 2021 11:33:09 -0400 Subject: [PATCH 1/5] Stepsize no longer reset to 1 if term_buffer = 0 (Issue #3023) --- src/stan/mcmc/covar_adaptation.hpp | 12 ++++++++--- src/stan/mcmc/var_adaptation.hpp | 12 ++++++++--- src/stan/mcmc/windowed_adaptation.hpp | 21 ++++++++++++++++++- src/test/unit/mcmc/covar_adaptation_test.cpp | 18 ++++++++++++---- src/test/unit/mcmc/var_adaptation_test.cpp | 15 ++++++++++--- .../unit/mcmc/windowed_adaptation_test.cpp | 14 +++++++++++++ 6 files changed, 78 insertions(+), 14 deletions(-) diff --git a/src/stan/mcmc/covar_adaptation.hpp b/src/stan/mcmc/covar_adaptation.hpp index 6c21c63e33a..05b1a87d49f 100644 --- a/src/stan/mcmc/covar_adaptation.hpp +++ b/src/stan/mcmc/covar_adaptation.hpp @@ -14,6 +14,12 @@ class covar_adaptation : public windowed_adaptation { explicit covar_adaptation(int n) : windowed_adaptation("covariance"), estimator_(n) {} + /** + * Return true if covariance was updated and adaptation is not finished + * + * @param covar Covariance + * @param q Last draw + */ bool learn_covariance(Eigen::MatrixXd& covar, const Eigen::VectorXd& q) { if (adaptation_window()) estimator_.add_sample(q); @@ -30,11 +36,11 @@ class covar_adaptation : public windowed_adaptation { estimator_.restart(); - ++adapt_window_counter_; - return true; + increment_window_counter(); + return true && !finished(); } - ++adapt_window_counter_; + increment_window_counter(); return false; } diff --git a/src/stan/mcmc/var_adaptation.hpp b/src/stan/mcmc/var_adaptation.hpp index c81de41d980..1edb8ff41f5 100644 --- a/src/stan/mcmc/var_adaptation.hpp +++ b/src/stan/mcmc/var_adaptation.hpp @@ -14,6 +14,12 @@ class var_adaptation : public windowed_adaptation { explicit var_adaptation(int n) : windowed_adaptation("variance"), estimator_(n) {} + /** + * Return true if variance was updated and adaptation is not finished + * + * @param var Diagonal covariance + * @param q Last draw + */ bool learn_variance(Eigen::VectorXd& var, const Eigen::VectorXd& q) { if (adaptation_window()) estimator_.add_sample(q); @@ -29,11 +35,11 @@ class var_adaptation : public windowed_adaptation { estimator_.restart(); - ++adapt_window_counter_; - return true; + increment_window_counter(); + return true && !finished(); } - ++adapt_window_counter_; + increment_window_counter(); return false; } diff --git a/src/stan/mcmc/windowed_adaptation.hpp b/src/stan/mcmc/windowed_adaptation.hpp index 36bf1d1d986..f1e4a38ffa3 100644 --- a/src/stan/mcmc/windowed_adaptation.hpp +++ b/src/stan/mcmc/windowed_adaptation.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include namespace stan { @@ -109,6 +109,25 @@ class windowed_adaptation : public base_adaptation { } } + /** + * Check if there is any more warmup left to do + */ + bool finished() { + if(adapt_window_counter_ + 1 >= num_warmup_) { + return true; + } else { + return false; + } + } + + /** + * Increment the window counter and return the new value + */ + unsigned int increment_window_counter() { + adapt_window_counter_ += 1; + return adapt_window_counter_; + } + protected: std::string estimator_name_; diff --git a/src/test/unit/mcmc/covar_adaptation_test.cpp b/src/test/unit/mcmc/covar_adaptation_test.cpp index f1e0853d884..2729494d745 100644 --- a/src/test/unit/mcmc/covar_adaptation_test.cpp +++ b/src/test/unit/mcmc/covar_adaptation_test.cpp @@ -15,15 +15,25 @@ TEST(McmcCovarAdaptation, learn_covariance) { target_covar *= 1e-3 * 5.0 / (n_learn + 5.0); stan::mcmc::covar_adaptation adapter(n); - adapter.set_window_params(50, 0, 0, n_learn, logger); - - for (int i = 0; i < n_learn; ++i) - adapter.learn_covariance(covar, q); + adapter.set_window_params(30, 0, 0, n_learn, logger); + for (int i = 0; i < n_learn - 1; ++i) { + EXPECT_FALSE(adapter.learn_covariance(covar, q)); + } + // Learn variance should return true at end of first window + EXPECT_TRUE(adapter.learn_covariance(covar, q)); + for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { EXPECT_EQ(target_covar(i, j), covar(i, j)); } } + + // Make sure learn_variance doesn't return true after second window (adaptation finished) + for (int i = 0; i < 2 * n_learn ; ++i) { + EXPECT_FALSE(adapter.learn_covariance(covar, q)); + } + EXPECT_TRUE(adapter.finished()); + EXPECT_EQ(0, logger.call_count()); } diff --git a/src/test/unit/mcmc/var_adaptation_test.cpp b/src/test/unit/mcmc/var_adaptation_test.cpp index 708f5b2e7f8..4d8b9dc49ec 100644 --- a/src/test/unit/mcmc/var_adaptation_test.cpp +++ b/src/test/unit/mcmc/var_adaptation_test.cpp @@ -15,13 +15,22 @@ TEST(McmcVarAdaptation, learn_variance) { target_var *= 1e-3 * 5.0 / (n_learn + 5.0); stan::mcmc::var_adaptation adapter(n); - adapter.set_window_params(50, 0, 0, n_learn, logger); + adapter.set_window_params(30, 0, 0, n_learn, logger); - for (int i = 0; i < n_learn; ++i) - adapter.learn_variance(var, q); + for (int i = 0; i < n_learn - 1; ++i) { + EXPECT_FALSE(adapter.learn_variance(var, q)); + } + // Learn variance should return true at end of first window + EXPECT_TRUE(adapter.learn_variance(var, q)); for (int i = 0; i < n; ++i) EXPECT_EQ(target_var(i), var(i)); + // Make sure learn_variance doesn't return true after second window (adaptation finished) + for (int i = 0; i < 2 * n_learn ; ++i) { + EXPECT_FALSE(adapter.learn_variance(var, q)); + } + EXPECT_TRUE(adapter.finished()); + EXPECT_EQ(0, logger.call_count()); } diff --git a/src/test/unit/mcmc/windowed_adaptation_test.cpp b/src/test/unit/mcmc/windowed_adaptation_test.cpp index c30455b0ff0..fdb10eed4c1 100644 --- a/src/test/unit/mcmc/windowed_adaptation_test.cpp +++ b/src/test/unit/mcmc/windowed_adaptation_test.cpp @@ -46,3 +46,17 @@ TEST(McmcWindowedAdaptation, set_window_params3) { ASSERT_EQ(0, logger.call_count()); ASSERT_EQ(0, logger.call_count_info()); } + +TEST(McmcWindowedAdaptation, finished) { + stan::test::unit::instrumented_logger logger; + + stan::mcmc::windowed_adaptation adapter("test"); + + adapter.set_window_params(1000, 75, 50, 25, logger); + + for(size_t i = 0; i < 999; i++) { + EXPECT_FALSE(adapter.finished()); + adapter.increment_window_counter(); + } + EXPECT_TRUE(adapter.finished()); +} From 7d2d478955f52884062787ea7b1e2d83957d2dac Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 19 Mar 2021 11:40:49 -0400 Subject: [PATCH 2/5] Reverted header (Issue #3023) --- src/stan/mcmc/windowed_adaptation.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stan/mcmc/windowed_adaptation.hpp b/src/stan/mcmc/windowed_adaptation.hpp index f1e4a38ffa3..5777af71611 100644 --- a/src/stan/mcmc/windowed_adaptation.hpp +++ b/src/stan/mcmc/windowed_adaptation.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include namespace stan { From 4b0ae48d60f96f6435902bb136fbb8c3e55e7de9 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Fri, 19 Mar 2021 15:47:12 +0000 Subject: [PATCH 3/5] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- src/stan/mcmc/windowed_adaptation.hpp | 2 +- src/test/unit/mcmc/covar_adaptation_test.cpp | 7 ++++--- src/test/unit/mcmc/var_adaptation_test.cpp | 5 +++-- src/test/unit/mcmc/windowed_adaptation_test.cpp | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/stan/mcmc/windowed_adaptation.hpp b/src/stan/mcmc/windowed_adaptation.hpp index 5777af71611..6e529ed00bd 100644 --- a/src/stan/mcmc/windowed_adaptation.hpp +++ b/src/stan/mcmc/windowed_adaptation.hpp @@ -113,7 +113,7 @@ class windowed_adaptation : public base_adaptation { * Check if there is any more warmup left to do */ bool finished() { - if(adapt_window_counter_ + 1 >= num_warmup_) { + if (adapt_window_counter_ + 1 >= num_warmup_) { return true; } else { return false; diff --git a/src/test/unit/mcmc/covar_adaptation_test.cpp b/src/test/unit/mcmc/covar_adaptation_test.cpp index 2729494d745..31998090fcc 100644 --- a/src/test/unit/mcmc/covar_adaptation_test.cpp +++ b/src/test/unit/mcmc/covar_adaptation_test.cpp @@ -22,15 +22,16 @@ TEST(McmcCovarAdaptation, learn_covariance) { } // Learn variance should return true at end of first window EXPECT_TRUE(adapter.learn_covariance(covar, q)); - + for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { EXPECT_EQ(target_covar(i, j), covar(i, j)); } } - // Make sure learn_variance doesn't return true after second window (adaptation finished) - for (int i = 0; i < 2 * n_learn ; ++i) { + // Make sure learn_variance doesn't return true after second window + // (adaptation finished) + for (int i = 0; i < 2 * n_learn; ++i) { EXPECT_FALSE(adapter.learn_covariance(covar, q)); } EXPECT_TRUE(adapter.finished()); diff --git a/src/test/unit/mcmc/var_adaptation_test.cpp b/src/test/unit/mcmc/var_adaptation_test.cpp index 4d8b9dc49ec..6580809ad3f 100644 --- a/src/test/unit/mcmc/var_adaptation_test.cpp +++ b/src/test/unit/mcmc/var_adaptation_test.cpp @@ -26,8 +26,9 @@ TEST(McmcVarAdaptation, learn_variance) { for (int i = 0; i < n; ++i) EXPECT_EQ(target_var(i), var(i)); - // Make sure learn_variance doesn't return true after second window (adaptation finished) - for (int i = 0; i < 2 * n_learn ; ++i) { + // Make sure learn_variance doesn't return true after second window + // (adaptation finished) + for (int i = 0; i < 2 * n_learn; ++i) { EXPECT_FALSE(adapter.learn_variance(var, q)); } EXPECT_TRUE(adapter.finished()); diff --git a/src/test/unit/mcmc/windowed_adaptation_test.cpp b/src/test/unit/mcmc/windowed_adaptation_test.cpp index fdb10eed4c1..f54c867d76d 100644 --- a/src/test/unit/mcmc/windowed_adaptation_test.cpp +++ b/src/test/unit/mcmc/windowed_adaptation_test.cpp @@ -54,7 +54,7 @@ TEST(McmcWindowedAdaptation, finished) { adapter.set_window_params(1000, 75, 50, 25, logger); - for(size_t i = 0; i < 999; i++) { + for (size_t i = 0; i < 999; i++) { EXPECT_FALSE(adapter.finished()); adapter.increment_window_counter(); } From 2e2c45002e2db4717fe310ea0e339a7779b2a050 Mon Sep 17 00:00:00 2001 From: Ben Date: Sat, 3 Apr 2021 13:47:12 -0700 Subject: [PATCH 4/5] Added test for sampler --- src/stan/mcmc/windowed_adaptation.hpp | 6 +-- src/test/unit/mcmc/covar_adaptation_test.cpp | 4 +- .../sample/hmc_nuts_dense_e_adapt_test.cpp | 43 +++++++++++++++++++ 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/stan/mcmc/windowed_adaptation.hpp b/src/stan/mcmc/windowed_adaptation.hpp index 6e529ed00bd..75b658b7f9d 100644 --- a/src/stan/mcmc/windowed_adaptation.hpp +++ b/src/stan/mcmc/windowed_adaptation.hpp @@ -113,11 +113,7 @@ class windowed_adaptation : public base_adaptation { * Check if there is any more warmup left to do */ bool finished() { - if (adapt_window_counter_ + 1 >= num_warmup_) { - return true; - } else { - return false; - } + return adapt_window_counter_ + 1 >= num_warmup_; } /** diff --git a/src/test/unit/mcmc/covar_adaptation_test.cpp b/src/test/unit/mcmc/covar_adaptation_test.cpp index 31998090fcc..9bcdf36a2a8 100644 --- a/src/test/unit/mcmc/covar_adaptation_test.cpp +++ b/src/test/unit/mcmc/covar_adaptation_test.cpp @@ -20,7 +20,7 @@ TEST(McmcCovarAdaptation, learn_covariance) { for (int i = 0; i < n_learn - 1; ++i) { EXPECT_FALSE(adapter.learn_covariance(covar, q)); } - // Learn variance should return true at end of first window + // Learn covariance should return true at end of first window EXPECT_TRUE(adapter.learn_covariance(covar, q)); for (int i = 0; i < n; ++i) { @@ -29,7 +29,7 @@ TEST(McmcCovarAdaptation, learn_covariance) { } } - // Make sure learn_variance doesn't return true after second window + // Make sure learn_covariance doesn't return true after second window // (adaptation finished) for (int i = 0; i < 2 * n_learn; ++i) { EXPECT_FALSE(adapter.learn_covariance(covar, q)); diff --git a/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_test.cpp b/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_test.cpp index 8638966d5dd..2aee830f39c 100644 --- a/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_test.cpp +++ b/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_test.cpp @@ -184,3 +184,46 @@ TEST_F(ServicesSampleHmcNutsDenseEAdapt, output_regression) { EXPECT_EQ(1, logger.find_info("seconds (Total)")); EXPECT_EQ(0, logger.call_count_error()); } + +TEST_F(ServicesSampleHmcNutsDenseEAdapt, no_timestep_reset) { + unsigned int random_seed = 0; + unsigned int chain = 1; + double init_radius = 0; + int num_warmup = 70; + int num_samples = 100; + int num_thin = 5; + bool save_warmup = true; + int refresh = 0; + double stepsize = 0.1; + double stepsize_jitter = 0; + int max_depth = 8; + double delta = .1; + double gamma = .1; + double kappa = .1; + double t0 = .1; + unsigned int init_buffer = 0; + unsigned int term_buffer = 0; + unsigned int window = 10; + stan::test::unit::instrumented_interrupt interrupt; + EXPECT_EQ(interrupt.call_count(), 0); + + int return_code = stan::services::sample::hmc_nuts_dense_e_adapt( + model, context, random_seed, chain, init_radius, num_warmup, num_samples, + num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, + delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, + logger, init, parameter, diagnostic); + + std::vector string_values = parameter.string_values(); + bool found_step_size = false; + for(size_t i = 0; i < string_values.size(); i++) { + // Make sure the sampler wrote a Step size and that it is not reset to exactly 1 + if(string_values[i].compare("Step size")) { + found_step_size = true; + EXPECT_NE(string_values[i].compare("Step size = 1"), 0); + } + } + + EXPECT_TRUE(found_step_size); + + EXPECT_EQ(return_code, 0); +} From 40ee1c23a0eb58472153d83b0256a37894a2bbdd Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sat, 3 Apr 2021 20:47:53 +0000 Subject: [PATCH 5/5] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- src/stan/mcmc/windowed_adaptation.hpp | 4 +--- .../unit/services/sample/hmc_nuts_dense_e_adapt_test.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/stan/mcmc/windowed_adaptation.hpp b/src/stan/mcmc/windowed_adaptation.hpp index 75b658b7f9d..81fb46eac04 100644 --- a/src/stan/mcmc/windowed_adaptation.hpp +++ b/src/stan/mcmc/windowed_adaptation.hpp @@ -112,9 +112,7 @@ class windowed_adaptation : public base_adaptation { /** * Check if there is any more warmup left to do */ - bool finished() { - return adapt_window_counter_ + 1 >= num_warmup_; - } + bool finished() { return adapt_window_counter_ + 1 >= num_warmup_; } /** * Increment the window counter and return the new value diff --git a/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_test.cpp b/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_test.cpp index 2aee830f39c..7fd9b11eaa0 100644 --- a/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_test.cpp +++ b/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_test.cpp @@ -215,9 +215,10 @@ TEST_F(ServicesSampleHmcNutsDenseEAdapt, no_timestep_reset) { std::vector string_values = parameter.string_values(); bool found_step_size = false; - for(size_t i = 0; i < string_values.size(); i++) { - // Make sure the sampler wrote a Step size and that it is not reset to exactly 1 - if(string_values[i].compare("Step size")) { + for (size_t i = 0; i < string_values.size(); i++) { + // Make sure the sampler wrote a Step size and that it is not reset to + // exactly 1 + if (string_values[i].compare("Step size")) { found_step_size = true; EXPECT_NE(string_values[i].compare("Step size = 1"), 0); }