Pipe minimizer termination messages to Solver::Summary.

All minimizer termination messages are now available as
Solver::Summary::error.

This is part of the ongoing refactoring or

Change-Id: I4514c3c042645bbd1471bcde9bd3dbf81d9ee8b0
diff --git a/internal/ceres/line_search_minimizer.cc b/internal/ceres/line_search_minimizer.cc
index 1093bad..4590afe 100644
--- a/internal/ceres/line_search_minimizer.cc
+++ b/internal/ceres/line_search_minimizer.cc
@@ -126,9 +126,9 @@
 
   // Do initial cost and Jacobian evaluation.
   if (!Evaluate(evaluator, x, &current_state)) {
-    LOG_IF(WARNING, is_not_silent)
-        << "Terminating: Cost and gradient evaluation failed.";
+    summary->error = "Terminating: Cost and gradient evaluation failed.";
     summary->termination_type = NUMERICAL_FAILURE;
+    LOG_IF(WARNING, is_not_silent) << summary->error;
     return;
   }
 
@@ -146,12 +146,14 @@
       options.gradient_tolerance * initial_gradient_max_norm;
 
   if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) {
-    VLOG_IF(1, is_not_silent)
-        << "Terminating: Gradient tolerance reached."
-        << "Relative gradient max norm: "
-        << iteration_summary.gradient_max_norm / initial_gradient_max_norm
-        << " <= " << options.gradient_tolerance;
+    summary->error =
+        StringPrintf("Terminating: Gradient tolerance reached. "
+                     "Relative gradient max norm: %e <= %e",
+                     iteration_summary.gradient_max_norm /
+                     initial_gradient_max_norm,
+                     options.gradient_tolerance);
     summary->termination_type = GRADIENT_TOLERANCE;
+    VLOG_IF(1, is_not_silent) << summary->error;
     return;
   }
 
@@ -198,10 +200,8 @@
                                      line_search_options,
                                      &summary->error));
   if (line_search.get() == NULL) {
-    LOG_IF(ERROR, is_not_silent)
-        << "Ceres bug: Unable to create a LineSearch object, please "
-        << "contact the developers!, error: " << summary->error;
     summary->termination_type = DID_NOT_RUN;
+    LOG_IF(ERROR, is_not_silent) << summary->error;
     return;
   }
 
@@ -215,17 +215,18 @@
 
     iteration_start_time = WallTimeInSeconds();
     if (iteration_summary.iteration >= options.max_num_iterations) {
-      VLOG_IF(1, is_not_silent)
-          << "Terminating: Maximum number of iterations reached.";
+      summary->error = "Terminating: Maximum number of iterations reached.";
       summary->termination_type = NO_CONVERGENCE;
+      VLOG_IF(1, is_not_silent) << summary->error;
       break;
     }
 
     const double total_solver_time = iteration_start_time - start_time +
         summary->preprocessor_time_in_seconds;
     if (total_solver_time >= options.max_solver_time_in_seconds) {
-      VLOG_IF(1, is_not_silent) << "Terminating: Maximum solver time reached.";
+      summary->error = "Terminating: Maximum solver time reached.";
       summary->termination_type = NO_CONVERGENCE;
+      VLOG_IF(1, is_not_silent) << summary->error;
       break;
     }
 
@@ -251,12 +252,11 @@
       // have already reached our specified maximum number of restarts,
       // terminate optimization.
       summary->error =
-          StringPrintf("Line search direction failure: specified "
+          StringPrintf("Termination: Line search direction failure: specified "
                        "max_num_line_search_direction_restarts: %d reached.",
                        options.max_num_line_search_direction_restarts);
-      LOG_IF(WARNING, is_not_silent) << summary->error
-                                     << " terminating optimization.";
       summary->termination_type = NUMERICAL_FAILURE;
+      LOG_IF(WARNING, is_not_silent) << summary->error;
       break;
     } else if (!line_search_status) {
       // Restart line search direction with gradient descent on first iteration
@@ -305,8 +305,8 @@
                        "(current_cost - previous_cost): %.5e",
                        initial_step_size, current_state.directional_derivative,
                        (current_state.cost - previous_state.cost));
-      LOG_IF(WARNING, is_not_silent) << summary->error;
       summary->termination_type = NUMERICAL_FAILURE;
+      LOG_IF(WARNING, is_not_silent) << summary->error;
       break;
     }
 
