1*bf2c3715SXin Li // This file is part of Eigen, a lightweight C++ template library 2*bf2c3715SXin Li // for linear algebra. 3*bf2c3715SXin Li // 4*bf2c3715SXin Li // Copyright (C) 2011-2014 Gael Guennebaud <[email protected]> 5*bf2c3715SXin Li // 6*bf2c3715SXin Li // This Source Code Form is subject to the terms of the Mozilla 7*bf2c3715SXin Li // Public License v. 2.0. If a copy of the MPL was not distributed 8*bf2c3715SXin Li // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 9*bf2c3715SXin Li 10*bf2c3715SXin Li #ifndef EIGEN_BASIC_PRECONDITIONERS_H 11*bf2c3715SXin Li #define EIGEN_BASIC_PRECONDITIONERS_H 12*bf2c3715SXin Li 13*bf2c3715SXin Li namespace Eigen { 14*bf2c3715SXin Li 15*bf2c3715SXin Li /** \ingroup IterativeLinearSolvers_Module 16*bf2c3715SXin Li * \brief A preconditioner based on the digonal entries 17*bf2c3715SXin Li * 18*bf2c3715SXin Li * This class allows to approximately solve for A.x = b problems assuming A is a diagonal matrix. 19*bf2c3715SXin Li * In other words, this preconditioner neglects all off diagonal entries and, in Eigen's language, solves for: 20*bf2c3715SXin Li \code 21*bf2c3715SXin Li A.diagonal().asDiagonal() . x = b 22*bf2c3715SXin Li \endcode 23*bf2c3715SXin Li * 24*bf2c3715SXin Li * \tparam _Scalar the type of the scalar. 25*bf2c3715SXin Li * 26*bf2c3715SXin Li * \implsparsesolverconcept 27*bf2c3715SXin Li * 28*bf2c3715SXin Li * This preconditioner is suitable for both selfadjoint and general problems. 29*bf2c3715SXin Li * The diagonal entries are pre-inverted and stored into a dense vector. 30*bf2c3715SXin Li * 31*bf2c3715SXin Li * \note A variant that has yet to be implemented would attempt to preserve the norm of each column. 32*bf2c3715SXin Li * 33*bf2c3715SXin Li * \sa class LeastSquareDiagonalPreconditioner, class ConjugateGradient 34*bf2c3715SXin Li */ 35*bf2c3715SXin Li template <typename _Scalar> 36*bf2c3715SXin Li class DiagonalPreconditioner 37*bf2c3715SXin Li { 38*bf2c3715SXin Li typedef _Scalar Scalar; 39*bf2c3715SXin Li typedef Matrix<Scalar,Dynamic,1> Vector; 40*bf2c3715SXin Li public: 41*bf2c3715SXin Li typedef typename Vector::StorageIndex StorageIndex; 42*bf2c3715SXin Li enum { 43*bf2c3715SXin Li ColsAtCompileTime = Dynamic, 44*bf2c3715SXin Li MaxColsAtCompileTime = Dynamic 45*bf2c3715SXin Li }; 46*bf2c3715SXin Li DiagonalPreconditioner()47*bf2c3715SXin Li DiagonalPreconditioner() : m_isInitialized(false) {} 48*bf2c3715SXin Li 49*bf2c3715SXin Li template<typename MatType> DiagonalPreconditioner(const MatType & mat)50*bf2c3715SXin Li explicit DiagonalPreconditioner(const MatType& mat) : m_invdiag(mat.cols()) 51*bf2c3715SXin Li { 52*bf2c3715SXin Li compute(mat); 53*bf2c3715SXin Li } 54*bf2c3715SXin Li rows()55*bf2c3715SXin Li EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_invdiag.size(); } cols()56*bf2c3715SXin Li EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_invdiag.size(); } 57*bf2c3715SXin Li 58*bf2c3715SXin Li template<typename MatType> analyzePattern(const MatType &)59*bf2c3715SXin Li DiagonalPreconditioner& analyzePattern(const MatType& ) 60*bf2c3715SXin Li { 61*bf2c3715SXin Li return *this; 62*bf2c3715SXin Li } 63*bf2c3715SXin Li 64*bf2c3715SXin Li template<typename MatType> factorize(const MatType & mat)65*bf2c3715SXin Li DiagonalPreconditioner& factorize(const MatType& mat) 66*bf2c3715SXin Li { 67*bf2c3715SXin Li m_invdiag.resize(mat.cols()); 68*bf2c3715SXin Li for(int j=0; j<mat.outerSize(); ++j) 69*bf2c3715SXin Li { 70*bf2c3715SXin Li typename MatType::InnerIterator it(mat,j); 71*bf2c3715SXin Li while(it && it.index()!=j) ++it; 72*bf2c3715SXin Li if(it && it.index()==j && it.value()!=Scalar(0)) 73*bf2c3715SXin Li m_invdiag(j) = Scalar(1)/it.value(); 74*bf2c3715SXin Li else 75*bf2c3715SXin Li m_invdiag(j) = Scalar(1); 76*bf2c3715SXin Li } 77*bf2c3715SXin Li m_isInitialized = true; 78*bf2c3715SXin Li return *this; 79*bf2c3715SXin Li } 80*bf2c3715SXin Li 81*bf2c3715SXin Li template<typename MatType> compute(const MatType & mat)82*bf2c3715SXin Li DiagonalPreconditioner& compute(const MatType& mat) 83*bf2c3715SXin Li { 84*bf2c3715SXin Li return factorize(mat); 85*bf2c3715SXin Li } 86*bf2c3715SXin Li 87*bf2c3715SXin Li /** \internal */ 88*bf2c3715SXin Li template<typename Rhs, typename Dest> _solve_impl(const Rhs & b,Dest & x)89*bf2c3715SXin Li void _solve_impl(const Rhs& b, Dest& x) const 90*bf2c3715SXin Li { 91*bf2c3715SXin Li x = m_invdiag.array() * b.array() ; 92*bf2c3715SXin Li } 93*bf2c3715SXin Li 94*bf2c3715SXin Li template<typename Rhs> inline const Solve<DiagonalPreconditioner, Rhs> solve(const MatrixBase<Rhs> & b)95*bf2c3715SXin Li solve(const MatrixBase<Rhs>& b) const 96*bf2c3715SXin Li { 97*bf2c3715SXin Li eigen_assert(m_isInitialized && "DiagonalPreconditioner is not initialized."); 98*bf2c3715SXin Li eigen_assert(m_invdiag.size()==b.rows() 99*bf2c3715SXin Li && "DiagonalPreconditioner::solve(): invalid number of rows of the right hand side matrix b"); 100*bf2c3715SXin Li return Solve<DiagonalPreconditioner, Rhs>(*this, b.derived()); 101*bf2c3715SXin Li } 102*bf2c3715SXin Li info()103*bf2c3715SXin Li ComputationInfo info() { return Success; } 104*bf2c3715SXin Li 105*bf2c3715SXin Li protected: 106*bf2c3715SXin Li Vector m_invdiag; 107*bf2c3715SXin Li bool m_isInitialized; 108*bf2c3715SXin Li }; 109*bf2c3715SXin Li 110*bf2c3715SXin Li /** \ingroup IterativeLinearSolvers_Module 111*bf2c3715SXin Li * \brief Jacobi preconditioner for LeastSquaresConjugateGradient 112*bf2c3715SXin Li * 113*bf2c3715SXin Li * This class allows to approximately solve for A' A x = A' b problems assuming A' A is a diagonal matrix. 114*bf2c3715SXin Li * In other words, this preconditioner neglects all off diagonal entries and, in Eigen's language, solves for: 115*bf2c3715SXin Li \code 116*bf2c3715SXin Li (A.adjoint() * A).diagonal().asDiagonal() * x = b 117*bf2c3715SXin Li \endcode 118*bf2c3715SXin Li * 119*bf2c3715SXin Li * \tparam _Scalar the type of the scalar. 120*bf2c3715SXin Li * 121*bf2c3715SXin Li * \implsparsesolverconcept 122*bf2c3715SXin Li * 123*bf2c3715SXin Li * The diagonal entries are pre-inverted and stored into a dense vector. 124*bf2c3715SXin Li * 125*bf2c3715SXin Li * \sa class LeastSquaresConjugateGradient, class DiagonalPreconditioner 126*bf2c3715SXin Li */ 127*bf2c3715SXin Li template <typename _Scalar> 128*bf2c3715SXin Li class LeastSquareDiagonalPreconditioner : public DiagonalPreconditioner<_Scalar> 129*bf2c3715SXin Li { 130*bf2c3715SXin Li typedef _Scalar Scalar; 131*bf2c3715SXin Li typedef typename NumTraits<Scalar>::Real RealScalar; 132*bf2c3715SXin Li typedef DiagonalPreconditioner<_Scalar> Base; 133*bf2c3715SXin Li using Base::m_invdiag; 134*bf2c3715SXin Li public: 135*bf2c3715SXin Li LeastSquareDiagonalPreconditioner()136*bf2c3715SXin Li LeastSquareDiagonalPreconditioner() : Base() {} 137*bf2c3715SXin Li 138*bf2c3715SXin Li template<typename MatType> LeastSquareDiagonalPreconditioner(const MatType & mat)139*bf2c3715SXin Li explicit LeastSquareDiagonalPreconditioner(const MatType& mat) : Base() 140*bf2c3715SXin Li { 141*bf2c3715SXin Li compute(mat); 142*bf2c3715SXin Li } 143*bf2c3715SXin Li 144*bf2c3715SXin Li template<typename MatType> analyzePattern(const MatType &)145*bf2c3715SXin Li LeastSquareDiagonalPreconditioner& analyzePattern(const MatType& ) 146*bf2c3715SXin Li { 147*bf2c3715SXin Li return *this; 148*bf2c3715SXin Li } 149*bf2c3715SXin Li 150*bf2c3715SXin Li template<typename MatType> factorize(const MatType & mat)151*bf2c3715SXin Li LeastSquareDiagonalPreconditioner& factorize(const MatType& mat) 152*bf2c3715SXin Li { 153*bf2c3715SXin Li // Compute the inverse squared-norm of each column of mat 154*bf2c3715SXin Li m_invdiag.resize(mat.cols()); 155*bf2c3715SXin Li if(MatType::IsRowMajor) 156*bf2c3715SXin Li { 157*bf2c3715SXin Li m_invdiag.setZero(); 158*bf2c3715SXin Li for(Index j=0; j<mat.outerSize(); ++j) 159*bf2c3715SXin Li { 160*bf2c3715SXin Li for(typename MatType::InnerIterator it(mat,j); it; ++it) 161*bf2c3715SXin Li m_invdiag(it.index()) += numext::abs2(it.value()); 162*bf2c3715SXin Li } 163*bf2c3715SXin Li for(Index j=0; j<mat.cols(); ++j) 164*bf2c3715SXin Li if(numext::real(m_invdiag(j))>RealScalar(0)) 165*bf2c3715SXin Li m_invdiag(j) = RealScalar(1)/numext::real(m_invdiag(j)); 166*bf2c3715SXin Li } 167*bf2c3715SXin Li else 168*bf2c3715SXin Li { 169*bf2c3715SXin Li for(Index j=0; j<mat.outerSize(); ++j) 170*bf2c3715SXin Li { 171*bf2c3715SXin Li RealScalar sum = mat.col(j).squaredNorm(); 172*bf2c3715SXin Li if(sum>RealScalar(0)) 173*bf2c3715SXin Li m_invdiag(j) = RealScalar(1)/sum; 174*bf2c3715SXin Li else 175*bf2c3715SXin Li m_invdiag(j) = RealScalar(1); 176*bf2c3715SXin Li } 177*bf2c3715SXin Li } 178*bf2c3715SXin Li Base::m_isInitialized = true; 179*bf2c3715SXin Li return *this; 180*bf2c3715SXin Li } 181*bf2c3715SXin Li 182*bf2c3715SXin Li template<typename MatType> compute(const MatType & mat)183*bf2c3715SXin Li LeastSquareDiagonalPreconditioner& compute(const MatType& mat) 184*bf2c3715SXin Li { 185*bf2c3715SXin Li return factorize(mat); 186*bf2c3715SXin Li } 187*bf2c3715SXin Li info()188*bf2c3715SXin Li ComputationInfo info() { return Success; } 189*bf2c3715SXin Li 190*bf2c3715SXin Li protected: 191*bf2c3715SXin Li }; 192*bf2c3715SXin Li 193*bf2c3715SXin Li /** \ingroup IterativeLinearSolvers_Module 194*bf2c3715SXin Li * \brief A naive preconditioner which approximates any matrix as the identity matrix 195*bf2c3715SXin Li * 196*bf2c3715SXin Li * \implsparsesolverconcept 197*bf2c3715SXin Li * 198*bf2c3715SXin Li * \sa class DiagonalPreconditioner 199*bf2c3715SXin Li */ 200*bf2c3715SXin Li class IdentityPreconditioner 201*bf2c3715SXin Li { 202*bf2c3715SXin Li public: 203*bf2c3715SXin Li IdentityPreconditioner()204*bf2c3715SXin Li IdentityPreconditioner() {} 205*bf2c3715SXin Li 206*bf2c3715SXin Li template<typename MatrixType> IdentityPreconditioner(const MatrixType &)207*bf2c3715SXin Li explicit IdentityPreconditioner(const MatrixType& ) {} 208*bf2c3715SXin Li 209*bf2c3715SXin Li template<typename MatrixType> analyzePattern(const MatrixType &)210*bf2c3715SXin Li IdentityPreconditioner& analyzePattern(const MatrixType& ) { return *this; } 211*bf2c3715SXin Li 212*bf2c3715SXin Li template<typename MatrixType> factorize(const MatrixType &)213*bf2c3715SXin Li IdentityPreconditioner& factorize(const MatrixType& ) { return *this; } 214*bf2c3715SXin Li 215*bf2c3715SXin Li template<typename MatrixType> compute(const MatrixType &)216*bf2c3715SXin Li IdentityPreconditioner& compute(const MatrixType& ) { return *this; } 217*bf2c3715SXin Li 218*bf2c3715SXin Li template<typename Rhs> solve(const Rhs & b)219*bf2c3715SXin Li inline const Rhs& solve(const Rhs& b) const { return b; } 220*bf2c3715SXin Li info()221*bf2c3715SXin Li ComputationInfo info() { return Success; } 222*bf2c3715SXin Li }; 223*bf2c3715SXin Li 224*bf2c3715SXin Li } // end namespace Eigen 225*bf2c3715SXin Li 226*bf2c3715SXin Li #endif // EIGEN_BASIC_PRECONDITIONERS_H 227