BasicPreconditioners.h 6.6 KB
Newer Older
Don Gagne's avatar
Don Gagne committed
1 2 3
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
4
// Copyright (C) 2011-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
Don Gagne's avatar
Don Gagne committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef EIGEN_BASIC_PRECONDITIONERS_H
#define EIGEN_BASIC_PRECONDITIONERS_H

namespace Eigen { 

/** \ingroup IterativeLinearSolvers_Module
  * \brief A preconditioner based on the digonal entries
  *
  * This class allows to approximately solve for A.x = b problems assuming A is a diagonal matrix.
  * In other words, this preconditioner neglects all off diagonal entries and, in Eigen's language, solves for:
20 21 22
    \code
    A.diagonal().asDiagonal() . x = b
    \endcode
Don Gagne's avatar
Don Gagne committed
23 24 25
  *
  * \tparam _Scalar the type of the scalar.
  *
26 27
  * \implsparsesolverconcept
  *
Don Gagne's avatar
Don Gagne committed
28 29 30 31 32
  * This preconditioner is suitable for both selfadjoint and general problems.
  * The diagonal entries are pre-inverted and stored into a dense vector.
  *
  * \note A variant that has yet to be implemented would attempt to preserve the norm of each column.
  *
33
  * \sa class LeastSquareDiagonalPreconditioner, class ConjugateGradient
Don Gagne's avatar
Don Gagne committed
34 35 36 37 38 39 40
  */
template <typename _Scalar>
class DiagonalPreconditioner
{
    typedef _Scalar Scalar;
    typedef Matrix<Scalar,Dynamic,1> Vector;
  public:
41 42 43 44 45
    typedef typename Vector::StorageIndex StorageIndex;
    enum {
      ColsAtCompileTime = Dynamic,
      MaxColsAtCompileTime = Dynamic
    };
Don Gagne's avatar
Don Gagne committed
46 47 48 49

    DiagonalPreconditioner() : m_isInitialized(false) {}

    template<typename MatType>
50
    explicit DiagonalPreconditioner(const MatType& mat) : m_invdiag(mat.cols())
Don Gagne's avatar
Don Gagne committed
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
    {
      compute(mat);
    }

    Index rows() const { return m_invdiag.size(); }
    Index cols() const { return m_invdiag.size(); }
    
    template<typename MatType>
    DiagonalPreconditioner& analyzePattern(const MatType& )
    {
      return *this;
    }
    
    template<typename MatType>
    DiagonalPreconditioner& factorize(const MatType& mat)
    {
      m_invdiag.resize(mat.cols());
      for(int j=0; j<mat.outerSize(); ++j)
      {
        typename MatType::InnerIterator it(mat,j);
        while(it && it.index()!=j) ++it;
72
        if(it && it.index()==j && it.value()!=Scalar(0))
Don Gagne's avatar
Don Gagne committed
73 74
          m_invdiag(j) = Scalar(1)/it.value();
        else
75
          m_invdiag(j) = Scalar(1);
Don Gagne's avatar
Don Gagne committed
76 77 78 79 80 81 82 83 84 85 86
      }
      m_isInitialized = true;
      return *this;
    }
    
    template<typename MatType>
    DiagonalPreconditioner& compute(const MatType& mat)
    {
      return factorize(mat);
    }

87
    /** \internal */
Don Gagne's avatar
Don Gagne committed
88
    template<typename Rhs, typename Dest>
89
    void _solve_impl(const Rhs& b, Dest& x) const
Don Gagne's avatar
Don Gagne committed
90 91 92 93
    {
      x = m_invdiag.array() * b.array() ;
    }

94
    template<typename Rhs> inline const Solve<DiagonalPreconditioner, Rhs>
Don Gagne's avatar
Don Gagne committed
95 96 97 98 99
    solve(const MatrixBase<Rhs>& b) const
    {
      eigen_assert(m_isInitialized && "DiagonalPreconditioner is not initialized.");
      eigen_assert(m_invdiag.size()==b.rows()
                && "DiagonalPreconditioner::solve(): invalid number of rows of the right hand side matrix b");
100
      return Solve<DiagonalPreconditioner, Rhs>(*this, b.derived());
Don Gagne's avatar
Don Gagne committed
101
    }
102 103
    
    ComputationInfo info() { return Success; }
Don Gagne's avatar
Don Gagne committed
104 105 106 107 108 109

