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;
}