CholmodSupport.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008-2010 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_CHOLMODSUPPORT_H
11 #define EIGEN_CHOLMODSUPPORT_H
12 
13 namespace Eigen {
14 
15 namespace internal {
16 
17 template<typename Scalar> struct cholmod_configure_matrix;
18 
19 template<> struct cholmod_configure_matrix<double> {
20  template<typename CholmodType>
21  static void run(CholmodType& mat) {
22  mat.xtype = CHOLMOD_REAL;
23  mat.dtype = CHOLMOD_DOUBLE;
24  }
25 };
26 
27 template<> struct cholmod_configure_matrix<std::complex<double> > {
28  template<typename CholmodType>
29  static void run(CholmodType& mat) {
30  mat.xtype = CHOLMOD_COMPLEX;
31  mat.dtype = CHOLMOD_DOUBLE;
32  }
33 };
34 
35 // Other scalar types are not yet suppotred by Cholmod
36 // template<> struct cholmod_configure_matrix<float> {
37 // template<typename CholmodType>
38 // static void run(CholmodType& mat) {
39 // mat.xtype = CHOLMOD_REAL;
40 // mat.dtype = CHOLMOD_SINGLE;
41 // }
42 // };
43 //
44 // template<> struct cholmod_configure_matrix<std::complex<float> > {
45 // template<typename CholmodType>
46 // static void run(CholmodType& mat) {
47 // mat.xtype = CHOLMOD_COMPLEX;
48 // mat.dtype = CHOLMOD_SINGLE;
49 // }
50 // };
51 
52 } // namespace internal
53 
57 template<typename _Scalar, int _Options, typename _StorageIndex>
59 {
60  cholmod_sparse res;
61  res.nzmax = mat.nonZeros();
62  res.nrow = mat.rows();
63  res.ncol = mat.cols();
64  res.p = mat.outerIndexPtr();
65  res.i = mat.innerIndexPtr();
66  res.x = mat.valuePtr();
67  res.z = 0;
68  res.sorted = 1;
69  if(mat.isCompressed())
70  {
71  res.packed = 1;
72  res.nz = 0;
73  }
74  else
75  {
76  res.packed = 0;
77  res.nz = mat.innerNonZeroPtr();
78  }
79 
80  res.dtype = 0;
81  res.stype = -1;
82 
84  {
85  res.itype = CHOLMOD_INT;
86  }
88  {
89  res.itype = CHOLMOD_LONG;
90  }
91  else
92  {
93  eigen_assert(false && "Index type not supported yet");
94  }
95 
96  // setup res.xtype
98 
99  res.stype = 0;
100 
101  return res;
102 }
103 
104 template<typename _Scalar, int _Options, typename _Index>
105 const cholmod_sparse viewAsCholmod(const SparseMatrix<_Scalar,_Options,_Index>& mat)
106 {
108  return res;
109 }
110 
111 template<typename _Scalar, int _Options, typename _Index>
112 const cholmod_sparse viewAsCholmod(const SparseVector<_Scalar,_Options,_Index>& mat)
113 {
115  return res;
116 }
117 
120 template<typename _Scalar, int _Options, typename _Index, unsigned int UpLo>
122 {
123  cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.matrix().const_cast_derived()));
124 
125  if(UpLo==Upper) res.stype = 1;
126  if(UpLo==Lower) res.stype = -1;
127 
128  return res;
129 }
130 
133 template<typename Derived>
135 {
136  EIGEN_STATIC_ASSERT((internal::traits<Derived>::Flags&RowMajorBit)==0,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
137  typedef typename Derived::Scalar Scalar;
138 
139  cholmod_dense res;
140  res.nrow = mat.rows();
141  res.ncol = mat.cols();
142  res.nzmax = res.nrow * res.ncol;
143  res.d = Derived::IsVectorAtCompileTime ? mat.derived().size() : mat.derived().outerStride();
144  res.x = (void*)(mat.derived().data());
145  res.z = 0;
146 
148 
149  return res;
150 }
151 
154 template<typename Scalar, int Flags, typename StorageIndex>
156 {
158  (cm.nrow, cm.ncol, static_cast<StorageIndex*>(cm.p)[cm.ncol],
159  static_cast<StorageIndex*>(cm.p), static_cast<StorageIndex*>(cm.i),static_cast<Scalar*>(cm.x) );
160 }
161 
164 };
165 
166 
172 template<typename _MatrixType, int _UpLo, typename Derived>
173 class CholmodBase : public SparseSolverBase<Derived>
174 {
175  protected:
177  using Base::derived;
178  using Base::m_isInitialized;
179  public:
180  typedef _MatrixType MatrixType;
181  enum { UpLo = _UpLo };
182  typedef typename MatrixType::Scalar Scalar;
183  typedef typename MatrixType::RealScalar RealScalar;
184  typedef MatrixType CholMatrixType;
185  typedef typename MatrixType::StorageIndex StorageIndex;
186  enum {
187  ColsAtCompileTime = MatrixType::ColsAtCompileTime,
188  MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
189  };
190 
191  public:
192 
194  : m_cholmodFactor(0), m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false)
195  {
196  EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
197  m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
198  cholmod_start(&m_cholmod);
199  }
200 
201  explicit CholmodBase(const MatrixType& matrix)
202  : m_cholmodFactor(0), m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false)
203  {
204  EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
205  m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
206  cholmod_start(&m_cholmod);
207  compute(matrix);
208  }
209 
211  {
212  if(m_cholmodFactor)
213  cholmod_free_factor(&m_cholmodFactor, &m_cholmod);
214  cholmod_finish(&m_cholmod);
215  }
216 
217  inline StorageIndex cols() const { return internal::convert_index<StorageIndex, Index>(m_cholmodFactor->n); }
218  inline StorageIndex rows() const { return internal::convert_index<StorageIndex, Index>(m_cholmodFactor->n); }
219 
226  {
227  eigen_assert(m_isInitialized && "Decomposition is not initialized.");
228  return m_info;
229  }
230 
232  Derived& compute(const MatrixType& matrix)
233  {
234  analyzePattern(matrix);
235  factorize(matrix);
236  return derived();
237  }
238 
245  void analyzePattern(const MatrixType& matrix)
246  {
247  if(m_cholmodFactor)
248  {
249  cholmod_free_factor(&m_cholmodFactor, &m_cholmod);
250  m_cholmodFactor = 0;
251  }
252  cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
253  m_cholmodFactor = cholmod_analyze(&A, &m_cholmod);
254 
255  this->m_isInitialized = true;
256  this->m_info = Success;
257  m_analysisIsOk = true;
258  m_factorizationIsOk = false;
259  }
260 
267  void factorize(const MatrixType& matrix)
268  {
269  eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
270  cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
271  cholmod_factorize_p(&A, m_shiftOffset, 0, 0, m_cholmodFactor, &m_cholmod);
272 
273  // If the factorization failed, minor is the column at which it did. On success minor == n.
274  this->m_info = (m_cholmodFactor->minor == m_cholmodFactor->n ? Success : NumericalIssue);
275  m_factorizationIsOk = true;
276  }
277 
280  cholmod_common& cholmod() { return m_cholmod; }
281 
282  #ifndef EIGEN_PARSED_BY_DOXYGEN
283 
284  template<typename Rhs,typename Dest>
285  void _solve_impl(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const
286  {
287  eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
288  const Index size = m_cholmodFactor->n;
289  EIGEN_UNUSED_VARIABLE(size);
290  eigen_assert(size==b.rows());
291 
292  // Cholmod needs column-major stoarge without inner-stride, which corresponds to the default behavior of Ref.
294 
295  cholmod_dense b_cd = viewAsCholmod(b_ref);
296  cholmod_dense* x_cd = cholmod_solve(CHOLMOD_A, m_cholmodFactor, &b_cd, &m_cholmod);
297  if(!x_cd)
298  {
299  this->m_info = NumericalIssue;
300  return;
301  }
302  // TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
303  dest = Matrix<Scalar,Dest::RowsAtCompileTime,Dest::ColsAtCompileTime>::Map(reinterpret_cast<Scalar*>(x_cd->x),b.rows(),b.cols());
304  cholmod_free_dense(&x_cd, &m_cholmod);
305  }
306 
308  template<typename RhsDerived, typename DestDerived>
310  {
311  eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
312  const Index size = m_cholmodFactor->n;
313  EIGEN_UNUSED_VARIABLE(size);
314  eigen_assert(size==b.rows());
315 
316  // note: cs stands for Cholmod Sparse
318  cholmod_sparse b_cs = viewAsCholmod(b_ref);
319  cholmod_sparse* x_cs = cholmod_spsolve(CHOLMOD_A, m_cholmodFactor, &b_cs, &m_cholmod);
320  if(!x_cs)
321  {
322  this->m_info = NumericalIssue;
323  return;
324  }
325  // TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
326  dest.derived() = viewAsEigen<typename DestDerived::Scalar,ColMajor,typename DestDerived::StorageIndex>(*x_cs);
327  cholmod_free_sparse(&x_cs, &m_cholmod);
328  }
329  #endif // EIGEN_PARSED_BY_DOXYGEN
330 
331 
341  Derived& setShift(const RealScalar& offset)
342  {
343  m_shiftOffset[0] = double(offset);
344  return derived();
345  }
346 
348  Scalar determinant() const
349  {
350  using std::exp;
351  return exp(logDeterminant());
352  }
353 
355  Scalar logDeterminant() const
356  {
357  using std::log;
358  using numext::real;
359  eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
360 
361  RealScalar logDet = 0;
362  Scalar *x = static_cast<Scalar*>(m_cholmodFactor->x);
363  if (m_cholmodFactor->is_super)
364  {
365  // Supernodal factorization stored as a packed list of dense column-major blocs,
366  // as described by the following structure:
367 
368  // super[k] == index of the first column of the j-th super node
369  StorageIndex *super = static_cast<StorageIndex*>(m_cholmodFactor->super);
370  // pi[k] == offset to the description of row indices
371  StorageIndex *pi = static_cast<StorageIndex*>(m_cholmodFactor->pi);
372  // px[k] == offset to the respective dense block
373  StorageIndex *px = static_cast<StorageIndex*>(m_cholmodFactor->px);
374 
375  Index nb_super_nodes = m_cholmodFactor->nsuper;
376  for (Index k=0; k < nb_super_nodes; ++k)
377  {
378  StorageIndex ncols = super[k + 1] - super[k];
379  StorageIndex nrows = pi[k + 1] - pi[k];
380 
381  Map<const Array<Scalar,1,Dynamic>, 0, InnerStride<> > sk(x + px[k], ncols, InnerStride<>(nrows+1));
382  logDet += sk.real().log().sum();
383  }
384  }
385  else
386  {
387  // Simplicial factorization stored as standard CSC matrix.
388  StorageIndex *p = static_cast<StorageIndex*>(m_cholmodFactor->p);
389  Index size = m_cholmodFactor->n;
390  for (Index k=0; k<size; ++k)
391  logDet += log(real( x[p[k]] ));
392  }
393  if (m_cholmodFactor->is_ll)
394  logDet *= 2.0;
395  return logDet;
396  };
397 
398  template<typename Stream>
399  void dumpMemory(Stream& /*s*/)
400  {}
401 
402  protected:
403  mutable cholmod_common m_cholmod;
404  cholmod_factor* m_cholmodFactor;
405  double m_shiftOffset[2];
409 };
410 
433 template<typename _MatrixType, int _UpLo = Lower>
434 class CholmodSimplicialLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLLT<_MatrixType, _UpLo> >
435 {
437  using Base::m_cholmod;
438 
439  public:
440 
441  typedef _MatrixType MatrixType;
442 
443  CholmodSimplicialLLT() : Base() { init(); }
444 
445  CholmodSimplicialLLT(const MatrixType& matrix) : Base()
446  {
447  init();
448  this->compute(matrix);
449  }
450 
452  protected:
453  void init()
454  {
455  m_cholmod.final_asis = 0;
456  m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
457  m_cholmod.final_ll = 1;
458  }
459 };
460 
461 
484 template<typename _MatrixType, int _UpLo = Lower>
485 class CholmodSimplicialLDLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLDLT<_MatrixType, _UpLo> >
486 {
488  using Base::m_cholmod;
489 
490  public:
491 
492  typedef _MatrixType MatrixType;
493 
494  CholmodSimplicialLDLT() : Base() { init(); }
495 
496  CholmodSimplicialLDLT(const MatrixType& matrix) : Base()
497  {
498  init();
499  this->compute(matrix);
500  }
501 
503  protected:
504  void init()
505  {
506  m_cholmod.final_asis = 1;
507  m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
508  }
509 };
510 
533 template<typename _MatrixType, int _UpLo = Lower>
534 class CholmodSupernodalLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSupernodalLLT<_MatrixType, _UpLo> >
535 {
537  using Base::m_cholmod;
538 
539  public:
540 
541  typedef _MatrixType MatrixType;
542 
543  CholmodSupernodalLLT() : Base() { init(); }
544 
545  CholmodSupernodalLLT(const MatrixType& matrix) : Base()
546  {
547  init();
548  this->compute(matrix);
549  }
550 
552  protected:
553  void init()
554  {
555  m_cholmod.final_asis = 1;
556  m_cholmod.supernodal = CHOLMOD_SUPERNODAL;
557  }
558 };
559 
584 template<typename _MatrixType, int _UpLo = Lower>
585 class CholmodDecomposition : public CholmodBase<_MatrixType, _UpLo, CholmodDecomposition<_MatrixType, _UpLo> >
586 {
588  using Base::m_cholmod;
589 
590  public:
591 
592  typedef _MatrixType MatrixType;
593 
594  CholmodDecomposition() : Base() { init(); }
595 
596  CholmodDecomposition(const MatrixType& matrix) : Base()
597  {
598  init();
599  this->compute(matrix);
600  }
601 
603 
604  void setMode(CholmodMode mode)
605  {
606  switch(mode)
607  {
608  case CholmodAuto:
609  m_cholmod.final_asis = 1;
610  m_cholmod.supernodal = CHOLMOD_AUTO;
611  break;
613  m_cholmod.final_asis = 0;
614  m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
615  m_cholmod.final_ll = 1;
616  break;
618  m_cholmod.final_asis = 1;
619  m_cholmod.supernodal = CHOLMOD_SUPERNODAL;
620  break;
621  case CholmodLDLt:
622  m_cholmod.final_asis = 1;
623  m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
624  break;
625  default:
626  break;
627  }
628  }
629  protected:
630  void init()
631  {
632  m_cholmod.final_asis = 1;
633  m_cholmod.supernodal = CHOLMOD_AUTO;
634  }
635 };
636 
637 } // end namespace Eigen
638 
639 #endif // EIGEN_CHOLMODSUPPORT_H
void setMode(CholmodMode mode)
StorageIndex rows() const
CholmodBase< _MatrixType, _UpLo, CholmodSupernodalLLT > Base
Scalar determinant() const
CholmodBase< _MatrixType, _UpLo, CholmodDecomposition > Base
EIGEN_DEVICE_FUNC RealReturnType real() const
A versatible sparse matrix representation.
Definition: SparseMatrix.h:96
EIGEN_DEVICE_FUNC const ExpReturnType exp() const
SparseSolverBase< Derived > Base
A matrix or vector expression mapping an existing array of data.
Definition: Map.h:88
cholmod_factor * m_cholmodFactor
void factorize(const MatrixType &matrix)
A base class for sparse solvers.
MappedSparseMatrix< Scalar, Flags, StorageIndex > viewAsEigen(cholmod_sparse &cm)
_MatrixType MatrixType
EIGEN_DEVICE_FUNC const LogReturnType log() const
Definition: LDLT.h:16
static constexpr size_t size(Tuple< Args... > &)
Provides access to the number of elements in a tuple as a compile-time constant expression.
Pseudo expression to manipulate a triangular sparse matrix as a selfadjoint matrix.
#define EIGEN_STATIC_ASSERT(CONDITION, MSG)
Definition: StaticAssert.h:122
CholmodBase(const MatrixType &matrix)
A supernodal Cholesky (LLT) factorization and solver based on Cholmod.
MatrixType CholMatrixType
CholmodDecomposition(const MatrixType &matrix)
const unsigned int RowMajorBit
Definition: Constants.h:61
CholmodBase< _MatrixType, _UpLo, CholmodSimplicialLDLT > Base
MatrixType::StorageIndex StorageIndex
cholmod_common & cholmod()
StorageIndex cols() const
Base class of any sparse matrices or sparse expressions.
void dumpMemory(Stream &)
a sparse vector class
Definition: SparseUtil.h:54
Convenience specialization of Stride to specify only an inner stride See class Map for some examples...
Definition: Stride.h:90
void analyzePattern(const MatrixType &matrix)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:33
#define eigen_assert(x)
Definition: Macros.h:577
void _solve_impl(const MatrixBase< Rhs > &b, MatrixBase< Dest > &dest) const
CholmodBase< _MatrixType, _UpLo, CholmodSimplicialLLT > Base
A general Cholesky factorization and solver based on Cholmod.
cholmod_sparse viewAsCholmod(Ref< SparseMatrix< _Scalar, _Options, _StorageIndex > > mat)
The base class for the direct Cholesky factorization of Cholmod.
ComputationInfo info() const
Reports whether previous computation was successful.
A matrix or vector expression mapping an existing expression.
Definition: Ref.h:190
A simplicial direct Cholesky (LLT) factorization and solver based on Cholmod.
MatrixType::RealScalar RealScalar
A simplicial direct Cholesky (LDLT) factorization and solver based on Cholmod.
Derived & compute(const MatrixType &matrix)
const Derived & derived() const
Derived & setShift(const RealScalar &offset)
cholmod_common m_cholmod
MatrixType::Scalar Scalar
ComputationInfo m_info
CholmodSimplicialLLT(const MatrixType &matrix)
CholmodSupernodalLLT(const MatrixType &matrix)
void run(Expr &expr, Dev &dev)
Definition: TensorSyclRun.h:33
const AutoDiffScalar< DerType > & real(const AutoDiffScalar< DerType > &x)
ComputationInfo
Definition: Constants.h:430
EIGEN_DEVICE_FUNC const Scalar & b
Base class for all dense matrices, vectors, and expressions.
Definition: MatrixBase.h:48
Scalar logDeterminant() const
#define EIGEN_UNUSED_VARIABLE(var)
Definition: Macros.h:616
void _solve_impl(const SparseMatrixBase< RhsDerived > &b, SparseMatrixBase< DestDerived > &dest) const
CholmodSimplicialLDLT(const MatrixType &matrix)
SparseMatrix< _Scalar, _Options, _StorageIndex > & const_cast_derived() const


hebiros
Author(s): Xavier Artache , Matthew Tesch
autogenerated on Thu Sep 3 2020 04:08:03