From 361634a90068babefa69bc55b47f2a51f9910dd0 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 28 May 2024 12:24:48 -0400 Subject: [PATCH 1/5] update error message for different init types so that users get nicer errors --- src/stan/services/util/initialize.hpp | 48 ++++++++++++++++--- .../unit/services/instrumented_callbacks.hpp | 17 ++++++- .../unit/services/util/initialize_test.cpp | 21 ++++---- 3 files changed, 67 insertions(+), 19 deletions(-) diff --git a/src/stan/services/util/initialize.hpp b/src/stan/services/util/initialize.hpp index 1ce2a09b0d6..1bc581ccc1a 100644 --- a/src/stan/services/util/initialize.hpp +++ b/src/stan/services/util/initialize.hpp @@ -102,8 +102,9 @@ std::vector initialize(Model& model, const InitContext& init, RNG& rng, model.transform_inits(context, disc_vector, unconstrained, &msg); } } catch (std::domain_error& e) { - if (msg.str().length() > 0) + if (msg.str().length() > 0) { logger.info(msg); + } logger.warn("Rejecting initial value:"); logger.warn( " Error evaluating the log probability" @@ -111,8 +112,9 @@ std::vector initialize(Model& model, const InitContext& init, RNG& rng, logger.warn(e.what()); continue; } catch (std::exception& e) { - if (msg.str().length() > 0) + if (msg.str().length() > 0) { logger.info(msg); + } logger.error( "Unrecoverable error evaluating the log probability" " at the initial value."); @@ -127,8 +129,9 @@ std::vector initialize(Model& model, const InitContext& init, RNG& rng, // the parameters. log_prob = model.template log_prob(unconstrained, disc_vector, &msg); - if (msg.str().length() > 0) + if (msg.str().length() > 0) { logger.info(msg); + } } catch (std::domain_error& e) { if (msg.str().length() > 0) logger.info(msg); @@ -139,8 +142,9 @@ std::vector initialize(Model& model, const InitContext& init, RNG& rng, logger.warn(e.what()); continue; } catch (std::exception& e) { - if (msg.str().length() > 0) + if (msg.str().length() > 0) { logger.info(msg); + } logger.error( "Unrecoverable error evaluating the log probability" " at the initial value."); @@ -165,8 +169,9 @@ std::vector initialize(Model& model, const InitContext& init, RNG& rng, log_prob = stan::model::log_prob_grad( model, unconstrained, disc_vector, gradient, &log_prob_msg); } catch (const std::exception& e) { - if (log_prob_msg.str().length() > 0) + if (log_prob_msg.str().length() > 0) { logger.info(log_prob_msg); + } logger.error(e.what()); throw; } @@ -210,8 +215,36 @@ std::vector initialize(Model& model, const InitContext& init, RNG& rng, return unconstrained; } } - - if (!is_initialized_with_zero) { + if (is_fully_initialized) { + logger.info(""); + logger.error("User-specified initialization failed."); + logger.error( + " Try specifying new initial values," + " use partially specialized initialization," + " reducing ranges of constrained values," + " or reparameterizing the model."); + } else if (any_initialized) { + logger.info(""); + std::stringstream msg; + msg << "Partial user-specified initialization failed. " + "Initialization of non user specified parameters " + "between (-" << init_radius << ", " << init_radius + << ") failed after" + << " " << MAX_INIT_TRIES << " attempts. "; + logger.error(msg); + logger.error( + " Try specifying full initial values," + " reducing ranges of constrained values," + " or reparameterizing the model."); + } else if (is_initialized_with_zero) { + logger.info(""); + logger.error("Initial values of 0 failed to initialize."); + logger.error( + " Try specifying new initial values," + " use partially specialized initialization," + " reducing ranges of constrained values," + " or reparameterizing the model."); + } else { logger.info(""); std::stringstream msg; msg << "Initialization between (-" << init_radius << ", " << init_radius @@ -222,6 +255,7 @@ std::vector initialize(Model& model, const InitContext& init, RNG& rng, " Try specifying initial values," " reducing ranges of constrained values," " or reparameterizing the model."); + } throw std::domain_error("Initialization failed."); } diff --git a/src/test/unit/services/instrumented_callbacks.hpp b/src/test/unit/services/instrumented_callbacks.hpp index 206d0b54f41..9ed91a4c67c 100644 --- a/src/test/unit/services/instrumented_callbacks.hpp +++ b/src/test/unit/services/instrumented_callbacks.hpp @@ -281,7 +281,22 @@ class instrumented_logger : public stan::callbacks::logger { count++; return count; } - +public: + std::vector return_all_logs() { + std::vector all_logs; + all_logs.reserve(debug_.size() + info_.size() + warn_.size() + error_.size() + fatal_.size() + 5); + all_logs.emplace_back("DEBUG"); + all_logs.insert(all_logs.end(), debug_.begin(), debug_.end()); + all_logs.emplace_back("INFO"); + all_logs.insert(all_logs.end(), info_.begin(), info_.end()); + all_logs.emplace_back("WARN"); + all_logs.insert(all_logs.end(), warn_.begin(), warn_.end()); + all_logs.emplace_back("ERROR"); + all_logs.insert(all_logs.end(), error_.begin(), error_.end()); + all_logs.emplace_back("FATAL"); + all_logs.insert(all_logs.end(), fatal_.begin(), fatal_.end()); + return all_logs; + } std::vector debug_; std::vector info_; std::vector warn_; diff --git a/src/test/unit/services/util/initialize_test.cpp b/src/test/unit/services/util/initialize_test.cpp index a0acf6db685..e268d9c20bc 100644 --- a/src/test/unit/services/util/initialize_test.cpp +++ b/src/test/unit/services/util/initialize_test.cpp @@ -1,15 +1,15 @@ #include #include -#include -#include -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include #include +#include +#include class ServicesUtilInitialize : public testing::Test { public: @@ -28,7 +28,7 @@ class ServicesUtilInitialize : public testing::Test { stan::rng_t rng; }; -TEST_F(ServicesUtilInitialize, radius_zero__print_false) { +TEST_F(ServicesUtilInitialize, radius_zero_print_false) { std::vector params; double init_radius = 0; @@ -250,7 +250,7 @@ class mock_throwing_model : public stan::model::prob_grad { } // namespace test -TEST_F(ServicesUtilInitialize, model_throws__radius_zero) { +TEST_F(ServicesUtilInitialize, model_throws_radius_zero) { test::mock_throwing_model throwing_model; double init_radius = 0; @@ -259,8 +259,7 @@ TEST_F(ServicesUtilInitialize, model_throws__radius_zero) { stan::services::util::initialize(throwing_model, empty_context, rng, init_radius, print_timing, logger, init), std::domain_error); - - EXPECT_EQ(3, logger.call_count()); + EXPECT_EQ(6, logger.call_count()); EXPECT_EQ(3, logger.call_count_warn()); EXPECT_EQ(1, logger.find_warn("throwing within log_prob")); } @@ -533,7 +532,7 @@ TEST_F(ServicesUtilInitialize, model_throws_in_write_array__radius_zero) { init_radius, print_timing, logger, init), std::domain_error); - EXPECT_EQ(3, logger.call_count()); + EXPECT_EQ(6, logger.call_count()); EXPECT_EQ(3, logger.call_count_warn()); EXPECT_EQ(1, logger.find_warn("throwing within write_array")); } From 1bcf1d4e97aef617ce1124949618a7e92ef35e22 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 28 May 2024 14:43:38 -0400 Subject: [PATCH 2/5] update --- src/stan/services/util/initialize.hpp | 10 ++-- .../test-models/good/services/test_fail.stan | 6 ++ .../unit/services/util/fail_init_test.cpp | 56 +++++++++++++++++++ 3 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 src/test/test-models/good/services/test_fail.stan create mode 100644 src/test/unit/services/util/fail_init_test.cpp diff --git a/src/stan/services/util/initialize.hpp b/src/stan/services/util/initialize.hpp index 1bc581ccc1a..d585f73dac1 100644 --- a/src/stan/services/util/initialize.hpp +++ b/src/stan/services/util/initialize.hpp @@ -220,8 +220,8 @@ std::vector initialize(Model& model, const InitContext& init, RNG& rng, logger.error("User-specified initialization failed."); logger.error( " Try specifying new initial values," - " use partially specialized initialization," - " reducing ranges of constrained values," + " using partially specialized initialization," + " reducing the range of constrained values," " or reparameterizing the model."); } else if (any_initialized) { logger.info(""); @@ -234,15 +234,15 @@ std::vector initialize(Model& model, const InitContext& init, RNG& rng, logger.error(msg); logger.error( " Try specifying full initial values," - " reducing ranges of constrained values," + " reducing the range of constrained values," " or reparameterizing the model."); } else if (is_initialized_with_zero) { logger.info(""); logger.error("Initial values of 0 failed to initialize."); logger.error( " Try specifying new initial values," - " use partially specialized initialization," - " reducing ranges of constrained values," + " using partially specialized initialization," + " reducing the range of constrained values," " or reparameterizing the model."); } else { logger.info(""); diff --git a/src/test/test-models/good/services/test_fail.stan b/src/test/test-models/good/services/test_fail.stan new file mode 100644 index 00000000000..d7465f91c23 --- /dev/null +++ b/src/test/test-models/good/services/test_fail.stan @@ -0,0 +1,6 @@ +parameters { + array[2] real y; +} +model { + reject(""); +} diff --git a/src/test/unit/services/util/fail_init_test.cpp b/src/test/unit/services/util/fail_init_test.cpp new file mode 100644 index 00000000000..1e0a0f8e29b --- /dev/null +++ b/src/test/unit/services/util/fail_init_test.cpp @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class ServicesUtilInitialize : public testing::Test { + public: + ServicesUtilInitialize() + : model(empty_context, 12345, &model_ss), + message(message_ss), + rng(stan::services::util::create_rng(0, 1)) {} + + stan_model model; + stan::io::empty_var_context empty_context; + std::stringstream model_ss; + std::stringstream message_ss; + stan::callbacks::stream_writer message; + stan::test::unit::instrumented_logger logger; + stan::test::unit::instrumented_writer init; + stan::rng_t rng; +}; + +TEST_F(ServicesUtilInitialize, model_throws__full_init) { + std::vector names_r; + std::vector values_r; + std::vector > dim_r; + names_r.push_back("y"); + values_r.push_back(6.35149); // 1.5 unconstrained: -10 + 20 * inv.logit(1.5) + values_r.push_back(-2.449187); // -0.5 unconstrained + std::vector d; + d.push_back(2); + dim_r.push_back(d); + stan::io::array_var_context init_context(names_r, values_r, dim_r); + + double init_radius = 2; + bool print_timing = false; + EXPECT_THROW( + stan::services::util::initialize(model, init_context, rng, + init_radius, print_timing, logger, init), + std::domain_error); + auto blah = logger.return_all_logs(); + for (auto&& m : blah) { + std::cout << m << std::endl; + } + EXPECT_EQ(303, logger.call_count()); + EXPECT_EQ(300, logger.call_count_warn()); + EXPECT_EQ(100, logger.find_warn("throwing within log_prob")); +} From 7f42c0114b32cd49787179fc628af206358f0fde Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 28 May 2024 14:44:34 -0400 Subject: [PATCH 3/5] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- src/stan/services/util/initialize.hpp | 5 ++--- src/test/unit/services/instrumented_callbacks.hpp | 6 ++++-- src/test/unit/services/util/fail_init_test.cpp | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/stan/services/util/initialize.hpp b/src/stan/services/util/initialize.hpp index d585f73dac1..a6467ae394d 100644 --- a/src/stan/services/util/initialize.hpp +++ b/src/stan/services/util/initialize.hpp @@ -228,8 +228,8 @@ std::vector initialize(Model& model, const InitContext& init, RNG& rng, std::stringstream msg; msg << "Partial user-specified initialization failed. " "Initialization of non user specified parameters " - "between (-" << init_radius << ", " << init_radius - << ") failed after" + "between (-" + << init_radius << ", " << init_radius << ") failed after" << " " << MAX_INIT_TRIES << " attempts. "; logger.error(msg); logger.error( @@ -255,7 +255,6 @@ std::vector initialize(Model& model, const InitContext& init, RNG& rng, " Try specifying initial values," " reducing ranges of constrained values," " or reparameterizing the model."); - } throw std::domain_error("Initialization failed."); } diff --git a/src/test/unit/services/instrumented_callbacks.hpp b/src/test/unit/services/instrumented_callbacks.hpp index 9ed91a4c67c..6b10126b1e1 100644 --- a/src/test/unit/services/instrumented_callbacks.hpp +++ b/src/test/unit/services/instrumented_callbacks.hpp @@ -281,10 +281,12 @@ class instrumented_logger : public stan::callbacks::logger { count++; return count; } -public: + + public: std::vector return_all_logs() { std::vector all_logs; - all_logs.reserve(debug_.size() + info_.size() + warn_.size() + error_.size() + fatal_.size() + 5); + all_logs.reserve(debug_.size() + info_.size() + warn_.size() + error_.size() + + fatal_.size() + 5); all_logs.emplace_back("DEBUG"); all_logs.insert(all_logs.end(), debug_.begin(), debug_.end()); all_logs.emplace_back("INFO"); diff --git a/src/test/unit/services/util/fail_init_test.cpp b/src/test/unit/services/util/fail_init_test.cpp index 1e0a0f8e29b..a840bceae78 100644 --- a/src/test/unit/services/util/fail_init_test.cpp +++ b/src/test/unit/services/util/fail_init_test.cpp @@ -43,8 +43,8 @@ TEST_F(ServicesUtilInitialize, model_throws__full_init) { double init_radius = 2; bool print_timing = false; EXPECT_THROW( - stan::services::util::initialize(model, init_context, rng, - init_radius, print_timing, logger, init), + stan::services::util::initialize(model, init_context, rng, init_radius, + print_timing, logger, init), std::domain_error); auto blah = logger.return_all_logs(); for (auto&& m : blah) { From 0d2b2762a15613c12b7f79e29b4a5d6e8b1842a3 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 28 May 2024 14:45:13 -0400 Subject: [PATCH 4/5] update --- src/test/unit/services/util/fail_init_test.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/unit/services/util/fail_init_test.cpp b/src/test/unit/services/util/fail_init_test.cpp index 1e0a0f8e29b..05288f799bf 100644 --- a/src/test/unit/services/util/fail_init_test.cpp +++ b/src/test/unit/services/util/fail_init_test.cpp @@ -46,10 +46,12 @@ TEST_F(ServicesUtilInitialize, model_throws__full_init) { stan::services::util::initialize(model, init_context, rng, init_radius, print_timing, logger, init), std::domain_error); - auto blah = logger.return_all_logs(); - for (auto&& m : blah) { + /* Uncomment to print all logs + auto logs = logger.return_all_logs(); + for (auto&& m : logs) { std::cout << m << std::endl; } + */ EXPECT_EQ(303, logger.call_count()); EXPECT_EQ(300, logger.call_count_warn()); EXPECT_EQ(100, logger.find_warn("throwing within log_prob")); From 2d1c7b11c4b0e15ed3f3958f56beedbc6fa77070 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 29 May 2024 10:52:02 -0400 Subject: [PATCH 5/5] fix new test --- src/test/unit/services/util/fail_init_test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/unit/services/util/fail_init_test.cpp b/src/test/unit/services/util/fail_init_test.cpp index 73f7eb4a5bd..0c6374b2001 100644 --- a/src/test/unit/services/util/fail_init_test.cpp +++ b/src/test/unit/services/util/fail_init_test.cpp @@ -52,7 +52,7 @@ TEST_F(ServicesUtilInitialize, model_throws__full_init) { std::cout << m << std::endl; } */ - EXPECT_EQ(303, logger.call_count()); - EXPECT_EQ(300, logger.call_count_warn()); - EXPECT_EQ(100, logger.find_warn("throwing within log_prob")); + EXPECT_EQ(6, logger.call_count()); + EXPECT_EQ(3, logger.call_count_warn()); + EXPECT_EQ(0, logger.find_warn("throwing within log_prob")); }