Eigen  3.3.0
 
Loading...
Searching...
No Matches
SimplicialCholesky.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008-2012 Gael Guennebaud <gael.guennebaud@inria.fr>
5//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10#ifndef EIGEN_SIMPLICIAL_CHOLESKY_H
11#define EIGEN_SIMPLICIAL_CHOLESKY_H
12
13namespace Eigen {
14
15enum SimplicialCholeskyMode {
16 SimplicialCholeskyLLT,
17 SimplicialCholeskyLDLT
18};
19
20namespace internal {
21 template<typename CholMatrixType, typename InputMatrixType>
22 struct simplicial_cholesky_grab_input {
23 typedef CholMatrixType const * ConstCholMatrixPtr;
24 static void run(const InputMatrixType& input, ConstCholMatrixPtr &pmat, CholMatrixType &tmp)
25 {
26 tmp = input;
27 pmat = &tmp;
28 }
29 };
30
31 template<typename MatrixType>
32 struct simplicial_cholesky_grab_input<MatrixType,MatrixType> {
33 typedef MatrixType const * ConstMatrixPtr;
34 static void run(const MatrixType& input, ConstMatrixPtr &pmat, MatrixType &/*tmp*/)
35 {
36 pmat = &input;
37 }
38 };
39} // end namespace internal
40
54template<typename Derived>
56{
58 using Base::m_isInitialized;
59
60 public:
61 typedef typename internal::traits<Derived>::MatrixType MatrixType;
62 typedef typename internal::traits<Derived>::OrderingType OrderingType;
63 enum { UpLo = internal::traits<Derived>::UpLo };
64 typedef typename MatrixType::Scalar Scalar;
65 typedef typename MatrixType::RealScalar RealScalar;
66 typedef typename MatrixType::StorageIndex StorageIndex;
68 typedef CholMatrixType const * ConstCholMatrixPtr;
71
72 enum {
73 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
74 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
75 };
76
77 public:
78
79 using Base::derived;
80
83 : m_info(Success), m_shiftOffset(0), m_shiftScale(1)
84 {}
85
86 explicit SimplicialCholeskyBase(const MatrixType& matrix)
87 : m_info(Success), m_shiftOffset(0), m_shiftScale(1)
88 {
89 derived().compute(matrix);
90 }
91
92 ~SimplicialCholeskyBase()
93 {
94 }
95
96 Derived& derived() { return *static_cast<Derived*>(this); }
97 const Derived& derived() const { return *static_cast<const Derived*>(this); }
98
99 inline Index cols() const { return m_matrix.cols(); }
100 inline Index rows() const { return m_matrix.rows(); }
101
108 {
109 eigen_assert(m_isInitialized && "Decomposition is not initialized.");
110 return m_info;
111 }
112
116 { return m_P; }
117
121 { return m_Pinv; }
122
132 Derived& setShift(const RealScalar& offset, const RealScalar& scale = 1)
133 {
134 m_shiftOffset = offset;
135 m_shiftScale = scale;
136 return derived();
137 }
138
139#ifndef EIGEN_PARSED_BY_DOXYGEN
141 template<typename Stream>
142 void dumpMemory(Stream& s)
143 {
144 int total = 0;
145 s << " L: " << ((total+=(m_matrix.cols()+1) * sizeof(int) + m_matrix.nonZeros()*(sizeof(int)+sizeof(Scalar))) >> 20) << "Mb" << "\n";
146 s << " diag: " << ((total+=m_diag.size() * sizeof(Scalar)) >> 20) << "Mb" << "\n";
147 s << " tree: " << ((total+=m_parent.size() * sizeof(int)) >> 20) << "Mb" << "\n";
148 s << " nonzeros: " << ((total+=m_nonZerosPerCol.size() * sizeof(int)) >> 20) << "Mb" << "\n";
149 s << " perm: " << ((total+=m_P.size() * sizeof(int)) >> 20) << "Mb" << "\n";
150 s << " perm^-1: " << ((total+=m_Pinv.size() * sizeof(int)) >> 20) << "Mb" << "\n";
151 s << " TOTAL: " << (total>> 20) << "Mb" << "\n";
152 }
153
155 template<typename Rhs,typename Dest>
156 void _solve_impl(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const
157 {
158 eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
159 eigen_assert(m_matrix.rows()==b.rows());
160
161 if(m_info!=Success)
162 return;
163
164 if(m_P.size()>0)
165 dest = m_P * b;
166 else
167 dest = b;
168
169 if(m_matrix.nonZeros()>0) // otherwise L==I
170 derived().matrixL().solveInPlace(dest);
171
172 if(m_diag.size()>0)
173 dest = m_diag.asDiagonal().inverse() * dest;
174
175 if (m_matrix.nonZeros()>0) // otherwise U==I
176 derived().matrixU().solveInPlace(dest);
177
178 if(m_P.size()>0)
179 dest = m_Pinv * dest;
180 }
181
182 template<typename Rhs,typename Dest>
183 void _solve_impl(const SparseMatrixBase<Rhs> &b, SparseMatrixBase<Dest> &dest) const
184 {
185 internal::solve_sparse_through_dense_panels(derived(), b, dest);
186 }
187
188#endif // EIGEN_PARSED_BY_DOXYGEN
189
190 protected:
191
193 template<bool DoLDLT>
194 void compute(const MatrixType& matrix)
195 {
196 eigen_assert(matrix.rows()==matrix.cols());
197 Index size = matrix.cols();
198 CholMatrixType tmp(size,size);
199 ConstCholMatrixPtr pmat;
200 ordering(matrix, pmat, tmp);
201 analyzePattern_preordered(*pmat, DoLDLT);
202 factorize_preordered<DoLDLT>(*pmat);
203 }
204
205 template<bool DoLDLT>
206 void factorize(const MatrixType& a)
207 {
208 eigen_assert(a.rows()==a.cols());
209 Index size = a.cols();
210 CholMatrixType tmp(size,size);
211 ConstCholMatrixPtr pmat;
212
213 if(m_P.size()==0 && (UpLo&Upper)==Upper)
214 {
215 // If there is no ordering, try to directly use the input matrix without any copy
216 internal::simplicial_cholesky_grab_input<CholMatrixType,MatrixType>::run(a, pmat, tmp);
217 }
218 else
219 {
220 tmp.template selfadjointView<Upper>() = a.template selfadjointView<UpLo>().twistedBy(m_P);
221 pmat = &tmp;
222 }
223
224 factorize_preordered<DoLDLT>(*pmat);
225 }
226
227 template<bool DoLDLT>
228 void factorize_preordered(const CholMatrixType& a);
229
230 void analyzePattern(const MatrixType& a, bool doLDLT)
231 {
232 eigen_assert(a.rows()==a.cols());
233 Index size = a.cols();
234 CholMatrixType tmp(size,size);
235 ConstCholMatrixPtr pmat;
236 ordering(a, pmat, tmp);
237 analyzePattern_preordered(*pmat,doLDLT);
238 }
239 void analyzePattern_preordered(const CholMatrixType& a, bool doLDLT);
240
241 void ordering(const MatrixType& a, ConstCholMatrixPtr &pmat, CholMatrixType& ap);
242
244 struct keep_diag {
245 inline bool operator() (const Index& row, const Index& col, const Scalar&) const
246 {
247 return row!=col;
248 }
249 };
250
251 mutable ComputationInfo m_info;
252 bool m_factorizationIsOk;
253 bool m_analysisIsOk;
254
255 CholMatrixType m_matrix;
256 VectorType m_diag; // the diagonal coefficients (LDLT mode)
257 VectorI m_parent; // elimination tree
258 VectorI m_nonZerosPerCol;
260 PermutationMatrix<Dynamic,Dynamic,StorageIndex> m_Pinv; // the inverse permutation
261
262 RealScalar m_shiftOffset;
263 RealScalar m_shiftScale;
264};
265
266template<typename _MatrixType, int _UpLo = Lower, typename _Ordering = AMDOrdering<typename _MatrixType::StorageIndex> > class SimplicialLLT;
267template<typename _MatrixType, int _UpLo = Lower, typename _Ordering = AMDOrdering<typename _MatrixType::StorageIndex> > class SimplicialLDLT;
268template<typename _MatrixType, int _UpLo = Lower, typename _Ordering = AMDOrdering<typename _MatrixType::StorageIndex> > class SimplicialCholesky;
269
270namespace internal {
271
272template<typename _MatrixType, int _UpLo, typename _Ordering> struct traits<SimplicialLLT<_MatrixType,_UpLo,_Ordering> >
273{
274 typedef _MatrixType MatrixType;
275 typedef _Ordering OrderingType;
276 enum { UpLo = _UpLo };
277 typedef typename MatrixType::Scalar Scalar;
278 typedef typename MatrixType::StorageIndex StorageIndex;
279 typedef SparseMatrix<Scalar, ColMajor, StorageIndex> CholMatrixType;
280 typedef TriangularView<const CholMatrixType, Eigen::Lower> MatrixL;
281 typedef TriangularView<const typename CholMatrixType::AdjointReturnType, Eigen::Upper> MatrixU;
282 static inline MatrixL getL(const MatrixType& m) { return MatrixL(m); }
283 static inline MatrixU getU(const MatrixType& m) { return MatrixU(m.adjoint()); }
284};
285
286template<typename _MatrixType,int _UpLo, typename _Ordering> struct traits<SimplicialLDLT<_MatrixType,_UpLo,_Ordering> >
287{
288 typedef _MatrixType MatrixType;
289 typedef _Ordering OrderingType;
290 enum { UpLo = _UpLo };
291 typedef typename MatrixType::Scalar Scalar;
292 typedef typename MatrixType::StorageIndex StorageIndex;
293 typedef SparseMatrix<Scalar, ColMajor, StorageIndex> CholMatrixType;
294 typedef TriangularView<const CholMatrixType, Eigen::UnitLower> MatrixL;
295 typedef TriangularView<const typename CholMatrixType::AdjointReturnType, Eigen::UnitUpper> MatrixU;
296 static inline MatrixL getL(const MatrixType& m) { return MatrixL(m); }
297 static inline MatrixU getU(const MatrixType& m) { return MatrixU(m.adjoint()); }
298};
299
300template<typename _MatrixType, int _UpLo, typename _Ordering> struct traits<SimplicialCholesky<_MatrixType,_UpLo,_Ordering> >
301{
302 typedef _MatrixType MatrixType;
303 typedef _Ordering OrderingType;
304 enum { UpLo = _UpLo };
305};
306
307}
308
329template<typename _MatrixType, int _UpLo, typename _Ordering>
330 class SimplicialLLT : public SimplicialCholeskyBase<SimplicialLLT<_MatrixType,_UpLo,_Ordering> >
331{
332public:
333 typedef _MatrixType MatrixType;
334 enum { UpLo = _UpLo };
336 typedef typename MatrixType::Scalar Scalar;
337 typedef typename MatrixType::RealScalar RealScalar;
338 typedef typename MatrixType::StorageIndex StorageIndex;
341 typedef internal::traits<SimplicialLLT> Traits;
342 typedef typename Traits::MatrixL MatrixL;
343 typedef typename Traits::MatrixU MatrixU;
344public:
348 explicit SimplicialLLT(const MatrixType& matrix)
349 : Base(matrix) {}
350
352 inline const MatrixL matrixL() const {
353 eigen_assert(Base::m_factorizationIsOk && "Simplicial LLT not factorized");
354 return Traits::getL(Base::m_matrix);
355 }
356
358 inline const MatrixU matrixU() const {
359 eigen_assert(Base::m_factorizationIsOk && "Simplicial LLT not factorized");
360 return Traits::getU(Base::m_matrix);
361 }
362
364 SimplicialLLT& compute(const MatrixType& matrix)
365 {
366 Base::template compute<false>(matrix);
367 return *this;
368 }
369
376 void analyzePattern(const MatrixType& a)
377 {
378 Base::analyzePattern(a, false);
379 }
380
387 void factorize(const MatrixType& a)
388 {
389 Base::template factorize<false>(a);
390 }
391
393 Scalar determinant() const
394 {
395 Scalar detL = Base::m_matrix.diagonal().prod();
396 return numext::abs2(detL);
397 }
398};
399
420template<typename _MatrixType, int _UpLo, typename _Ordering>
421 class SimplicialLDLT : public SimplicialCholeskyBase<SimplicialLDLT<_MatrixType,_UpLo,_Ordering> >
422{
423public:
424 typedef _MatrixType MatrixType;
425 enum { UpLo = _UpLo };
427 typedef typename MatrixType::Scalar Scalar;
428 typedef typename MatrixType::RealScalar RealScalar;
429 typedef typename MatrixType::StorageIndex StorageIndex;
432 typedef internal::traits<SimplicialLDLT> Traits;
433 typedef typename Traits::MatrixL MatrixL;
434 typedef typename Traits::MatrixU MatrixU;
435public:
438
440 explicit SimplicialLDLT(const MatrixType& matrix)
441 : Base(matrix) {}
442
444 inline const VectorType vectorD() const {
445 eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized");
446 return Base::m_diag;
447 }
449 inline const MatrixL matrixL() const {
450 eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized");
451 return Traits::getL(Base::m_matrix);
452 }
453
455 inline const MatrixU matrixU() const {
456 eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized");
457 return Traits::getU(Base::m_matrix);
458 }
459
461 SimplicialLDLT& compute(const MatrixType& matrix)
462 {
463 Base::template compute<true>(matrix);
464 return *this;
465 }
466
473 void analyzePattern(const MatrixType& a)
474 {
475 Base::analyzePattern(a, true);
476 }
477
484 void factorize(const MatrixType& a)
485 {
486 Base::template factorize<true>(a);
487 }
488
490 Scalar determinant() const
491 {
492 return Base::m_diag.prod();
493 }
494};
495
502template<typename _MatrixType, int _UpLo, typename _Ordering>
503 class SimplicialCholesky : public SimplicialCholeskyBase<SimplicialCholesky<_MatrixType,_UpLo,_Ordering> >
504{
505public:
506 typedef _MatrixType MatrixType;
507 enum { UpLo = _UpLo };
509 typedef typename MatrixType::Scalar Scalar;
510 typedef typename MatrixType::RealScalar RealScalar;
511 typedef typename MatrixType::StorageIndex StorageIndex;
514 typedef internal::traits<SimplicialCholesky> Traits;
515 typedef internal::traits<SimplicialLDLT<MatrixType,UpLo> > LDLTTraits;
516 typedef internal::traits<SimplicialLLT<MatrixType,UpLo> > LLTTraits;
517 public:
518 SimplicialCholesky() : Base(), m_LDLT(true) {}
519
520 explicit SimplicialCholesky(const MatrixType& matrix)
521 : Base(), m_LDLT(true)
522 {
523 compute(matrix);
524 }
525
526 SimplicialCholesky& setMode(SimplicialCholeskyMode mode)
527 {
528 switch(mode)
529 {
530 case SimplicialCholeskyLLT:
531 m_LDLT = false;
532 break;
533 case SimplicialCholeskyLDLT:
534 m_LDLT = true;
535 break;
536 default:
537 break;
538 }
539
540 return *this;
541 }
542
543 inline const VectorType vectorD() const {
544 eigen_assert(Base::m_factorizationIsOk && "Simplicial Cholesky not factorized");
545 return Base::m_diag;
546 }
547 inline const CholMatrixType rawMatrix() const {
548 eigen_assert(Base::m_factorizationIsOk && "Simplicial Cholesky not factorized");
549 return Base::m_matrix;
550 }
551
553 SimplicialCholesky& compute(const MatrixType& matrix)
554 {
555 if(m_LDLT)
556 Base::template compute<true>(matrix);
557 else
558 Base::template compute<false>(matrix);
559 return *this;
560 }
561
568 void analyzePattern(const MatrixType& a)
569 {
570 Base::analyzePattern(a, m_LDLT);
571 }
572
579 void factorize(const MatrixType& a)
580 {
581 if(m_LDLT)
582 Base::template factorize<true>(a);
583 else
584 Base::template factorize<false>(a);
585 }
586
588 template<typename Rhs,typename Dest>
589 void _solve_impl(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const
590 {
591 eigen_assert(Base::m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
592 eigen_assert(Base::m_matrix.rows()==b.rows());
593
594 if(Base::m_info!=Success)
595 return;
596
597 if(Base::m_P.size()>0)
598 dest = Base::m_P * b;
599 else
600 dest = b;
601
602 if(Base::m_matrix.nonZeros()>0) // otherwise L==I
603 {
604 if(m_LDLT)
605 LDLTTraits::getL(Base::m_matrix).solveInPlace(dest);
606 else
607 LLTTraits::getL(Base::m_matrix).solveInPlace(dest);
608 }
609
610 if(Base::m_diag.size()>0)
611 dest = Base::m_diag.asDiagonal().inverse() * dest;
612
613 if (Base::m_matrix.nonZeros()>0) // otherwise I==I
614 {
615 if(m_LDLT)
616 LDLTTraits::getU(Base::m_matrix).solveInPlace(dest);
617 else
618 LLTTraits::getU(Base::m_matrix).solveInPlace(dest);
619 }
620
621 if(Base::m_P.size()>0)
622 dest = Base::m_Pinv * dest;
623 }
624
626 template<typename Rhs,typename Dest>
627 void _solve_impl(const SparseMatrixBase<Rhs> &b, SparseMatrixBase<Dest> &dest) const
628 {
629 internal::solve_sparse_through_dense_panels(*this, b, dest);
630 }
631
632 Scalar determinant() const
633 {
634 if(m_LDLT)
635 {
636 return Base::m_diag.prod();
637 }
638 else
639 {
640 Scalar detL = Diagonal<const CholMatrixType>(Base::m_matrix).prod();
641 return numext::abs2(detL);
642 }
643 }
644
645 protected:
646 bool m_LDLT;
647};
648
649template<typename Derived>
650void SimplicialCholeskyBase<Derived>::ordering(const MatrixType& a, ConstCholMatrixPtr &pmat, CholMatrixType& ap)
651{
652 eigen_assert(a.rows()==a.cols());
653 const Index size = a.rows();
654 pmat = &ap;
655 // Note that ordering methods compute the inverse permutation
656 if(!internal::is_same<OrderingType,NaturalOrdering<Index> >::value)
657 {
658 {
659 CholMatrixType C;
660 C = a.template selfadjointView<UpLo>();
661
662 OrderingType ordering;
663 ordering(C,m_Pinv);
664 }
665
666 if(m_Pinv.size()>0) m_P = m_Pinv.inverse();
667 else m_P.resize(0);
668
669 ap.resize(size,size);
670 ap.template selfadjointView<Upper>() = a.template selfadjointView<UpLo>().twistedBy(m_P);
671 }
672 else
673 {
674 m_Pinv.resize(0);
675 m_P.resize(0);
676 if(int(UpLo)==int(Lower) || MatrixType::IsRowMajor)
677 {
678 // we have to transpose the lower part to to the upper one
679 ap.resize(size,size);
680 ap.template selfadjointView<Upper>() = a.template selfadjointView<UpLo>();
681 }
682 else
683 internal::simplicial_cholesky_grab_input<CholMatrixType,MatrixType>::run(a, pmat, ap);
684 }
685}
686
687} // end namespace Eigen
688
689#endif // EIGEN_SIMPLICIAL_CHOLESKY_H
Index rows() const
Definition: EigenBase.h:58
Base class for all dense matrices, vectors, and expressions.
Definition: MatrixBase.h:50
const DiagonalWrapper< const Derived > asDiagonal() const
Definition: DiagonalMatrix.h:277
The matrix class, also used for vectors and row-vectors.
Definition: Matrix.h:180
Index size() const
Definition: PermutationMatrix.h:108
Permutation matrix.
Definition: PermutationMatrix.h:309
A base class for direct sparse Cholesky factorizations.
Definition: SimplicialCholesky.h:56
SimplicialCholeskyBase()
Definition: SimplicialCholesky.h:82
ComputationInfo info() const
Reports whether previous computation was successful.
Definition: SimplicialCholesky.h:107
const PermutationMatrix< Dynamic, Dynamic, StorageIndex > & permutationP() const
Definition: SimplicialCholesky.h:115
Derived & setShift(const RealScalar &offset, const RealScalar &scale=1)
Definition: SimplicialCholesky.h:132
void compute(const MatrixType &matrix)
Definition: SimplicialCholesky.h:194
const PermutationMatrix< Dynamic, Dynamic, StorageIndex > & permutationPinv() const
Definition: SimplicialCholesky.h:120
Definition: SimplicialCholesky.h:504
SimplicialCholesky & compute(const MatrixType &matrix)
Definition: SimplicialCholesky.h:553
void analyzePattern(const MatrixType &a)
Definition: SimplicialCholesky.h:568
void factorize(const MatrixType &a)
Definition: SimplicialCholesky.h:579
A direct sparse LDLT Cholesky factorizations without square root.
Definition: SimplicialCholesky.h:422
SimplicialLDLT(const MatrixType &matrix)
Definition: SimplicialCholesky.h:440
SimplicialLDLT()
Definition: SimplicialCholesky.h:437
SimplicialLDLT & compute(const MatrixType &matrix)
Definition: SimplicialCholesky.h:461
void factorize(const MatrixType &a)
Definition: SimplicialCholesky.h:484
Scalar determinant() const
Definition: SimplicialCholesky.h:490
void analyzePattern(const MatrixType &a)
Definition: SimplicialCholesky.h:473
const VectorType vectorD() const
Definition: SimplicialCholesky.h:444
const MatrixL matrixL() const
Definition: SimplicialCholesky.h:449
const MatrixU matrixU() const
Definition: SimplicialCholesky.h:455
A direct sparse LLT Cholesky factorizations.
Definition: SimplicialCholesky.h:331
const MatrixU matrixU() const
Definition: SimplicialCholesky.h:358
SimplicialLLT(const MatrixType &matrix)
Definition: SimplicialCholesky.h:348
SimplicialLLT & compute(const MatrixType &matrix)
Definition: SimplicialCholesky.h:364
void factorize(const MatrixType &a)
Definition: SimplicialCholesky.h:387
Scalar determinant() const
Definition: SimplicialCholesky.h:393
SimplicialLLT()
Definition: SimplicialCholesky.h:346
void analyzePattern(const MatrixType &a)
Definition: SimplicialCholesky.h:376
const MatrixL matrixL() const
Definition: SimplicialCholesky.h:352
A versatible sparse matrix representation.
Definition: SparseMatrix.h:94
Index nonZeros() const
Definition: SparseCompressedBase.h:56
Index rows() const
Definition: SparseMatrix.h:132
Index cols() const
Definition: SparseMatrix.h:134
A base class for sparse solvers.
Definition: SparseSolverBase.h:68
ComputationInfo
Definition: Constants.h:430
@ Upper
Definition: Constants.h:206
@ Success
Definition: Constants.h:432
Namespace containing all symbols from the Eigen library.
Definition: Core:287
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:33
Definition: SimplicialCholesky.h:244