Eigen  3.2.7
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
CholmodSupport.h
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008-2010 Gael Guennebaud <[email protected]>
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_CHOLMODSUPPORT_H
11 #define EIGEN_CHOLMODSUPPORT_H
12 
13 namespace Eigen {
14 
15 namespace internal {
16 
17 template<typename Scalar, typename CholmodType>
18 void cholmod_configure_matrix(CholmodType& mat)
19 {
20  if (internal::is_same<Scalar,float>::value)
21  {
22  mat.xtype = CHOLMOD_REAL;
23  mat.dtype = CHOLMOD_SINGLE;
24  }
25  else if (internal::is_same<Scalar,double>::value)
26  {
27  mat.xtype = CHOLMOD_REAL;
28  mat.dtype = CHOLMOD_DOUBLE;
29  }
30  else if (internal::is_same<Scalar,std::complex<float> >::value)
31  {
32  mat.xtype = CHOLMOD_COMPLEX;
33  mat.dtype = CHOLMOD_SINGLE;
34  }
35  else if (internal::is_same<Scalar,std::complex<double> >::value)
36  {
37  mat.xtype = CHOLMOD_COMPLEX;
38  mat.dtype = CHOLMOD_DOUBLE;
39  }
40  else
41  {
42  eigen_assert(false && "Scalar type not supported by CHOLMOD");
43  }
44 }
45 
46 } // namespace internal
47 
51 template<typename _Scalar, int _Options, typename _Index>
53 {
54  cholmod_sparse res;
55  res.nzmax = mat.nonZeros();
56  res.nrow = mat.rows();;
57  res.ncol = mat.cols();
58  res.p = mat.outerIndexPtr();
59  res.i = mat.innerIndexPtr();
60  res.x = mat.valuePtr();
61  res.z = 0;
62  res.sorted = 1;
63  if(mat.isCompressed())
64  {
65  res.packed = 1;
66  res.nz = 0;
67  }
68  else
69  {
70  res.packed = 0;
71  res.nz = mat.innerNonZeroPtr();
72  }
73 
74  res.dtype = 0;
75  res.stype = -1;
76 
77  if (internal::is_same<_Index,int>::value)
78  {
79  res.itype = CHOLMOD_INT;
80  }
81  else if (internal::is_same<_Index,SuiteSparse_long>::value)
82  {
83  res.itype = CHOLMOD_LONG;
84  }
85  else
86  {
87  eigen_assert(false && "Index type not supported yet");
88  }
89 
90  // setup res.xtype
91  internal::cholmod_configure_matrix<_Scalar>(res);
92 
93  res.stype = 0;
94 
95  return res;
96 }
97 
98 template<typename _Scalar, int _Options, typename _Index>
99 const cholmod_sparse viewAsCholmod(const SparseMatrix<_Scalar,_Options,_Index>& mat)
100 {
101  cholmod_sparse res = viewAsCholmod(mat.const_cast_derived());
102  return res;
103 }
104 
107 template<typename _Scalar, int _Options, typename _Index, unsigned int UpLo>
109 {
110  cholmod_sparse res = viewAsCholmod(mat.matrix().const_cast_derived());
111 
112  if(UpLo==Upper) res.stype = 1;
113  if(UpLo==Lower) res.stype = -1;
114 
115  return res;
116 }
117 
120 template<typename Derived>
122 {
123  EIGEN_STATIC_ASSERT((internal::traits<Derived>::Flags&RowMajorBit)==0,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
124  typedef typename Derived::Scalar Scalar;
125 
126  cholmod_dense res;
127  res.nrow = mat.rows();
128  res.ncol = mat.cols();
129  res.nzmax = res.nrow * res.ncol;
130  res.d = Derived::IsVectorAtCompileTime ? mat.derived().size() : mat.derived().outerStride();
131  res.x = (void*)(mat.derived().data());
132  res.z = 0;
133 
134  internal::cholmod_configure_matrix<Scalar>(res);
135 
136  return res;
137 }
138 
141 template<typename Scalar, int Flags, typename Index>
143 {
145  (cm.nrow, cm.ncol, static_cast<Index*>(cm.p)[cm.ncol],
146  static_cast<Index*>(cm.p), static_cast<Index*>(cm.i),static_cast<Scalar*>(cm.x) );
147 }
148 
149 enum CholmodMode {
150  CholmodAuto, CholmodSimplicialLLt, CholmodSupernodalLLt, CholmodLDLt
151 };
152 
153 
159 template<typename _MatrixType, int _UpLo, typename Derived>
160 class CholmodBase : internal::noncopyable
161 {
162  public:
163  typedef _MatrixType MatrixType;
164  enum { UpLo = _UpLo };
165  typedef typename MatrixType::Scalar Scalar;
166  typedef typename MatrixType::RealScalar RealScalar;
167  typedef MatrixType CholMatrixType;
168  typedef typename MatrixType::Index Index;
169 
170  public:
171 
172  CholmodBase()
173  : m_cholmodFactor(0), m_info(Success), m_isInitialized(false)
174  {
175  m_shiftOffset[0] = m_shiftOffset[1] = RealScalar(0.0);
176  cholmod_start(&m_cholmod);
177  }
178 
179  CholmodBase(const MatrixType& matrix)
180  : m_cholmodFactor(0), m_info(Success), m_isInitialized(false)
181  {
182  m_shiftOffset[0] = m_shiftOffset[1] = RealScalar(0.0);
183  cholmod_start(&m_cholmod);
184  compute(matrix);
185  }
186 
187  ~CholmodBase()
188  {
189  if(m_cholmodFactor)
190  cholmod_free_factor(&m_cholmodFactor, &m_cholmod);
191  cholmod_finish(&m_cholmod);
192  }
193 
194  inline Index cols() const { return m_cholmodFactor->n; }
195  inline Index rows() const { return m_cholmodFactor->n; }
196 
197  Derived& derived() { return *static_cast<Derived*>(this); }
198  const Derived& derived() const { return *static_cast<const Derived*>(this); }
199 
206  {
207  eigen_assert(m_isInitialized && "Decomposition is not initialized.");
208  return m_info;
209  }
210 
212  Derived& compute(const MatrixType& matrix)
213  {
214  analyzePattern(matrix);
215  factorize(matrix);
216  return derived();
217  }
218 
223  template<typename Rhs>
224  inline const internal::solve_retval<CholmodBase, Rhs>
225  solve(const MatrixBase<Rhs>& b) const
226  {
227  eigen_assert(m_isInitialized && "LLT is not initialized.");
228  eigen_assert(rows()==b.rows()
229  && "CholmodDecomposition::solve(): invalid number of rows of the right hand side matrix b");
230  return internal::solve_retval<CholmodBase, Rhs>(*this, b.derived());
231  }
232 
237  template<typename Rhs>
238  inline const internal::sparse_solve_retval<CholmodBase, Rhs>
239  solve(const SparseMatrixBase<Rhs>& b) const
240  {
241  eigen_assert(m_isInitialized && "LLT is not initialized.");
242  eigen_assert(rows()==b.rows()
243  && "CholmodDecomposition::solve(): invalid number of rows of the right hand side matrix b");
244  return internal::sparse_solve_retval<CholmodBase, Rhs>(*this, b.derived());
245  }
246 
253  void analyzePattern(const MatrixType& matrix)
254  {
255  if(m_cholmodFactor)
256  {
257  cholmod_free_factor(&m_cholmodFactor, &m_cholmod);
258  m_cholmodFactor = 0;
259  }
260  cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
261  m_cholmodFactor = cholmod_analyze(&A, &m_cholmod);
262 
263  this->m_isInitialized = true;
264  this->m_info = Success;
265  m_analysisIsOk = true;
266  m_factorizationIsOk = false;
267  }
268 
275  void factorize(const MatrixType& matrix)
276  {
277  eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
278  cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
279  cholmod_factorize_p(&A, m_shiftOffset, 0, 0, m_cholmodFactor, &m_cholmod);
280 
281  // If the factorization failed, minor is the column at which it did. On success minor == n.
282  this->m_info = (m_cholmodFactor->minor == m_cholmodFactor->n ? Success : NumericalIssue);
283  m_factorizationIsOk = true;
284  }
285 
288  cholmod_common& cholmod() { return m_cholmod; }
289 
290  #ifndef EIGEN_PARSED_BY_DOXYGEN
291 
292  template<typename Rhs,typename Dest>
293  void _solve(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const
294  {
295  eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
296  const Index size = m_cholmodFactor->n;
297  EIGEN_UNUSED_VARIABLE(size);
298  eigen_assert(size==b.rows());
299 
300  // note: cd stands for Cholmod Dense
301  Rhs& b_ref(b.const_cast_derived());
302  cholmod_dense b_cd = viewAsCholmod(b_ref);
303  cholmod_dense* x_cd = cholmod_solve(CHOLMOD_A, m_cholmodFactor, &b_cd, &m_cholmod);
304  if(!x_cd)
305  {
306  this->m_info = NumericalIssue;
307  }
308  // TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
309  dest = Matrix<Scalar,Dest::RowsAtCompileTime,Dest::ColsAtCompileTime>::Map(reinterpret_cast<Scalar*>(x_cd->x),b.rows(),b.cols());
310  cholmod_free_dense(&x_cd, &m_cholmod);
311  }
312 
314  template<typename RhsScalar, int RhsOptions, typename RhsIndex, typename DestScalar, int DestOptions, typename DestIndex>
315  void _solve(const SparseMatrix<RhsScalar,RhsOptions,RhsIndex> &b, SparseMatrix<DestScalar,DestOptions,DestIndex> &dest) const
316  {
317  eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
318  const Index size = m_cholmodFactor->n;
319  EIGEN_UNUSED_VARIABLE(size);
320  eigen_assert(size==b.rows());
321 
322  // note: cs stands for Cholmod Sparse
323  cholmod_sparse b_cs = viewAsCholmod(b);
324  cholmod_sparse* x_cs = cholmod_spsolve(CHOLMOD_A, m_cholmodFactor, &b_cs, &m_cholmod);
325  if(!x_cs)
326  {
327  this->m_info = NumericalIssue;
328  }
329  // TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
330  dest = viewAsEigen<DestScalar,DestOptions,DestIndex>(*x_cs);
331  cholmod_free_sparse(&x_cs, &m_cholmod);
332  }
333  #endif // EIGEN_PARSED_BY_DOXYGEN
334 
335 
345  Derived& setShift(const RealScalar& offset)
346  {
347  m_shiftOffset[0] = offset;
348  return derived();
349  }
350 
351  template<typename Stream>
352  void dumpMemory(Stream& /*s*/)
353  {}
354 
355  protected:
356  mutable cholmod_common m_cholmod;
357  cholmod_factor* m_cholmodFactor;
358  RealScalar m_shiftOffset[2];
359  mutable ComputationInfo m_info;
360  bool m_isInitialized;
361  int m_factorizationIsOk;
362  int m_analysisIsOk;
363 };
364 
383 template<typename _MatrixType, int _UpLo = Lower>
384 class CholmodSimplicialLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLLT<_MatrixType, _UpLo> >
385 {
387  using Base::m_cholmod;
388 
389  public:
390 
391  typedef _MatrixType MatrixType;
392 
393  CholmodSimplicialLLT() : Base() { init(); }
394 
395  CholmodSimplicialLLT(const MatrixType& matrix) : Base()
396  {
397  init();
398  Base::compute(matrix);
399  }
400 
402  protected:
403  void init()
404  {
405  m_cholmod.final_asis = 0;
406  m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
407  m_cholmod.final_ll = 1;
408  }
409 };
410 
411 
430 template<typename _MatrixType, int _UpLo = Lower>
431 class CholmodSimplicialLDLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLDLT<_MatrixType, _UpLo> >
432 {
434  using Base::m_cholmod;
435 
436  public:
437 
438  typedef _MatrixType MatrixType;
439 
440  CholmodSimplicialLDLT() : Base() { init(); }
441 
442  CholmodSimplicialLDLT(const MatrixType& matrix) : Base()
443  {
444  init();
445  Base::compute(matrix);
446  }
447 
449  protected:
450  void init()
451  {
452  m_cholmod.final_asis = 1;
453  m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
454  }
455 };
456 
475 template<typename _MatrixType, int _UpLo = Lower>
476 class CholmodSupernodalLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSupernodalLLT<_MatrixType, _UpLo> >
477 {
479  using Base::m_cholmod;
480 
481  public:
482 
483  typedef _MatrixType MatrixType;
484 
485  CholmodSupernodalLLT() : Base() { init(); }
486 
487  CholmodSupernodalLLT(const MatrixType& matrix) : Base()
488  {
489  init();
490  Base::compute(matrix);
491  }
492 
494  protected:
495  void init()
496  {
497  m_cholmod.final_asis = 1;
498  m_cholmod.supernodal = CHOLMOD_SUPERNODAL;
499  }
500 };
501 
522 template<typename _MatrixType, int _UpLo = Lower>
523 class CholmodDecomposition : public CholmodBase<_MatrixType, _UpLo, CholmodDecomposition<_MatrixType, _UpLo> >
524 {
526  using Base::m_cholmod;
527 
528  public:
529 
530  typedef _MatrixType MatrixType;
531 
532  CholmodDecomposition() : Base() { init(); }
533 
534  CholmodDecomposition(const MatrixType& matrix) : Base()
535  {
536  init();
537  Base::compute(matrix);
538  }
539 
541 
542  void setMode(CholmodMode mode)
543  {
544  switch(mode)
545  {
546  case CholmodAuto:
547  m_cholmod.final_asis = 1;
548  m_cholmod.supernodal = CHOLMOD_AUTO;
549  break;
550  case CholmodSimplicialLLt:
551  m_cholmod.final_asis = 0;
552  m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
553  m_cholmod.final_ll = 1;
554  break;
555  case CholmodSupernodalLLt:
556  m_cholmod.final_asis = 1;
557  m_cholmod.supernodal = CHOLMOD_SUPERNODAL;
558  break;
559  case CholmodLDLt:
560  m_cholmod.final_asis = 1;
561  m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
562  break;
563  default:
564  break;
565  }
566  }
567  protected:
568  void init()
569  {
570  m_cholmod.final_asis = 1;
571  m_cholmod.supernodal = CHOLMOD_AUTO;
572  }
573 };
574 
575 namespace internal {
576 
577 template<typename _MatrixType, int _UpLo, typename Derived, typename Rhs>
578 struct solve_retval<CholmodBase<_MatrixType,_UpLo,Derived>, Rhs>
579  : solve_retval_base<CholmodBase<_MatrixType,_UpLo,Derived>, Rhs>
580 {
582  EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs)
583 
584  template<typename Dest> void evalTo(Dest& dst) const
585  {
586  dec()._solve(rhs(),dst);
587  }
588 };
589 
590 template<typename _MatrixType, int _UpLo, typename Derived, typename Rhs>
591 struct sparse_solve_retval<CholmodBase<_MatrixType,_UpLo,Derived>, Rhs>
592  : sparse_solve_retval_base<CholmodBase<_MatrixType,_UpLo,Derived>, Rhs>
593 {
594  typedef CholmodBase<_MatrixType,_UpLo,Derived> Dec;
595  EIGEN_MAKE_SPARSE_SOLVE_HELPERS(Dec,Rhs)
596 
597  template<typename Dest> void evalTo(Dest& dst) const
598  {
599  dec()._solve(rhs(),dst);
600  }
601 };
602 
603 } // end namespace internal
604 
605 } // end namespace Eigen
606 
607 #endif // EIGEN_CHOLMODSUPPORT_H
void factorize(const MatrixType &matrix)
Definition: CholmodSupport.h:275
Index rows() const
Definition: SparseMatrix.h:119
void analyzePattern(const MatrixType &matrix)
Definition: CholmodSupport.h:253
Index cols() const
Definition: SparseMatrix.h:121
Definition: Constants.h:167
const Scalar * valuePtr() const
Definition: SparseMatrix.h:131
A versatible sparse matrix representation.
Definition: SparseMatrix.h:85
bool isCompressed() const
Definition: SparseMatrix.h:116
ComputationInfo info() const
Reports whether previous computation was successful.
Definition: CholmodSupport.h:205
Definition: Constants.h:378
const internal::sparse_solve_retval< CholmodBase, Rhs > solve(const SparseMatrixBase< Rhs > &b) const
Definition: CholmodSupport.h:239
Pseudo expression to manipulate a triangular sparse matrix as a selfadjoint matrix.
Definition: SparseSelfAdjointView.h:49
const Index * innerNonZeroPtr() const
Definition: SparseMatrix.h:158
A supernodal Cholesky (LLT) factorization and solver based on Cholmod.
Definition: CholmodSupport.h:476
const Index * outerIndexPtr() const
Definition: SparseMatrix.h:149
Definition: Constants.h:169
MappedSparseMatrix< Scalar, Flags, Index > viewAsEigen(cholmod_sparse &cm)
Definition: CholmodSupport.h:142
Index nonZeros() const
Definition: SparseMatrix.h:246
Base class of any sparse matrices or sparse expressions.
Definition: ForwardDeclarations.h:239
Derived & setShift(const RealScalar &offset)
Definition: CholmodSupport.h:345
cholmod_sparse viewAsCholmod(SparseMatrix< _Scalar, _Options, _Index > &mat)
Definition: CholmodSupport.h:52
Derived & derived()
Definition: EigenBase.h:34
A general Cholesky factorization and solver based on Cholmod.
Definition: CholmodSupport.h:523
const internal::solve_retval< CholmodBase, Rhs > solve(const MatrixBase< Rhs > &b) const
Definition: CholmodSupport.h:225
The base class for the direct Cholesky factorization of Cholmod.
Definition: CholmodSupport.h:160
A simplicial direct Cholesky (LLT) factorization and solver based on Cholmod.
Definition: CholmodSupport.h:384
A simplicial direct Cholesky (LDLT) factorization and solver based on Cholmod.
Definition: CholmodSupport.h:431
Definition: Constants.h:376
const unsigned int RowMajorBit
Definition: Constants.h:53
Index rows() const
Definition: SparseMatrixBase.h:159
ComputationInfo
Definition: Constants.h:374
Sparse matrix.
Definition: MappedSparseMatrix.h:31
Derived & compute(const MatrixType &matrix)
Definition: CholmodSupport.h:212
Base class for all dense matrices, vectors, and expressions.
Definition: MatrixBase.h:48
cholmod_common & cholmod()
Definition: CholmodSupport.h:288
const Index * innerIndexPtr() const
Definition: SparseMatrix.h:140