Add iteration and time reporting for inner iterations.

Also

1. Remove an inadvertent LOG(INFO) from trust_region_minimizer.cc
2. Refactor some of the code in FullReport to reduce duplication
   across line search and trust region minimizers.
3. Consistent capitalization.

Change-Id: I9078b1704efab23d2858530636f524e60c7d9016
diff --git a/include/ceres/solver.h b/include/ceres/solver.h
index 8f394ea..d339bcc 100644
--- a/include/ceres/solver.h
+++ b/include/ceres/solver.h
@@ -599,6 +599,7 @@
 
     int num_successful_steps;
     int num_unsuccessful_steps;
+    int num_inner_iteration_steps;
 
     // When the user calls Solve, before the actual optimization
     // occurs, Ceres performs a number of preprocessing steps. These
@@ -620,6 +621,7 @@
     double linear_solver_time_in_seconds;
     double residual_evaluation_time_in_seconds;
     double jacobian_evaluation_time_in_seconds;
+    double inner_iteration_time_in_seconds;
 
     // Preprocessor summary.
     int num_parameter_blocks;
@@ -649,20 +651,22 @@
     vector<int> linear_solver_ordering_given;
     vector<int> linear_solver_ordering_used;
 
+    bool inner_iterations_given;
+    bool inner_iterations_used;
+
+    vector<int> inner_iteration_ordering_given;
+    vector<int> inner_iteration_ordering_used;
+
     PreconditionerType preconditioner_type;
 
     TrustRegionStrategyType trust_region_strategy_type;
     DoglegType dogleg_type;
-    bool inner_iterations;
 
     SparseLinearAlgebraLibraryType sparse_linear_algebra_library;
 
     LineSearchDirectionType line_search_direction_type;
     LineSearchType line_search_type;
     int max_lbfgs_rank;
-
-    vector<int> inner_iteration_ordering_given;
-    vector<int> inner_iteration_ordering_used;
   };
 
   // Once a least squares problem has been built, this function takes
diff --git a/internal/ceres/solver.cc b/internal/ceres/solver.cc
index ea9ff1f..5acbbfd 100644
--- a/internal/ceres/solver.cc
+++ b/internal/ceres/solver.cc
@@ -91,6 +91,7 @@
       fixed_cost(-1.0),
       num_successful_steps(-1),
       num_unsuccessful_steps(-1),
+      num_inner_iteration_steps(-1),
       preprocessor_time_in_seconds(-1.0),
       minimizer_time_in_seconds(-1.0),
       postprocessor_time_in_seconds(-1.0),
@@ -98,6 +99,7 @@
       linear_solver_time_in_seconds(-1.0),
       residual_evaluation_time_in_seconds(-1.0),
       jacobian_evaluation_time_in_seconds(-1.0),
+      inner_iteration_time_in_seconds(-1.0),
       num_parameter_blocks(-1),
       num_parameters(-1),
       num_effective_parameters(-1),
@@ -114,9 +116,10 @@
       num_linear_solver_threads_used(-1),
       linear_solver_type_given(SPARSE_NORMAL_CHOLESKY),
       linear_solver_type_used(SPARSE_NORMAL_CHOLESKY),
+      inner_iterations_given(false),
+      inner_iterations_used(false),
       preconditioner_type(IDENTITY),
       trust_region_strategy_type(LEVENBERG_MARQUARDT),
-      inner_iterations(false),
       sparse_linear_algebra_library(SUITE_SPARSE),
       line_search_direction_type(LBFGS),
       line_search_type(ARMIJO) {
@@ -184,9 +187,8 @@
                   num_residuals, num_residuals_reduced);
   }
 
