Eigen  5.0.1
 
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// SPDX-License-Identifier: MPL-2.0
10
11#ifndef EIGEN_SIMPLICIAL_CHOLESKY_H
12#define EIGEN_SIMPLICIAL_CHOLESKY_H
13
14// IWYU pragma: private
15#include "./InternalHeaderCheck.h"
16
17namespace Eigen {
18
19enum SimplicialCholeskyMode { SimplicialCholeskyLLT, SimplicialCholeskyLDLT };
20
21namespace internal {
22template <typename CholMatrixType, typename InputMatrixType>
23struct simplicial_cholesky_grab_input {
24 using ConstCholMatrixPtr = const CholMatrixType*;
25 static void run(const InputMatrixType& input, ConstCholMatrixPtr& pmat, CholMatrixType& tmp) {
26 tmp = input;
27 pmat = &tmp;
28 }
29};
30
31template <typename MatrixType>
32struct simplicial_cholesky_grab_input<MatrixType, MatrixType> {
33 using ConstMatrixPtr = const MatrixType*;
34 static void run(const MatrixType& input, ConstMatrixPtr& pmat, MatrixType& /*tmp*/) { pmat = &input; }
35};
36
37// Compute a fill-reducing permutation for SimplicialCholesky. The generic path
38// builds the full Scalar-valued symmetric matrix that the user's OrderingType
39// expects. The AMDOrdering specialization below skips that copy: AMD reads
40// only the sparsity pattern, so we can hand it a SparseSelfAdjointView<UpLo>
41// whose pattern-only overload materializes the underlying triangle as
42// SparseMatrix<signed char> and expands once.
43template <bool UseAMDFastPath>
44struct simplicial_cholesky_amd_dispatch {
45 template <int UpLo_, bool NonHermitian, typename Ordering, typename MatrixType, typename CholMatrixType,
46 typename Perm>
47 static void run(const MatrixType& a, CholMatrixType& C, Perm& perm) {
48 permute_symm_to_fullsymm<UpLo_, NonHermitian>(a, C, nullptr);
49 Ordering ordering;
50 ordering(C, perm);
51 }
52};
53
54template <>
55struct simplicial_cholesky_amd_dispatch<true> {
56 template <int UpLo_, bool /*NonHermitian*/, typename Ordering, typename MatrixType, typename CholMatrixType,
57 typename Perm>
58 static void run(const MatrixType& a, CholMatrixType& /*C*/, Perm& perm) {
59 // Pattern-only: works for both Hermitian and NonHermitian variants because
60 // AMD's selfadjointView overload never reads scalar values, so the
61 // selfadjoint-vs-symmetric distinction (which only affects value
62 // expansion) is irrelevant.
63 Ordering ordering;
64 ordering(a.template selfadjointView<UpLo_>(), perm);
65 }
66};
67} // end namespace internal
68
82template <typename Derived>
84 using Base = SparseSolverBase<Derived>;
85 using Base::m_isInitialized;
86
87 public:
88 using MatrixType = typename internal::traits<Derived>::MatrixType;
89 using OrderingType = typename internal::traits<Derived>::OrderingType;
90 enum { UpLo = internal::traits<Derived>::UpLo };
91 using Scalar = typename MatrixType::Scalar;
92 using RealScalar = typename MatrixType::RealScalar;
93 using DiagonalScalar = typename internal::traits<Derived>::DiagonalScalar;
94 using StorageIndex = typename MatrixType::StorageIndex;
96 using ConstCholMatrixPtr = const CholMatrixType*;
97 using VectorType = Matrix<Scalar, Dynamic, 1>;
99
100 enum { ColsAtCompileTime = MatrixType::ColsAtCompileTime, MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime };
101
102 public:
103 using Base::derived;
104
107 : m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false), m_shiftOffset(0), m_shiftScale(1) {}
108
109 explicit SimplicialCholeskyBase(const MatrixType& matrix)
110 : m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false), m_shiftOffset(0), m_shiftScale(1) {
111 derived().compute(matrix);
112 }
113
114 Derived& derived() { return *static_cast<Derived*>(this); }
115 const Derived& derived() const { return *static_cast<const Derived*>(this); }
116
117 inline Index cols() const { return m_matrix.cols(); }
118 inline Index rows() const { return m_matrix.rows(); }
119
126 eigen_assert(m_isInitialized && "Decomposition is not initialized.");
127 return m_info;
128 }
129
133
137
148 Derived& setShift(const DiagonalScalar& offset, const DiagonalScalar& scale = 1) {
149 m_shiftOffset = offset;
150 m_shiftScale = scale;
151 return derived();
152 }
153
154#ifndef EIGEN_PARSED_BY_DOXYGEN
156 template <typename Stream>
157 void dumpMemory(Stream& s) {
158 int total = 0;
159 s << " L: "
160 << ((total += (m_matrix.cols() + 1) * sizeof(int) + m_matrix.nonZeros() * (sizeof(int) + sizeof(Scalar))) >> 20)
161 << "Mb"
162 << "\n";
163 s << " diag: " << ((total += m_diag.size() * sizeof(Scalar)) >> 20) << "Mb"
164 << "\n";
165 s << " tree: " << ((total += m_parent.size() * sizeof(int)) >> 20) << "Mb"
166 << "\n";
167 s << " nonzeros: " << ((total += m_workSpace.size() * sizeof(int)) >> 20) << "Mb"
168 << "\n";
169 s << " perm: " << ((total += m_P.size() * sizeof(int)) >> 20) << "Mb"
170 << "\n";
171 s << " perm^-1: " << ((total += m_Pinv.size() * sizeof(int)) >> 20) << "Mb"
172 << "\n";
173 s << " TOTAL: " << (total >> 20) << "Mb"
174 << "\n";
175 }
176
178 template <typename Rhs, typename Dest>
179 void _solve_impl(const MatrixBase<Rhs>& b, MatrixBase<Dest>& dest) const {
180 eigen_assert(m_factorizationIsOk &&
181 "The decomposition is not in a valid state for solving, you must first call either compute() or "
182 "symbolic()/numeric()");
183 eigen_assert(m_matrix.rows() == b.rows());
184
185 if (m_info != Success) return;
186
187 if (m_P.size() > 0)
188 dest = m_P * b;
189 else
190 dest = b;
191
192 if (m_matrix.nonZeros() > 0) // otherwise L==I
193 derived().matrixL().solveInPlace(dest);
194
195 if (m_diag.size() > 0) dest = m_diag.asDiagonal().inverse() * dest;
196
197 if (m_matrix.nonZeros() > 0) // otherwise U==I
198 derived().matrixU().solveInPlace(dest);
199
200 if (m_P.size() > 0) dest = m_Pinv * dest;
201 }
202
203 template <typename Rhs, typename Dest>
204 void _solve_impl(const SparseMatrixBase<Rhs>& b, SparseMatrixBase<Dest>& dest) const {
205 internal::solve_sparse_through_dense_panels(derived(), b, dest);
206 }
207
208#endif // EIGEN_PARSED_BY_DOXYGEN
209
210 protected:
212 template <bool DoLDLT, bool NonHermitian>
213 void compute(const MatrixType& matrix) {
214 eigen_assert(matrix.rows() == matrix.cols());
215 Index size = matrix.cols();
216 CholMatrixType tmp(size, size);
217 ConstCholMatrixPtr pmat;
218 ordering<NonHermitian>(matrix, pmat, tmp);
219 analyzePattern_preordered(*pmat, DoLDLT);
220 factorize_preordered<DoLDLT, NonHermitian>(*pmat);
221 }
222
223 template <bool DoLDLT, bool NonHermitian>
224 void factorize(const MatrixType& a) {
225 eigen_assert(a.rows() == a.cols());
226 Index size = a.cols();
227 CholMatrixType tmp(size, size);
228 ConstCholMatrixPtr pmat;
229
230 if (m_P.size() == 0 && (int(UpLo) & int(Upper)) == Upper) {
231 // If there is no ordering, try to directly use the input matrix without any copy
232 internal::simplicial_cholesky_grab_input<CholMatrixType, MatrixType>::run(a, pmat, tmp);
233 } else {
234 internal::permute_symm_to_symm<UpLo, Upper, NonHermitian>(a, tmp, m_P.indices().data());
235 pmat = &tmp;
236 }
237
238 factorize_preordered<DoLDLT, NonHermitian>(*pmat);
239 }
240
241 template <bool DoLDLT, bool NonHermitian>
242 void factorize_preordered(const CholMatrixType& a);
243 template <bool DoLDLT, bool NonHermitian, bool UsePackets>
244 void factorize_preordered_impl(const CholMatrixType& a);
245
246 template <bool DoLDLT, bool NonHermitian>
247 void analyzePattern(const MatrixType& a) {
248 eigen_assert(a.rows() == a.cols());
249 Index size = a.cols();
250 CholMatrixType tmp(size, size);
251 ConstCholMatrixPtr pmat;
252 ordering<NonHermitian>(a, pmat, tmp);
253 analyzePattern_preordered(*pmat, DoLDLT);
254 }
255 void analyzePattern_preordered(const CholMatrixType& a, bool doLDLT);
256
257 template <bool NonHermitian>
258 void ordering(const MatrixType& a, ConstCholMatrixPtr& pmat, CholMatrixType& ap);
259
260 inline DiagonalScalar getDiag(Scalar x) { return internal::traits<Derived>::getDiag(x); }
261 inline Scalar getSymm(Scalar x) { return internal::traits<Derived>::getSymm(x); }
262
264 struct keep_diag {
265 inline bool operator()(const Index& row, const Index& col, const Scalar&) const { return row != col; }
266 };
267
268 mutable ComputationInfo m_info;
269 // Set once factorize() has run, success or not: factorize_preordered() breaks out on a bad pivot, leaving
270 // the tails of m_diag and of m_matrix's diagonal unwritten. Readers of those also need m_info == Success.
271 bool m_factorizationIsOk;
272 bool m_analysisIsOk;
273
274 CholMatrixType m_matrix;
275 VectorType m_diag; // the diagonal coefficients (LDLT mode)
276 VectorI m_parent; // elimination tree
277 VectorI m_workSpace;
279 PermutationMatrix<Dynamic, Dynamic, StorageIndex> m_Pinv; // the inverse permutation
280
281 DiagonalScalar m_shiftOffset;
282 DiagonalScalar m_shiftScale;
283};
284
285template <typename MatrixType_, int UpLo_ = Lower,
287class SimplicialLLT;
288template <typename MatrixType_, int UpLo_ = Lower,
290class SimplicialLDLT;
291template <typename MatrixType_, int UpLo_ = Lower,
294template <typename MatrixType_, int UpLo_ = Lower,
297template <typename MatrixType_, int UpLo_ = Lower,
300
301namespace internal {
302
303template <typename MatrixType_, int UpLo_, typename Ordering_>
304struct traits<SimplicialLLT<MatrixType_, UpLo_, Ordering_> > {
305 using MatrixType = MatrixType_;
306 using OrderingType = Ordering_;
307 enum { UpLo = UpLo_ };
308 using Scalar = typename MatrixType::Scalar;
309 using DiagonalScalar = typename MatrixType::RealScalar;
310 using StorageIndex = typename MatrixType::StorageIndex;
311 using CholMatrixType = SparseMatrix<Scalar, ColMajor, StorageIndex>;
312 using MatrixL = TriangularView<const CholMatrixType, Eigen::Lower>;
313 using MatrixU = TriangularView<const typename CholMatrixType::AdjointReturnType, Eigen::Upper>;
314 static inline MatrixL getL(const CholMatrixType& m) { return MatrixL(m); }
315 static inline MatrixU getU(const CholMatrixType& m) { return MatrixU(m.adjoint()); }
316 static inline DiagonalScalar getDiag(Scalar x) { return numext::real(x); }
317 static inline Scalar getSymm(Scalar x) { return numext::conj(x); }
318};
319
320template <typename MatrixType_, int UpLo_, typename Ordering_>
321struct traits<SimplicialLDLT<MatrixType_, UpLo_, Ordering_> > {
322 using MatrixType = MatrixType_;
323 using OrderingType = Ordering_;
324 enum { UpLo = UpLo_ };
325 using Scalar = typename MatrixType::Scalar;
326 using DiagonalScalar = typename MatrixType::RealScalar;
327 using StorageIndex = typename MatrixType::StorageIndex;
328 using CholMatrixType = SparseMatrix<Scalar, ColMajor, StorageIndex>;
329 using MatrixL = TriangularView<const CholMatrixType, Eigen::UnitLower>;
330 using MatrixU = TriangularView<const typename CholMatrixType::AdjointReturnType, Eigen::UnitUpper>;
331 static inline MatrixL getL(const CholMatrixType& m) { return MatrixL(m); }
332 static inline MatrixU getU(const CholMatrixType& m) { return MatrixU(m.adjoint()); }
333 static inline DiagonalScalar getDiag(Scalar x) { return numext::real(x); }
334 static inline Scalar getSymm(Scalar x) { return numext::conj(x); }
335};
336
337template <typename MatrixType_, int UpLo_, typename Ordering_>
338struct traits<SimplicialNonHermitianLLT<MatrixType_, UpLo_, Ordering_> > {
339 using MatrixType = MatrixType_;
340 using OrderingType = Ordering_;
341 enum { UpLo = UpLo_ };
342 using Scalar = typename MatrixType::Scalar;
343 using DiagonalScalar = typename MatrixType::Scalar;
344 using StorageIndex = typename MatrixType::StorageIndex;
345 using CholMatrixType = SparseMatrix<Scalar, ColMajor, StorageIndex>;
346 using MatrixL = TriangularView<const CholMatrixType, Eigen::Lower>;
347 using MatrixU = TriangularView<const typename CholMatrixType::ConstTransposeReturnType, Eigen::Upper>;
348 static inline MatrixL getL(const CholMatrixType& m) { return MatrixL(m); }
349 static inline MatrixU getU(const CholMatrixType& m) { return MatrixU(m.transpose()); }
350 static inline DiagonalScalar getDiag(Scalar x) { return x; }
351 static inline Scalar getSymm(Scalar x) { return x; }
352};
353
354template <typename MatrixType_, int UpLo_, typename Ordering_>
355struct traits<SimplicialNonHermitianLDLT<MatrixType_, UpLo_, Ordering_> > {
356 using MatrixType = MatrixType_;
357 using OrderingType = Ordering_;
358 enum { UpLo = UpLo_ };
359 using Scalar = typename MatrixType::Scalar;
360 using DiagonalScalar = typename MatrixType::Scalar;
361 using StorageIndex = typename MatrixType::StorageIndex;
362 using CholMatrixType = SparseMatrix<Scalar, ColMajor, StorageIndex>;
363 using MatrixL = TriangularView<const CholMatrixType, Eigen::UnitLower>;
364 using MatrixU = TriangularView<const typename CholMatrixType::ConstTransposeReturnType, Eigen::UnitUpper>;
365 static inline MatrixL getL(const CholMatrixType& m) { return MatrixL(m); }
366 static inline MatrixU getU(const CholMatrixType& m) { return MatrixU(m.transpose()); }
367 static inline DiagonalScalar getDiag(Scalar x) { return x; }
368 static inline Scalar getSymm(Scalar x) { return x; }
369};
370
371template <typename MatrixType_, int UpLo_, typename Ordering_>
372struct traits<SimplicialCholesky<MatrixType_, UpLo_, Ordering_> > {
373 using MatrixType = MatrixType_;
374 using OrderingType = Ordering_;
375 enum { UpLo = UpLo_ };
376 using Scalar = typename MatrixType::Scalar;
377 using DiagonalScalar = typename MatrixType::RealScalar;
378 static inline DiagonalScalar getDiag(Scalar x) { return numext::real(x); }
379 static inline Scalar getSymm(Scalar x) { return numext::conj(x); }
380};
381
382} // namespace internal
383
404template <typename MatrixType_, int UpLo_, typename Ordering_>
405class SimplicialLLT : public SimplicialCholeskyBase<SimplicialLLT<MatrixType_, UpLo_, Ordering_> > {
406 public:
407 using MatrixType = MatrixType_;
408 enum { UpLo = UpLo_ };
410 using Scalar = typename MatrixType::Scalar;
411 using RealScalar = typename MatrixType::RealScalar;
412 using StorageIndex = typename MatrixType::StorageIndex;
413 using CholMatrixType = SparseMatrix<Scalar, ColMajor, Index>;
414 using VectorType = Matrix<Scalar, Dynamic, 1>;
415 using Traits = internal::traits<SimplicialLLT>;
416 using MatrixL = typename Traits::MatrixL;
417 using MatrixU = typename Traits::MatrixU;
418
419 public:
421 SimplicialLLT() : Base() {}
423 explicit SimplicialLLT(const MatrixType& matrix) : Base(matrix) {}
424
426 inline const MatrixL matrixL() const {
427 eigen_assert(Base::m_factorizationIsOk && "Simplicial LLT not factorized");
428 return Traits::getL(Base::m_matrix);
429 }
430
432 inline const MatrixU matrixU() const {
433 eigen_assert(Base::m_factorizationIsOk && "Simplicial LLT not factorized");
434 return Traits::getU(Base::m_matrix);
435 }
436
438 SimplicialLLT& compute(const MatrixType& matrix) {
439 Base::template compute<false, false>(matrix);
440 return *this;
441 }
442
449 void analyzePattern(const MatrixType& a) { Base::template analyzePattern<false, false>(a); }
450
458 void factorize(const MatrixType& a) { Base::template factorize<false, false>(a); }
459
461 Scalar determinant() const {
462 eigen_assert(Base::m_factorizationIsOk && Base::m_info == Success &&
463 "Simplicial LLT is not factorized, or its factorization failed");
464 Scalar detL = Base::m_matrix.diagonal().prod();
465 return numext::abs2(detL);
466 }
467
469 RealScalar absDeterminant() const {
470 eigen_assert(Base::m_factorizationIsOk && Base::m_info == Success &&
471 "Simplicial LLT is not factorized, or its factorization failed");
472 return numext::abs2(Base::m_matrix.diagonal().prod());
473 }
474
480 RealScalar logAbsDeterminant() const {
481 eigen_assert(Base::m_factorizationIsOk && Base::m_info == Success &&
482 "Simplicial LLT is not factorized, or its factorization failed");
483 return RealScalar(2) * Base::m_matrix.diagonal().cwiseAbs().array().log().sum();
484 }
485
491 Scalar signDeterminant() const {
492 eigen_assert(Base::m_factorizationIsOk && Base::m_info == Success &&
493 "Simplicial LLT is not factorized, or its factorization failed");
494 return Scalar(1);
495 }
496};
497
518template <typename MatrixType_, int UpLo_, typename Ordering_>
519class SimplicialLDLT : public SimplicialCholeskyBase<SimplicialLDLT<MatrixType_, UpLo_, Ordering_> > {
520 public:
521 using MatrixType = MatrixType_;
522 enum { UpLo = UpLo_ };
524 using Scalar = typename MatrixType::Scalar;
525 using RealScalar = typename MatrixType::RealScalar;
526 using StorageIndex = typename MatrixType::StorageIndex;
528 using VectorType = Matrix<Scalar, Dynamic, 1>;
529 using Traits = internal::traits<SimplicialLDLT>;
530 using MatrixL = typename Traits::MatrixL;
531 using MatrixU = typename Traits::MatrixU;
532
533 public:
535 SimplicialLDLT() : Base() {}
536
538 explicit SimplicialLDLT(const MatrixType& matrix) : Base(matrix) {}
539
541 inline const VectorType vectorD() const {
542 eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized");
543 return Base::m_diag;
544 }
545
546 inline const MatrixL matrixL() const {
547 eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized");
548 return Traits::getL(Base::m_matrix);
549 }
550
552 inline const MatrixU matrixU() const {
553 eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized");
554 return Traits::getU(Base::m_matrix);
555 }
556
558 SimplicialLDLT& compute(const MatrixType& matrix) {
559 Base::template compute<true, false>(matrix);
560 return *this;
561 }
562
569 void analyzePattern(const MatrixType& a) { Base::template analyzePattern<true, false>(a); }
570
578 void factorize(const MatrixType& a) { Base::template factorize<true, false>(a); }
579
581 Scalar determinant() const {
582 eigen_assert(Base::m_factorizationIsOk && Base::m_info == Success &&
583 "Simplicial LDLT is not factorized, or its factorization failed");
584 return Base::m_diag.prod();
585 }
586
588 RealScalar absDeterminant() const {
589 eigen_assert(Base::m_factorizationIsOk && Base::m_info == Success &&
590 "Simplicial LDLT is not factorized, or its factorization failed");
591 return numext::abs(Base::m_diag.real().prod());
592 }
593
599 RealScalar logAbsDeterminant() const {
600 eigen_assert(Base::m_factorizationIsOk && Base::m_info == Success &&
601 "Simplicial LDLT is not factorized, or its factorization failed");
602 return Base::m_diag.real().cwiseAbs().array().log().sum();
603 }
604
606 Scalar signDeterminant() const {
607 eigen_assert(Base::m_factorizationIsOk && Base::m_info == Success &&
608 "Simplicial LDLT is not factorized, or its factorization failed");
609 return Scalar(Base::m_diag.real().array().sign().prod());
610 }
611};
612
633template <typename MatrixType_, int UpLo_, typename Ordering_>
635 : public SimplicialCholeskyBase<SimplicialNonHermitianLLT<MatrixType_, UpLo_, Ordering_> > {
636 public:
637 using MatrixType = MatrixType_;
638 enum { UpLo = UpLo_ };
640 using Scalar = typename MatrixType::Scalar;
641 using RealScalar = typename MatrixType::RealScalar;
642 using StorageIndex = typename MatrixType::StorageIndex;
644 using VectorType = Matrix<Scalar, Dynamic, 1>;
645 using Traits = internal::traits<SimplicialNonHermitianLLT>;
646 using MatrixL = typename Traits::MatrixL;
647 using MatrixU = typename Traits::MatrixU;
648
649 public:
652
654 explicit SimplicialNonHermitianLLT(const MatrixType& matrix) : Base(matrix) {}
655
657 inline const MatrixL matrixL() const {
658 eigen_assert(Base::m_factorizationIsOk && "Simplicial LLT not factorized");
659 return Traits::getL(Base::m_matrix);
660 }
661
663 inline const MatrixU matrixU() const {
664 eigen_assert(Base::m_factorizationIsOk && "Simplicial LLT not factorized");
665 return Traits::getU(Base::m_matrix);
666 }
667
669 SimplicialNonHermitianLLT& compute(const MatrixType& matrix) {
670 Base::template compute<false, true>(matrix);
671 return *this;
672 }
673
680 void analyzePattern(const MatrixType& a) { Base::template analyzePattern<false, true>(a); }
681
689 void factorize(const MatrixType& a) { Base::template factorize<false, true>(a); }
690
692 Scalar determinant() const {
693 eigen_assert(Base::m_factorizationIsOk && Base::m_info == Success &&
694 "Simplicial LLT is not factorized, or its factorization failed");
695 Scalar detL = Base::m_matrix.diagonal().prod();
696 return detL * detL;
697 }
698
700 RealScalar absDeterminant() const {
701 eigen_assert(Base::m_factorizationIsOk && Base::m_info == Success &&
702 "Simplicial LLT is not factorized, or its factorization failed");
703 return numext::abs2(Base::m_matrix.diagonal().prod());
704 }
705
711 RealScalar logAbsDeterminant() const {
712 eigen_assert(Base::m_factorizationIsOk && Base::m_info == Success &&
713 "Simplicial LLT is not factorized, or its factorization failed");
714 return RealScalar(2) * Base::m_matrix.diagonal().cwiseAbs().array().log().sum();
715 }
716
718 Scalar signDeterminant() const {
719 eigen_assert(Base::m_factorizationIsOk && Base::m_info == Success &&
720 "Simplicial LLT is not factorized, or its factorization failed");
721 Scalar signL = Base::m_matrix.diagonal().array().sign().prod();
722 return signL * signL;
723 }
724};
725
746template <typename MatrixType_, int UpLo_, typename Ordering_>
748 : public SimplicialCholeskyBase<SimplicialNonHermitianLDLT<MatrixType_, UpLo_, Ordering_> > {
749 public:
750 using MatrixType = MatrixType_;
751 enum { UpLo = UpLo_ };
753 using Scalar = typename MatrixType::Scalar;
754 using RealScalar = typename MatrixType::RealScalar;
755 using StorageIndex = typename MatrixType::StorageIndex;
757 using VectorType = Matrix<Scalar, Dynamic, 1>;
758 using Traits = internal::traits<SimplicialNonHermitianLDLT>;
759 using MatrixL = typename Traits::MatrixL;
760 using MatrixU = typename Traits::MatrixU;
761
762 public:
765
767 explicit SimplicialNonHermitianLDLT(const MatrixType& matrix) : Base(matrix) {}
768
770 inline const VectorType vectorD() const {
771 eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized");
772 return Base::m_diag;
773 }
774
775 inline const MatrixL matrixL() const {
776 eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized");
777 return Traits::getL(Base::m_matrix);
778 }
779
781 inline const MatrixU matrixU() const {
782 eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized");
783 return Traits::getU(Base::m_matrix);
784 }
785
787 SimplicialNonHermitianLDLT& compute(const MatrixType& matrix) {
788 Base::template compute<true, true>(matrix);
789 return *this;
790 }
791
798 void analyzePattern(const MatrixType& a) { Base::template analyzePattern<true, true>(a); }
799
807 void factorize(const MatrixType& a) { Base::template factorize<true, true>(a); }
808
810 Scalar determinant() const {
811 eigen_assert(Base::m_factorizationIsOk && Base::m_info == Success &&
812 "Simplicial LDLT is not factorized, or its factorization failed");
813 return Base::m_diag.prod();
814 }
815
817 RealScalar absDeterminant() const {
818 eigen_assert(Base::m_factorizationIsOk && Base::m_info == Success &&
819 "Simplicial LDLT is not factorized, or its factorization failed");
820 return numext::abs(Base::m_diag.prod());
821 }
822
828 RealScalar logAbsDeterminant() const {
829 eigen_assert(Base::m_factorizationIsOk && Base::m_info == Success &&
830 "Simplicial LDLT is not factorized, or its factorization failed");
831 return Base::m_diag.cwiseAbs().array().log().sum();
832 }
833
835 Scalar signDeterminant() const {
836 eigen_assert(Base::m_factorizationIsOk && Base::m_info == Success &&
837 "Simplicial LDLT is not factorized, or its factorization failed");
838 return Base::m_diag.array().sign().prod();
839 }
840};
841
848template <typename MatrixType_, int UpLo_, typename Ordering_>
849class SimplicialCholesky : public SimplicialCholeskyBase<SimplicialCholesky<MatrixType_, UpLo_, Ordering_> > {
850 public:
851 using MatrixType = MatrixType_;
852 enum { UpLo = UpLo_ };
854 using Scalar = typename MatrixType::Scalar;
855 using RealScalar = typename MatrixType::RealScalar;
856 using StorageIndex = typename MatrixType::StorageIndex;
858 using VectorType = Matrix<Scalar, Dynamic, 1>;
859 using LDLTTraits = internal::traits<SimplicialLDLT<MatrixType, UpLo>>;
860 using LLTTraits = internal::traits<SimplicialLLT<MatrixType, UpLo>>;
861
862 public:
863 SimplicialCholesky() : Base(), m_LDLT(true) {}
864
865 explicit SimplicialCholesky(const MatrixType& matrix) : Base(), m_LDLT(true) { compute(matrix); }
866
867 SimplicialCholesky& setMode(SimplicialCholeskyMode mode) {
868 switch (mode) {
869 case SimplicialCholeskyLLT:
870 m_LDLT = false;
871 break;
872 case SimplicialCholeskyLDLT:
873 m_LDLT = true;
874 break;
875 default:
876 break;
877 }
878
879 return *this;
880 }
881
882 inline const VectorType vectorD() const {
883 eigen_assert(Base::m_factorizationIsOk && "Simplicial Cholesky not factorized");
884 return Base::m_diag;
885 }
886 inline const CholMatrixType rawMatrix() const {
887 eigen_assert(Base::m_factorizationIsOk && "Simplicial Cholesky not factorized");
888 return Base::m_matrix;
889 }
890
892 SimplicialCholesky& compute(const MatrixType& matrix) {
893 if (m_LDLT)
894 Base::template compute<true, false>(matrix);
895 else
896 Base::template compute<false, false>(matrix);
897 return *this;
898 }
899
906 void analyzePattern(const MatrixType& a) {
907 if (m_LDLT)
908 Base::template analyzePattern<true, false>(a);
909 else
910 Base::template analyzePattern<false, false>(a);
911 }
912
920 void factorize(const MatrixType& a) {
921 if (m_LDLT)
922 Base::template factorize<true, false>(a);
923 else
924 Base::template factorize<false, false>(a);
925 }
926
928 template <typename Rhs, typename Dest>
929 void _solve_impl(const MatrixBase<Rhs>& b, MatrixBase<Dest>& dest) const {
930 eigen_assert(Base::m_factorizationIsOk &&
931 "The decomposition is not in a valid state for solving, you must first call either compute() or "
932 "symbolic()/numeric()");
933 eigen_assert(Base::m_matrix.rows() == b.rows());
934
935 if (Base::m_info != Success) return;
936
937 if (Base::m_P.size() > 0)
938 dest = Base::m_P * b;
939 else
940 dest = b;
941
942 if (Base::m_matrix.nonZeros() > 0) // otherwise L==I
943 {
944 if (m_LDLT)
945 LDLTTraits::getL(Base::m_matrix).solveInPlace(dest);
946 else
947 LLTTraits::getL(Base::m_matrix).solveInPlace(dest);
948 }
949
950 if (Base::m_diag.size() > 0) dest = Base::m_diag.real().asDiagonal().inverse() * dest;
951
952 if (Base::m_matrix.nonZeros() > 0) // otherwise U==I
953 {
954 if (m_LDLT)
955 LDLTTraits::getU(Base::m_matrix).solveInPlace(dest);
956 else
957 LLTTraits::getU(Base::m_matrix).solveInPlace(dest);
958 }
959
960 if (Base::m_P.size() > 0) dest = Base::m_Pinv * dest;
961 }
962
964 template <typename Rhs, typename Dest>
965 void _solve_impl(const SparseMatrixBase<Rhs>& b, SparseMatrixBase<Dest>& dest) const {
966 internal::solve_sparse_through_dense_panels(*this, b, dest);
967 }
968
969 Scalar determinant() const {
970 eigen_assert(Base::m_factorizationIsOk && Base::m_info == Success &&
971 "Simplicial Cholesky is not factorized, or its factorization failed");
972 if (m_LDLT) {
973 return Base::m_diag.prod();
974 } else {
975 Scalar detL = Diagonal<const CholMatrixType>(Base::m_matrix).prod();
976 return numext::abs2(detL);
977 }
978 }
979
980 protected:
981 bool m_LDLT;
982};
983
984template <typename Derived>
985template <bool NonHermitian>
986void SimplicialCholeskyBase<Derived>::ordering(const MatrixType& a, ConstCholMatrixPtr& pmat, CholMatrixType& ap) {
987 eigen_assert(a.rows() == a.cols());
988 const Index size = a.rows();
989 pmat = &ap;
990 // Note that ordering methods compute the inverse permutation
991 EIGEN_IF_CONSTEXPR ((!std::is_same<OrderingType, NaturalOrdering<StorageIndex> >::value)) {
992 {
993 CholMatrixType C;
994 constexpr bool kUseAMDFastPath = std::is_same<OrderingType, AMDOrdering<StorageIndex> >::value;
995 internal::simplicial_cholesky_amd_dispatch<kUseAMDFastPath>::template run<UpLo, NonHermitian, OrderingType>(
996 a, C, m_Pinv);
997 }
998
999 if (m_Pinv.size() > 0)
1000 m_P = m_Pinv.inverse();
1001 else
1002 m_P.resize(0);
1003
1004 ap.resize(size, size);
1005 internal::permute_symm_to_symm<UpLo, Upper, NonHermitian>(a, ap, m_P.indices().data());
1006 } else {
1007 m_Pinv.resize(0);
1008 m_P.resize(0);
1009 EIGEN_IF_CONSTEXPR (int(UpLo) == int(Lower) || MatrixType::IsRowMajor) {
1010 // we have to transpose the lower part to the upper one
1011 ap.resize(size, size);
1012 internal::permute_symm_to_symm<UpLo, Upper, NonHermitian>(a, ap, nullptr);
1013 } else
1014 internal::simplicial_cholesky_grab_input<CholMatrixType, MatrixType>::run(a, pmat, ap);
1015 }
1016}
1017
1018} // end namespace Eigen
1019
1020#endif // EIGEN_SIMPLICIAL_CHOLESKY_H
Definition Ordering.h:31
constexpr RealReturnType real() const
Definition DenseBase.h:93
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:53
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:188
Definition Ordering.h:80
Index size() const
Definition PermutationMatrix.h:139
Permutation matrix.
Definition PermutationMatrix.h:346
constexpr const IndicesType & indices() const
Definition PermutationMatrix.h:400
SimplicialCholeskyBase()
Definition SimplicialCholesky.h:106
void compute(const MatrixType &matrix)
Definition SimplicialCholesky.h:213
ComputationInfo info() const
Reports whether previous computation was successful.
Definition SimplicialCholesky.h:125
const PermutationMatrix< Dynamic, Dynamic, StorageIndex > & permutationP() const
Definition SimplicialCholesky.h:132
Derived & setShift(const DiagonalScalar &offset, const DiagonalScalar &scale=1)
Definition SimplicialCholesky.h:148
const PermutationMatrix< Dynamic, Dynamic, StorageIndex > & permutationPinv() const
Definition SimplicialCholesky.h:136
Definition SimplicialCholesky.h:849
void factorize(const MatrixType &a)
Definition SimplicialCholesky.h:920
void analyzePattern(const MatrixType &a)
Definition SimplicialCholesky.h:906
SimplicialCholesky & compute(const MatrixType &matrix)
Definition SimplicialCholesky.h:892
A direct sparse LDLT Cholesky factorizations without square root.
Definition SimplicialCholesky.h:519
RealScalar logAbsDeterminant() const
Definition SimplicialCholesky.h:599
Scalar determinant() const
Definition SimplicialCholesky.h:581
const MatrixL matrixL() const
Definition SimplicialCholesky.h:546
SimplicialLDLT(const MatrixType &matrix)
Definition SimplicialCholesky.h:538
Scalar signDeterminant() const
Definition SimplicialCholesky.h:606
const MatrixU matrixU() const
Definition SimplicialCholesky.h:552
void analyzePattern(const MatrixType &a)
Definition SimplicialCholesky.h:569
void factorize(const MatrixType &a)
Definition SimplicialCholesky.h:578
const VectorType vectorD() const
Definition SimplicialCholesky.h:541
RealScalar absDeterminant() const
Definition SimplicialCholesky.h:588
SimplicialLDLT & compute(const MatrixType &matrix)
Definition SimplicialCholesky.h:558
SimplicialLDLT()
Definition SimplicialCholesky.h:535
A direct sparse LLT Cholesky factorizations.
Definition SimplicialCholesky.h:405
Scalar signDeterminant() const
Definition SimplicialCholesky.h:491
const MatrixL matrixL() const
Definition SimplicialCholesky.h:426
SimplicialLLT & compute(const MatrixType &matrix)
Definition SimplicialCholesky.h:438
Scalar determinant() const
Definition SimplicialCholesky.h:461
RealScalar logAbsDeterminant() const
Definition SimplicialCholesky.h:480
RealScalar absDeterminant() const
Definition SimplicialCholesky.h:469
const MatrixU matrixU() const
Definition SimplicialCholesky.h:432
SimplicialLLT()
Definition SimplicialCholesky.h:421
void analyzePattern(const MatrixType &a)
Definition SimplicialCholesky.h:449
void factorize(const MatrixType &a)
Definition SimplicialCholesky.h:458
SimplicialLLT(const MatrixType &matrix)
Definition SimplicialCholesky.h:423
A direct sparse LDLT Cholesky factorizations without square root, for symmetric non-hermitian matrice...
Definition SimplicialCholesky.h:748
SimplicialNonHermitianLDLT()
Definition SimplicialCholesky.h:764
Scalar determinant() const
Definition SimplicialCholesky.h:810
RealScalar absDeterminant() const
Definition SimplicialCholesky.h:817
Scalar signDeterminant() const
Definition SimplicialCholesky.h:835
RealScalar logAbsDeterminant() const
Definition SimplicialCholesky.h:828
SimplicialNonHermitianLDLT & compute(const MatrixType &matrix)
Definition SimplicialCholesky.h:787
const MatrixU matrixU() const
Definition SimplicialCholesky.h:781
const MatrixL matrixL() const
Definition SimplicialCholesky.h:775
const VectorType vectorD() const
Definition SimplicialCholesky.h:770
SimplicialNonHermitianLDLT(const MatrixType &matrix)
Definition SimplicialCholesky.h:767
void factorize(const MatrixType &a)
Definition SimplicialCholesky.h:807
void analyzePattern(const MatrixType &a)
Definition SimplicialCholesky.h:798
A direct sparse LLT Cholesky factorizations, for symmetric non-hermitian matrices.
Definition SimplicialCholesky.h:635
void factorize(const MatrixType &a)
Definition SimplicialCholesky.h:689
const MatrixU matrixU() const
Definition SimplicialCholesky.h:663
RealScalar absDeterminant() const
Definition SimplicialCholesky.h:700
SimplicialNonHermitianLLT()
Definition SimplicialCholesky.h:651
SimplicialNonHermitianLLT & compute(const MatrixType &matrix)
Definition SimplicialCholesky.h:669
Scalar determinant() const
Definition SimplicialCholesky.h:692
const MatrixL matrixL() const
Definition SimplicialCholesky.h:657
void analyzePattern(const MatrixType &a)
Definition SimplicialCholesky.h:680
RealScalar logAbsDeterminant() const
Definition SimplicialCholesky.h:711
SimplicialNonHermitianLLT(const MatrixType &matrix)
Definition SimplicialCholesky.h:654
Scalar signDeterminant() const
Definition SimplicialCholesky.h:718
A versatile sparse matrix representation.
Definition SparseMatrix.h:122
Index cols() const
Definition SparseMatrix.h:162
Index rows() const
Definition SparseMatrix.h:160
Index nonZeros() const
Definition SparseCompressedBase.h:65
ComputationInfo
Definition Constants.h:455
@ Lower
Definition Constants.h:212
@ Upper
Definition Constants.h:214
@ Success
Definition Constants.h:457
Definition SimplicialCholesky.h:264