gtsam  3.2.1
gtsam
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ConjugateGradientSolver.h
1 /* ----------------------------------------------------------------------------
2 
3  * GTSAM Copyright 2010, Georgia Tech Research Corporation,
4  * Atlanta, Georgia 30332-0415
5  * All Rights Reserved
6  * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7 
8  * See LICENSE for the license information
9 
10  * -------------------------------------------------------------------------- */
11 
12 #pragma once
13 
14 #include <gtsam/linear/IterativeSolver.h>
15 #include <iosfwd>
16 
17 namespace gtsam {
18 
23 
24 public:
26  typedef boost::shared_ptr<ConjugateGradientParameters> shared_ptr;
27 
28  size_t minIterations_;
29  size_t maxIterations_;
30  size_t reset_;
31  double epsilon_rel_;
32  double epsilon_abs_;
33 
34  /* Matrix Operation Kernel */
35  enum BLASKernel {
36  GTSAM = 0,
37  } blas_kernel_ ;
38 
40  : minIterations_(1), maxIterations_(500), reset_(501), epsilon_rel_(1e-3),
41  epsilon_abs_(1e-3), blas_kernel_(GTSAM) {}
42 
43  ConjugateGradientParameters(size_t minIterations, size_t maxIterations, size_t reset,
44  double epsilon_rel, double epsilon_abs, BLASKernel blas)
45  : minIterations_(minIterations), maxIterations_(maxIterations), reset_(reset),
46  epsilon_rel_(epsilon_rel), epsilon_abs_(epsilon_abs), blas_kernel_(blas) {}
47 
48  ConjugateGradientParameters(const ConjugateGradientParameters &p)
49  : Base(p), minIterations_(p.minIterations_), maxIterations_(p.maxIterations_), reset_(p.reset_),
50  epsilon_rel_(p.epsilon_rel_), epsilon_abs_(p.epsilon_abs_), blas_kernel_(GTSAM) {}
51 
52  /* general interface */
53  inline size_t minIterations() const { return minIterations_; }
54  inline size_t maxIterations() const { return maxIterations_; }
55  inline size_t reset() const { return reset_; }
56  inline double epsilon() const { return epsilon_rel_; }
57  inline double epsilon_rel() const { return epsilon_rel_; }
58  inline double epsilon_abs() const { return epsilon_abs_; }
59 
60  inline size_t getMinIterations() const { return minIterations_; }
61  inline size_t getMaxIterations() const { return maxIterations_; }
62  inline size_t getReset() const { return reset_; }
63  inline double getEpsilon() const { return epsilon_rel_; }
64  inline double getEpsilon_rel() const { return epsilon_rel_; }
65  inline double getEpsilon_abs() const { return epsilon_abs_; }
66 
67  inline void setMinIterations(size_t value) { minIterations_ = value; }
68  inline void setMaxIterations(size_t value) { maxIterations_ = value; }
69  inline void setReset(size_t value) { reset_ = value; }
70  inline void setEpsilon(double value) { epsilon_rel_ = value; }
71  inline void setEpsilon_rel(double value) { epsilon_rel_ = value; }
72  inline void setEpsilon_abs(double value) { epsilon_abs_ = value; }
73 
74 
75  void print() const { Base::print(); }
76  virtual void print(std::ostream &os) const;
77 
78  static std::string blasTranslator(const BLASKernel k) ;
79  static BLASKernel blasTranslator(const std::string &s) ;
80 };
81 
82 /*********************************************************************************************/
83 /*
84  * A template of linear preconditioned conjugate gradient method.
85  * System class should support residual(v, g), multiply(v,Av), leftPrecondition(v, S^{-t}v,
86  * rightPrecondition(v, S^{-1}v), scal(alpha,v), dot(v,v), axpy(alpha,x,y)
87  * Note that the residual is in the preconditioned domain. Refer to Section 9.2 of Saad's book.
88  */
89 template <class S, class V>
90 V preconditionedConjugateGradient(const S &system, const V &initial, const ConjugateGradientParameters &parameters) {
91 
92  V estimate, residual, direction, q1, q2;
93  estimate = residual = direction = q1 = q2 = initial;
94 
95  system.residual(estimate, q1); /* q1 = b-Ax */
96  system.leftPrecondition(q1, residual); /* r = S^{-T} (b-Ax) */
97  system.rightPrecondition(residual, direction);/* d = S^{-1} r */
98 
99  double currentGamma = system.dot(residual, residual), prevGamma, alpha, beta;
100 
101  const size_t iMaxIterations = parameters.maxIterations(),
102  iMinIterations = parameters.minIterations(),
103  iReset = parameters.reset() ;
104  const double threshold = std::max(parameters.epsilon_abs(),
105  parameters.epsilon() * parameters.epsilon() * currentGamma);
106 
107  if (parameters.verbosity() >= ConjugateGradientParameters::COMPLEXITY )
108  std::cout << "[PCG] epsilon = " << parameters.epsilon()
109  << ", max = " << parameters.maxIterations()
110  << ", reset = " << parameters.reset()
111  << ", ||r0||^2 = " << currentGamma
112  << ", threshold = " << threshold << std::endl;
113 
114  size_t k;
115  for ( k = 1 ; k <= iMaxIterations && (currentGamma > threshold || k <= iMinIterations) ; k++ ) {
116 
117  if ( k % iReset == 0 ) {
118  system.residual(estimate, q1); /* q1 = b-Ax */
119  system.leftPrecondition(q1, residual); /* r = S^{-T} (b-Ax) */
120  system.rightPrecondition(residual, direction); /* d = S^{-1} r */
121  currentGamma = system.dot(residual, residual);
122  }
123  system.multiply(direction, q1); /* q1 = A d */
124  alpha = currentGamma / system.dot(direction, q1); /* alpha = gamma / (d' A d) */
125  system.axpy(alpha, direction, estimate); /* estimate += alpha * direction */
126  system.leftPrecondition(q1, q2); /* q2 = S^{-T} * q1 */
127  system.axpy(-alpha, q2, residual); /* residual -= alpha * q2 */
128  prevGamma = currentGamma;
129  currentGamma = system.dot(residual, residual); /* gamma = |residual|^2 */
130  beta = currentGamma / prevGamma;
131  system.rightPrecondition(residual, q1); /* q1 = S^{-1} residual */
132  system.scal(beta, direction);
133  system.axpy(1.0, q1, direction); /* direction = q1 + beta * direction */
134 
135  if (parameters.verbosity() >= ConjugateGradientParameters::ERROR )
136  std::cout << "[PCG] k = " << k
137  << ", alpha = " << alpha
138  << ", beta = " << beta
139  << ", ||r||^2 = " << currentGamma
140  << std::endl;
141  }
142  if (parameters.verbosity() >= ConjugateGradientParameters::COMPLEXITY )
143  std::cout << "[PCG] iterations = " << k
144  << ", ||r||^2 = " << currentGamma
145  << std::endl;
146 
147  return estimate;
148 }
149 
150 
151 }
size_t reset_
number of iterations before reset
Definition: ConjugateGradientSolver.h:30
double epsilon_rel_
threshold for relative error decrease
Definition: ConjugateGradientSolver.h:31
parameters for iterative linear solvers
Definition: IterativeSolver.h:38
size_t minIterations_
minimum number of cg iterations
Definition: ConjugateGradientSolver.h:28
void print(const Matrix &A, const string &s, ostream &stream)
print a matrix
Definition: Matrix.cpp:183
double max(const Vector &a)
Return the max element of a vector.
Definition: Vector.cpp:238
BLASKernel
Definition: ConjugateGradientSolver.h:35
double epsilon_abs_
threshold for absolute error decrease
Definition: ConjugateGradientSolver.h:32
parameters for the conjugate gradient method
Definition: ConjugateGradientSolver.h:22
size_t maxIterations_
maximum number of cg iterations
Definition: ConjugateGradientSolver.h:29