-  // TODO(sameeragarwal): Refactor this into separate functions.
-
   if (minimizer_type == TRUST_REGION) {
+    // TRUST_SEARCH HEADER
     StringAppendF(&report, "\nMinimizer                 %19s\n",
                   "TRUST_REGION");
     if (linear_solver_type_used == SPARSE_NORMAL_CHOLESKY ||
@@ -194,12 +196,12 @@
         (linear_solver_type_used == ITERATIVE_SCHUR &&
          (preconditioner_type == CLUSTER_JACOBI ||
           preconditioner_type == CLUSTER_TRIDIAGONAL))) {
-      StringAppendF(&report, "\nSparse Linear Algebra Library %15s\n",
+      StringAppendF(&report, "\nSparse linear algebra library %15s\n",
                     SparseLinearAlgebraLibraryTypeToString(
                                 sparse_linear_algebra_library));
     }
 
-    StringAppendF(&report, "Trust Region Strategy     %19s",
+    StringAppendF(&report, "Trust region strategy     %19s",
                   TrustRegionStrategyTypeToString(
                       trust_region_strategy_type));
     if (trust_region_strategy_type == DOGLEG) {
@@ -227,7 +229,7 @@
                     "N/A", "N/A");
     }
 
-    StringAppendF(&report, "Threads:            % 25d% 25d\n",
+    StringAppendF(&report, "Threads             % 25d% 25d\n",
                   num_threads_given, num_threads_used);
     StringAppendF(&report, "Linear solver threads % 23d% 25d\n",
                   num_linear_solver_threads_given,
@@ -244,7 +246,14 @@
                     used.c_str());
     }
 
-    if (inner_iterations) {
+    if (inner_iterations_given) {
+      StringAppendF(&report,
+                    "Use inner iterations     %20s     %20s\n",
+                    inner_iterations_given ? "True" : "False",
+                    inner_iterations_used ? "True" : "False");
+    }
+
+    if (inner_iterations_used) {
       string given;
       StringifyOrdering(inner_iteration_ordering_given, &given);
       string used;
@@ -254,57 +263,8 @@
                   given.c_str(),
                   used.c_str());
     }
-
-    if (termination_type == DID_NOT_RUN) {
-      CHECK(!error.empty())
-          << "Solver terminated with DID_NOT_RUN but the solver did not "
-          << "return a reason. This is a Ceres error. Please report this "
-          << "to the Ceres team";
-      StringAppendF(&report, "Termination:           %20s\n",
-                    "DID_NOT_RUN");
-      StringAppendF(&report, "Reason: %s\n", error.c_str());
-      return report;
-    }
-
-    StringAppendF(&report, "\nCost:\n");
-    StringAppendF(&report, "Initial        % 30e\n", initial_cost);
-    if (termination_type != NUMERICAL_FAILURE &&
-        termination_type != USER_ABORT) {
-      StringAppendF(&report, "Final          % 30e\n", final_cost);
-      StringAppendF(&report, "Change         % 30e\n",
-                    initial_cost - final_cost);
-    }
-
-    StringAppendF(&report, "\nNumber of iterations:\n");
-    StringAppendF(&report, "Successful               % 20d\n",
-                  num_successful_steps);
-    StringAppendF(&report, "Unsuccessful             % 20d\n",
-                  num_unsuccessful_steps);
-    StringAppendF(&report, "Total                    % 20d\n",
-                  num_successful_steps + num_unsuccessful_steps);
-
-    StringAppendF(&report, "\nTime (in seconds):\n");
-    StringAppendF(&report, "Preprocessor        %25.3f\n",
-                  preprocessor_time_in_seconds);
-    StringAppendF(&report, "\n  Residual Evaluations %22.3f\n",
-                  residual_evaluation_time_in_seconds);
-    StringAppendF(&report, "  Jacobian Evaluations %22.3f\n",
-                  jacobian_evaluation_time_in_seconds);
-    StringAppendF(&report, "  Linear Solver       %23.3f\n",
-                  linear_solver_time_in_seconds);
-    StringAppendF(&report, "Minimizer           %25.3f\n\n",
-                  minimizer_time_in_seconds);
-
-    StringAppendF(&report, "Postprocessor        %24.3f\n",
-                  postprocessor_time_in_seconds);
-
-    StringAppendF(&report, "Total               %25.3f\n\n",
-                  total_time_in_seconds);
-
-    StringAppendF(&report, "Termination:        %25s\n",
-                  SolverTerminationTypeToString(termination_type));
   } else {
-    // LINE_SEARCH
+    // LINE_SEARCH HEADER
     StringAppendF(&report, "\nMinimizer                 %19s\n", "LINE_SEARCH");
     if (line_search_direction_type == LBFGS) {
       StringAppendF(&report, "Line search direction     %19s(%d)\n",
@@ -321,52 +281,72 @@
     StringAppendF(&report, "\n");
 
     StringAppendF(&report, "%45s    %21s\n", "Given",  "Used");
-    StringAppendF(&report, "Threads:            % 25d% 25d\n",
+    StringAppendF(&report, "Threads             % 25d% 25d\n",
                   num_threads_given, num_threads_used);
 
-    if (termination_type == DID_NOT_RUN) {
-      CHECK(!error.empty())
-          << "Solver terminated with DID_NOT_RUN but the solver did not "
-          << "return a reason. This is a Ceres error. Please report this "
-          << "to the Ceres team";
-      StringAppendF(&report, "Termination:           %20s\n",
-                    "DID_NOT_RUN");
-      StringAppendF(&report, "Reason: %s\n", error.c_str());
-      return report;
-    }
-
-    StringAppendF(&report, "\nCost:\n");
-    StringAppendF(&report, "Initial        % 30e\n", initial_cost);
-    if (termination_type != NUMERICAL_FAILURE &&
-        termination_type != USER_ABORT) {
-      StringAppendF(&report, "Final          % 30e\n", final_cost);
-      StringAppendF(&report, "Change         % 30e\n",
-                    initial_cost - final_cost);
-    }
-
-    StringAppendF(&report, "\nNumber of iterations:    % 20d\n",
-                  static_cast<int>(iterations.size() - 1));
-
-    StringAppendF(&report, "\nTime (in seconds):\n");
-    StringAppendF(&report, "Preprocessor        %25.3f\n",
-                  preprocessor_time_in_seconds);
-    StringAppendF(&report, "\n  Residual Evaluations %22.3f\n",
-                  residual_evaluation_time_in_seconds);
-    StringAppendF(&report, "  Jacobian Evaluations %22.3f\n",
-                  jacobian_evaluation_time_in_seconds);
-    StringAppendF(&report, "Minimizer           %25.3f\n\n",
-                  minimizer_time_in_seconds);
-
-    StringAppendF(&report, "Postprocessor        %24.3f\n",
-                  postprocessor_time_in_seconds);
-
-    StringAppendF(&report, "Total               %25.3f\n\n",
-                  total_time_in_seconds);
-
-    StringAppendF(&report, "Termination:        %25s\n",
-                  SolverTerminationTypeToString(termination_type));
   }
 
+  if (termination_type == DID_NOT_RUN) {
+    CHECK(!error.empty())
+        << "Solver terminated with DID_NOT_RUN but the solver did not "
+        << "return a reason. This is a Ceres error. Please report this "
+        << "to the Ceres team";
+    StringAppendF(&report, "Termination:           %20s\n",
+                  "DID_NOT_RUN");
+    StringAppendF(&report, "Reason: %s\n", error.c_str());
+    return report;
+  }
+
+  StringAppendF(&report, "\nCost:\n");
+  StringAppendF(&report, "Initial        % 30e\n", initial_cost);
+  if (termination_type != NUMERICAL_FAILURE &&
+      termination_type != USER_ABORT) {
+    StringAppendF(&report, "Final          % 30e\n", final_cost);
+    StringAppendF(&report, "Change         % 30e\n",
+                  initial_cost - final_cost);
+  }
+
+  StringAppendF(&report, "\nMinimizer iterations         % 16d\n",
+                num_successful_steps + num_unsuccessful_steps);
+  StringAppendF(&report, "Successful steps               % 14d\n",
+                num_successful_steps);
+  StringAppendF(&report, "Unsuccessful steps             % 14d\n",
+                num_unsuccessful_steps);
+  if (inner_iterations_used) {
+    StringAppendF(&report, "Steps with inner iterations    % 14d\n",
+                  num_inner_iteration_steps);
+  }
+
+  StringAppendF(&report, "\nTime (in seconds):\n");
+  StringAppendF(&report, "Preprocessor        %25.3f\n",
+                preprocessor_time_in_seconds);
+
+  StringAppendF(&report, "\n  Residual evaluation %23.3f\n",
+                residual_evaluation_time_in_seconds);
+  StringAppendF(&report, "  Jacobian evaluation %23.3f\n",
+                jacobian_evaluation_time_in_seconds);
+
+  if (minimizer_type == TRUST_REGION) {
+    StringAppendF(&report, "  Linear solver       %23.3f\n",
+                  linear_solver_time_in_seconds);
+  }
+
+  if (inner_iterations_used) {
+    StringAppendF(&report, "  Inner iterations    %23.3f\n",
+                  inner_iteration_time_in_seconds);
+  }
+
+  StringAppendF(&report, "Minimizer           %25.3f\n\n",
+                minimizer_time_in_seconds);
+
+  StringAppendF(&report, "Postprocessor        %24.3f\n",
+                postprocessor_time_in_seconds);
+
+  StringAppendF(&report, "Total               %25.3f\n\n",
+                total_time_in_seconds);
+
+  StringAppendF(&report, "Termination:        %25s\n",
+                SolverTerminationTypeToString(termination_type));
   return report;
 };
 
diff --git a/internal/ceres/solver_impl.cc b/internal/ceres/solver_impl.cc
index 56993c8..76e9c92 100644
--- a/internal/ceres/solver_impl.cc
+++ b/internal/ceres/solver_impl.cc
@@ -536,8 +536,7 @@
       }
     }
   }
