gtsam  3.2.1
gtsam
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NonlinearConjugateGradientOptimizer.h
1 
8 #pragma once
9 
10 #include <gtsam/base/Manifold.h>
12 #include <boost/tuple/tuple.hpp>
13 
14 namespace gtsam {
15 
18 public:
21  : Base(graph, values) {}
22 };
23 
25  /* a class for the nonlinearConjugateGradient template */
26  class System {
27  public:
28  typedef Values State;
29  typedef VectorValues Gradient;
31 
32  protected:
33  const NonlinearFactorGraph &graph_;
34 
35  public:
36  System(const NonlinearFactorGraph &graph): graph_(graph) {}
37  double error(const State &state) const ;
38  Gradient gradient(const State &state) const ;
39  State advance(const State &current, const double alpha, const Gradient &g) const ;
40  };
41 
42 public:
43  typedef NonlinearOptimizer Base;
46  typedef boost::shared_ptr<NonlinearConjugateGradientOptimizer> shared_ptr;
47 
48 protected:
49  States state_;
50  Parameters params_;
51 
52 public:
53 
54  NonlinearConjugateGradientOptimizer(const NonlinearFactorGraph& graph, const Values& initialValues,
55  const Parameters& params = Parameters())
56  : Base(graph), state_(graph, initialValues), params_(params) {}
57 
59  virtual void iterate();
60  virtual const Values& optimize ();
61  virtual const NonlinearOptimizerState& _state() const { return state_; }
62  virtual const NonlinearOptimizerParams& _params() const { return params_; }
63 };
64 
66 template <class S, class V, class W>
67 double lineSearch(const S &system, const V currentValues, const W &gradient) {
68 
69  /* normalize it such that it becomes a unit vector */
70  const double g = gradient.norm();
71 
72  // perform the golden section search algorithm to decide the the optimal step size
73  // detail refer to http://en.wikipedia.org/wiki/Golden_section_search
74  const double phi = 0.5*(1.0+std::sqrt(5.0)), resphi = 2.0 - phi, tau = 1e-5;
75  double minStep = -1.0/g, maxStep = 0,
76  newStep = minStep + (maxStep-minStep) / (phi+1.0) ;
77 
78  V newValues = system.advance(currentValues, newStep, gradient);
79  double newError = system.error(newValues);
80 
81  while (true) {
82  const bool flag = (maxStep - newStep > newStep - minStep) ? true : false ;
83  const double testStep = flag ?
84  newStep + resphi * (maxStep - newStep) : newStep - resphi * (newStep - minStep);
85 
86  if ( (maxStep- minStep) < tau * (std::fabs(testStep) + std::fabs(newStep)) ) {
87  return 0.5*(minStep+maxStep);
88  }
89 
90  const V testValues = system.advance(currentValues, testStep, gradient);
91  const double testError = system.error(testValues);
92 
93  // update the working range
94  if ( testError >= newError ) {
95  if ( flag ) maxStep = testStep;
96  else minStep = testStep;
97  }
98  else {
99  if ( flag ) {
100  minStep = newStep;
101  newStep = testStep;
102  newError = testError;
103  }
104  else {
105  maxStep = newStep;
106  newStep = testStep;
107  newError = testError;
108  }
109  }
110  }
111  return 0.0;
112 }
113 
123 template <class S, class V>
124 boost::tuple<V, int> nonlinearConjugateGradient(const S &system, const V &initial, const NonlinearOptimizerParams &params, const bool singleIteration, const bool gradientDescent = false) {
125 
126  // GTSAM_CONCEPT_MANIFOLD_TYPE(V);
127 
128  int iteration = 0;
129 
130  // check if we're already close enough
131  double currentError = system.error(initial);
132  if(currentError <= params.errorTol) {
133  if (params.verbosity >= NonlinearOptimizerParams::ERROR){
134  std::cout << "Exiting, as error = " << currentError << " < " << params.errorTol << std::endl;
135  }
136  return boost::tie(initial, iteration);
137  }
138 
139  V currentValues = initial;
140  typename S::Gradient currentGradient = system.gradient(currentValues), prevGradient,
141  direction = currentGradient;
142 
143  /* do one step of gradient descent */
144  V prevValues = currentValues; double prevError = currentError;
145  double alpha = lineSearch(system, currentValues, direction);
146  currentValues = system.advance(prevValues, alpha, direction);
147  currentError = system.error(currentValues);
148 
149  // Maybe show output
150  if (params.verbosity >= NonlinearOptimizerParams::ERROR) std::cout << "Initial error: " << currentError << std::endl;
151 
152  // Iterative loop
153  do {
154  if ( gradientDescent == true) {
155  direction = system.gradient(currentValues);
156  }
157  else {
158  prevGradient = currentGradient;
159  currentGradient = system.gradient(currentValues);
160  const double beta = std::max(0.0, currentGradient.dot(currentGradient-prevGradient)/currentGradient.dot(currentGradient));
161  direction = currentGradient + (beta*direction);
162  }
163 
164  alpha = lineSearch(system, currentValues, direction);
165 
166  prevValues = currentValues; prevError = currentError;
167 
168  currentValues = system.advance(prevValues, alpha, direction);
169  currentError = system.error(currentValues);
170 
171  // Maybe show output
172  if(params.verbosity >= NonlinearOptimizerParams::ERROR) std::cout << "currentError: " << currentError << std::endl;
173  } while( ++iteration < params.maxIterations &&
174  !singleIteration &&
175  !checkConvergence(params.relativeErrorTol, params.absoluteErrorTol, params.errorTol, prevError, currentError, params.verbosity));
176 
177  // Printing if verbose
178  if (params.verbosity >= NonlinearOptimizerParams::ERROR && iteration >= params.maxIterations)
179  std::cout << "nonlinearConjugateGradient: Terminating because reached maximum iterations" << std::endl;
180 
181  return boost::tie(currentValues, iteration);
182 }
183 
184 }
185 
double lineSearch(const S &system, const V currentValues, const W &gradient)
Implement the golden-section line search algorithm.
Definition: NonlinearConjugateGradientOptimizer.h:67
double errorTol
The maximum total error to stop iterating (default 0.0)
Definition: NonlinearOptimizerParams.h:43
An implementation of the nonlinear cg method using the template below.
Definition: NonlinearConjugateGradientOptimizer.h:17
Base class and basic functions for Manifold types.
The common parameters for Nonlinear optimizers.
Definition: NonlinearOptimizerParams.h:33
double absoluteErrorTol
The maximum absolute error decrease to stop iterating (default 1e-5)
Definition: NonlinearOptimizerParams.h:42
double relativeErrorTol
The maximum relative error decrease to stop iterating (default 1e-5)
Definition: NonlinearOptimizerParams.h:41
Definition: NonlinearConjugateGradientOptimizer.h:24
A non-templated config holding any types of Manifold-group elements.
Definition: Values.h:75
bool checkConvergence(double relativeErrorTreshold, double absoluteErrorTreshold, double errorThreshold, double currentError, double newError, NonlinearOptimizerParams::Verbosity verbosity)
Check whether the relative error decrease is less than relativeErrorTreshold, the absolute error decr...
Definition: NonlinearOptimizer.cpp:138
boost::tuple< V, int > nonlinearConjugateGradient(const S &system, const V &initial, const NonlinearOptimizerParams &params, const bool singleIteration, const bool gradientDescent=false)
Implement the nonlinear conjugate gradient method using the Polak-Ribieve formula suggested in http:/...
Definition: NonlinearConjugateGradientOptimizer.h:124
This is the abstract interface for classes that can optimize for the maximum-likelihood estimate of a...
Definition: NonlinearOptimizer.h:134
double max(const Vector &a)
Return the max element of a vector.
Definition: Vector.cpp:238
A non-linear factor graph is a graph of non-Gaussian, i.e.
Definition: NonlinearFactorGraph.h:69
int maxIterations
The maximum iterations to stop iterating (default 100)
Definition: NonlinearOptimizerParams.h:40
Point3 optimize(const NonlinearFactorGraph &graph, const Values &values, Key landmarkKey)
Optimize for triangulation.
Definition: triangulation.cpp:72
Base class and parameters for nonlinear optimization algorithms.
This class represents a collection of vector-valued variables associated each with a unique integer i...
Definition: VectorValues.h:89
Verbosity verbosity
The printing verbosity during optimization (default SILENT)
Definition: NonlinearOptimizerParams.h:44
Base class for a nonlinear optimization state, including the current estimate of the variable values...
Definition: NonlinearOptimizer.h:35