blob: fccf63b598aefee94759d55ef50142f06970e62c [file] [log] [blame]
Sameer Agarwal1d11be92012-11-25 19:28:06 -08001// Ceres Solver - A fast non-linear least squares minimizer
2// Copyright 2012 Google Inc. All rights reserved.
3// http://code.google.com/p/ceres-solver/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are met:
7//
8// * Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13// * Neither the name of Google Inc. nor the names of its contributors may be
14// used to endorse or promote products derived from this software without
15// specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27// POSSIBILITY OF SUCH DAMAGE.
28//
29// Author: sameeragarwal@google.com (Sameer Agarwal)
30//
31// Interface for and implementation of various Line search algorithms.
32
33#ifndef CERES_INTERNAL_LINE_SEARCH_H_
34#define CERES_INTERNAL_LINE_SEARCH_H_
35
36#include <glog/logging.h>
37#include <vector>
38#include "ceres/internal/eigen.h"
39#include "ceres/internal/port.h"
40
41namespace ceres {
42namespace internal {
43
44class Evaluator;
45
46// Line search is another name for a one dimensional optimization
47// algorithm. The name "line search" comes from the fact one
48// dimensional optimization problems that arise as subproblems of
49// general multidimensional optimization problems.
50//
51// While finding the exact minimum of a one dimensionl function is
52// hard, instances of LineSearch find a point that satisfies a
53// sufficient decrease condition. Depending on the particular
54// condition used, we get a variety of different line search
55// algorithms, e.g., Armijo, Wolfe etc.
56class LineSearch {
57 public:
58 class Function;
59
60 struct Options {
61 Options()
62 : interpolation_degree(1),
63 use_higher_degree_interpolation_when_possible(false),
64 sufficient_decrease(1e-4),
65 min_relative_step_size_change(1e-3),
66 max_relative_step_size_change(0.6),
67 step_size_threshold(1e-9),
68 function(NULL) {}
69
70 // TODO(sameeragarwal): Replace this with enums which are common
71 // across various line searches.
72 //
73 // Degree of the polynomial used to approximate the objective
74 // function. Valid values are {0, 1, 2}.
75 //
76 // For Armijo line search
77 //
78 // 0: Bisection based backtracking search.
79 // 1: Quadratic interpolation.
80 // 2: Cubic interpolation.
81 int interpolation_degree;
82
83 // Usually its possible to increase the degree of the
84 // interpolation polynomial by storing and using an extra point.
85 bool use_higher_degree_interpolation_when_possible;
86
87 // Armijo line search parameters.
88
89 // Solving the line search problem exactly is computationally
90 // prohibitive. Fortunately, line search based optimization
91 // algorithms can still guarantee convergence if instead of an
92 // exact solution, the line search algorithm returns a solution
93 // which decreases the value of the objective function
94 // sufficiently. More precisely, we are looking for a step_size
95 // s.t.
96 //
97 // f(step_size) <= f(0) + sufficient_decrease * f'(0) * step_size
98 double sufficient_decrease;
99
100 // In each iteration of the Armijo line search,
101 //
102 // new_step_size >= min_relative_step_size_change * step_size
103 double min_relative_step_size_change;
104
105 // In each iteration of the Armijo line search,
106 //
107 // new_step_size <= max_relative_step_size_change * step_size
108 double max_relative_step_size_change;
109
110 // If during the line search, the step_size falls below this
111 // value, it is truncated to zero.
112 double step_size_threshold;
113
114 // The one dimensional function that the line search algorithm
115 // minimizes.
116 Function* function;
117 };
118
119 // An object used by the line search to access the function values
120 // and gradient of the one dimensional function being optimized.
121 //
122 // In practice, this object will provide access to the objective
123 // function value and the directional derivative of the underlying
124 // optimization problem along a specific search direction.
125 //
126 // See LineSearchFunction for an example implementation.
127 class Function {
128 public:
129 virtual ~Function() {}
130 // Evaluate the line search objective
131 //
132 // f(x) = p(position + x * direction)
133 //
134 // Where, p is the objective function of the general optimization
135 // problem.
136 //
137 // g is the gradient f'(x) at x.
138 //
Sameer Agarwalf4d01642012-11-26 12:55:58 -0800139 // f must not be null. The gradient is computed only if g is not null.
Sameer Agarwal1d11be92012-11-25 19:28:06 -0800140 virtual bool Evaluate(double x, double* f, double* g) = 0;
141 };
142
143 // Result of the line search.
144 struct Summary {
145 Summary()
146 : success(false),
147 optimal_step_size(0.0),
148 num_evaluations(0) {}
149
150 bool success;
151 double optimal_step_size;
152 int num_evaluations;
153 };
154
155 virtual ~LineSearch() {}
156
157 // Perform the line search.
158 //
Sameer Agarwalf4d01642012-11-26 12:55:58 -0800159 // initial_step_size must be a positive number.
160 //
161 // initial_cost and initial_gradient are the values and gradient of
162 // the function at zero.
163 // summary must not be null and will contain the result of the line
164 // search.
Sameer Agarwal1d11be92012-11-25 19:28:06 -0800165 //
166 // Summary::success is true if a non-zero step size is found.
167 virtual void Search(const LineSearch::Options& options,
168 double initial_step_size,
Sameer Agarwalf4d01642012-11-26 12:55:58 -0800169 double initial_cost,
170 double initial_gradient,
Sameer Agarwal1d11be92012-11-25 19:28:06 -0800171 Summary* summary) = 0;
172};
173
174class LineSearchFunction : public LineSearch::Function {
175 public:
176 explicit LineSearchFunction(Evaluator* evaluator);
177 virtual ~LineSearchFunction() {}
178 void Init(const Vector& position, const Vector& direction);
179 virtual bool Evaluate(const double x, double* f, double* g);
180
181 private:
182 Evaluator* evaluator_;
183 Vector position_;
184 Vector direction_;
185
186 // evaluation_point = Evaluator::Plus(position_, x * direction_);
187 Vector evaluation_point_;
188
189 // scaled_direction = x * direction_;
190 Vector scaled_direction_;
191 Vector gradient_;
192};
193
194// Backtracking and interpolation based Armijo line search. This
195// implementation is based on the Armijo line search that ships in the
196// minFunc package by Mark Schmidt.
197//
198// For more details: http://www.di.ens.fr/~mschmidt/Software/minFunc.html
199class ArmijoLineSearch : public LineSearch {
200 public:
201 virtual ~ArmijoLineSearch() {}
202 virtual void Search(const LineSearch::Options& options,
203 double initial_step_size,
Sameer Agarwalf4d01642012-11-26 12:55:58 -0800204 double initial_cost,
205 double initial_gradient,
Sameer Agarwal1d11be92012-11-25 19:28:06 -0800206 Summary* summary);
207};
208
209} // namespace internal
210} // namespace ceres
211
212#endif // CERES_INTERNAL_LINE_SEARCH_H_