11#ifndef EIGEN_CONJUGATE_GRADIENT_H
12#define EIGEN_CONJUGATE_GRADIENT_H
15#include "./InternalHeaderCheck.h"
30template <
typename MatrixType,
typename Rhs,
typename Dest,
typename Preconditioner>
31EIGEN_DONT_INLINE
void conjugate_gradient(
const MatrixType& mat,
const Rhs& rhs, Dest& x,
const Preconditioner& precond,
32 Index& iters,
typename Dest::RealScalar& tol_error) {
33 using RealScalar =
typename Dest::RealScalar;
34 using Scalar =
typename Dest::Scalar;
38 using VectorType =
typename Dest::PlainObject;
40 RealScalar tol = tol_error;
41 Index maxIters = iters;
45 VectorType residual = rhs - mat * x;
47 RealScalar rhsNorm = rhs.stableNorm();
54 const RealScalar considerAsZero = (std::numeric_limits<RealScalar>::min)();
55 RealScalar threshold = numext::maxi(RealScalar(tol * rhsNorm), considerAsZero);
56 RealScalar residualNorm = residual.stableNorm();
57 if (residualNorm < threshold) {
59 tol_error = residualNorm / rhsNorm;
64 const RealScalar residualScale = internal::iterative_solver_scaling_factor(residualNorm);
65 residual /= residualScale;
66 threshold /= residualScale;
69 p = precond.solve(residual);
71 VectorType z(n), tmp(n);
72 RealScalar absNew = numext::real(residual.dot(p));
74 while (i < maxIters) {
75 tmp.noalias() = mat * p;
77 Scalar alpha = absNew / p.dot(tmp);
78 x += (residualScale * alpha) * p;
79 residual -= alpha * tmp;
81 residualNorm = residual.stableNorm();
82 if (residualNorm < threshold)
break;
84 z = precond.solve(residual);
86 RealScalar absOld = absNew;
87 absNew = numext::real(residual.dot(z));
88 RealScalar beta = absNew / absOld;
92 tol_error = residualNorm / (rhsNorm / residualScale);
98template <
typename MatrixType_,
int UpLo_ =
Lower,
104template <
typename MatrixType_,
int UpLo_,
typename Preconditioner_>
105struct traits<ConjugateGradient<MatrixType_, UpLo_, Preconditioner_> > {
106 using MatrixType = MatrixType_;
107 using Preconditioner = Preconditioner_;
160template <
typename MatrixType_,
int UpLo_,
typename Preconditioner_>
166 using Base::m_isInitialized;
167 using Base::m_iterations;
171 using MatrixType = MatrixType_;
172 using Scalar =
typename MatrixType::Scalar;
173 using RealScalar =
typename MatrixType::RealScalar;
174 using Preconditioner = Preconditioner_;
176 enum { UpLo = UpLo_ };
192 template <
typename MatrixDerived>
196 template <
typename Rhs,
typename Dest>
197 void _solve_vector_with_guess_impl(
const Rhs& b, Dest& x)
const {
199 using ActualMatrixType =
typename Base::ActualMatrixType;
201 TransposeInput = (!MatrixWrapper::MatrixFree) && (UpLo == (
Lower |
Upper)) && (!MatrixType::IsRowMajor) &&
202 (!NumTraits<Scalar>::IsComplex)
204 using RowMajorWrapper =
205 std::conditional_t<TransposeInput, Transpose<const ActualMatrixType>, ActualMatrixType
const&>;
206 EIGEN_STATIC_ASSERT(internal::check_implication(MatrixWrapper::MatrixFree, UpLo == (
Lower |
Upper)),
207 MATRIX_FREE_CONJUGATE_GRADIENT_IS_COMPATIBLE_WITH_UPPER_UNION_LOWER_MODE_ONLY);
208 using SelfAdjointWrapper =
209 std::conditional_t<UpLo == (
Lower |
Upper), RowMajorWrapper,
210 typename MatrixWrapper::template ConstSelfAdjointViewReturnType<UpLo>::Type>;
213 m_error = Base::m_tolerance;
215 RowMajorWrapper row_mat(matrix());
216 internal::conjugate_gradient(SelfAdjointWrapper(row_mat), b, x, Base::m_preconditioner, m_iterations, m_error);
A conjugate gradient solver for sparse (or dense) self-adjoint problems.
Definition ConjugateGradient.h:161
ConjugateGradient(const EigenBase< MatrixDerived > &A)
Definition ConjugateGradient.h:193
ConjugateGradient()
Definition ConjugateGradient.h:180
A preconditioner based on the diagonal entries.
Definition BasicPreconditioners.h:40
IterativeSolverBase()
Definition IterativeSolverBase.h:136
Index maxIterations() const
Definition IterativeSolverBase.h:245
Expression of an array as a mathematical vector or matrix.
Definition ArrayWrapper.h:120
@ Lower
Definition Constants.h:212
@ Upper
Definition Constants.h:214
@ Success
Definition Constants.h:457
@ NoConvergence
Definition Constants.h:461
Definition EigenBase.h:34