-
-  event_logger.AddEvent("CreateIIM");
+  event_logger.AddEvent("CreateInnerIterationMinimizer");
 
   // The optimizer works on contiguous parameter vectors; allocate some.
   Vector parameters(reduced_program->NumParameters());
@@ -1264,6 +1263,8 @@
     const Program& program,
     const ProblemImpl::ParameterMap& parameter_map,
     Solver::Summary* summary) {
+  summary->inner_iterations_given = true;
+
   scoped_ptr<CoordinateDescentMinimizer> inner_iteration_minimizer(
       new CoordinateDescentMinimizer);
   scoped_ptr<ParameterBlockOrdering> inner_iteration_ordering;
@@ -1306,9 +1307,9 @@
     return NULL;
   }
 
-  summary->inner_iterations = true;
+  summary->inner_iterations_used = true;
+  summary->inner_iteration_time_in_seconds = 0.0;
   SummarizeOrdering(ordering_ptr, &(summary->inner_iteration_ordering_used));
-
   return inner_iteration_minimizer.release();
 }
 
diff --git a/internal/ceres/trust_region_minimizer.cc b/internal/ceres/trust_region_minimizer.cc
index ab0f44b..3206dec 100644
--- a/internal/ceres/trust_region_minimizer.cc
+++ b/internal/ceres/trust_region_minimizer.cc
@@ -319,6 +319,8 @@
       } else {
         // Check if performing an inner iteration will make it better.
         if (inner_iterations_are_enabled) {
+          ++summary->num_inner_iteration_steps;
+          double inner_iteration_start_time = WallTimeInSeconds();
           const double x_plus_delta_cost = new_cost;
           Vector inner_iteration_x = x_plus_delta;
           Solver::Summary inner_iteration_summary;
@@ -347,10 +349,12 @@
             // Disable inner iterations once the relative improvement
             // drops below tolerance.
             if (!inner_iterations_are_enabled) {
-              LOG(INFO) << "Disabling inner iterations. Progress : "
-                        << inner_iteration_relative_progress;
+              VLOG(2) << "Disabling inner iterations. Progress : "
+                      << inner_iteration_relative_progress;
             }
           }
+          summary->inner_iteration_time_in_seconds +=
+              WallTimeInSeconds() - inner_iteration_start_time;
         }
       }
 
diff --git a/internal/ceres/wall_time.cc b/internal/ceres/wall_time.cc
index e63d20c..85c4417 100644
--- a/internal/ceres/wall_time.cc
+++ b/internal/ceres/wall_time.cc
@@ -86,7 +86,7 @@
   last_event_time_ = current_time;
 
   StringAppendF(&events_,
-                "  %25s : %10.5f   %10.5f\n",
+                "  %30s : %10.5f   %10.5f\n",
                 event_name.c_str(),
                 relative_time_delta,
                 absolute_time_delta);