  protected:
    Vector m_invdiag;
    bool m_isInitialized;
};

110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
/** \ingroup IterativeLinearSolvers_Module
  * \brief Jacobi preconditioner for LeastSquaresConjugateGradient
  *
  * This class allows to approximately solve for A' A x  = A' b problems assuming A' A is a diagonal matrix.
  * In other words, this preconditioner neglects all off diagonal entries and, in Eigen's language, solves for:
    \code
    (A.adjoint() * A).diagonal().asDiagonal() * x = b
    \endcode
  *
  * \tparam _Scalar the type of the scalar.
  *
  * \implsparsesolverconcept
  *
  * The diagonal entries are pre-inverted and stored into a dense vector.
  * 
  * \sa class LeastSquaresConjugateGradient, class DiagonalPreconditioner
  */
template <typename _Scalar>
class LeastSquareDiagonalPreconditioner : public DiagonalPreconditioner<_Scalar>
Don Gagne's avatar
Don Gagne committed
129
{
130 131 132 133 134
    typedef _Scalar Scalar;
    typedef typename NumTraits<Scalar>::Real RealScalar;
    typedef DiagonalPreconditioner<_Scalar> Base;
    using Base::m_invdiag;
  public:
Don Gagne's avatar
Don Gagne committed
135

136
    LeastSquareDiagonalPreconditioner() : Base() {}
Don Gagne's avatar
Don Gagne committed
137

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
    template<typename MatType>
    explicit LeastSquareDiagonalPreconditioner(const MatType& mat) : Base()
    {
      compute(mat);
    }

    template<typename MatType>
    LeastSquareDiagonalPreconditioner& analyzePattern(const MatType& )
    {
      return *this;
    }
    
    template<typename MatType>
    LeastSquareDiagonalPreconditioner& factorize(const MatType& mat)
    {
      // Compute the inverse squared-norm of each column of mat
      m_invdiag.resize(mat.cols());
      if(MatType::IsRowMajor)
      {
        m_invdiag.setZero();
        for(Index j=0; j<mat.outerSize(); ++j)
        {
          for(typename MatType::InnerIterator it(mat,j); it; ++it)
            m_invdiag(it.index()) += numext::abs2(it.value());
        }
        for(Index j=0; j<mat.cols(); ++j)
          if(numext::real(m_invdiag(j))>RealScalar(0))
            m_invdiag(j) = RealScalar(1)/numext::real(m_invdiag(j));
      }
      else
      {
        for(Index j=0; j<mat.outerSize(); ++j)
        {
          RealScalar sum = mat.col(j).squaredNorm();
          if(sum>RealScalar(0))
            m_invdiag(j) = RealScalar(1)/sum;
          else
            m_invdiag(j) = RealScalar(1);
        }
      }
      Base::m_isInitialized = true;
      return *this;
    }
    
    template<typename MatType>
    LeastSquareDiagonalPreconditioner& compute(const MatType& mat)
    {
      return factorize(mat);
    }
    
    ComputationInfo info() { return Success; }

  protected:
};
Don Gagne's avatar
Don Gagne committed
192 193 194 195

/** \ingroup IterativeLinearSolvers_Module
  * \brief A naive preconditioner which approximates any matrix as the identity matrix
  *
196 197
  * \implsparsesolverconcept
  *
Don Gagne's avatar
Don Gagne committed
198 199 200 201 202 203 204 205 206
  * \sa class DiagonalPreconditioner
  */
class IdentityPreconditioner
{
  public:

    IdentityPreconditioner() {}

    template<typename MatrixType>
207
    explicit IdentityPreconditioner(const MatrixType& ) {}
Don Gagne's avatar
Don Gagne committed
208 209 210 211 212 213 214 215 216 217 218 219
    
    template<typename MatrixType>
    IdentityPreconditioner& analyzePattern(const MatrixType& ) { return *this; }
    
    template<typename MatrixType>
    IdentityPreconditioner& factorize(const MatrixType& ) { return *this; }

    template<typename MatrixType>
    IdentityPreconditioner& compute(const MatrixType& ) { return *this; }
    
    template<typename Rhs>
    inline const Rhs& solve(const Rhs& b) const { return b; }
220 221
    
    ComputationInfo info() { return Success; }
Don Gagne's avatar
Don Gagne committed
222 223 224 225 226
};

} // end namespace Eigen

#endif // EIGEN_BASIC_PRECONDITIONERS_H