Compute & report timing information for line searches.

- We now compute & report the cumulative time spent performing the
  following tasks as part of a line search:
  - Evaluation of the univariate cost function value & gradient.
  - Minimization of the interpolating polynomial.
  - Total time spent performing line searches.
- This information is now reported for all minimizers, although only in
  the case of a constrained problem for the TR minimizer.
- Remove LineSearch::Function abstraction in place of using
  LineSearchFunction implementation directly, and remove virtual
  functions from LineSearchFunction.
-- LineSearch::Function added an unnecessary level of abstraction since
   the user always had to create a LineSearchFunction anyway to use a
   Ceres Evaluator, and it added an unncessary virtual function call.

Change-Id: Ia4e1921d78f351ae119875aa97a3ea5e8b5d9877
diff --git a/internal/ceres/line_search.h b/internal/ceres/line_search.h
index 97b9bc6..ea72f74 100644
--- a/internal/ceres/line_search.h
+++ b/internal/ceres/line_search.h
@@ -44,6 +44,7 @@
 
 class Evaluator;
 struct FunctionSample;
+class LineSearchFunction;
 
 // Line search is another name for a one dimensional optimization
 // algorithm. The name "line search" comes from the fact one
@@ -57,7 +58,7 @@
 // algorithms, e.g., Armijo, Wolfe etc.
 class LineSearch {
  public:
-  class Function;
+  struct Summary;
 
   struct Options {
     Options()
@@ -147,31 +148,7 @@
 
     // The one dimensional function that the line search algorithm
     // minimizes.
-    Function* function;
-  };
-
-  // An object used by the line search to access the function values
-  // and gradient of the one dimensional function being optimized.
-  //
-  // In practice, this object will provide access to the objective
-  // function value and the directional derivative of the underlying
-  // optimization problem along a specific search direction.
-  //
-  // See LineSearchFunction for an example implementation.
-  class Function {
-   public:
-    virtual ~Function() {}
-    // Evaluate the line search objective
-    //
-    //   f(x) = p(position + x * direction)
-    //
-    // Where, p is the objective function of the general optimization
-    // problem.
-    //
-    // g is the gradient f'(x) at x.
-    //
-    // f must not be null. The gradient is computed only if g is not null.
-    virtual bool Evaluate(double x, double* f, double* g) = 0;
+    LineSearchFunction* function;
   };
 
   // Result of the line search.
@@ -181,13 +158,27 @@
           optimal_step_size(0.0),
           num_function_evaluations(0),
           num_gradient_evaluations(0),
-          num_iterations(0) {}
+          num_iterations(0),
+          cost_evaluation_time_in_seconds(-1.0),
+          gradient_evaluation_time_in_seconds(-1.0),
+          polynomial_minimization_time_in_seconds(-1.0),
+          total_time_in_seconds(-1.0) {}
 
     bool success;
     double optimal_step_size;
     int num_function_evaluations;
     int num_gradient_evaluations;
     int num_iterations;
+    // Cumulative time spent evaluating the value of the cost function across
+    // all iterations.
+    double cost_evaluation_time_in_seconds;
+    // Cumulative time spent evaluating the gradient of the cost function across
+    // all iterations.
+    double gradient_evaluation_time_in_seconds;
+    // Cumulative time spent minimizing the interpolating polynomial to compute
+    // the next candidate step size across all iterations.
+    double polynomial_minimization_time_in_seconds;
+    double total_time_in_seconds;
     string error;
   };
 
@@ -208,10 +199,10 @@
   // search.
   //
   // Summary::success is true if a non-zero step size is found.