@@ -355,13 +355,14 @@
     iteration_summary.gradient_norm = sqrt(current_state.gradient_squared_norm);
 
     if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) {
-      VLOG_IF(1, is_not_silent)
-          << "Terminating: Gradient tolerance reached."
-          << "Relative gradient max norm: "
-          << (iteration_summary.gradient_max_norm /
-              initial_gradient_max_norm)
-          << " <= " << options.gradient_tolerance;
+      summary->error =
+          StringPrintf("Terminating: Gradient tolerance reached. "
+                       "Relative gradient max norm: %e <= %e. ",
+                       (iteration_summary.gradient_max_norm /
+                        initial_gradient_max_norm),
+                       options.gradient_tolerance);
       summary->termination_type = GRADIENT_TOLERANCE;
+      VLOG_IF(1, is_not_silent) << summary->error;
       break;
     }
 
@@ -369,12 +370,14 @@
     const double absolute_function_tolerance =
         options.function_tolerance * previous_state.cost;
     if (fabs(iteration_summary.cost_change) < absolute_function_tolerance) {
-      VLOG_IF(1, is_not_silent)
-          << "Terminating. Function tolerance reached. "
-          << "|cost_change|/cost: "
-          << fabs(iteration_summary.cost_change) / previous_state.cost
-          << " <= " << options.function_tolerance;
+      summary->error =
+          StringPrintf("Terminating. Function tolerance reached. "
+                       "|cost_change|/cost: %e <= %e",
+                       fabs(iteration_summary.cost_change) /
+                       previous_state.cost,
+                       options.function_tolerance);
       summary->termination_type = FUNCTION_TOLERANCE;
+      VLOG_IF(1, is_not_silent) << summary->error;
       return;
     }
 
diff --git a/internal/ceres/trust_region_minimizer.cc b/internal/ceres/trust_region_minimizer.cc
index e09c008..9b630e1 100644
--- a/internal/ceres/trust_region_minimizer.cc
+++ b/internal/ceres/trust_region_minimizer.cc
@@ -117,8 +117,6 @@
   iteration_summary.step_norm = 0.0;
   iteration_summary.relative_decrease = 0.0;
   iteration_summary.trust_region_radius = strategy->Radius();
-  // TODO(sameeragarwal): Rename eta to linear_solver_accuracy or
-  // something similar across the board.
   iteration_summary.eta = options_.eta;
   iteration_summary.linear_solver_iterations = 0;
   iteration_summary.step_solver_time_in_seconds = 0;
@@ -130,9 +128,9 @@
                            residuals.data(),
                            gradient.data(),
                            jacobian)) {
-    LOG_IF(WARNING, is_not_silent)
-        << "Terminating: Residual and Jacobian evaluation failed.";
+    summary->error = "Terminating: Residual and Jacobian evaluation failed.";
     summary->termination_type = NUMERICAL_FAILURE;
+    LOG_IF(WARNING, is_not_silent) << summary->error;
     return;
   }
 
@@ -156,12 +154,13 @@
       options_.gradient_tolerance * initial_gradient_max_norm;
 
   if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) {
-    VLOG_IF(1, is_not_silent) << "Terminating: Gradient tolerance reached."
-                              << "Relative gradient max norm: "
-                              << (iteration_summary.gradient_max_norm /
-                                  initial_gradient_max_norm)
-                              << " <= " << options_.gradient_tolerance;
+    summary->error = StringPrintf("Terminating: Gradient tolerance reached. "
+                                    "Relative gradient max norm: %e <= %e",
+                                    (iteration_summary.gradient_max_norm /
+                                     initial_gradient_max_norm),
+                                    options_.gradient_tolerance);
     summary->termination_type = GRADIENT_TOLERANCE;
+    VLOG_IF(1, is_not_silent) << summary->error;
     return;
   }
 
@@ -189,18 +188,18 @@
 
     iteration_start_time = WallTimeInSeconds();
     if (iteration_summary.iteration >= options_.max_num_iterations) {
-      VLOG_IF(1, is_not_silent)
-          << "Terminating: Maximum number of iterations reached.";
+      summary->error = "Terminating: Maximum number of iterations reached.";
       summary->termination_type = NO_CONVERGENCE;
+      VLOG_IF(1, is_not_silent) << summary->error;
       return;
     }
 
     const double total_solver_time = iteration_start_time - start_time +
         summary->preprocessor_time_in_seconds;
     if (total_solver_time >= options_.max_solver_time_in_seconds) {
-      VLOG_IF(1, is_not_silent)
-          << "Terminating: Maximum solver time reached.";
+      summary->error = "Terminating: Maximum solver time reached.";
       summary->termination_type = NO_CONVERGENCE;
+      VLOG_IF(1, is_not_silent) << summary->error;
       return;
     }
 
@@ -237,14 +236,16 @@
     iteration_summary.step_is_valid = false;
     iteration_summary.step_is_successful = false;
 
