File indexing completed on 2025-12-17 10:25:20
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef EIGEN_SIMPLICIAL_CHOLESKY_H
0011 #define EIGEN_SIMPLICIAL_CHOLESKY_H
0012
0013 namespace RivetEigen {
0014
0015 enum SimplicialCholeskyMode {
0016 SimplicialCholeskyLLT,
0017 SimplicialCholeskyLDLT
0018 };
0019
0020 namespace internal {
0021 template<typename CholMatrixType, typename InputMatrixType>
0022 struct simplicial_cholesky_grab_input {
0023 typedef CholMatrixType const * ConstCholMatrixPtr;
0024 static void run(const InputMatrixType& input, ConstCholMatrixPtr &pmat, CholMatrixType &tmp)
0025 {
0026 tmp = input;
0027 pmat = &tmp;
0028 }
0029 };
0030
0031 template<typename MatrixType>
0032 struct simplicial_cholesky_grab_input<MatrixType,MatrixType> {
0033 typedef MatrixType const * ConstMatrixPtr;
0034 static void run(const MatrixType& input, ConstMatrixPtr &pmat, MatrixType &)
0035 {
0036 pmat = &input;
0037 }
0038 };
0039 }
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 template<typename Derived>
0055 class SimplicialCholeskyBase : public SparseSolverBase<Derived>
0056 {
0057 typedef SparseSolverBase<Derived> Base;
0058 using Base::m_isInitialized;
0059
0060 public:
0061 typedef typename internal::traits<Derived>::MatrixType MatrixType;
0062 typedef typename internal::traits<Derived>::OrderingType OrderingType;
0063 enum { UpLo = internal::traits<Derived>::UpLo };
0064 typedef typename MatrixType::Scalar Scalar;
0065 typedef typename MatrixType::RealScalar RealScalar;
0066 typedef typename MatrixType::StorageIndex StorageIndex;
0067 typedef SparseMatrix<Scalar,ColMajor,StorageIndex> CholMatrixType;
0068 typedef CholMatrixType const * ConstCholMatrixPtr;
0069 typedef Matrix<Scalar,Dynamic,1> VectorType;
0070 typedef Matrix<StorageIndex,Dynamic,1> VectorI;
0071
0072 enum {
0073 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
0074 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
0075 };
0076
0077 public:
0078
0079 using Base::derived;
0080
0081
0082 SimplicialCholeskyBase()
0083 : m_info(Success),
0084 m_factorizationIsOk(false),
0085 m_analysisIsOk(false),
0086 m_shiftOffset(0),
0087 m_shiftScale(1)
0088 {}
0089
0090 explicit SimplicialCholeskyBase(const MatrixType& matrix)
0091 : m_info(Success),
0092 m_factorizationIsOk(false),
0093 m_analysisIsOk(false),
0094 m_shiftOffset(0),
0095 m_shiftScale(1)
0096 {
0097 derived().compute(matrix);
0098 }
0099
0100 ~SimplicialCholeskyBase()
0101 {
0102 }
0103
0104 Derived& derived() { return *static_cast<Derived*>(this); }
0105 const Derived& derived() const { return *static_cast<const Derived*>(this); }
0106
0107 inline Index cols() const { return m_matrix.cols(); }
0108 inline Index rows() const { return m_matrix.rows(); }
0109
0110
0111
0112
0113
0114
0115 ComputationInfo info() const
0116 {
0117 eigen_assert(m_isInitialized && "Decomposition is not initialized.");
0118 return m_info;
0119 }
0120
0121
0122
0123 const PermutationMatrix<Dynamic,Dynamic,StorageIndex>& permutationP() const
0124 { return m_P; }
0125
0126
0127
0128 const PermutationMatrix<Dynamic,Dynamic,StorageIndex>& permutationPinv() const
0129 { return m_Pinv; }
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140 Derived& setShift(const RealScalar& offset, const RealScalar& scale = 1)
0141 {
0142 m_shiftOffset = offset;
0143 m_shiftScale = scale;
0144 return derived();
0145 }
0146
0147 #ifndef EIGEN_PARSED_BY_DOXYGEN
0148
0149 template<typename Stream>
0150 void dumpMemory(Stream& s)
0151 {
0152 int total = 0;
0153 s << " L: " << ((total+=(m_matrix.cols()+1) * sizeof(int) + m_matrix.nonZeros()*(sizeof(int)+sizeof(Scalar))) >> 20) << "Mb" << "\n";
0154 s << " diag: " << ((total+=m_diag.size() * sizeof(Scalar)) >> 20) << "Mb" << "\n";
0155 s << " tree: " << ((total+=m_parent.size() * sizeof(int)) >> 20) << "Mb" << "\n";
0156 s << " nonzeros: " << ((total+=m_nonZerosPerCol.size() * sizeof(int)) >> 20) << "Mb" << "\n";
0157 s << " perm: " << ((total+=m_P.size() * sizeof(int)) >> 20) << "Mb" << "\n";
0158 s << " perm^-1: " << ((total+=m_Pinv.size() * sizeof(int)) >> 20) << "Mb" << "\n";
0159 s << " TOTAL: " << (total>> 20) << "Mb" << "\n";
0160 }
0161
0162
0163 template<typename Rhs,typename Dest>
0164 void _solve_impl(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const
0165 {
0166 eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
0167 eigen_assert(m_matrix.rows()==b.rows());
0168
0169 if(m_info!=Success)
0170 return;
0171
0172 if(m_P.size()>0)
0173 dest = m_P * b;
0174 else
0175 dest = b;
0176
0177 if(m_matrix.nonZeros()>0)
0178 derived().matrixL().solveInPlace(dest);
0179
0180 if(m_diag.size()>0)
0181 dest = m_diag.asDiagonal().inverse() * dest;
0182
0183 if (m_matrix.nonZeros()>0)
0184 derived().matrixU().solveInPlace(dest);
0185
0186 if(m_P.size()>0)
0187 dest = m_Pinv * dest;
0188 }
0189
0190 template<typename Rhs,typename Dest>
0191 void _solve_impl(const SparseMatrixBase<Rhs> &b, SparseMatrixBase<Dest> &dest) const
0192 {
0193 internal::solve_sparse_through_dense_panels(derived(), b, dest);
0194 }
0195
0196 #endif
0197
0198 protected:
0199
0200
0201 template<bool DoLDLT>
0202 void compute(const MatrixType& matrix)
0203 {
0204 eigen_assert(matrix.rows()==matrix.cols());
0205 Index size = matrix.cols();
0206 CholMatrixType tmp(size,size);
0207 ConstCholMatrixPtr pmat;
0208 ordering(matrix, pmat, tmp);
0209 analyzePattern_preordered(*pmat, DoLDLT);
0210 factorize_preordered<DoLDLT>(*pmat);
0211 }
0212
0213 template<bool DoLDLT>
0214 void factorize(const MatrixType& a)
0215 {
0216 eigen_assert(a.rows()==a.cols());
0217 Index size = a.cols();
0218 CholMatrixType tmp(size,size);
0219 ConstCholMatrixPtr pmat;
0220
0221 if(m_P.size() == 0 && (int(UpLo) & int(Upper)) == Upper)
0222 {
0223
0224 internal::simplicial_cholesky_grab_input<CholMatrixType,MatrixType>::run(a, pmat, tmp);
0225 }
0226 else
0227 {
0228 tmp.template selfadjointView<Upper>() = a.template selfadjointView<UpLo>().twistedBy(m_P);
0229 pmat = &tmp;
0230 }
0231
0232 factorize_preordered<DoLDLT>(*pmat);
0233 }
0234
0235 template<bool DoLDLT>
0236 void factorize_preordered(const CholMatrixType& a);
0237
0238 void analyzePattern(const MatrixType& a, bool doLDLT)
0239 {
0240 eigen_assert(a.rows()==a.cols());
0241 Index size = a.cols();
0242 CholMatrixType tmp(size,size);
0243 ConstCholMatrixPtr pmat;
0244 ordering(a, pmat, tmp);
0245 analyzePattern_preordered(*pmat,doLDLT);
0246 }
0247 void analyzePattern_preordered(const CholMatrixType& a, bool doLDLT);
0248
0249 void ordering(const MatrixType& a, ConstCholMatrixPtr &pmat, CholMatrixType& ap);
0250
0251
0252 struct keep_diag {
0253 inline bool operator() (const Index& row, const Index& col, const Scalar&) const
0254 {
0255 return row!=col;
0256 }
0257 };
0258
0259 mutable ComputationInfo m_info;
0260 bool m_factorizationIsOk;
0261 bool m_analysisIsOk;
0262
0263 CholMatrixType m_matrix;
0264 VectorType m_diag;
0265 VectorI m_parent;
0266 VectorI m_nonZerosPerCol;
0267 PermutationMatrix<Dynamic,Dynamic,StorageIndex> m_P;
0268 PermutationMatrix<Dynamic,Dynamic,StorageIndex> m_Pinv;
0269
0270 RealScalar m_shiftOffset;
0271 RealScalar m_shiftScale;
0272 };
0273
0274 template<typename _MatrixType, int _UpLo = Lower, typename _Ordering = AMDOrdering<typename _MatrixType::StorageIndex> > class SimplicialLLT;
0275 template<typename _MatrixType, int _UpLo = Lower, typename _Ordering = AMDOrdering<typename _MatrixType::StorageIndex> > class SimplicialLDLT;
0276 template<typename _MatrixType, int _UpLo = Lower, typename _Ordering = AMDOrdering<typename _MatrixType::StorageIndex> > class SimplicialCholesky;
0277
0278 namespace internal {
0279
0280 template<typename _MatrixType, int _UpLo, typename _Ordering> struct traits<SimplicialLLT<_MatrixType,_UpLo,_Ordering> >
0281 {
0282 typedef _MatrixType MatrixType;
0283 typedef _Ordering OrderingType;
0284 enum { UpLo = _UpLo };
0285 typedef typename MatrixType::Scalar Scalar;
0286 typedef typename MatrixType::StorageIndex StorageIndex;
0287 typedef SparseMatrix<Scalar, ColMajor, StorageIndex> CholMatrixType;
0288 typedef TriangularView<const CholMatrixType, RivetEigen::Lower> MatrixL;
0289 typedef TriangularView<const typename CholMatrixType::AdjointReturnType, RivetEigen::Upper> MatrixU;
0290 static inline MatrixL getL(const CholMatrixType& m) { return MatrixL(m); }
0291 static inline MatrixU getU(const CholMatrixType& m) { return MatrixU(m.adjoint()); }
0292 };
0293
0294 template<typename _MatrixType,int _UpLo, typename _Ordering> struct traits<SimplicialLDLT<_MatrixType,_UpLo,_Ordering> >
0295 {
0296 typedef _MatrixType MatrixType;
0297 typedef _Ordering OrderingType;
0298 enum { UpLo = _UpLo };
0299 typedef typename MatrixType::Scalar Scalar;
0300 typedef typename MatrixType::StorageIndex StorageIndex;
0301 typedef SparseMatrix<Scalar, ColMajor, StorageIndex> CholMatrixType;
0302 typedef TriangularView<const CholMatrixType, RivetEigen::UnitLower> MatrixL;
0303 typedef TriangularView<const typename CholMatrixType::AdjointReturnType, RivetEigen::UnitUpper> MatrixU;
0304 static inline MatrixL getL(const CholMatrixType& m) { return MatrixL(m); }
0305 static inline MatrixU getU(const CholMatrixType& m) { return MatrixU(m.adjoint()); }
0306 };
0307
0308 template<typename _MatrixType, int _UpLo, typename _Ordering> struct traits<SimplicialCholesky<_MatrixType,_UpLo,_Ordering> >
0309 {
0310 typedef _MatrixType MatrixType;
0311 typedef _Ordering OrderingType;
0312 enum { UpLo = _UpLo };
0313 };
0314
0315 }
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337 template<typename _MatrixType, int _UpLo, typename _Ordering>
0338 class SimplicialLLT : public SimplicialCholeskyBase<SimplicialLLT<_MatrixType,_UpLo,_Ordering> >
0339 {
0340 public:
0341 typedef _MatrixType MatrixType;
0342 enum { UpLo = _UpLo };
0343 typedef SimplicialCholeskyBase<SimplicialLLT> Base;
0344 typedef typename MatrixType::Scalar Scalar;
0345 typedef typename MatrixType::RealScalar RealScalar;
0346 typedef typename MatrixType::StorageIndex StorageIndex;
0347 typedef SparseMatrix<Scalar,ColMajor,Index> CholMatrixType;
0348 typedef Matrix<Scalar,Dynamic,1> VectorType;
0349 typedef internal::traits<SimplicialLLT> Traits;
0350 typedef typename Traits::MatrixL MatrixL;
0351 typedef typename Traits::MatrixU MatrixU;
0352 public:
0353
0354 SimplicialLLT() : Base() {}
0355
0356 explicit SimplicialLLT(const MatrixType& matrix)
0357 : Base(matrix) {}
0358
0359
0360 inline const MatrixL matrixL() const {
0361 eigen_assert(Base::m_factorizationIsOk && "Simplicial LLT not factorized");
0362 return Traits::getL(Base::m_matrix);
0363 }
0364
0365
0366 inline const MatrixU matrixU() const {
0367 eigen_assert(Base::m_factorizationIsOk && "Simplicial LLT not factorized");
0368 return Traits::getU(Base::m_matrix);
0369 }
0370
0371
0372 SimplicialLLT& compute(const MatrixType& matrix)
0373 {
0374 Base::template compute<false>(matrix);
0375 return *this;
0376 }
0377
0378
0379
0380
0381
0382
0383
0384 void analyzePattern(const MatrixType& a)
0385 {
0386 Base::analyzePattern(a, false);
0387 }
0388
0389
0390
0391
0392
0393
0394
0395 void factorize(const MatrixType& a)
0396 {
0397 Base::template factorize<false>(a);
0398 }
0399
0400
0401 Scalar determinant() const
0402 {
0403 Scalar detL = Base::m_matrix.diagonal().prod();
0404 return numext::abs2(detL);
0405 }
0406 };
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428 template<typename _MatrixType, int _UpLo, typename _Ordering>
0429 class SimplicialLDLT : public SimplicialCholeskyBase<SimplicialLDLT<_MatrixType,_UpLo,_Ordering> >
0430 {
0431 public:
0432 typedef _MatrixType MatrixType;
0433 enum { UpLo = _UpLo };
0434 typedef SimplicialCholeskyBase<SimplicialLDLT> Base;
0435 typedef typename MatrixType::Scalar Scalar;
0436 typedef typename MatrixType::RealScalar RealScalar;
0437 typedef typename MatrixType::StorageIndex StorageIndex;
0438 typedef SparseMatrix<Scalar,ColMajor,StorageIndex> CholMatrixType;
0439 typedef Matrix<Scalar,Dynamic,1> VectorType;
0440 typedef internal::traits<SimplicialLDLT> Traits;
0441 typedef typename Traits::MatrixL MatrixL;
0442 typedef typename Traits::MatrixU MatrixU;
0443 public:
0444
0445 SimplicialLDLT() : Base() {}
0446
0447
0448 explicit SimplicialLDLT(const MatrixType& matrix)
0449 : Base(matrix) {}
0450
0451
0452 inline const VectorType vectorD() const {
0453 eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized");
0454 return Base::m_diag;
0455 }
0456
0457 inline const MatrixL matrixL() const {
0458 eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized");
0459 return Traits::getL(Base::m_matrix);
0460 }
0461
0462
0463 inline const MatrixU matrixU() const {
0464 eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized");
0465 return Traits::getU(Base::m_matrix);
0466 }
0467
0468
0469 SimplicialLDLT& compute(const MatrixType& matrix)
0470 {
0471 Base::template compute<true>(matrix);
0472 return *this;
0473 }
0474
0475
0476
0477
0478
0479
0480
0481 void analyzePattern(const MatrixType& a)
0482 {
0483 Base::analyzePattern(a, true);
0484 }
0485
0486
0487
0488
0489
0490
0491
0492 void factorize(const MatrixType& a)
0493 {
0494 Base::template factorize<true>(a);
0495 }
0496
0497
0498 Scalar determinant() const
0499 {
0500 return Base::m_diag.prod();
0501 }
0502 };
0503
0504
0505
0506
0507
0508
0509
0510 template<typename _MatrixType, int _UpLo, typename _Ordering>
0511 class SimplicialCholesky : public SimplicialCholeskyBase<SimplicialCholesky<_MatrixType,_UpLo,_Ordering> >
0512 {
0513 public:
0514 typedef _MatrixType MatrixType;
0515 enum { UpLo = _UpLo };
0516 typedef SimplicialCholeskyBase<SimplicialCholesky> Base;
0517 typedef typename MatrixType::Scalar Scalar;
0518 typedef typename MatrixType::RealScalar RealScalar;
0519 typedef typename MatrixType::StorageIndex StorageIndex;
0520 typedef SparseMatrix<Scalar,ColMajor,StorageIndex> CholMatrixType;
0521 typedef Matrix<Scalar,Dynamic,1> VectorType;
0522 typedef internal::traits<SimplicialCholesky> Traits;
0523 typedef internal::traits<SimplicialLDLT<MatrixType,UpLo> > LDLTTraits;
0524 typedef internal::traits<SimplicialLLT<MatrixType,UpLo> > LLTTraits;
0525 public:
0526 SimplicialCholesky() : Base(), m_LDLT(true) {}
0527
0528 explicit SimplicialCholesky(const MatrixType& matrix)
0529 : Base(), m_LDLT(true)
0530 {
0531 compute(matrix);
0532 }
0533
0534 SimplicialCholesky& setMode(SimplicialCholeskyMode mode)
0535 {
0536 switch(mode)
0537 {
0538 case SimplicialCholeskyLLT:
0539 m_LDLT = false;
0540 break;
0541 case SimplicialCholeskyLDLT:
0542 m_LDLT = true;
0543 break;
0544 default:
0545 break;
0546 }
0547
0548 return *this;
0549 }
0550
0551 inline const VectorType vectorD() const {
0552 eigen_assert(Base::m_factorizationIsOk && "Simplicial Cholesky not factorized");
0553 return Base::m_diag;
0554 }
0555 inline const CholMatrixType rawMatrix() const {
0556 eigen_assert(Base::m_factorizationIsOk && "Simplicial Cholesky not factorized");
0557 return Base::m_matrix;
0558 }
0559
0560
0561 SimplicialCholesky& compute(const MatrixType& matrix)
0562 {
0563 if(m_LDLT)
0564 Base::template compute<true>(matrix);
0565 else
0566 Base::template compute<false>(matrix);
0567 return *this;
0568 }
0569
0570
0571
0572
0573
0574
0575
0576 void analyzePattern(const MatrixType& a)
0577 {
0578 Base::analyzePattern(a, m_LDLT);
0579 }
0580
0581
0582
0583
0584
0585
0586
0587 void factorize(const MatrixType& a)
0588 {
0589 if(m_LDLT)
0590 Base::template factorize<true>(a);
0591 else
0592 Base::template factorize<false>(a);
0593 }
0594
0595
0596 template<typename Rhs,typename Dest>
0597 void _solve_impl(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const
0598 {
0599 eigen_assert(Base::m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
0600 eigen_assert(Base::m_matrix.rows()==b.rows());
0601
0602 if(Base::m_info!=Success)
0603 return;
0604
0605 if(Base::m_P.size()>0)
0606 dest = Base::m_P * b;
0607 else
0608 dest = b;
0609
0610 if(Base::m_matrix.nonZeros()>0)
0611 {
0612 if(m_LDLT)
0613 LDLTTraits::getL(Base::m_matrix).solveInPlace(dest);
0614 else
0615 LLTTraits::getL(Base::m_matrix).solveInPlace(dest);
0616 }
0617
0618 if(Base::m_diag.size()>0)
0619 dest = Base::m_diag.real().asDiagonal().inverse() * dest;
0620
0621 if (Base::m_matrix.nonZeros()>0)
0622 {
0623 if(m_LDLT)
0624 LDLTTraits::getU(Base::m_matrix).solveInPlace(dest);
0625 else
0626 LLTTraits::getU(Base::m_matrix).solveInPlace(dest);
0627 }
0628
0629 if(Base::m_P.size()>0)
0630 dest = Base::m_Pinv * dest;
0631 }
0632
0633
0634 template<typename Rhs,typename Dest>
0635 void _solve_impl(const SparseMatrixBase<Rhs> &b, SparseMatrixBase<Dest> &dest) const
0636 {
0637 internal::solve_sparse_through_dense_panels(*this, b, dest);
0638 }
0639
0640 Scalar determinant() const
0641 {
0642 if(m_LDLT)
0643 {
0644 return Base::m_diag.prod();
0645 }
0646 else
0647 {
0648 Scalar detL = Diagonal<const CholMatrixType>(Base::m_matrix).prod();
0649 return numext::abs2(detL);
0650 }
0651 }
0652
0653 protected:
0654 bool m_LDLT;
0655 };
0656
0657 template<typename Derived>
0658 void SimplicialCholeskyBase<Derived>::ordering(const MatrixType& a, ConstCholMatrixPtr &pmat, CholMatrixType& ap)
0659 {
0660 eigen_assert(a.rows()==a.cols());
0661 const Index size = a.rows();
0662 pmat = ≈
0663
0664 if(!internal::is_same<OrderingType,NaturalOrdering<Index> >::value)
0665 {
0666 {
0667 CholMatrixType C;
0668 C = a.template selfadjointView<UpLo>();
0669
0670 OrderingType ordering;
0671 ordering(C,m_Pinv);
0672 }
0673
0674 if(m_Pinv.size()>0) m_P = m_Pinv.inverse();
0675 else m_P.resize(0);
0676
0677 ap.resize(size,size);
0678 ap.template selfadjointView<Upper>() = a.template selfadjointView<UpLo>().twistedBy(m_P);
0679 }
0680 else
0681 {
0682 m_Pinv.resize(0);
0683 m_P.resize(0);
0684 if(int(UpLo)==int(Lower) || MatrixType::IsRowMajor)
0685 {
0686
0687 ap.resize(size,size);
0688 ap.template selfadjointView<Upper>() = a.template selfadjointView<UpLo>();
0689 }
0690 else
0691 internal::simplicial_cholesky_grab_input<CholMatrixType,MatrixType>::run(a, pmat, ap);
0692 }
0693 }
0694
0695 }
0696
0697 #endif