xref: /aosp_15_r20/external/eigen/Eigen/src/SparseCholesky/SimplicialCholesky.h (revision bf2c37156dfe67e5dfebd6d394bad8b2ab5804d4)
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) 2008-2012 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_SIMPLICIAL_CHOLESKY_H
11*bf2c3715SXin Li #define EIGEN_SIMPLICIAL_CHOLESKY_H
12*bf2c3715SXin Li 
13*bf2c3715SXin Li namespace Eigen {
14*bf2c3715SXin Li 
15*bf2c3715SXin Li enum SimplicialCholeskyMode {
16*bf2c3715SXin Li   SimplicialCholeskyLLT,
17*bf2c3715SXin Li   SimplicialCholeskyLDLT
18*bf2c3715SXin Li };
19*bf2c3715SXin Li 
20*bf2c3715SXin Li namespace internal {
21*bf2c3715SXin Li   template<typename CholMatrixType, typename InputMatrixType>
22*bf2c3715SXin Li   struct simplicial_cholesky_grab_input {
23*bf2c3715SXin Li     typedef CholMatrixType const * ConstCholMatrixPtr;
runsimplicial_cholesky_grab_input24*bf2c3715SXin Li     static void run(const InputMatrixType& input, ConstCholMatrixPtr &pmat, CholMatrixType &tmp)
25*bf2c3715SXin Li     {
26*bf2c3715SXin Li       tmp = input;
27*bf2c3715SXin Li       pmat = &tmp;
28*bf2c3715SXin Li     }
29*bf2c3715SXin Li   };
30*bf2c3715SXin Li 
31*bf2c3715SXin Li   template<typename MatrixType>
32*bf2c3715SXin Li   struct simplicial_cholesky_grab_input<MatrixType,MatrixType> {
33*bf2c3715SXin Li     typedef MatrixType const * ConstMatrixPtr;
34*bf2c3715SXin Li     static void run(const MatrixType& input, ConstMatrixPtr &pmat, MatrixType &/*tmp*/)
35*bf2c3715SXin Li     {
36*bf2c3715SXin Li       pmat = &input;
37*bf2c3715SXin Li     }
38*bf2c3715SXin Li   };
39*bf2c3715SXin Li } // end namespace internal
40*bf2c3715SXin Li 
41*bf2c3715SXin Li /** \ingroup SparseCholesky_Module
42*bf2c3715SXin Li   * \brief A base class for direct sparse Cholesky factorizations
43*bf2c3715SXin Li   *
44*bf2c3715SXin Li   * This is a base class for LL^T and LDL^T Cholesky factorizations of sparse matrices that are
45*bf2c3715SXin Li   * selfadjoint and positive definite. These factorizations allow for solving A.X = B where
46*bf2c3715SXin Li   * X and B can be either dense or sparse.
47*bf2c3715SXin Li   *
48*bf2c3715SXin Li   * In order to reduce the fill-in, a symmetric permutation P is applied prior to the factorization
49*bf2c3715SXin Li   * such that the factorized matrix is P A P^-1.
50*bf2c3715SXin Li   *
51*bf2c3715SXin Li   * \tparam Derived the type of the derived class, that is the actual factorization type.
52*bf2c3715SXin Li   *
53*bf2c3715SXin Li   */
54*bf2c3715SXin Li template<typename Derived>
55*bf2c3715SXin Li class SimplicialCholeskyBase : public SparseSolverBase<Derived>
56*bf2c3715SXin Li {
57*bf2c3715SXin Li     typedef SparseSolverBase<Derived> Base;
58*bf2c3715SXin Li     using Base::m_isInitialized;
59*bf2c3715SXin Li 
60*bf2c3715SXin Li   public:
61*bf2c3715SXin Li     typedef typename internal::traits<Derived>::MatrixType MatrixType;
62*bf2c3715SXin Li     typedef typename internal::traits<Derived>::OrderingType OrderingType;
63*bf2c3715SXin Li     enum { UpLo = internal::traits<Derived>::UpLo };
64*bf2c3715SXin Li     typedef typename MatrixType::Scalar Scalar;
65*bf2c3715SXin Li     typedef typename MatrixType::RealScalar RealScalar;
66*bf2c3715SXin Li     typedef typename MatrixType::StorageIndex StorageIndex;
67*bf2c3715SXin Li     typedef SparseMatrix<Scalar,ColMajor,StorageIndex> CholMatrixType;
68*bf2c3715SXin Li     typedef CholMatrixType const * ConstCholMatrixPtr;
69*bf2c3715SXin Li     typedef Matrix<Scalar,Dynamic,1> VectorType;
70*bf2c3715SXin Li     typedef Matrix<StorageIndex,Dynamic,1> VectorI;
71*bf2c3715SXin Li 
72*bf2c3715SXin Li     enum {
73*bf2c3715SXin Li       ColsAtCompileTime = MatrixType::ColsAtCompileTime,
74*bf2c3715SXin Li       MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
75*bf2c3715SXin Li     };
76*bf2c3715SXin Li 
77*bf2c3715SXin Li   public:
78*bf2c3715SXin Li 
79*bf2c3715SXin Li     using Base::derived;
80*bf2c3715SXin Li 
81*bf2c3715SXin Li     /** Default constructor */
82*bf2c3715SXin Li     SimplicialCholeskyBase()
83*bf2c3715SXin Li       : m_info(Success),
84*bf2c3715SXin Li         m_factorizationIsOk(false),
85*bf2c3715SXin Li         m_analysisIsOk(false),
86*bf2c3715SXin Li         m_shiftOffset(0),
87*bf2c3715SXin Li         m_shiftScale(1)
88*bf2c3715SXin Li     {}
89*bf2c3715SXin Li 
90*bf2c3715SXin Li     explicit SimplicialCholeskyBase(const MatrixType& matrix)
91*bf2c3715SXin Li       : m_info(Success),
92*bf2c3715SXin Li         m_factorizationIsOk(false),
93*bf2c3715SXin Li         m_analysisIsOk(false),
94*bf2c3715SXin Li         m_shiftOffset(0),
95*bf2c3715SXin Li         m_shiftScale(1)
96*bf2c3715SXin Li     {
97*bf2c3715SXin Li       derived().compute(matrix);
98*bf2c3715SXin Li     }
99*bf2c3715SXin Li 
100*bf2c3715SXin Li     ~SimplicialCholeskyBase()
101*bf2c3715SXin Li     {
102*bf2c3715SXin Li     }
103*bf2c3715SXin Li 
104*bf2c3715SXin Li     Derived& derived() { return *static_cast<Derived*>(this); }
105*bf2c3715SXin Li     const Derived& derived() const { return *static_cast<const Derived*>(this); }
106*bf2c3715SXin Li 
107*bf2c3715SXin Li     inline Index cols() const { return m_matrix.cols(); }
108*bf2c3715SXin Li     inline Index rows() const { return m_matrix.rows(); }
109*bf2c3715SXin Li 
110*bf2c3715SXin Li     /** \brief Reports whether previous computation was successful.
111*bf2c3715SXin Li       *
112*bf2c3715SXin Li       * \returns \c Success if computation was successful,
113*bf2c3715SXin Li       *          \c NumericalIssue if the matrix.appears to be negative.
114*bf2c3715SXin Li       */
115*bf2c3715SXin Li     ComputationInfo info() const
116*bf2c3715SXin Li     {
117*bf2c3715SXin Li       eigen_assert(m_isInitialized && "Decomposition is not initialized.");
118*bf2c3715SXin Li       return m_info;
119*bf2c3715SXin Li     }
120*bf2c3715SXin Li 
121*bf2c3715SXin Li     /** \returns the permutation P
122*bf2c3715SXin Li       * \sa permutationPinv() */
123*bf2c3715SXin Li     const PermutationMatrix<Dynamic,Dynamic,StorageIndex>& permutationP() const
124*bf2c3715SXin Li     { return m_P; }
125*bf2c3715SXin Li 
126*bf2c3715SXin Li     /** \returns the inverse P^-1 of the permutation P
127*bf2c3715SXin Li       * \sa permutationP() */
128*bf2c3715SXin Li     const PermutationMatrix<Dynamic,Dynamic,StorageIndex>& permutationPinv() const
129*bf2c3715SXin Li     { return m_Pinv; }
130*bf2c3715SXin Li 
131*bf2c3715SXin Li     /** Sets the shift parameters that will be used to adjust the diagonal coefficients during the numerical factorization.
132*bf2c3715SXin Li       *
133*bf2c3715SXin Li       * During the numerical factorization, the diagonal coefficients are transformed by the following linear model:\n
134*bf2c3715SXin Li       * \c d_ii = \a offset + \a scale * \c d_ii
135*bf2c3715SXin Li       *
136*bf2c3715SXin Li       * The default is the identity transformation with \a offset=0, and \a scale=1.
137*bf2c3715SXin Li       *
138*bf2c3715SXin Li       * \returns a reference to \c *this.
139*bf2c3715SXin Li       */
140*bf2c3715SXin Li     Derived& setShift(const RealScalar& offset, const RealScalar& scale = 1)
141*bf2c3715SXin Li     {
142*bf2c3715SXin Li       m_shiftOffset = offset;
143*bf2c3715SXin Li       m_shiftScale = scale;
144*bf2c3715SXin Li       return derived();
145*bf2c3715SXin Li     }
146*bf2c3715SXin Li 
147*bf2c3715SXin Li #ifndef EIGEN_PARSED_BY_DOXYGEN
148*bf2c3715SXin Li     /** \internal */
149*bf2c3715SXin Li     template<typename Stream>
150*bf2c3715SXin Li     void dumpMemory(Stream& s)
151*bf2c3715SXin Li     {
152*bf2c3715SXin Li       int total = 0;
153*bf2c3715SXin Li       s << "  L:        " << ((total+=(m_matrix.cols()+1) * sizeof(int) + m_matrix.nonZeros()*(sizeof(int)+sizeof(Scalar))) >> 20) << "Mb" << "\n";
154*bf2c3715SXin Li       s << "  diag:     " << ((total+=m_diag.size() * sizeof(Scalar)) >> 20) << "Mb" << "\n";
155*bf2c3715SXin Li       s << "  tree:     " << ((total+=m_parent.size() * sizeof(int)) >> 20) << "Mb" << "\n";
156*bf2c3715SXin Li       s << "  nonzeros: " << ((total+=m_nonZerosPerCol.size() * sizeof(int)) >> 20) << "Mb" << "\n";
157*bf2c3715SXin Li       s << "  perm:     " << ((total+=m_P.size() * sizeof(int)) >> 20) << "Mb" << "\n";
158*bf2c3715SXin Li       s << "  perm^-1:  " << ((total+=m_Pinv.size() * sizeof(int)) >> 20) << "Mb" << "\n";
159*bf2c3715SXin Li       s << "  TOTAL:    " << (total>> 20) << "Mb" << "\n";
160*bf2c3715SXin Li     }
161*bf2c3715SXin Li 
162*bf2c3715SXin Li     /** \internal */
163*bf2c3715SXin Li     template<typename Rhs,typename Dest>
164*bf2c3715SXin Li     void _solve_impl(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const
165*bf2c3715SXin Li     {
166*bf2c3715SXin Li       eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
167*bf2c3715SXin Li       eigen_assert(m_matrix.rows()==b.rows());
168*bf2c3715SXin Li 
169*bf2c3715SXin Li       if(m_info!=Success)
170*bf2c3715SXin Li         return;
171*bf2c3715SXin Li 
172*bf2c3715SXin Li       if(m_P.size()>0)
173*bf2c3715SXin Li         dest = m_P * b;
174*bf2c3715SXin Li       else
175*bf2c3715SXin Li         dest = b;
176*bf2c3715SXin Li 
177*bf2c3715SXin Li       if(m_matrix.nonZeros()>0) // otherwise L==I
178*bf2c3715SXin Li         derived().matrixL().solveInPlace(dest);
179*bf2c3715SXin Li 
180*bf2c3715SXin Li       if(m_diag.size()>0)
181*bf2c3715SXin Li         dest = m_diag.asDiagonal().inverse() * dest;
182*bf2c3715SXin Li 
183*bf2c3715SXin Li       if (m_matrix.nonZeros()>0) // otherwise U==I
184*bf2c3715SXin Li         derived().matrixU().solveInPlace(dest);
185*bf2c3715SXin Li 
186*bf2c3715SXin Li       if(m_P.size()>0)
187*bf2c3715SXin Li         dest = m_Pinv * dest;
188*bf2c3715SXin Li     }
189*bf2c3715SXin Li 
190*bf2c3715SXin Li     template<typename Rhs,typename Dest>
191*bf2c3715SXin Li     void _solve_impl(const SparseMatrixBase<Rhs> &b, SparseMatrixBase<Dest> &dest) const
192*bf2c3715SXin Li     {
193*bf2c3715SXin Li       internal::solve_sparse_through_dense_panels(derived(), b, dest);
194*bf2c3715SXin Li     }
195*bf2c3715SXin Li 
196*bf2c3715SXin Li #endif // EIGEN_PARSED_BY_DOXYGEN
197*bf2c3715SXin Li 
198*bf2c3715SXin Li   protected:
199*bf2c3715SXin Li 
200*bf2c3715SXin Li     /** Computes the sparse Cholesky decomposition of \a matrix */
201*bf2c3715SXin Li     template<bool DoLDLT>
202*bf2c3715SXin Li     void compute(const MatrixType& matrix)
203*bf2c3715SXin Li     {
204*bf2c3715SXin Li       eigen_assert(matrix.rows()==matrix.cols());
205*bf2c3715SXin Li       Index size = matrix.cols();
206*bf2c3715SXin Li       CholMatrixType tmp(size,size);
207*bf2c3715SXin Li       ConstCholMatrixPtr pmat;
208*bf2c3715SXin Li       ordering(matrix, pmat, tmp);
209*bf2c3715SXin Li       analyzePattern_preordered(*pmat, DoLDLT);
210*bf2c3715SXin Li       factorize_preordered<DoLDLT>(*pmat);
211*bf2c3715SXin Li     }
212*bf2c3715SXin Li 
213*bf2c3715SXin Li     template<bool DoLDLT>
214*bf2c3715SXin Li     void factorize(const MatrixType& a)
215*bf2c3715SXin Li     {
216*bf2c3715SXin Li       eigen_assert(a.rows()==a.cols());
217*bf2c3715SXin Li       Index size = a.cols();
218*bf2c3715SXin Li       CholMatrixType tmp(size,size);
219*bf2c3715SXin Li       ConstCholMatrixPtr pmat;
220*bf2c3715SXin Li 
221*bf2c3715SXin Li       if(m_P.size() == 0 && (int(UpLo) & int(Upper)) == Upper)
222*bf2c3715SXin Li       {
223*bf2c3715SXin Li         // If there is no ordering, try to directly use the input matrix without any copy
224*bf2c3715SXin Li         internal::simplicial_cholesky_grab_input<CholMatrixType,MatrixType>::run(a, pmat, tmp);
225*bf2c3715SXin Li       }
226*bf2c3715SXin Li       else
227*bf2c3715SXin Li       {
228*bf2c3715SXin Li         tmp.template selfadjointView<Upper>() = a.template selfadjointView<UpLo>().twistedBy(m_P);
229*bf2c3715SXin Li         pmat = &tmp;
230*bf2c3715SXin Li       }
231*bf2c3715SXin Li 
232*bf2c3715SXin Li       factorize_preordered<DoLDLT>(*pmat);
233*bf2c3715SXin Li     }
234*bf2c3715SXin Li 
235*bf2c3715SXin Li     template<bool DoLDLT>
236*bf2c3715SXin Li     void factorize_preordered(const CholMatrixType& a);
237*bf2c3715SXin Li 
238*bf2c3715SXin Li     void analyzePattern(const MatrixType& a, bool doLDLT)
239*bf2c3715SXin Li     {
240*bf2c3715SXin Li       eigen_assert(a.rows()==a.cols());
241*bf2c3715SXin Li       Index size = a.cols();
242*bf2c3715SXin Li       CholMatrixType tmp(size,size);
243*bf2c3715SXin Li       ConstCholMatrixPtr pmat;
244*bf2c3715SXin Li       ordering(a, pmat, tmp);
245*bf2c3715SXin Li       analyzePattern_preordered(*pmat,doLDLT);
246*bf2c3715SXin Li     }
247*bf2c3715SXin Li     void analyzePattern_preordered(const CholMatrixType& a, bool doLDLT);
248*bf2c3715SXin Li 
249*bf2c3715SXin Li     void ordering(const MatrixType& a, ConstCholMatrixPtr &pmat, CholMatrixType& ap);
250*bf2c3715SXin Li 
251*bf2c3715SXin Li     /** keeps off-diagonal entries; drops diagonal entries */
252*bf2c3715SXin Li     struct keep_diag {
253*bf2c3715SXin Li       inline bool operator() (const Index& row, const Index& col, const Scalar&) const
254*bf2c3715SXin Li       {
255*bf2c3715SXin Li         return row!=col;
256*bf2c3715SXin Li       }
257*bf2c3715SXin Li     };
258*bf2c3715SXin Li 
259*bf2c3715SXin Li     mutable ComputationInfo m_info;
260*bf2c3715SXin Li     bool m_factorizationIsOk;
261*bf2c3715SXin Li     bool m_analysisIsOk;
262*bf2c3715SXin Li 
263*bf2c3715SXin Li     CholMatrixType m_matrix;
264*bf2c3715SXin Li     VectorType m_diag;                                // the diagonal coefficients (LDLT mode)
265*bf2c3715SXin Li     VectorI m_parent;                                 // elimination tree
266*bf2c3715SXin Li     VectorI m_nonZerosPerCol;
267*bf2c3715SXin Li     PermutationMatrix<Dynamic,Dynamic,StorageIndex> m_P;     // the permutation
268*bf2c3715SXin Li     PermutationMatrix<Dynamic,Dynamic,StorageIndex> m_Pinv;  // the inverse permutation
269*bf2c3715SXin Li 
270*bf2c3715SXin Li     RealScalar m_shiftOffset;
271*bf2c3715SXin Li     RealScalar m_shiftScale;
272*bf2c3715SXin Li };
273*bf2c3715SXin Li 
274*bf2c3715SXin Li template<typename _MatrixType, int _UpLo = Lower, typename _Ordering = AMDOrdering<typename _MatrixType::StorageIndex> > class SimplicialLLT;
275*bf2c3715SXin Li template<typename _MatrixType, int _UpLo = Lower, typename _Ordering = AMDOrdering<typename _MatrixType::StorageIndex> > class SimplicialLDLT;
276*bf2c3715SXin Li template<typename _MatrixType, int _UpLo = Lower, typename _Ordering = AMDOrdering<typename _MatrixType::StorageIndex> > class SimplicialCholesky;
277*bf2c3715SXin Li 
278*bf2c3715SXin Li namespace internal {
279*bf2c3715SXin Li 
280*bf2c3715SXin Li template<typename _MatrixType, int _UpLo, typename _Ordering> struct traits<SimplicialLLT<_MatrixType,_UpLo,_Ordering> >
281*bf2c3715SXin Li {
282*bf2c3715SXin Li   typedef _MatrixType MatrixType;
283*bf2c3715SXin Li   typedef _Ordering OrderingType;
284*bf2c3715SXin Li   enum { UpLo = _UpLo };
285*bf2c3715SXin Li   typedef typename MatrixType::Scalar                         Scalar;
286*bf2c3715SXin Li   typedef typename MatrixType::StorageIndex                   StorageIndex;
287*bf2c3715SXin Li   typedef SparseMatrix<Scalar, ColMajor, StorageIndex>        CholMatrixType;
288*bf2c3715SXin Li   typedef TriangularView<const CholMatrixType, Eigen::Lower>  MatrixL;
289*bf2c3715SXin Li   typedef TriangularView<const typename CholMatrixType::AdjointReturnType, Eigen::Upper>   MatrixU;
290*bf2c3715SXin Li   static inline MatrixL getL(const CholMatrixType& m) { return MatrixL(m); }
291*bf2c3715SXin Li   static inline MatrixU getU(const CholMatrixType& m) { return MatrixU(m.adjoint()); }
292*bf2c3715SXin Li };
293*bf2c3715SXin Li 
294*bf2c3715SXin Li template<typename _MatrixType,int _UpLo, typename _Ordering> struct traits<SimplicialLDLT<_MatrixType,_UpLo,_Ordering> >
295*bf2c3715SXin Li {
296*bf2c3715SXin Li   typedef _MatrixType MatrixType;
297*bf2c3715SXin Li   typedef _Ordering OrderingType;
298*bf2c3715SXin Li   enum { UpLo = _UpLo };
299*bf2c3715SXin Li   typedef typename MatrixType::Scalar                             Scalar;
300*bf2c3715SXin Li   typedef typename MatrixType::StorageIndex                       StorageIndex;
301*bf2c3715SXin Li   typedef SparseMatrix<Scalar, ColMajor, StorageIndex>            CholMatrixType;
302*bf2c3715SXin Li   typedef TriangularView<const CholMatrixType, Eigen::UnitLower>  MatrixL;
303*bf2c3715SXin Li   typedef TriangularView<const typename CholMatrixType::AdjointReturnType, Eigen::UnitUpper> MatrixU;
304*bf2c3715SXin Li   static inline MatrixL getL(const CholMatrixType& m) { return MatrixL(m); }
305*bf2c3715SXin Li   static inline MatrixU getU(const CholMatrixType& m) { return MatrixU(m.adjoint()); }
306*bf2c3715SXin Li };
307*bf2c3715SXin Li 
308*bf2c3715SXin Li template<typename _MatrixType, int _UpLo, typename _Ordering> struct traits<SimplicialCholesky<_MatrixType,_UpLo,_Ordering> >
309*bf2c3715SXin Li {
310*bf2c3715SXin Li   typedef _MatrixType MatrixType;
311*bf2c3715SXin Li   typedef _Ordering OrderingType;
312*bf2c3715SXin Li   enum { UpLo = _UpLo };
313*bf2c3715SXin Li };
314*bf2c3715SXin Li 
315*bf2c3715SXin Li }
316*bf2c3715SXin Li 
317*bf2c3715SXin Li /** \ingroup SparseCholesky_Module
318*bf2c3715SXin Li   * \class SimplicialLLT
319*bf2c3715SXin Li   * \brief A direct sparse LLT Cholesky factorizations
320*bf2c3715SXin Li   *
321*bf2c3715SXin Li   * This class provides a LL^T Cholesky factorizations of sparse matrices that are
322*bf2c3715SXin Li   * selfadjoint and positive definite. The factorization allows for solving A.X = B where
323*bf2c3715SXin Li   * X and B can be either dense or sparse.
324*bf2c3715SXin Li   *
325*bf2c3715SXin Li   * In order to reduce the fill-in, a symmetric permutation P is applied prior to the factorization
326*bf2c3715SXin Li   * such that the factorized matrix is P A P^-1.
327*bf2c3715SXin Li   *
328*bf2c3715SXin Li   * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
329*bf2c3715SXin Li   * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
330*bf2c3715SXin Li   *               or Upper. Default is Lower.
331*bf2c3715SXin Li   * \tparam _Ordering The ordering method to use, either AMDOrdering<> or NaturalOrdering<>. Default is AMDOrdering<>
332*bf2c3715SXin Li   *
333*bf2c3715SXin Li   * \implsparsesolverconcept
334*bf2c3715SXin Li   *
335*bf2c3715SXin Li   * \sa class SimplicialLDLT, class AMDOrdering, class NaturalOrdering
336*bf2c3715SXin Li   */
337*bf2c3715SXin Li template<typename _MatrixType, int _UpLo, typename _Ordering>
338*bf2c3715SXin Li     class SimplicialLLT : public SimplicialCholeskyBase<SimplicialLLT<_MatrixType,_UpLo,_Ordering> >
339*bf2c3715SXin Li {
340*bf2c3715SXin Li public:
341*bf2c3715SXin Li     typedef _MatrixType MatrixType;
342*bf2c3715SXin Li     enum { UpLo = _UpLo };
343*bf2c3715SXin Li     typedef SimplicialCholeskyBase<SimplicialLLT> Base;
344*bf2c3715SXin Li     typedef typename MatrixType::Scalar Scalar;
345*bf2c3715SXin Li     typedef typename MatrixType::RealScalar RealScalar;
346*bf2c3715SXin Li     typedef typename MatrixType::StorageIndex StorageIndex;
347*bf2c3715SXin Li     typedef SparseMatrix<Scalar,ColMajor,Index> CholMatrixType;
348*bf2c3715SXin Li     typedef Matrix<Scalar,Dynamic,1> VectorType;
349*bf2c3715SXin Li     typedef internal::traits<SimplicialLLT> Traits;
350*bf2c3715SXin Li     typedef typename Traits::MatrixL  MatrixL;
351*bf2c3715SXin Li     typedef typename Traits::MatrixU  MatrixU;
352*bf2c3715SXin Li public:
353*bf2c3715SXin Li     /** Default constructor */
354*bf2c3715SXin Li     SimplicialLLT() : Base() {}
355*bf2c3715SXin Li     /** Constructs and performs the LLT factorization of \a matrix */
356*bf2c3715SXin Li     explicit SimplicialLLT(const MatrixType& matrix)
357*bf2c3715SXin Li         : Base(matrix) {}
358*bf2c3715SXin Li 
359*bf2c3715SXin Li     /** \returns an expression of the factor L */
360*bf2c3715SXin Li     inline const MatrixL matrixL() const {
361*bf2c3715SXin Li         eigen_assert(Base::m_factorizationIsOk && "Simplicial LLT not factorized");
362*bf2c3715SXin Li         return Traits::getL(Base::m_matrix);
363*bf2c3715SXin Li     }
364*bf2c3715SXin Li 
365*bf2c3715SXin Li     /** \returns an expression of the factor U (= L^*) */
366*bf2c3715SXin Li     inline const MatrixU matrixU() const {
367*bf2c3715SXin Li         eigen_assert(Base::m_factorizationIsOk && "Simplicial LLT not factorized");
368*bf2c3715SXin Li         return Traits::getU(Base::m_matrix);
369*bf2c3715SXin Li     }
370*bf2c3715SXin Li 
371*bf2c3715SXin Li     /** Computes the sparse Cholesky decomposition of \a matrix */
372*bf2c3715SXin Li     SimplicialLLT& compute(const MatrixType& matrix)
373*bf2c3715SXin Li     {
374*bf2c3715SXin Li       Base::template compute<false>(matrix);
375*bf2c3715SXin Li       return *this;
376*bf2c3715SXin Li     }
377*bf2c3715SXin Li 
378*bf2c3715SXin Li     /** Performs a symbolic decomposition on the sparcity of \a matrix.
379*bf2c3715SXin Li       *
380*bf2c3715SXin Li       * This function is particularly useful when solving for several problems having the same structure.
381*bf2c3715SXin Li       *
382*bf2c3715SXin Li       * \sa factorize()
383*bf2c3715SXin Li       */
384*bf2c3715SXin Li     void analyzePattern(const MatrixType& a)
385*bf2c3715SXin Li     {
386*bf2c3715SXin Li       Base::analyzePattern(a, false);
387*bf2c3715SXin Li     }
388*bf2c3715SXin Li 
389*bf2c3715SXin Li     /** Performs a numeric decomposition of \a matrix
390*bf2c3715SXin Li       *
391*bf2c3715SXin Li       * The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed.
392*bf2c3715SXin Li       *
393*bf2c3715SXin Li       * \sa analyzePattern()
394*bf2c3715SXin Li       */
395*bf2c3715SXin Li     void factorize(const MatrixType& a)
396*bf2c3715SXin Li     {
397*bf2c3715SXin Li       Base::template factorize<false>(a);
398*bf2c3715SXin Li     }
399*bf2c3715SXin Li 
400*bf2c3715SXin Li     /** \returns the determinant of the underlying matrix from the current factorization */
401*bf2c3715SXin Li     Scalar determinant() const
402*bf2c3715SXin Li     {
403*bf2c3715SXin Li       Scalar detL = Base::m_matrix.diagonal().prod();
404*bf2c3715SXin Li       return numext::abs2(detL);
405*bf2c3715SXin Li     }
406*bf2c3715SXin Li };
407*bf2c3715SXin Li 
408*bf2c3715SXin Li /** \ingroup SparseCholesky_Module
409*bf2c3715SXin Li   * \class SimplicialLDLT
410*bf2c3715SXin Li   * \brief A direct sparse LDLT Cholesky factorizations without square root.
411*bf2c3715SXin Li   *
412*bf2c3715SXin Li   * This class provides a LDL^T Cholesky factorizations without square root of sparse matrices that are
413*bf2c3715SXin Li   * selfadjoint and positive definite. The factorization allows for solving A.X = B where
414*bf2c3715SXin Li   * X and B can be either dense or sparse.
415*bf2c3715SXin Li   *
416*bf2c3715SXin Li   * In order to reduce the fill-in, a symmetric permutation P is applied prior to the factorization
417*bf2c3715SXin Li   * such that the factorized matrix is P A P^-1.
418*bf2c3715SXin Li   *
419*bf2c3715SXin Li   * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
420*bf2c3715SXin Li   * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
421*bf2c3715SXin Li   *               or Upper. Default is Lower.
422*bf2c3715SXin Li   * \tparam _Ordering The ordering method to use, either AMDOrdering<> or NaturalOrdering<>. Default is AMDOrdering<>
423*bf2c3715SXin Li   *
424*bf2c3715SXin Li   * \implsparsesolverconcept
425*bf2c3715SXin Li   *
426*bf2c3715SXin Li   * \sa class SimplicialLLT, class AMDOrdering, class NaturalOrdering
427*bf2c3715SXin Li   */
428*bf2c3715SXin Li template<typename _MatrixType, int _UpLo, typename _Ordering>
429*bf2c3715SXin Li     class SimplicialLDLT : public SimplicialCholeskyBase<SimplicialLDLT<_MatrixType,_UpLo,_Ordering> >
430*bf2c3715SXin Li {
431*bf2c3715SXin Li public:
432*bf2c3715SXin Li     typedef _MatrixType MatrixType;
433*bf2c3715SXin Li     enum { UpLo = _UpLo };
434*bf2c3715SXin Li     typedef SimplicialCholeskyBase<SimplicialLDLT> Base;
435*bf2c3715SXin Li     typedef typename MatrixType::Scalar Scalar;
436*bf2c3715SXin Li     typedef typename MatrixType::RealScalar RealScalar;
437*bf2c3715SXin Li     typedef typename MatrixType::StorageIndex StorageIndex;
438*bf2c3715SXin Li     typedef SparseMatrix<Scalar,ColMajor,StorageIndex> CholMatrixType;
439*bf2c3715SXin Li     typedef Matrix<Scalar,Dynamic,1> VectorType;
440*bf2c3715SXin Li     typedef internal::traits<SimplicialLDLT> Traits;
441*bf2c3715SXin Li     typedef typename Traits::MatrixL  MatrixL;
442*bf2c3715SXin Li     typedef typename Traits::MatrixU  MatrixU;
443*bf2c3715SXin Li public:
444*bf2c3715SXin Li     /** Default constructor */
445*bf2c3715SXin Li     SimplicialLDLT() : Base() {}
446*bf2c3715SXin Li 
447*bf2c3715SXin Li     /** Constructs and performs the LLT factorization of \a matrix */
448*bf2c3715SXin Li     explicit SimplicialLDLT(const MatrixType& matrix)
449*bf2c3715SXin Li         : Base(matrix) {}
450*bf2c3715SXin Li 
451*bf2c3715SXin Li     /** \returns a vector expression of the diagonal D */
452*bf2c3715SXin Li     inline const VectorType vectorD() const {
453*bf2c3715SXin Li         eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized");
454*bf2c3715SXin Li         return Base::m_diag;
455*bf2c3715SXin Li     }
456*bf2c3715SXin Li     /** \returns an expression of the factor L */
457*bf2c3715SXin Li     inline const MatrixL matrixL() const {
458*bf2c3715SXin Li         eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized");
459*bf2c3715SXin Li         return Traits::getL(Base::m_matrix);
460*bf2c3715SXin Li     }
461*bf2c3715SXin Li 
462*bf2c3715SXin Li     /** \returns an expression of the factor U (= L^*) */
463*bf2c3715SXin Li     inline const MatrixU matrixU() const {
464*bf2c3715SXin Li         eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized");
465*bf2c3715SXin Li         return Traits::getU(Base::m_matrix);
466*bf2c3715SXin Li     }
467*bf2c3715SXin Li 
468*bf2c3715SXin Li     /** Computes the sparse Cholesky decomposition of \a matrix */
469*bf2c3715SXin Li     SimplicialLDLT& compute(const MatrixType& matrix)
470*bf2c3715SXin Li     {
471*bf2c3715SXin Li       Base::template compute<true>(matrix);
472*bf2c3715SXin Li       return *this;
473*bf2c3715SXin Li     }
474*bf2c3715SXin Li 
475*bf2c3715SXin Li     /** Performs a symbolic decomposition on the sparcity of \a matrix.
476*bf2c3715SXin Li       *
477*bf2c3715SXin Li       * This function is particularly useful when solving for several problems having the same structure.
478*bf2c3715SXin Li       *
479*bf2c3715SXin Li       * \sa factorize()
480*bf2c3715SXin Li       */
481*bf2c3715SXin Li     void analyzePattern(const MatrixType& a)
482*bf2c3715SXin Li     {
483*bf2c3715SXin Li       Base::analyzePattern(a, true);
484*bf2c3715SXin Li     }
485*bf2c3715SXin Li 
486*bf2c3715SXin Li     /** Performs a numeric decomposition of \a matrix
487*bf2c3715SXin Li       *
488*bf2c3715SXin Li       * The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed.
489*bf2c3715SXin Li       *
490*bf2c3715SXin Li       * \sa analyzePattern()
491*bf2c3715SXin Li       */
492*bf2c3715SXin Li     void factorize(const MatrixType& a)
493*bf2c3715SXin Li     {
494*bf2c3715SXin Li       Base::template factorize<true>(a);
495*bf2c3715SXin Li     }
496*bf2c3715SXin Li 
497*bf2c3715SXin Li     /** \returns the determinant of the underlying matrix from the current factorization */
498*bf2c3715SXin Li     Scalar determinant() const
499*bf2c3715SXin Li     {
500*bf2c3715SXin Li       return Base::m_diag.prod();
501*bf2c3715SXin Li     }
502*bf2c3715SXin Li };
503*bf2c3715SXin Li 
504*bf2c3715SXin Li /** \deprecated use SimplicialLDLT or class SimplicialLLT
505*bf2c3715SXin Li   * \ingroup SparseCholesky_Module
506*bf2c3715SXin Li   * \class SimplicialCholesky
507*bf2c3715SXin Li   *
508*bf2c3715SXin Li   * \sa class SimplicialLDLT, class SimplicialLLT
509*bf2c3715SXin Li   */
510*bf2c3715SXin Li template<typename _MatrixType, int _UpLo, typename _Ordering>
511*bf2c3715SXin Li     class SimplicialCholesky : public SimplicialCholeskyBase<SimplicialCholesky<_MatrixType,_UpLo,_Ordering> >
512*bf2c3715SXin Li {
513*bf2c3715SXin Li public:
514*bf2c3715SXin Li     typedef _MatrixType MatrixType;
515*bf2c3715SXin Li     enum { UpLo = _UpLo };
516*bf2c3715SXin Li     typedef SimplicialCholeskyBase<SimplicialCholesky> Base;
517*bf2c3715SXin Li     typedef typename MatrixType::Scalar Scalar;
518*bf2c3715SXin Li     typedef typename MatrixType::RealScalar RealScalar;
519*bf2c3715SXin Li     typedef typename MatrixType::StorageIndex StorageIndex;
520*bf2c3715SXin Li     typedef SparseMatrix<Scalar,ColMajor,StorageIndex> CholMatrixType;
521*bf2c3715SXin Li     typedef Matrix<Scalar,Dynamic,1> VectorType;
522*bf2c3715SXin Li     typedef internal::traits<SimplicialCholesky> Traits;
523*bf2c3715SXin Li     typedef internal::traits<SimplicialLDLT<MatrixType,UpLo> > LDLTTraits;
524*bf2c3715SXin Li     typedef internal::traits<SimplicialLLT<MatrixType,UpLo>  > LLTTraits;
525*bf2c3715SXin Li   public:
526*bf2c3715SXin Li     SimplicialCholesky() : Base(), m_LDLT(true) {}
527*bf2c3715SXin Li 
528*bf2c3715SXin Li     explicit SimplicialCholesky(const MatrixType& matrix)
529*bf2c3715SXin Li       : Base(), m_LDLT(true)
530*bf2c3715SXin Li     {
531*bf2c3715SXin Li       compute(matrix);
532*bf2c3715SXin Li     }
533*bf2c3715SXin Li 
534*bf2c3715SXin Li     SimplicialCholesky& setMode(SimplicialCholeskyMode mode)
535*bf2c3715SXin Li     {
536*bf2c3715SXin Li       switch(mode)
537*bf2c3715SXin Li       {
538*bf2c3715SXin Li       case SimplicialCholeskyLLT:
539*bf2c3715SXin Li         m_LDLT = false;
540*bf2c3715SXin Li         break;
541*bf2c3715SXin Li       case SimplicialCholeskyLDLT:
542*bf2c3715SXin Li         m_LDLT = true;
543*bf2c3715SXin Li         break;
544*bf2c3715SXin Li       default:
545*bf2c3715SXin Li         break;
546*bf2c3715SXin Li       }
547*bf2c3715SXin Li 
548*bf2c3715SXin Li       return *this;
549*bf2c3715SXin Li     }
550*bf2c3715SXin Li 
551*bf2c3715SXin Li     inline const VectorType vectorD() const {
552*bf2c3715SXin Li         eigen_assert(Base::m_factorizationIsOk && "Simplicial Cholesky not factorized");
553*bf2c3715SXin Li         return Base::m_diag;
554*bf2c3715SXin Li     }
555*bf2c3715SXin Li     inline const CholMatrixType rawMatrix() const {
556*bf2c3715SXin Li         eigen_assert(Base::m_factorizationIsOk && "Simplicial Cholesky not factorized");
557*bf2c3715SXin Li         return Base::m_matrix;
558*bf2c3715SXin Li     }
559*bf2c3715SXin Li 
560*bf2c3715SXin Li     /** Computes the sparse Cholesky decomposition of \a matrix */
561*bf2c3715SXin Li     SimplicialCholesky& compute(const MatrixType& matrix)
562*bf2c3715SXin Li     {
563*bf2c3715SXin Li       if(m_LDLT)
564*bf2c3715SXin Li         Base::template compute<true>(matrix);
565*bf2c3715SXin Li       else
566*bf2c3715SXin Li         Base::template compute<false>(matrix);
567*bf2c3715SXin Li       return *this;
568*bf2c3715SXin Li     }
569*bf2c3715SXin Li 
570*bf2c3715SXin Li     /** Performs a symbolic decomposition on the sparcity of \a matrix.
571*bf2c3715SXin Li       *
572*bf2c3715SXin Li       * This function is particularly useful when solving for several problems having the same structure.
573*bf2c3715SXin Li       *
574*bf2c3715SXin Li       * \sa factorize()
575*bf2c3715SXin Li       */
576*bf2c3715SXin Li     void analyzePattern(const MatrixType& a)
577*bf2c3715SXin Li     {
578*bf2c3715SXin Li       Base::analyzePattern(a, m_LDLT);
579*bf2c3715SXin Li     }
580*bf2c3715SXin Li 
581*bf2c3715SXin Li     /** Performs a numeric decomposition of \a matrix
582*bf2c3715SXin Li       *
583*bf2c3715SXin Li       * The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed.
584*bf2c3715SXin Li       *
585*bf2c3715SXin Li       * \sa analyzePattern()
586*bf2c3715SXin Li       */
587*bf2c3715SXin Li     void factorize(const MatrixType& a)
588*bf2c3715SXin Li     {
589*bf2c3715SXin Li       if(m_LDLT)
590*bf2c3715SXin Li         Base::template factorize<true>(a);
591*bf2c3715SXin Li       else
592*bf2c3715SXin Li         Base::template factorize<false>(a);
593*bf2c3715SXin Li     }
594*bf2c3715SXin Li 
595*bf2c3715SXin Li     /** \internal */
596*bf2c3715SXin Li     template<typename Rhs,typename Dest>
597*bf2c3715SXin Li     void _solve_impl(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const
598*bf2c3715SXin Li     {
599*bf2c3715SXin Li       eigen_assert(Base::m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
600*bf2c3715SXin Li       eigen_assert(Base::m_matrix.rows()==b.rows());
601*bf2c3715SXin Li 
602*bf2c3715SXin Li       if(Base::m_info!=Success)
603*bf2c3715SXin Li         return;
604*bf2c3715SXin Li 
605*bf2c3715SXin Li       if(Base::m_P.size()>0)
606*bf2c3715SXin Li         dest = Base::m_P * b;
607*bf2c3715SXin Li       else
608*bf2c3715SXin Li         dest = b;
609*bf2c3715SXin Li 
610*bf2c3715SXin Li       if(Base::m_matrix.nonZeros()>0) // otherwise L==I
611*bf2c3715SXin Li       {
612*bf2c3715SXin Li         if(m_LDLT)
613*bf2c3715SXin Li           LDLTTraits::getL(Base::m_matrix).solveInPlace(dest);
614*bf2c3715SXin Li         else
615*bf2c3715SXin Li           LLTTraits::getL(Base::m_matrix).solveInPlace(dest);
616*bf2c3715SXin Li       }
617*bf2c3715SXin Li 
618*bf2c3715SXin Li       if(Base::m_diag.size()>0)
619*bf2c3715SXin Li         dest = Base::m_diag.real().asDiagonal().inverse() * dest;
620*bf2c3715SXin Li 
621*bf2c3715SXin Li       if (Base::m_matrix.nonZeros()>0) // otherwise I==I
622*bf2c3715SXin Li       {
623*bf2c3715SXin Li         if(m_LDLT)
624*bf2c3715SXin Li           LDLTTraits::getU(Base::m_matrix).solveInPlace(dest);
625*bf2c3715SXin Li         else
626*bf2c3715SXin Li           LLTTraits::getU(Base::m_matrix).solveInPlace(dest);
627*bf2c3715SXin Li       }
628*bf2c3715SXin Li 
629*bf2c3715SXin Li       if(Base::m_P.size()>0)
630*bf2c3715SXin Li         dest = Base::m_Pinv * dest;
631*bf2c3715SXin Li     }
632*bf2c3715SXin Li 
633*bf2c3715SXin Li     /** \internal */
634*bf2c3715SXin Li     template<typename Rhs,typename Dest>
635*bf2c3715SXin Li     void _solve_impl(const SparseMatrixBase<Rhs> &b, SparseMatrixBase<Dest> &dest) const
636*bf2c3715SXin Li     {
637*bf2c3715SXin Li       internal::solve_sparse_through_dense_panels(*this, b, dest);
638*bf2c3715SXin Li     }
639*bf2c3715SXin Li 
640*bf2c3715SXin Li     Scalar determinant() const
641*bf2c3715SXin Li     {
642*bf2c3715SXin Li       if(m_LDLT)
643*bf2c3715SXin Li       {
644*bf2c3715SXin Li         return Base::m_diag.prod();
645*bf2c3715SXin Li       }
646*bf2c3715SXin Li       else
647*bf2c3715SXin Li       {
648*bf2c3715SXin Li         Scalar detL = Diagonal<const CholMatrixType>(Base::m_matrix).prod();
649*bf2c3715SXin Li         return numext::abs2(detL);
650*bf2c3715SXin Li       }
651*bf2c3715SXin Li     }
652*bf2c3715SXin Li 
653*bf2c3715SXin Li   protected:
654*bf2c3715SXin Li     bool m_LDLT;
655*bf2c3715SXin Li };
656*bf2c3715SXin Li 
657*bf2c3715SXin Li template<typename Derived>
658*bf2c3715SXin Li void SimplicialCholeskyBase<Derived>::ordering(const MatrixType& a, ConstCholMatrixPtr &pmat, CholMatrixType& ap)
659*bf2c3715SXin Li {
660*bf2c3715SXin Li   eigen_assert(a.rows()==a.cols());
661*bf2c3715SXin Li   const Index size = a.rows();
662*bf2c3715SXin Li   pmat = &ap;
663*bf2c3715SXin Li   // Note that ordering methods compute the inverse permutation
664*bf2c3715SXin Li   if(!internal::is_same<OrderingType,NaturalOrdering<Index> >::value)
665*bf2c3715SXin Li   {
666*bf2c3715SXin Li     {
667*bf2c3715SXin Li       CholMatrixType C;
668*bf2c3715SXin Li       C = a.template selfadjointView<UpLo>();
669*bf2c3715SXin Li 
670*bf2c3715SXin Li       OrderingType ordering;
671*bf2c3715SXin Li       ordering(C,m_Pinv);
672*bf2c3715SXin Li     }
673*bf2c3715SXin Li 
674*bf2c3715SXin Li     if(m_Pinv.size()>0) m_P = m_Pinv.inverse();
675*bf2c3715SXin Li     else                m_P.resize(0);
676*bf2c3715SXin Li 
677*bf2c3715SXin Li     ap.resize(size,size);
678*bf2c3715SXin Li     ap.template selfadjointView<Upper>() = a.template selfadjointView<UpLo>().twistedBy(m_P);
679*bf2c3715SXin Li   }
680*bf2c3715SXin Li   else
681*bf2c3715SXin Li   {
682*bf2c3715SXin Li     m_Pinv.resize(0);
683*bf2c3715SXin Li     m_P.resize(0);
684*bf2c3715SXin Li     if(int(UpLo)==int(Lower) || MatrixType::IsRowMajor)
685*bf2c3715SXin Li     {
686*bf2c3715SXin Li       // we have to transpose the lower part to to the upper one
687*bf2c3715SXin Li       ap.resize(size,size);
688*bf2c3715SXin Li       ap.template selfadjointView<Upper>() = a.template selfadjointView<UpLo>();
689*bf2c3715SXin Li     }
690*bf2c3715SXin Li     else
691*bf2c3715SXin Li       internal::simplicial_cholesky_grab_input<CholMatrixType,MatrixType>::run(a, pmat, ap);
692*bf2c3715SXin Li   }
693*bf2c3715SXin Li }
694*bf2c3715SXin Li 
695*bf2c3715SXin Li } // end namespace Eigen
696*bf2c3715SXin Li 
697*bf2c3715SXin Li #endif // EIGEN_SIMPLICIAL_CHOLESKY_H
698