-    double model_cost_change = 0.0;
     if (strategy_summary.termination_type == FATAL_ERROR) {
-      summary->error = "Terminating. Linear solver encountered a fatal error.";
-      LOG_IF(WARNING, is_not_silent) << summary->error;
+      summary->error =
+          "Terminating. Linear solver failed due to unrecoverable "
+          "non-numeric causes. Please see the error log for clues. ";
       summary->termination_type = NUMERICAL_FAILURE;
+      LOG_IF(WARNING, is_not_silent) << summary->error;
       return;
     }
 
+    double model_cost_change = 0.0;
     if (strategy_summary.termination_type != FAILURE) {
       // new_model_cost
       //  = 1/2 [f + J * step]^2
@@ -278,8 +279,8 @@
             "Terminating. Number of successive invalid steps more "
             "than Solver::Options::max_num_consecutive_invalid_steps: %d",
             options_.max_num_consecutive_invalid_steps);
-        LOG_IF(WARNING, is_not_silent) << summary->error;
         summary->termination_type = NUMERICAL_FAILURE;
+        LOG_IF(WARNING, is_not_silent) << summary->error;
         return;
       }
 
@@ -366,13 +367,14 @@
       const double step_size_tolerance =  options_.parameter_tolerance *
           (x_norm + options_.parameter_tolerance);
       if (iteration_summary.step_norm <= step_size_tolerance) {
-        VLOG_IF(1, is_not_silent)
-            << "Terminating. Parameter tolerance reached. "
-            << "relative step_norm: "
-            << (iteration_summary.step_norm /
-                (x_norm + options_.parameter_tolerance))
-            << " <= " << options_.parameter_tolerance;
+        summary->error =
+            StringPrintf("Terminating. Parameter tolerance reached. "
+                         "relative step_norm: %e <= %e.",
+                         (iteration_summary.step_norm /
+                          (x_norm + options_.parameter_tolerance)),
+                         options_.parameter_tolerance);
         summary->termination_type = PARAMETER_TOLERANCE;
+        VLOG_IF(1, is_not_silent) << summary->error;
         return;
       }
 
@@ -380,11 +382,13 @@
       const double absolute_function_tolerance =
           options_.function_tolerance * cost;
       if (fabs(iteration_summary.cost_change) < absolute_function_tolerance) {
-        VLOG_IF(1, is_not_silent) << "Terminating. Function tolerance reached. "
-                                  << "|cost_change|/cost: "
-                                  << fabs(iteration_summary.cost_change) / cost
-                                  << " <= " << options_.function_tolerance;
+        summary->error =
+            StringPrintf("Terminating. Function tolerance reached. "
+                         "|cost_change|/cost: %e <= %e",
+                         fabs(iteration_summary.cost_change) / cost,
+                         options_.function_tolerance);
         summary->termination_type = FUNCTION_TOLERANCE;
+        VLOG_IF(1, is_not_silent) << summary->error;
         return;
       }
 
@@ -483,8 +487,8 @@
                                jacobian)) {
         summary->error =
             "Terminating: Residual and Jacobian evaluation failed.";
-        LOG_IF(WARNING, is_not_silent) << summary->error;
         summary->termination_type = NUMERICAL_FAILURE;
+        LOG_IF(WARNING, is_not_silent) << summary->error;
         return;
       }
 
@@ -492,12 +496,14 @@
       iteration_summary.gradient_norm = gradient.norm();
 
       if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) {
-        VLOG_IF(1, is_not_silent) << "Terminating: Gradient tolerance reached."
-                                  << "Relative gradient max norm: "
-                                  << (iteration_summary.gradient_max_norm /
-                                      initial_gradient_max_norm)
-                                  << " <= " << options_.gradient_tolerance;
+        summary->error =
+            StringPrintf("Terminating: Gradient tolerance reached. "
+                         "Relative gradient max norm: %e <= %e",
+                         (iteration_summary.gradient_max_norm /
+                          initial_gradient_max_norm),
+                         options_.gradient_tolerance);
         summary->termination_type = GRADIENT_TOLERANCE;
+        VLOG_IF(1, is_not_silent) << summary->error;
         return;
       }
 
@@ -560,9 +566,9 @@
     iteration_summary.trust_region_radius = strategy->Radius();
     if (iteration_summary.trust_region_radius <
         options_.min_trust_region_radius) {
-      VLOG_IF(1, is_not_silent)
-          << "Termination. Minimum trust region radius reached.";
+      summary->error = "Termination. Minimum trust region radius reached.";
       summary->termination_type = PARAMETER_TOLERANCE;
+      VLOG_IF(1, is_not_silent) << summary->error;
       return;
     }