Warning, file /include/eigen3/Eigen/src/CholmodSupport/CholmodSupport.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef EIGEN_CHOLMODSUPPORT_H
0011 #define EIGEN_CHOLMODSUPPORT_H
0012
0013 namespace Eigen {
0014
0015 namespace internal {
0016
0017 template<typename Scalar> struct cholmod_configure_matrix;
0018
0019 template<> struct cholmod_configure_matrix<double> {
0020 template<typename CholmodType>
0021 static void run(CholmodType& mat) {
0022 mat.xtype = CHOLMOD_REAL;
0023 mat.dtype = CHOLMOD_DOUBLE;
0024 }
0025 };
0026
0027 template<> struct cholmod_configure_matrix<std::complex<double> > {
0028 template<typename CholmodType>
0029 static void run(CholmodType& mat) {
0030 mat.xtype = CHOLMOD_COMPLEX;
0031 mat.dtype = CHOLMOD_DOUBLE;
0032 }
0033 };
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 }
0053
0054
0055
0056
0057 template<typename _Scalar, int _Options, typename _StorageIndex>
0058 cholmod_sparse viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_StorageIndex> > mat)
0059 {
0060 cholmod_sparse res;
0061 res.nzmax = mat.nonZeros();
0062 res.nrow = mat.rows();
0063 res.ncol = mat.cols();
0064 res.p = mat.outerIndexPtr();
0065 res.i = mat.innerIndexPtr();
0066 res.x = mat.valuePtr();
0067 res.z = 0;
0068 res.sorted = 1;
0069 if(mat.isCompressed())
0070 {
0071 res.packed = 1;
0072 res.nz = 0;
0073 }
0074 else
0075 {
0076 res.packed = 0;
0077 res.nz = mat.innerNonZeroPtr();
0078 }
0079
0080 res.dtype = 0;
0081 res.stype = -1;
0082
0083 if (internal::is_same<_StorageIndex,int>::value)
0084 {
0085 res.itype = CHOLMOD_INT;
0086 }
0087 else if (internal::is_same<_StorageIndex,SuiteSparse_long>::value)
0088 {
0089 res.itype = CHOLMOD_LONG;
0090 }
0091 else
0092 {
0093 eigen_assert(false && "Index type not supported yet");
0094 }
0095
0096
0097 internal::cholmod_configure_matrix<_Scalar>::run(res);
0098
0099 res.stype = 0;
0100
0101 return res;
0102 }
0103
0104 template<typename _Scalar, int _Options, typename _Index>
0105 const cholmod_sparse viewAsCholmod(const SparseMatrix<_Scalar,_Options,_Index>& mat)
0106 {
0107 cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.const_cast_derived()));
0108 return res;
0109 }
0110
0111 template<typename _Scalar, int _Options, typename _Index>
0112 const cholmod_sparse viewAsCholmod(const SparseVector<_Scalar,_Options,_Index>& mat)
0113 {
0114 cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.const_cast_derived()));
0115 return res;
0116 }
0117
0118
0119
0120 template<typename _Scalar, int _Options, typename _Index, unsigned int UpLo>
0121 cholmod_sparse viewAsCholmod(const SparseSelfAdjointView<const SparseMatrix<_Scalar,_Options,_Index>, UpLo>& mat)
0122 {
0123 cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.matrix().const_cast_derived()));
0124
0125 if(UpLo==Upper) res.stype = 1;
0126 if(UpLo==Lower) res.stype = -1;
0127
0128 EIGEN_STATIC_ASSERT((_Options & RowMajorBit) == 0 || NumTraits<_Scalar>::IsComplex == 0, THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
0129 if(_Options & RowMajorBit) res.stype *=-1;
0130
0131 return res;
0132 }
0133
0134
0135
0136 template<typename Derived>
0137 cholmod_dense viewAsCholmod(MatrixBase<Derived>& mat)
0138 {
0139 EIGEN_STATIC_ASSERT((internal::traits<Derived>::Flags&RowMajorBit)==0,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
0140 typedef typename Derived::Scalar Scalar;
0141
0142 cholmod_dense res;
0143 res.nrow = mat.rows();
0144 res.ncol = mat.cols();
0145 res.nzmax = res.nrow * res.ncol;
0146 res.d = Derived::IsVectorAtCompileTime ? mat.derived().size() : mat.derived().outerStride();
0147 res.x = (void*)(mat.derived().data());
0148 res.z = 0;
0149
0150 internal::cholmod_configure_matrix<Scalar>::run(res);
0151
0152 return res;
0153 }
0154
0155
0156
0157 template<typename Scalar, int Flags, typename StorageIndex>
0158 MappedSparseMatrix<Scalar,Flags,StorageIndex> viewAsEigen(cholmod_sparse& cm)
0159 {
0160 return MappedSparseMatrix<Scalar,Flags,StorageIndex>
0161 (cm.nrow, cm.ncol, static_cast<StorageIndex*>(cm.p)[cm.ncol],
0162 static_cast<StorageIndex*>(cm.p), static_cast<StorageIndex*>(cm.i),static_cast<Scalar*>(cm.x) );
0163 }
0164
0165 namespace internal {
0166
0167
0168
0169 #define EIGEN_CHOLMOD_SPECIALIZE0(ret, name) \
0170 template<typename _StorageIndex> inline ret cm_ ## name (cholmod_common &Common) { return cholmod_ ## name (&Common); } \
0171 template<> inline ret cm_ ## name<SuiteSparse_long> (cholmod_common &Common) { return cholmod_l_ ## name (&Common); }
0172
0173 #define EIGEN_CHOLMOD_SPECIALIZE1(ret, name, t1, a1) \
0174 template<typename _StorageIndex> inline ret cm_ ## name (t1& a1, cholmod_common &Common) { return cholmod_ ## name (&a1, &Common); } \
0175 template<> inline ret cm_ ## name<SuiteSparse_long> (t1& a1, cholmod_common &Common) { return cholmod_l_ ## name (&a1, &Common); }
0176
0177 EIGEN_CHOLMOD_SPECIALIZE0(int, start)
0178 EIGEN_CHOLMOD_SPECIALIZE0(int, finish)
0179
0180 EIGEN_CHOLMOD_SPECIALIZE1(int, free_factor, cholmod_factor*, L)
0181 EIGEN_CHOLMOD_SPECIALIZE1(int, free_dense, cholmod_dense*, X)
0182 EIGEN_CHOLMOD_SPECIALIZE1(int, free_sparse, cholmod_sparse*, A)
0183
0184 EIGEN_CHOLMOD_SPECIALIZE1(cholmod_factor*, analyze, cholmod_sparse, A)
0185
0186 template<typename _StorageIndex> inline cholmod_dense* cm_solve (int sys, cholmod_factor& L, cholmod_dense& B, cholmod_common &Common) { return cholmod_solve (sys, &L, &B, &Common); }
0187 template<> inline cholmod_dense* cm_solve<SuiteSparse_long> (int sys, cholmod_factor& L, cholmod_dense& B, cholmod_common &Common) { return cholmod_l_solve (sys, &L, &B, &Common); }
0188
0189 template<typename _StorageIndex> inline cholmod_sparse* cm_spsolve (int sys, cholmod_factor& L, cholmod_sparse& B, cholmod_common &Common) { return cholmod_spsolve (sys, &L, &B, &Common); }
0190 template<> inline cholmod_sparse* cm_spsolve<SuiteSparse_long> (int sys, cholmod_factor& L, cholmod_sparse& B, cholmod_common &Common) { return cholmod_l_spsolve (sys, &L, &B, &Common); }
0191
0192 template<typename _StorageIndex>
0193 inline int cm_factorize_p (cholmod_sparse* A, double beta[2], _StorageIndex* fset, std::size_t fsize, cholmod_factor* L, cholmod_common &Common) { return cholmod_factorize_p (A, beta, fset, fsize, L, &Common); }
0194 template<>
0195 inline int cm_factorize_p<SuiteSparse_long> (cholmod_sparse* A, double beta[2], SuiteSparse_long* fset, std::size_t fsize, cholmod_factor* L, cholmod_common &Common) { return cholmod_l_factorize_p (A, beta, fset, fsize, L, &Common); }
0196
0197 #undef EIGEN_CHOLMOD_SPECIALIZE0
0198 #undef EIGEN_CHOLMOD_SPECIALIZE1
0199
0200 }
0201
0202
0203 enum CholmodMode {
0204 CholmodAuto, CholmodSimplicialLLt, CholmodSupernodalLLt, CholmodLDLt
0205 };
0206
0207
0208
0209
0210
0211
0212
0213 template<typename _MatrixType, int _UpLo, typename Derived>
0214 class CholmodBase : public SparseSolverBase<Derived>
0215 {
0216 protected:
0217 typedef SparseSolverBase<Derived> Base;
0218 using Base::derived;
0219 using Base::m_isInitialized;
0220 public:
0221 typedef _MatrixType MatrixType;
0222 enum { UpLo = _UpLo };
0223 typedef typename MatrixType::Scalar Scalar;
0224 typedef typename MatrixType::RealScalar RealScalar;
0225 typedef MatrixType CholMatrixType;
0226 typedef typename MatrixType::StorageIndex StorageIndex;
0227 enum {
0228 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
0229 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
0230 };
0231
0232 public:
0233
0234 CholmodBase()
0235 : m_cholmodFactor(0), m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false)
0236 {
0237 EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
0238 m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
0239 internal::cm_start<StorageIndex>(m_cholmod);
0240 }
0241
0242 explicit CholmodBase(const MatrixType& matrix)
0243 : m_cholmodFactor(0), m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false)
0244 {
0245 EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
0246 m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
0247 internal::cm_start<StorageIndex>(m_cholmod);
0248 compute(matrix);
0249 }
0250
0251 ~CholmodBase()
0252 {
0253 if(m_cholmodFactor)
0254 internal::cm_free_factor<StorageIndex>(m_cholmodFactor, m_cholmod);
0255 internal::cm_finish<StorageIndex>(m_cholmod);
0256 }
0257
0258 inline StorageIndex cols() const { return internal::convert_index<StorageIndex, Index>(m_cholmodFactor->n); }
0259 inline StorageIndex rows() const { return internal::convert_index<StorageIndex, Index>(m_cholmodFactor->n); }
0260
0261
0262
0263
0264
0265
0266 ComputationInfo info() const
0267 {
0268 eigen_assert(m_isInitialized && "Decomposition is not initialized.");
0269 return m_info;
0270 }
0271
0272
0273 Derived& compute(const MatrixType& matrix)
0274 {
0275 analyzePattern(matrix);
0276 factorize(matrix);
0277 return derived();
0278 }
0279
0280
0281
0282
0283
0284
0285
0286 void analyzePattern(const MatrixType& matrix)
0287 {
0288 if(m_cholmodFactor)
0289 {
0290 internal::cm_free_factor<StorageIndex>(m_cholmodFactor, m_cholmod);
0291 m_cholmodFactor = 0;
0292 }
0293 cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
0294 m_cholmodFactor = internal::cm_analyze<StorageIndex>(A, m_cholmod);
0295
0296 this->m_isInitialized = true;
0297 this->m_info = Success;
0298 m_analysisIsOk = true;
0299 m_factorizationIsOk = false;
0300 }
0301
0302
0303
0304
0305
0306
0307
0308 void factorize(const MatrixType& matrix)
0309 {
0310 eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
0311 cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
0312 internal::cm_factorize_p<StorageIndex>(&A, m_shiftOffset, 0, 0, m_cholmodFactor, m_cholmod);
0313
0314
0315 this->m_info = (m_cholmodFactor->minor == m_cholmodFactor->n ? Success : NumericalIssue);
0316 m_factorizationIsOk = true;
0317 }
0318
0319
0320
0321 cholmod_common& cholmod() { return m_cholmod; }
0322
0323 #ifndef EIGEN_PARSED_BY_DOXYGEN
0324
0325 template<typename Rhs,typename Dest>
0326 void _solve_impl(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const
0327 {
0328 eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
0329 const Index size = m_cholmodFactor->n;
0330 EIGEN_UNUSED_VARIABLE(size);
0331 eigen_assert(size==b.rows());
0332
0333
0334 Ref<const Matrix<typename Rhs::Scalar,Dynamic,Dynamic,ColMajor> > b_ref(b.derived());
0335
0336 cholmod_dense b_cd = viewAsCholmod(b_ref);
0337 cholmod_dense* x_cd = internal::cm_solve<StorageIndex>(CHOLMOD_A, *m_cholmodFactor, b_cd, m_cholmod);
0338 if(!x_cd)
0339 {
0340 this->m_info = NumericalIssue;
0341 return;
0342 }
0343
0344
0345 dest = Matrix<Scalar,Dest::RowsAtCompileTime,Dest::ColsAtCompileTime>::Map(reinterpret_cast<Scalar*>(x_cd->x),b.rows(),b.cols());
0346 internal::cm_free_dense<StorageIndex>(x_cd, m_cholmod);
0347 }
0348
0349
0350 template<typename RhsDerived, typename DestDerived>
0351 void _solve_impl(const SparseMatrixBase<RhsDerived> &b, SparseMatrixBase<DestDerived> &dest) const
0352 {
0353 eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
0354 const Index size = m_cholmodFactor->n;
0355 EIGEN_UNUSED_VARIABLE(size);
0356 eigen_assert(size==b.rows());
0357
0358
0359 Ref<SparseMatrix<typename RhsDerived::Scalar,ColMajor,typename RhsDerived::StorageIndex> > b_ref(b.const_cast_derived());
0360 cholmod_sparse b_cs = viewAsCholmod(b_ref);
0361 cholmod_sparse* x_cs = internal::cm_spsolve<StorageIndex>(CHOLMOD_A, *m_cholmodFactor, b_cs, m_cholmod);
0362 if(!x_cs)
0363 {
0364 this->m_info = NumericalIssue;
0365 return;
0366 }
0367
0368
0369 dest.derived() = viewAsEigen<typename DestDerived::Scalar,ColMajor,typename DestDerived::StorageIndex>(*x_cs);
0370 internal::cm_free_sparse<StorageIndex>(x_cs, m_cholmod);
0371 }
0372 #endif
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384 Derived& setShift(const RealScalar& offset)
0385 {
0386 m_shiftOffset[0] = double(offset);
0387 return derived();
0388 }
0389
0390
0391 Scalar determinant() const
0392 {
0393 using std::exp;
0394 return exp(logDeterminant());
0395 }
0396
0397
0398 Scalar logDeterminant() const
0399 {
0400 using std::log;
0401 using numext::real;
0402 eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
0403
0404 RealScalar logDet = 0;
0405 Scalar *x = static_cast<Scalar*>(m_cholmodFactor->x);
0406 if (m_cholmodFactor->is_super)
0407 {
0408
0409
0410
0411
0412 StorageIndex *super = static_cast<StorageIndex*>(m_cholmodFactor->super);
0413
0414 StorageIndex *pi = static_cast<StorageIndex*>(m_cholmodFactor->pi);
0415
0416 StorageIndex *px = static_cast<StorageIndex*>(m_cholmodFactor->px);
0417
0418 Index nb_super_nodes = m_cholmodFactor->nsuper;
0419 for (Index k=0; k < nb_super_nodes; ++k)
0420 {
0421 StorageIndex ncols = super[k + 1] - super[k];
0422 StorageIndex nrows = pi[k + 1] - pi[k];
0423
0424 Map<const Array<Scalar,1,Dynamic>, 0, InnerStride<> > sk(x + px[k], ncols, InnerStride<>(nrows+1));
0425 logDet += sk.real().log().sum();
0426 }
0427 }
0428 else
0429 {
0430
0431 StorageIndex *p = static_cast<StorageIndex*>(m_cholmodFactor->p);
0432 Index size = m_cholmodFactor->n;
0433 for (Index k=0; k<size; ++k)
0434 logDet += log(real( x[p[k]] ));
0435 }
0436 if (m_cholmodFactor->is_ll)
0437 logDet *= 2.0;
0438 return logDet;
0439 };
0440
0441 template<typename Stream>
0442 void dumpMemory(Stream& )
0443 {}
0444
0445 protected:
0446 mutable cholmod_common m_cholmod;
0447 cholmod_factor* m_cholmodFactor;
0448 double m_shiftOffset[2];
0449 mutable ComputationInfo m_info;
0450 int m_factorizationIsOk;
0451 int m_analysisIsOk;
0452 };
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476 template<typename _MatrixType, int _UpLo = Lower>
0477 class CholmodSimplicialLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLLT<_MatrixType, _UpLo> >
0478 {
0479 typedef CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLLT> Base;
0480 using Base::m_cholmod;
0481
0482 public:
0483
0484 typedef _MatrixType MatrixType;
0485
0486 CholmodSimplicialLLT() : Base() { init(); }
0487
0488 CholmodSimplicialLLT(const MatrixType& matrix) : Base()
0489 {
0490 init();
0491 this->compute(matrix);
0492 }
0493
0494 ~CholmodSimplicialLLT() {}
0495 protected:
0496 void init()
0497 {
0498 m_cholmod.final_asis = 0;
0499 m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
0500 m_cholmod.final_ll = 1;
0501 }
0502 };
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527 template<typename _MatrixType, int _UpLo = Lower>
0528 class CholmodSimplicialLDLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLDLT<_MatrixType, _UpLo> >
0529 {
0530 typedef CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLDLT> Base;
0531 using Base::m_cholmod;
0532
0533 public:
0534
0535 typedef _MatrixType MatrixType;
0536
0537 CholmodSimplicialLDLT() : Base() { init(); }
0538
0539 CholmodSimplicialLDLT(const MatrixType& matrix) : Base()
0540 {
0541 init();
0542 this->compute(matrix);
0543 }
0544
0545 ~CholmodSimplicialLDLT() {}
0546 protected:
0547 void init()
0548 {
0549 m_cholmod.final_asis = 1;
0550 m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
0551 }
0552 };
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576 template<typename _MatrixType, int _UpLo = Lower>
0577 class CholmodSupernodalLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSupernodalLLT<_MatrixType, _UpLo> >
0578 {
0579 typedef CholmodBase<_MatrixType, _UpLo, CholmodSupernodalLLT> Base;
0580 using Base::m_cholmod;
0581
0582 public:
0583
0584 typedef _MatrixType MatrixType;
0585
0586 CholmodSupernodalLLT() : Base() { init(); }
0587
0588 CholmodSupernodalLLT(const MatrixType& matrix) : Base()
0589 {
0590 init();
0591 this->compute(matrix);
0592 }
0593
0594 ~CholmodSupernodalLLT() {}
0595 protected:
0596 void init()
0597 {
0598 m_cholmod.final_asis = 1;
0599 m_cholmod.supernodal = CHOLMOD_SUPERNODAL;
0600 }
0601 };
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627 template<typename _MatrixType, int _UpLo = Lower>
0628 class CholmodDecomposition : public CholmodBase<_MatrixType, _UpLo, CholmodDecomposition<_MatrixType, _UpLo> >
0629 {
0630 typedef CholmodBase<_MatrixType, _UpLo, CholmodDecomposition> Base;
0631 using Base::m_cholmod;
0632
0633 public:
0634
0635 typedef _MatrixType MatrixType;
0636
0637 CholmodDecomposition() : Base() { init(); }
0638
0639 CholmodDecomposition(const MatrixType& matrix) : Base()
0640 {
0641 init();
0642 this->compute(matrix);
0643 }
0644
0645 ~CholmodDecomposition() {}
0646
0647 void setMode(CholmodMode mode)
0648 {
0649 switch(mode)
0650 {
0651 case CholmodAuto:
0652 m_cholmod.final_asis = 1;
0653 m_cholmod.supernodal = CHOLMOD_AUTO;
0654 break;
0655 case CholmodSimplicialLLt:
0656 m_cholmod.final_asis = 0;
0657 m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
0658 m_cholmod.final_ll = 1;
0659 break;
0660 case CholmodSupernodalLLt:
0661 m_cholmod.final_asis = 1;
0662 m_cholmod.supernodal = CHOLMOD_SUPERNODAL;
0663 break;
0664 case CholmodLDLt:
0665 m_cholmod.final_asis = 1;
0666 m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
0667 break;
0668 default:
0669 break;
0670 }
0671 }
0672 protected:
0673 void init()
0674 {
0675 m_cholmod.final_asis = 1;
0676 m_cholmod.supernodal = CHOLMOD_AUTO;
0677 }
0678 };
0679
0680 }
0681
0682 #endif