-  virtual void Search(double step_size_estimate,
-                      double initial_cost,
-                      double initial_gradient,
-                      Summary* summary) = 0;
+  void Search(double step_size_estimate,
+              double initial_cost,
+              double initial_gradient,
+              Summary* summary) const;
   double InterpolatingPolynomialMinimizingStepSize(
       const LineSearchInterpolationType& interpolation_type,
       const FunctionSample& lowerbound_sample,
@@ -224,16 +215,41 @@
   const LineSearch::Options& options() const { return options_; }
 
  private:
+  virtual void DoSearch(double step_size_estimate,
+                        double initial_cost,
+                        double initial_gradient,
+                        Summary* summary) const = 0;
+
+ private:
   LineSearch::Options options_;
 };
 
-class LineSearchFunction : public LineSearch::Function {
+// An object used by the line search to access the function values
+// and gradient of the one dimensional function being optimized.
+//
+// In practice, this object provides access to the objective
+// function value and the directional derivative of the underlying
+// optimization problem along a specific search direction.
+class LineSearchFunction {
  public:
   explicit LineSearchFunction(Evaluator* evaluator);
-  virtual ~LineSearchFunction() {}
   void Init(const Vector& position, const Vector& direction);
-  virtual bool Evaluate(double x, double* f, double* g);
+  // Evaluate the line search objective
+  //
+  //   f(x) = p(position + x * direction)
+  //
+  // Where, p is the objective function of the general optimization
+  // problem.
+  //
+  // g is the gradient f'(x) at x.
+  //
+  // f must not be null. The gradient is computed only if g is not null.
+  bool Evaluate(double x, double* f, double* g);
   double DirectionInfinityNorm() const;
+  // Resets to now, the start point for the results from TimeStatistics().
+  void ResetTimeStatistics();
+  void TimeStatistics(double* cost_evaluation_time_in_seconds,
+                      double* gradient_evaluation_time_in_seconds) const;
 
  private:
   Evaluator* evaluator_;
@@ -246,6 +262,13 @@
   // scaled_direction = x * direction_;
   Vector scaled_direction_;
   Vector gradient_;
+
+  // We may not exclusively own the evaluator (e.g. in the Trust Region
+  // minimizer), hence we need to save the initial evaluation durations for the
+  // value & gradient to accurately determine the duration of the evaluations
+  // we invoked.  These are reset by a call to ResetTimeStatistics().
+  double initial_evaluator_residual_time_in_seconds;
+  double initial_evaluator_jacobian_time_in_seconds;
 };
 
 // Backtracking and interpolation based Armijo line search. This
@@ -257,10 +280,12 @@
  public:
   explicit ArmijoLineSearch(const LineSearch::Options& options);
   virtual ~ArmijoLineSearch() {}
-  virtual void Search(double step_size_estimate,
-                      double initial_cost,
-                      double initial_gradient,
-                      Summary* summary);
+
+ private:
+  virtual void DoSearch(double step_size_estimate,
+                        double initial_cost,
+                        double initial_gradient,
+                        Summary* summary) const;
 };
 
 // Bracketing / Zoom Strong Wolfe condition line search.  This implementation
@@ -274,23 +299,26 @@
  public:
   explicit WolfeLineSearch(const LineSearch::Options& options);
   virtual ~WolfeLineSearch() {}
-  virtual void Search(double step_size_estimate,
-                      double initial_cost,
-                      double initial_gradient,
-                      Summary* summary);
+
   // Returns true iff either a valid point, or valid bracket are found.
   bool BracketingPhase(const FunctionSample& initial_position,
                        const double step_size_estimate,
                        FunctionSample* bracket_low,
                        FunctionSample* bracket_high,
                        bool* perform_zoom_search,
-                       Summary* summary);
+                       Summary* summary) const;
   // Returns true iff final_line_sample satisfies strong Wolfe conditions.
   bool ZoomPhase(const FunctionSample& initial_position,
                  FunctionSample bracket_low,
                  FunctionSample bracket_high,
                  FunctionSample* solution,
-                 Summary* summary);
+                 Summary* summary) const;
+
+ private:
+  virtual void DoSearch(double step_size_estimate,
+                        double initial_cost,
+                        double initial_gradient,
+                        Summary* summary) const;
 };
 
 }  // namespace internal