blob: b8b582c3fb1793f8b60acf4ce3a48e129cd75b4c [file] [log] [blame]
Sameer Agarwal9883fc32012-11-30 12:32:43 -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
Sameer Agarwal8140f0f2013-03-12 09:45:08 -070031#ifndef CERES_NO_LINE_SEARCH_MINIMIZER
32
Sameer Agarwal9883fc32012-11-30 12:32:43 -080033#include "ceres/line_search_direction.h"
34#include "ceres/line_search_minimizer.h"
35#include "ceres/low_rank_inverse_hessian.h"
36#include "ceres/internal/eigen.h"
37#include "glog/logging.h"
38
39namespace ceres {
40namespace internal {
41
42class SteepestDescent : public LineSearchDirection {
43 public:
44 virtual ~SteepestDescent() {}
45 bool NextDirection(const LineSearchMinimizer::State& previous,
46 const LineSearchMinimizer::State& current,
47 Vector* search_direction) {
48 *search_direction = -current.gradient;
49 return true;
50 }
51};
52
53class NonlinearConjugateGradient : public LineSearchDirection {
54 public:
55 NonlinearConjugateGradient(const NonlinearConjugateGradientType type,
56 const double function_tolerance)
57 : type_(type),
58 function_tolerance_(function_tolerance) {
59 }
60
61 bool NextDirection(const LineSearchMinimizer::State& previous,
62 const LineSearchMinimizer::State& current,
63 Vector* search_direction) {
64 double beta = 0.0;
65 Vector gradient_change;
66 switch (type_) {
67 case FLETCHER_REEVES:
68 beta = current.gradient_squared_norm / previous.gradient_squared_norm;
69 break;
70 case POLAK_RIBIRERE:
71 gradient_change = current.gradient - previous.gradient;
72 beta = (current.gradient.dot(gradient_change) /
73 previous.gradient_squared_norm);
74 break;
75 case HESTENES_STIEFEL:
76 gradient_change = current.gradient - previous.gradient;
77 beta = (current.gradient.dot(gradient_change) /
78 previous.search_direction.dot(gradient_change));
79 break;
80 default:
81 LOG(FATAL) << "Unknown nonlinear conjugate gradient type: " << type_;
82 }
83
84 *search_direction = -current.gradient + beta * previous.search_direction;
Sameer Agarwal509f68c2013-02-20 01:39:03 -080085 const double directional_derivative =
Sameer Agarwal931c3092013-02-25 09:46:21 -080086 current.gradient.dot(*search_direction);
Sameer Agarwal9883fc32012-11-30 12:32:43 -080087 if (directional_derivative > -function_tolerance_) {
88 LOG(WARNING) << "Restarting non-linear conjugate gradients: "
89 << directional_derivative;
90 *search_direction = -current.gradient;
91 };
92
93 return true;
94 }
95
96 private:
97 const NonlinearConjugateGradientType type_;
98 const double function_tolerance_;
99};
100
101class LBFGS : public LineSearchDirection {
102 public:
103 LBFGS(const int num_parameters, const int max_lbfgs_rank)
104 : low_rank_inverse_hessian_(num_parameters, max_lbfgs_rank) {}
105
106 virtual ~LBFGS() {}
107
108 bool NextDirection(const LineSearchMinimizer::State& previous,
109 const LineSearchMinimizer::State& current,
110 Vector* search_direction) {
111 low_rank_inverse_hessian_.Update(
112 previous.search_direction * previous.step_size,
113 current.gradient - previous.gradient);
114 search_direction->setZero();
115 low_rank_inverse_hessian_.RightMultiply(current.gradient.data(),
116 search_direction->data());
117 *search_direction *= -1.0;
118 return true;
119 }
120
121 private:
122 LowRankInverseHessian low_rank_inverse_hessian_;
123};
124
125LineSearchDirection*
Sameer Agarwal509f68c2013-02-20 01:39:03 -0800126LineSearchDirection::Create(const LineSearchDirection::Options& options) {
Sameer Agarwal9883fc32012-11-30 12:32:43 -0800127 if (options.type == STEEPEST_DESCENT) {
128 return new SteepestDescent;
129 }
130
131 if (options.type == NONLINEAR_CONJUGATE_GRADIENT) {
132 return new NonlinearConjugateGradient(
133 options.nonlinear_conjugate_gradient_type,
134 options.function_tolerance);
135 }
136
137 if (options.type == ceres::LBFGS) {
138 return new ceres::internal::LBFGS(options.num_parameters,
139 options.max_lbfgs_rank);
140 }
141
142 LOG(ERROR) << "Unknown line search direction type: " << options.type;
143 return NULL;
144}
145
146} // namespace internal
147} // namespace ceres
Sameer Agarwal8140f0f2013-03-12 09:45:08 -0700148
149#endif // CERES_NO_LINE_SEARCH_MINIMIZER