Fix a bug in Minimizer::RunCallbacks. Solver::Summary::message was not being updated when the solver terminated because of a user's iteration callback indicating success or failure. Thanks to Sergey Sharybin for reporting this. Change-Id: I27e6e5eed086920ddf765461b0159417ac79d7b3
diff --git a/internal/ceres/line_search_minimizer.cc b/internal/ceres/line_search_minimizer.cc index 3e8d18a..ae77a73 100644 --- a/internal/ceres/line_search_minimizer.cc +++ b/internal/ceres/line_search_minimizer.cc
@@ -207,7 +207,7 @@ int num_line_search_direction_restarts = 0; while (true) { - if (!RunCallbacks(options.callbacks, iteration_summary, summary)) { + if (!RunCallbacks(options, iteration_summary, summary)) { break; }
diff --git a/internal/ceres/minimizer.cc b/internal/ceres/minimizer.cc index bdb6a11..a20eed5 100644 --- a/internal/ceres/minimizer.cc +++ b/internal/ceres/minimizer.cc
@@ -37,13 +37,14 @@ Minimizer::~Minimizer() {} -bool Minimizer::RunCallbacks(const vector<IterationCallback*> callbacks, +bool Minimizer::RunCallbacks(const Minimizer::Options& options, const IterationSummary& iteration_summary, Solver::Summary* summary) { + const bool is_not_silent = !options.is_silent; CallbackReturnType status = SOLVER_CONTINUE; int i = 0; - while (status == SOLVER_CONTINUE && i < callbacks.size()) { - status = (*callbacks[i])(iteration_summary); + while (status == SOLVER_CONTINUE && i < options.callbacks.size()) { + status = (*options.callbacks[i])(iteration_summary); ++i; } switch (status) { @@ -51,11 +52,13 @@ return true; case SOLVER_TERMINATE_SUCCESSFULLY: summary->termination_type = USER_SUCCESS; - VLOG(1) << "Terminating: User callback returned USER_SUCCESS."; + summary->message = "User callback returned SOLVER_TERMINATE_SUCCESSFULLY."; + VLOG_IF(is_not_silent, 1) << "Terminating: " << summary->message; return false; case SOLVER_ABORT: summary->termination_type = USER_FAILURE; - VLOG(1) << "Terminating: User callback returned USER_ABORT."; + summary->message = "User callback returned SOLVER_ABORT."; + VLOG_IF(is_not_silent, 1) << "Terminating: " << summary->message; return false; default: LOG(FATAL) << "Unknown type of user callback status";
diff --git a/internal/ceres/minimizer.h b/internal/ceres/minimizer.h index f9f2b51..f1da3f7 100644 --- a/internal/ceres/minimizer.h +++ b/internal/ceres/minimizer.h
@@ -186,7 +186,7 @@ bool is_constrained; }; - static bool RunCallbacks(const vector<IterationCallback*> callbacks, + static bool RunCallbacks(const Options& options, const IterationSummary& iteration_summary, Solver::Summary* summary);
diff --git a/internal/ceres/minimizer_test.cc b/internal/ceres/minimizer_test.cc index 1058036..0d8b617 100644 --- a/internal/ceres/minimizer_test.cc +++ b/internal/ceres/minimizer_test.cc
@@ -44,7 +44,7 @@ } }; -TEST(MinimizerTest, InitializationCopiesCallbacks) { +TEST(Minimizer, InitializationCopiesCallbacks) { FakeIterationCallback callback0; FakeIterationCallback callback1; @@ -59,5 +59,42 @@ EXPECT_EQ(minimizer_options.callbacks[1], &callback1); } +class AbortingIterationCallback : public IterationCallback { + public: + virtual ~AbortingIterationCallback() {} + virtual CallbackReturnType operator()(const IterationSummary& summary) { + return SOLVER_ABORT; + } +}; + +TEST(Minimizer, UserAbortUpdatesSummaryMessage) { + AbortingIterationCallback callback; + Solver::Options solver_options; + solver_options.callbacks.push_back(&callback); + Minimizer::Options minimizer_options(solver_options); + Solver::Summary summary; + Minimizer::RunCallbacks(minimizer_options, IterationSummary(), &summary); + EXPECT_EQ(summary.message, "User callback returned SOLVER_ABORT."); +} + +class SucceedingIterationCallback : public IterationCallback { + public: + virtual ~SucceedingIterationCallback() {} + virtual CallbackReturnType operator()(const IterationSummary& summary) { + return SOLVER_TERMINATE_SUCCESSFULLY; + } +}; + +TEST(Minimizer, UserSuccessUpdatesSummaryMessage) { + SucceedingIterationCallback callback; + Solver::Options solver_options; + solver_options.callbacks.push_back(&callback); + Minimizer::Options minimizer_options(solver_options); + Solver::Summary summary; + Minimizer::RunCallbacks(minimizer_options, IterationSummary(), &summary); + EXPECT_EQ(summary.message, + "User callback returned SOLVER_TERMINATE_SUCCESSFULLY."); +} + } // namespace internal } // namespace ceres
diff --git a/internal/ceres/trust_region_minimizer.cc b/internal/ceres/trust_region_minimizer.cc index 8f8ec98..4be5619 100644 --- a/internal/ceres/trust_region_minimizer.cc +++ b/internal/ceres/trust_region_minimizer.cc
@@ -256,7 +256,7 @@ bool inner_iterations_are_enabled = options.inner_iteration_minimizer != NULL; while (true) { bool inner_iterations_were_useful = false; - if (!RunCallbacks(options.callbacks, iteration_summary, summary)) { + if (!RunCallbacks(options, iteration_summary, summary)) { return; }