SOPT
Sparse OPTimisation
conjugate_gradient.h
Go to the documentation of this file.
1 #ifndef SOPT_CONJUGATE_GRADIENT
2 #define SOPT_CONJUGATE_GRADIENT
3 
4 #include "sopt/config.h"
5 #include <limits>
6 #include <type_traits>
7 #include "sopt/logging.h"
8 #include "sopt/maths.h"
9 #include "sopt/types.h"
10 #include "sopt/wrapper.h"
11 
12 namespace sopt {
17  template <typename T>
18  class ApplyMatrix;
19 
20  public:
22  struct Diagnostic {
28  bool good;
29  };
31  template <typename T>
32  struct DiagnosticAndResult : public Diagnostic {
34  };
39  ConjugateGradient(t_uint itermax = std::numeric_limits<t_uint>::max(), t_real tolerance = 1e-8)
40  : tolerance_(tolerance), itermax_(itermax) {}
41  virtual ~ConjugateGradient() {}
42 
48  template <typename VECTOR, typename T1, typename T2>
49  Diagnostic operator()(VECTOR &x, Eigen::MatrixBase<T1> const &A,
50  Eigen::MatrixBase<T2> const &b) const {
51  return implementation(x, A, b);
52  }
56  template <typename VECTOR, typename T1, typename T2>
57  typename std::enable_if<not std::is_base_of<Eigen::EigenBase<T1>, T1>::value, Diagnostic>::type
58  operator()(VECTOR &x, T1 const &A, Eigen::MatrixBase<T2> const &b) const {
59  return implementation(x, details::wrap<typename VECTOR::PlainObject>(A), b);
60  }
64  template <typename T0, typename A_TYPE>
66  Eigen::MatrixBase<T0> const &b) const {
69  *static_cast<Diagnostic *>(&result) = operator()(result.result, A, b);
70  return result;
71  }
72 
75  t_uint itermax() const { return itermax_; }
78  void itermax(t_uint const &itermax) { itermax_ = itermax; }
80  t_real tolerance() const { return tolerance_; }
82  void tolerance(t_real const &tolerance) {
83  if (tolerance <= 0e0) throw std::domain_error("Incorrect tolerance input");
84  tolerance_ = tolerance;
85  }
86 
87  protected:
89  t_real tolerance_;
91  t_uint itermax_;
93  Image<> work_v;
95  Image<> work_r;
97  Image<> work_p;
98 
99  private:
103  template <typename VECTOR, typename T1, typename MATRIXLIKE>
104  Diagnostic implementation(VECTOR &x, MATRIXLIKE const &A, Eigen::MatrixBase<T1> const &b) const;
105 };
106 
107 template <typename VECTOR, typename T1, typename MATRIXLIKE>
108 ConjugateGradient::Diagnostic ConjugateGradient::implementation(
109  VECTOR &x, MATRIXLIKE const &A, Eigen::MatrixBase<T1> const &b) const {
110  using Scalar = typename T1::Scalar;
111  using Real = typename real_type<Scalar>::type;
112 
113  x.resize(b.size());
114  if (std::abs((b.transpose().conjugate() * b)(0)) < tolerance()) {
115  x.fill(0);
116  return {0, 0, true};
117  }
118 
119  Vector<Scalar> Ap(b.size());
120 
121  x = b;
122  Vector<Scalar> residuals = b - A * x;
123  Vector<Scalar> p = residuals;
124  Real residual = std::abs((residuals.transpose().conjugate() * residuals)(0));
125 
126  t_uint i(0);
127  for (; i < itermax(); ++i) {
128  Ap = A * p;
129  Scalar const alpha = residual / (p.transpose().conjugate() * Ap)(0);
130  x += alpha * p;
131  residuals -= alpha * Ap;
132 
133  Real new_residual = std::abs((residuals.transpose().conjugate() * residuals)(0));
134  SOPT_LOW_LOG("CG iteration {} - residuals: {}", i, new_residual);
135  if (std::abs(new_residual) < tolerance()) {
136  residual = new_residual;
137  break;
138  }
139 
140  p = residuals + new_residual / residual * p;
141  residual = new_residual;
142  }
143  return {i, residual, residual < tolerance()};
144 }
145 } // namespace sopt
146 #endif
constexpr Scalar b
sopt::t_real Scalar
Solves $Ax = b$ for $x$, given $A$ and $b$.
void tolerance(t_real const &tolerance)
Sets tolerance criteria.
t_real tolerance() const
Tolerance criteria.
void itermax(t_uint const &itermax)
Sets maximum number of iterations.
ConjugateGradient(t_uint itermax=std::numeric_limits< t_uint >::max(), t_real tolerance=1e-8)
Creates conjugate gradient operator.
t_uint itermax() const
Maximum number of iterations.
std::enable_if< not std::is_base_of< Eigen::EigenBase< T1 >, T1 >::value, Diagnostic >::type operator()(VECTOR &x, T1 const &A, Eigen::MatrixBase< T2 > const &b) const
Computes $x$ for $Ax=b$.
Diagnostic operator()(VECTOR &x, Eigen::MatrixBase< T1 > const &A, Eigen::MatrixBase< T2 > const &b) const
Computes $x$ for $Ax=b$.
DiagnosticAndResult< typename T0::Scalar > operator()(A_TYPE const &A, Eigen::MatrixBase< T0 > const &b) const
Computes $x$ for $Ax=b$.
#define SOPT_LOW_LOG(...)
Low priority message.
Definition: logging.h:227
double t_real
Root of the type hierarchy for real numbers.
Definition: types.h:17
size_t t_uint
Root of the type hierarchy for unsigned integers.
Definition: types.h:15
Eigen::Array< T, Eigen::Dynamic, Eigen::Dynamic > Image
A 2-dimensional list of elements of given type.
Definition: types.h:39
Eigen::Matrix< T, Eigen::Dynamic, 1 > Vector
A vector of a given type.
Definition: types.h:24
Values indicating how the algorithm ran and its result;.
Values indicating how the algorithm ran.
t_uint niters
Number of iterations.
bool good
Wether convergence was achieved.
sopt::Vector< Scalar > Vector
Definition: inpainting.cc:28