version 0.4
truncatedconjugategradient.hh
Go to the documentation of this file.
1// Original File: https://gitlab.com/libeigen/eigen/-/blob/master/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h
2// SPDX-FileCopyrightText: 2011-2014 Copyright (C) Gael Guennebaud <gael.guennebaud@inria.fr>
3// SPDX-License-Identifier: MPL-2.0
4// Modifications:
5// SPDX-FileCopyrightText: 2021-2024 The Ikarus Developers mueller@ibb.uni-stuttgart.de
6// SPDX-License-Identifier: LGPL-3.0-or-later
7
19#pragma once
20#include <Eigen/Core>
21#include <Eigen/Dense>
22#include <Eigen/Sparse>
23
24namespace Eigen {
25 enum class TCGStopReason : int {
32 };
33 template <typename Scalar>
34 struct TCGInfo {
36 Scalar Delta = 100000;
37 Scalar kappa = 0.1;
38 Scalar theta = 1.0;
39 Eigen::Index mininner = 1;
40 Eigen::Index maxinner = 1000;
41 Eigen::Index numInnerIter = 0;
42
43 void initRuntimeOptions(int _num_dof_solve) {
44 maxinner = _num_dof_solve * 2;
45 Delta = 100000; // typical distance of manifold
46 // Delta0 = Delta_bar/8.0;
47 }
48 };
49 namespace internal {
50
66 template <typename MatrixType, typename Rhs, typename Dest, typename Preconditioner>
67 void truncated_conjugate_gradient(const MatrixType& mat, const Rhs& rhs, Dest& x, const Preconditioner& precond,
68 Eigen::Index& iters, typename Dest::RealScalar& tol_error,
70 using std::abs;
71 using std::sqrt;
72 typedef typename Dest::RealScalar RealScalar;
73 typedef typename Dest::Scalar Scalar;
74 typedef Matrix<Scalar, Dynamic, 1> VectorType;
75
76 RealScalar tol = tol_error;
77 Index maxIters = iters;
78
79 Index n = mat.cols();
80
81 VectorType residual = rhs - mat * x; // initial residual
82
83 RealScalar rhsNorm2 = rhs.norm();
84 const RealScalar considerAsZero = (std::numeric_limits<RealScalar>::min)();
85
86 if (rhsNorm2 <= considerAsZero) {
87 x.setZero();
88 iters = 0;
89 tol_error = 0;
90 return;
91 }
92 RealScalar threshold = numext::maxi(tol * tol * rhsNorm2 * rhsNorm2, considerAsZero);
93 RealScalar residualNorm2 = residual.norm();
94 if (residualNorm2 * residualNorm2 < threshold) {
95 iters = 0;
96 tol_error = (residualNorm2 / rhsNorm2);
97 return;
98 }
99
100 double e_Pd = 0.0;
101 double e_Pe_new = 0.0;
102 double e_Pe = x.squaredNorm();
103 double d_Pd;
104 double d_Hd;
105 VectorType p(n);
106 p = precond.solve(residual); // initial search direction
107 // bool coutflag=true;
109 VectorType z(n), tmp(n);
110 RealScalar absNew = numext::real(residual.dot(p)); // the square of the absolute value of r scaled by invM
111 d_Pd = absNew;
112 Index i = 1;
113 while (i < maxIters) {
114 tmp.noalias() = mat * p; // the bottleneck of the algorithm
115 d_Hd = p.dot(tmp);
116 Scalar alpha = absNew / d_Hd; // the amount we travel on dir
117
118 e_Pe_new = e_Pe + 2.0 * alpha * e_Pd + alpha * alpha * d_Pd;
119
120 if (d_Hd <= 0 || e_Pe_new >= _info.Delta * _info.Delta) // negative curvature or execdet trustregion
121 {
122 double tau = (-e_Pd + sqrt(e_Pd * e_Pd + d_Pd * (_info.Delta * _info.Delta - e_Pe))) / d_Pd;
123
124 x += tau * p;
125 if (d_Hd <= 0)
127 else
129
130 break;
131 }
132 e_Pe = e_Pe_new;
133 x += alpha * p; // update solution
134 residual -= alpha * tmp; // update residual
135
136 residualNorm2 = residual.norm();
137
138 if (i >= _info.mininner
139 && residualNorm2 <= rhsNorm2 * std::min(rhsNorm2, _info.kappa)) // missing pow(rhsNorm2,_info.theta
140 {
141 // Residual is small enough to quit
142 if (_info.kappa < rhsNorm2)
144 else
146 break;
147 }
148 if (residualNorm2 < threshold) break;
149
150 z = precond.solve(residual); // approximately solve for "A z = residual"
151
152 RealScalar absOld = absNew;
153 absNew = numext::real(residual.dot(z)); // update the absolute value of r
154 RealScalar beta = absNew / absOld; // calculate the Gram-Schmidt value used to create the new search direction
155
156 e_Pd = beta * (e_Pd + alpha * d_Pd);
157 d_Pd = absNew + beta * beta * d_Pd;
158
159 p = z + beta * p; // update search direction
160 i++;
161 }
162 tol_error = (residualNorm2 / rhsNorm2);
163 iters = i;
164 _info.numInnerIter = i;
165 }
166
167 } // namespace internal
168
169 template <typename MatrixType, int UpLo = Lower,
170 typename Preconditioner = DiagonalPreconditioner<typename MatrixType::Scalar> >
171 class TruncatedConjugateGradient;
172
173 namespace internal {
174
175 template <typename MatrixType_, int UpLo, typename Preconditioner_>
176 struct traits<TruncatedConjugateGradient<MatrixType_, UpLo, Preconditioner_> > {
177 typedef MatrixType_ MatrixType;
178 typedef Preconditioner_ Preconditioner;
179 };
180
181 } // namespace internal
182
190 template <typename MatrixType_, int UpLo_, typename Preconditioner_>
192 : public IterativeSolverBase<TruncatedConjugateGradient<MatrixType_, UpLo_, Preconditioner_> > {
193 public:
194 typedef IterativeSolverBase<TruncatedConjugateGradient> Base;
196 : Base(std::move(other)), algInfo{other.algInfo} {}
197
198 private:
199 using Base::m_error;
200 using Base::m_info;
201 using Base::m_isInitialized;
202 using Base::m_iterations;
203 using Base::matrix;
204 mutable TCGInfo<typename MatrixType_::RealScalar> algInfo;
205
206 public:
207 typedef MatrixType_ MatrixType;
208 typedef typename MatrixType::Scalar Scalar;
209 typedef typename MatrixType::RealScalar RealScalar;
210 typedef Preconditioner_ Preconditioner;
211
212 enum { UpLo = UpLo_ };
213
214 public:
220
225 void setInfo(TCGInfo<typename MatrixType::RealScalar> _alginfo) { this->algInfo = _alginfo; }
228
239 template <typename MatrixDerived>
240 explicit TruncatedConjugateGradient(const EigenBase<MatrixDerived>& A) : Base(A.derived()) {}
241
243
245 template <typename Rhs, typename Dest>
246 void _solve_vector_with_guess_impl(const Rhs& b, Dest& x) const {
247 typedef typename Base::MatrixWrapper MatrixWrapper;
248 typedef typename Base::ActualMatrixType ActualMatrixType;
249 enum {
250 TransposeInput = (!MatrixWrapper::MatrixFree) && (UpLo == (Lower | Upper)) && (!MatrixType::IsRowMajor)
251 && (!NumTraits<Scalar>::IsComplex)
252 };
253 typedef std::conditional_t<TransposeInput, Transpose<const ActualMatrixType>, ActualMatrixType const&>
254 RowMajorWrapper;
255 EIGEN_STATIC_ASSERT(internal::check_implication(MatrixWrapper::MatrixFree, UpLo == (Lower | Upper)),
256 MATRIX_FREE_CONJUGATE_GRADIENT_IS_COMPATIBLE_WITH_UPPER_UNION_LOWER_MODE_ONLY);
257 typedef std::conditional_t<UpLo == (Lower | Upper), RowMajorWrapper,
258 typename MatrixWrapper::template ConstSelfAdjointViewReturnType<UpLo>::Type>
259 SelfAdjointWrapper;
260
261 m_iterations = Base::maxIterations();
262 m_error = Base::m_tolerance;
263
264 RowMajorWrapper row_mat(matrix());
265 internal::truncated_conjugate_gradient(SelfAdjointWrapper(row_mat), b, x, Base::m_preconditioner, m_iterations,
266 m_error, algInfo);
267 m_info = m_error <= Base::m_tolerance ? Success : NoConvergence;
268 }
269
270 protected:
271 };
272
273} // end namespace Eigen
Definition: truncatedconjugategradient.hh:24
TCGStopReason
Definition: truncatedconjugategradient.hh:25
void truncated_conjugate_gradient(const MatrixType &mat, const Rhs &rhs, Dest &x, const Preconditioner &precond, Eigen::Index &iters, typename Dest::RealScalar &tol_error, TCGInfo< typename Dest::RealScalar > &_info)
Definition: truncatedconjugategradient.hh:67
Definition: truncatedconjugategradient.hh:34
Scalar kappa
Definition: truncatedconjugategradient.hh:37
Eigen::Index mininner
Definition: truncatedconjugategradient.hh:39
Eigen::Index maxinner
Definition: truncatedconjugategradient.hh:40
Scalar Delta
Definition: truncatedconjugategradient.hh:36
void initRuntimeOptions(int _num_dof_solve)
Definition: truncatedconjugategradient.hh:43
TCGStopReason stop_tCG
Definition: truncatedconjugategradient.hh:35
Scalar theta
Definition: truncatedconjugategradient.hh:38
Eigen::Index numInnerIter
Definition: truncatedconjugategradient.hh:41
Iterative solver for solving linear systems using the truncated conjugate gradient method.
Definition: truncatedconjugategradient.hh:192
TruncatedConjugateGradient()
Definition: truncatedconjugategradient.hh:227
@ UpLo
Definition: truncatedconjugategradient.hh:212
void _solve_vector_with_guess_impl(const Rhs &b, Dest &x) const
Definition: truncatedconjugategradient.hh:246
TruncatedConjugateGradient(TruncatedConjugateGradient &&other) noexcept
Definition: truncatedconjugategradient.hh:195
TCGInfo< typename MatrixType::RealScalar > getInfo()
Get information about the truncated conjugate gradient algorithm.
Definition: truncatedconjugategradient.hh:219
Preconditioner_ Preconditioner
Definition: truncatedconjugategradient.hh:210
TruncatedConjugateGradient(const EigenBase< MatrixDerived > &A)
Definition: truncatedconjugategradient.hh:240
void setInfo(TCGInfo< typename MatrixType::RealScalar > _alginfo)
Set information about the truncated conjugate gradient algorithm.
Definition: truncatedconjugategradient.hh:225
MatrixType::Scalar Scalar
Definition: truncatedconjugategradient.hh:208
MatrixType::RealScalar RealScalar
Definition: truncatedconjugategradient.hh:209
MatrixType_ MatrixType
Definition: truncatedconjugategradient.hh:207
~TruncatedConjugateGradient()
Definition: truncatedconjugategradient.hh:242
IterativeSolverBase< TruncatedConjugateGradient > Base
Definition: truncatedconjugategradient.hh:194
Preconditioner_ Preconditioner
Definition: truncatedconjugategradient.hh:178
Definition: concepts.hh:25