Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GaussianProcessTuning/HeuristicLab.Eigen/Eigen/src/SparseCholesky/SimplicialCholesky.h @ 10617

Last change on this file since 10617 was 9562, checked in by gkronber, 12 years ago

#1967 worked on Gaussian process evolution.

File size: 29.5 KB
Line 
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/*
11
12NOTE: the _symbolic, and _numeric functions has been adapted from
13      the LDL library:
14
15LDL Copyright (c) 2005 by Timothy A. Davis.  All Rights Reserved.
16
17LDL License:
18
19    Your use or distribution of LDL or any modified version of
20    LDL implies that you agree to this License.
21
22    This library is free software; you can redistribute it and/or
23    modify it under the terms of the GNU Lesser General Public
24    License as published by the Free Software Foundation; either
25    version 2.1 of the License, or (at your option) any later version.
26
27    This library is distributed in the hope that it will be useful,
28    but WITHOUT ANY WARRANTY; without even the implied warranty of
29    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
30    Lesser General Public License for more details.
31
32    You should have received a copy of the GNU Lesser General Public
33    License along with this library; if not, write to the Free Software
34    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
35    USA
36
37    Permission is hereby granted to use or copy this program under the
38    terms of the GNU LGPL, provided that the Copyright, this License,
39    and the Availability of the original version is retained on all copies.
40    User documentation of any code that uses this code or any modified
41    version of this code must cite the Copyright, this License, the
42    Availability note, and "Used by permission." Permission to modify
43    the code and to distribute modified code is granted, provided the
44    Copyright, this License, and the Availability note are retained,
45    and a notice that the code was modified is included.
46 */
47
48#include "../Core/util/NonMPL2.h"
49
50#ifndef EIGEN_SIMPLICIAL_CHOLESKY_H
51#define EIGEN_SIMPLICIAL_CHOLESKY_H
52
53namespace Eigen {
54
55enum SimplicialCholeskyMode {
56  SimplicialCholeskyLLT,
57  SimplicialCholeskyLDLT
58};
59
60/** \ingroup SparseCholesky_Module
61  * \brief A direct sparse Cholesky factorizations
62  *
63  * These classes provide LL^T and LDL^T Cholesky factorizations of sparse matrices that are
64  * selfadjoint and positive definite. The factorization allows for solving A.X = B where
65  * X and B can be either dense or sparse.
66  *
67  * In order to reduce the fill-in, a symmetric permutation P is applied prior to the factorization
68  * such that the factorized matrix is P A P^-1.
69  *
70  * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
71  * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
72  *               or Upper. Default is Lower.
73  *
74  */
75template<typename Derived>
76class SimplicialCholeskyBase : internal::noncopyable
77{
78  public:
79    typedef typename internal::traits<Derived>::MatrixType MatrixType;
80    enum { UpLo = internal::traits<Derived>::UpLo };
81    typedef typename MatrixType::Scalar Scalar;
82    typedef typename MatrixType::RealScalar RealScalar;
83    typedef typename MatrixType::Index Index;
84    typedef SparseMatrix<Scalar,ColMajor,Index> CholMatrixType;
85    typedef Matrix<Scalar,Dynamic,1> VectorType;
86
87  public:
88
89    /** Default constructor */
90    SimplicialCholeskyBase()
91      : m_info(Success), m_isInitialized(false), m_shiftOffset(0), m_shiftScale(1)
92    {}
93
94    SimplicialCholeskyBase(const MatrixType& matrix)
95      : m_info(Success), m_isInitialized(false), m_shiftOffset(0), m_shiftScale(1)
96    {
97      derived().compute(matrix);
98    }
99
100    ~SimplicialCholeskyBase()
101    {
102    }
103
104    Derived& derived() { return *static_cast<Derived*>(this); }
105    const Derived& derived() const { return *static_cast<const Derived*>(this); }
106   
107    inline Index cols() const { return m_matrix.cols(); }
108    inline Index rows() const { return m_matrix.rows(); }
109   
110    /** \brief Reports whether previous computation was successful.
111      *
112      * \returns \c Success if computation was succesful,
113      *          \c NumericalIssue if the matrix.appears to be negative.
114      */
115    ComputationInfo info() const
116    {
117      eigen_assert(m_isInitialized && "Decomposition is not initialized.");
118      return m_info;
119    }
120   
121    /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A.
122      *
123      * \sa compute()
124      */
125    template<typename Rhs>
126    inline const internal::solve_retval<SimplicialCholeskyBase, Rhs>
127    solve(const MatrixBase<Rhs>& b) const
128    {
129      eigen_assert(m_isInitialized && "Simplicial LLT or LDLT is not initialized.");
130      eigen_assert(rows()==b.rows()
131                && "SimplicialCholeskyBase::solve(): invalid number of rows of the right hand side matrix b");
132      return internal::solve_retval<SimplicialCholeskyBase, Rhs>(*this, b.derived());
133    }
134   
135    /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A.
136      *
137      * \sa compute()
138      */
139    template<typename Rhs>
140    inline const internal::sparse_solve_retval<SimplicialCholeskyBase, Rhs>
141    solve(const SparseMatrixBase<Rhs>& b) const
142    {
143      eigen_assert(m_isInitialized && "Simplicial LLT or LDLT is not initialized.");
144      eigen_assert(rows()==b.rows()
145                && "SimplicialCholesky::solve(): invalid number of rows of the right hand side matrix b");
146      return internal::sparse_solve_retval<SimplicialCholeskyBase, Rhs>(*this, b.derived());
147    }
148   
149    /** \returns the permutation P
150      * \sa permutationPinv() */
151    const PermutationMatrix<Dynamic,Dynamic,Index>& permutationP() const
152    { return m_P; }
153   
154    /** \returns the inverse P^-1 of the permutation P
155      * \sa permutationP() */
156    const PermutationMatrix<Dynamic,Dynamic,Index>& permutationPinv() const
157    { return m_Pinv; }
158
159    /** Sets the shift parameters that will be used to adjust the diagonal coefficients during the numerical factorization.
160      *
161      * During the numerical factorization, the diagonal coefficients are transformed by the following linear model:\n
162      * \c d_ii = \a offset + \a scale * \c d_ii
163      *
164      * The default is the identity transformation with \a offset=0, and \a scale=1.
165      *
166      * \returns a reference to \c *this.
167      */
168    Derived& setShift(const RealScalar& offset, const RealScalar& scale = 1)
169    {
170      m_shiftOffset = offset;
171      m_shiftScale = scale;
172      return derived();
173    }
174
175#ifndef EIGEN_PARSED_BY_DOXYGEN
176    /** \internal */
177    template<typename Stream>
178    void dumpMemory(Stream& s)
179    {
180      int total = 0;
181      s << "  L:        " << ((total+=(m_matrix.cols()+1) * sizeof(int) + m_matrix.nonZeros()*(sizeof(int)+sizeof(Scalar))) >> 20) << "Mb" << "\n";
182      s << "  diag:     " << ((total+=m_diag.size() * sizeof(Scalar)) >> 20) << "Mb" << "\n";
183      s << "  tree:     " << ((total+=m_parent.size() * sizeof(int)) >> 20) << "Mb" << "\n";
184      s << "  nonzeros: " << ((total+=m_nonZerosPerCol.size() * sizeof(int)) >> 20) << "Mb" << "\n";
185      s << "  perm:     " << ((total+=m_P.size() * sizeof(int)) >> 20) << "Mb" << "\n";
186      s << "  perm^-1:  " << ((total+=m_Pinv.size() * sizeof(int)) >> 20) << "Mb" << "\n";
187      s << "  TOTAL:    " << (total>> 20) << "Mb" << "\n";
188    }
189
190    /** \internal */
191    template<typename Rhs,typename Dest>
192    void _solve(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const
193    {
194      eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
195      eigen_assert(m_matrix.rows()==b.rows());
196
197      if(m_info!=Success)
198        return;
199
200      if(m_P.size()>0)
201        dest = m_P * b;
202      else
203        dest = b;
204
205      if(m_matrix.nonZeros()>0) // otherwise L==I
206        derived().matrixL().solveInPlace(dest);
207
208      if(m_diag.size()>0)
209        dest = m_diag.asDiagonal().inverse() * dest;
210
211      if (m_matrix.nonZeros()>0) // otherwise U==I
212        derived().matrixU().solveInPlace(dest);
213
214      if(m_P.size()>0)
215        dest = m_Pinv * dest;
216    }
217
218    /** \internal */
219    template<typename Rhs, typename DestScalar, int DestOptions, typename DestIndex>
220    void _solve_sparse(const Rhs& b, SparseMatrix<DestScalar,DestOptions,DestIndex> &dest) const
221    {
222      eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
223      eigen_assert(m_matrix.rows()==b.rows());
224     
225      // we process the sparse rhs per block of NbColsAtOnce columns temporarily stored into a dense matrix.
226      static const int NbColsAtOnce = 4;
227      int rhsCols = b.cols();
228      int size = b.rows();
229      Eigen::Matrix<DestScalar,Dynamic,Dynamic> tmp(size,rhsCols);
230      for(int k=0; k<rhsCols; k+=NbColsAtOnce)
231      {
232        int actualCols = std::min<int>(rhsCols-k, NbColsAtOnce);
233        tmp.leftCols(actualCols) = b.middleCols(k,actualCols);
234        tmp.leftCols(actualCols) = derived().solve(tmp.leftCols(actualCols));
235        dest.middleCols(k,actualCols) = tmp.leftCols(actualCols).sparseView();
236      }
237    }
238
239#endif // EIGEN_PARSED_BY_DOXYGEN
240
241  protected:
242   
243    /** Computes the sparse Cholesky decomposition of \a matrix */
244    template<bool DoLDLT>
245    void compute(const MatrixType& matrix)
246    {
247      eigen_assert(matrix.rows()==matrix.cols());
248      Index size = matrix.cols();
249      CholMatrixType ap(size,size);
250      ordering(matrix, ap);
251      analyzePattern_preordered(ap, DoLDLT);
252      factorize_preordered<DoLDLT>(ap);
253    }
254   
255    template<bool DoLDLT>
256    void factorize(const MatrixType& a)
257    {
258      eigen_assert(a.rows()==a.cols());
259      int size = a.cols();
260      CholMatrixType ap(size,size);
261      ap.template selfadjointView<Upper>() = a.template selfadjointView<UpLo>().twistedBy(m_P);
262      factorize_preordered<DoLDLT>(ap);
263    }
264
265    template<bool DoLDLT>
266    void factorize_preordered(const CholMatrixType& a);
267
268    void analyzePattern(const MatrixType& a, bool doLDLT)
269    {
270      eigen_assert(a.rows()==a.cols());
271      int size = a.cols();
272      CholMatrixType ap(size,size);
273      ordering(a, ap);
274      analyzePattern_preordered(ap,doLDLT);
275    }
276    void analyzePattern_preordered(const CholMatrixType& a, bool doLDLT);
277   
278    void ordering(const MatrixType& a, CholMatrixType& ap);
279
280    /** keeps off-diagonal entries; drops diagonal entries */
281    struct keep_diag {
282      inline bool operator() (const Index& row, const Index& col, const Scalar&) const
283      {
284        return row!=col;
285      }
286    };
287
288    mutable ComputationInfo m_info;
289    bool m_isInitialized;
290    bool m_factorizationIsOk;
291    bool m_analysisIsOk;
292   
293    CholMatrixType m_matrix;
294    VectorType m_diag;                                // the diagonal coefficients (LDLT mode)
295    VectorXi m_parent;                                // elimination tree
296    VectorXi m_nonZerosPerCol;
297    PermutationMatrix<Dynamic,Dynamic,Index> m_P;     // the permutation
298    PermutationMatrix<Dynamic,Dynamic,Index> m_Pinv;  // the inverse permutation
299
300    RealScalar m_shiftOffset;
301    RealScalar m_shiftScale;
302};
303
304template<typename _MatrixType, int _UpLo = Lower> class SimplicialLLT;
305template<typename _MatrixType, int _UpLo = Lower> class SimplicialLDLT;
306template<typename _MatrixType, int _UpLo = Lower> class SimplicialCholesky;
307
308namespace internal {
309
310template<typename _MatrixType, int _UpLo> struct traits<SimplicialLLT<_MatrixType,_UpLo> >
311{
312  typedef _MatrixType MatrixType;
313  enum { UpLo = _UpLo };
314  typedef typename MatrixType::Scalar                         Scalar;
315  typedef typename MatrixType::Index                          Index;
316  typedef SparseMatrix<Scalar, ColMajor, Index>               CholMatrixType;
317  typedef SparseTriangularView<CholMatrixType, Eigen::Lower>  MatrixL;
318  typedef SparseTriangularView<typename CholMatrixType::AdjointReturnType, Eigen::Upper>   MatrixU;
319  static inline MatrixL getL(const MatrixType& m) { return m; }
320  static inline MatrixU getU(const MatrixType& m) { return m.adjoint(); }
321};
322
323template<typename _MatrixType,int _UpLo> struct traits<SimplicialLDLT<_MatrixType,_UpLo> >
324{
325  typedef _MatrixType MatrixType;
326  enum { UpLo = _UpLo };
327  typedef typename MatrixType::Scalar                             Scalar;
328  typedef typename MatrixType::Index                              Index;
329  typedef SparseMatrix<Scalar, ColMajor, Index>                   CholMatrixType;
330  typedef SparseTriangularView<CholMatrixType, Eigen::UnitLower>  MatrixL;
331  typedef SparseTriangularView<typename CholMatrixType::AdjointReturnType, Eigen::UnitUpper> MatrixU;
332  static inline MatrixL getL(const MatrixType& m) { return m; }
333  static inline MatrixU getU(const MatrixType& m) { return m.adjoint(); }
334};
335
336template<typename _MatrixType, int _UpLo> struct traits<SimplicialCholesky<_MatrixType,_UpLo> >
337{
338  typedef _MatrixType MatrixType;
339  enum { UpLo = _UpLo };
340};
341
342}
343
344/** \ingroup SparseCholesky_Module
345  * \class SimplicialLLT
346  * \brief A direct sparse LLT Cholesky factorizations
347  *
348  * This class provides a LL^T Cholesky factorizations of sparse matrices that are
349  * selfadjoint and positive definite. The factorization allows for solving A.X = B where
350  * X and B can be either dense or sparse.
351  *
352  * In order to reduce the fill-in, a symmetric permutation P is applied prior to the factorization
353  * such that the factorized matrix is P A P^-1.
354  *
355  * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
356  * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
357  *               or Upper. Default is Lower.
358  *
359  * \sa class SimplicialLDLT
360  */
361template<typename _MatrixType, int _UpLo>
362    class SimplicialLLT : public SimplicialCholeskyBase<SimplicialLLT<_MatrixType,_UpLo> >
363{
364public:
365    typedef _MatrixType MatrixType;
366    enum { UpLo = _UpLo };
367    typedef SimplicialCholeskyBase<SimplicialLLT> Base;
368    typedef typename MatrixType::Scalar Scalar;
369    typedef typename MatrixType::RealScalar RealScalar;
370    typedef typename MatrixType::Index Index;
371    typedef SparseMatrix<Scalar,ColMajor,Index> CholMatrixType;
372    typedef Matrix<Scalar,Dynamic,1> VectorType;
373    typedef internal::traits<SimplicialLLT> Traits;
374    typedef typename Traits::MatrixL  MatrixL;
375    typedef typename Traits::MatrixU  MatrixU;
376public:
377    /** Default constructor */
378    SimplicialLLT() : Base() {}
379    /** Constructs and performs the LLT factorization of \a matrix */
380    SimplicialLLT(const MatrixType& matrix)
381        : Base(matrix) {}
382
383    /** \returns an expression of the factor L */
384    inline const MatrixL matrixL() const {
385        eigen_assert(Base::m_factorizationIsOk && "Simplicial LLT not factorized");
386        return Traits::getL(Base::m_matrix);
387    }
388
389    /** \returns an expression of the factor U (= L^*) */
390    inline const MatrixU matrixU() const {
391        eigen_assert(Base::m_factorizationIsOk && "Simplicial LLT not factorized");
392        return Traits::getU(Base::m_matrix);
393    }
394   
395    /** Computes the sparse Cholesky decomposition of \a matrix */
396    SimplicialLLT& compute(const MatrixType& matrix)
397    {
398      Base::template compute<false>(matrix);
399      return *this;
400    }
401
402    /** Performs a symbolic decomposition on the sparcity of \a matrix.
403      *
404      * This function is particularly useful when solving for several problems having the same structure.
405      *
406      * \sa factorize()
407      */
408    void analyzePattern(const MatrixType& a)
409    {
410      Base::analyzePattern(a, false);
411    }
412
413    /** Performs a numeric decomposition of \a matrix
414      *
415      * The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed.
416      *
417      * \sa analyzePattern()
418      */
419    void factorize(const MatrixType& a)
420    {
421      Base::template factorize<false>(a);
422    }
423
424    /** \returns the determinant of the underlying matrix from the current factorization */
425    Scalar determinant() const
426    {
427      Scalar detL = Base::m_matrix.diagonal().prod();
428      return internal::abs2(detL);
429    }
430};
431
432/** \ingroup SparseCholesky_Module
433  * \class SimplicialLDLT
434  * \brief A direct sparse LDLT Cholesky factorizations without square root.
435  *
436  * This class provides a LDL^T Cholesky factorizations without square root of sparse matrices that are
437  * selfadjoint and positive definite. The factorization allows for solving A.X = B where
438  * X and B can be either dense or sparse.
439  *
440  * In order to reduce the fill-in, a symmetric permutation P is applied prior to the factorization
441  * such that the factorized matrix is P A P^-1.
442  *
443  * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
444  * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
445  *               or Upper. Default is Lower.
446  *
447  * \sa class SimplicialLLT
448  */
449template<typename _MatrixType, int _UpLo>
450    class SimplicialLDLT : public SimplicialCholeskyBase<SimplicialLDLT<_MatrixType,_UpLo> >
451{
452public:
453    typedef _MatrixType MatrixType;
454    enum { UpLo = _UpLo };
455    typedef SimplicialCholeskyBase<SimplicialLDLT> Base;
456    typedef typename MatrixType::Scalar Scalar;
457    typedef typename MatrixType::RealScalar RealScalar;
458    typedef typename MatrixType::Index Index;
459    typedef SparseMatrix<Scalar,ColMajor,Index> CholMatrixType;
460    typedef Matrix<Scalar,Dynamic,1> VectorType;
461    typedef internal::traits<SimplicialLDLT> Traits;
462    typedef typename Traits::MatrixL  MatrixL;
463    typedef typename Traits::MatrixU  MatrixU;
464public:
465    /** Default constructor */
466    SimplicialLDLT() : Base() {}
467
468    /** Constructs and performs the LLT factorization of \a matrix */
469    SimplicialLDLT(const MatrixType& matrix)
470        : Base(matrix) {}
471
472    /** \returns a vector expression of the diagonal D */
473    inline const VectorType vectorD() const {
474        eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized");
475        return Base::m_diag;
476    }
477    /** \returns an expression of the factor L */
478    inline const MatrixL matrixL() const {
479        eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized");
480        return Traits::getL(Base::m_matrix);
481    }
482
483    /** \returns an expression of the factor U (= L^*) */
484    inline const MatrixU matrixU() const {
485        eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized");
486        return Traits::getU(Base::m_matrix);
487    }
488
489    /** Computes the sparse Cholesky decomposition of \a matrix */
490    SimplicialLDLT& compute(const MatrixType& matrix)
491    {
492      Base::template compute<true>(matrix);
493      return *this;
494    }
495   
496    /** Performs a symbolic decomposition on the sparcity of \a matrix.
497      *
498      * This function is particularly useful when solving for several problems having the same structure.
499      *
500      * \sa factorize()
501      */
502    void analyzePattern(const MatrixType& a)
503    {
504      Base::analyzePattern(a, true);
505    }
506
507    /** Performs a numeric decomposition of \a matrix
508      *
509      * The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed.
510      *
511      * \sa analyzePattern()
512      */
513    void factorize(const MatrixType& a)
514    {
515      Base::template factorize<true>(a);
516    }
517
518    /** \returns the determinant of the underlying matrix from the current factorization */
519    Scalar determinant() const
520    {
521      return Base::m_diag.prod();
522    }
523};
524
525/** \deprecated use SimplicialLDLT or class SimplicialLLT
526  * \ingroup SparseCholesky_Module
527  * \class SimplicialCholesky
528  *
529  * \sa class SimplicialLDLT, class SimplicialLLT
530  */
531template<typename _MatrixType, int _UpLo>
532    class SimplicialCholesky : public SimplicialCholeskyBase<SimplicialCholesky<_MatrixType,_UpLo> >
533{
534public:
535    typedef _MatrixType MatrixType;
536    enum { UpLo = _UpLo };
537    typedef SimplicialCholeskyBase<SimplicialCholesky> Base;
538    typedef typename MatrixType::Scalar Scalar;
539    typedef typename MatrixType::RealScalar RealScalar;
540    typedef typename MatrixType::Index Index;
541    typedef SparseMatrix<Scalar,ColMajor,Index> CholMatrixType;
542    typedef Matrix<Scalar,Dynamic,1> VectorType;
543    typedef internal::traits<SimplicialCholesky> Traits;
544    typedef internal::traits<SimplicialLDLT<MatrixType,UpLo> > LDLTTraits;
545    typedef internal::traits<SimplicialLLT<MatrixType,UpLo>  > LLTTraits;
546  public:
547    SimplicialCholesky() : Base(), m_LDLT(true) {}
548
549    SimplicialCholesky(const MatrixType& matrix)
550      : Base(), m_LDLT(true)
551    {
552      compute(matrix);
553    }
554
555    SimplicialCholesky& setMode(SimplicialCholeskyMode mode)
556    {
557      switch(mode)
558      {
559      case SimplicialCholeskyLLT:
560        m_LDLT = false;
561        break;
562      case SimplicialCholeskyLDLT:
563        m_LDLT = true;
564        break;
565      default:
566        break;
567      }
568
569      return *this;
570    }
571
572    inline const VectorType vectorD() const {
573        eigen_assert(Base::m_factorizationIsOk && "Simplicial Cholesky not factorized");
574        return Base::m_diag;
575    }
576    inline const CholMatrixType rawMatrix() const {
577        eigen_assert(Base::m_factorizationIsOk && "Simplicial Cholesky not factorized");
578        return Base::m_matrix;
579    }
580   
581    /** Computes the sparse Cholesky decomposition of \a matrix */
582    SimplicialCholesky& compute(const MatrixType& matrix)
583    {
584      if(m_LDLT)
585        Base::template compute<true>(matrix);
586      else
587        Base::template compute<false>(matrix);
588      return *this;
589    }
590
591    /** Performs a symbolic decomposition on the sparcity of \a matrix.
592      *
593      * This function is particularly useful when solving for several problems having the same structure.
594      *
595      * \sa factorize()
596      */
597    void analyzePattern(const MatrixType& a)
598    {
599      Base::analyzePattern(a, m_LDLT);
600    }
601
602    /** Performs a numeric decomposition of \a matrix
603      *
604      * The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed.
605      *
606      * \sa analyzePattern()
607      */
608    void factorize(const MatrixType& a)
609    {
610      if(m_LDLT)
611        Base::template factorize<true>(a);
612      else
613        Base::template factorize<false>(a);
614    }
615
616    /** \internal */
617    template<typename Rhs,typename Dest>
618    void _solve(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const
619    {
620      eigen_assert(Base::m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
621      eigen_assert(Base::m_matrix.rows()==b.rows());
622
623      if(Base::m_info!=Success)
624        return;
625
626      if(Base::m_P.size()>0)
627        dest = Base::m_P * b;
628      else
629        dest = b;
630
631      if(Base::m_matrix.nonZeros()>0) // otherwise L==I
632      {
633        if(m_LDLT)
634          LDLTTraits::getL(Base::m_matrix).solveInPlace(dest);
635        else
636          LLTTraits::getL(Base::m_matrix).solveInPlace(dest);
637      }
638
639      if(Base::m_diag.size()>0)
640        dest = Base::m_diag.asDiagonal().inverse() * dest;
641
642      if (Base::m_matrix.nonZeros()>0) // otherwise I==I
643      {
644        if(m_LDLT)
645          LDLTTraits::getU(Base::m_matrix).solveInPlace(dest);
646        else
647          LLTTraits::getU(Base::m_matrix).solveInPlace(dest);
648      }
649
650      if(Base::m_P.size()>0)
651        dest = Base::m_Pinv * dest;
652    }
653   
654    Scalar determinant() const
655    {
656      if(m_LDLT)
657      {
658        return Base::m_diag.prod();
659      }
660      else
661      {
662        Scalar detL = Diagonal<const CholMatrixType>(Base::m_matrix).prod();
663        return internal::abs2(detL);
664      }
665    }
666   
667  protected:
668    bool m_LDLT;
669};
670
671template<typename Derived>
672void SimplicialCholeskyBase<Derived>::ordering(const MatrixType& a, CholMatrixType& ap)
673{
674  eigen_assert(a.rows()==a.cols());
675  const Index size = a.rows();
676  // TODO allows to configure the permutation
677  // Note that amd compute the inverse permutation
678  {
679    CholMatrixType C;
680    C = a.template selfadjointView<UpLo>();
681    // remove diagonal entries:
682    // seems not to be needed
683    // C.prune(keep_diag());
684    internal::minimum_degree_ordering(C, m_Pinv);
685  }
686
687  if(m_Pinv.size()>0)
688    m_P = m_Pinv.inverse();
689  else
690    m_P.resize(0);
691
692  ap.resize(size,size);
693  ap.template selfadjointView<Upper>() = a.template selfadjointView<UpLo>().twistedBy(m_P);
694}
695
696template<typename Derived>
697void SimplicialCholeskyBase<Derived>::analyzePattern_preordered(const CholMatrixType& ap, bool doLDLT)
698{
699  const Index size = ap.rows();
700  m_matrix.resize(size, size);
701  m_parent.resize(size);
702  m_nonZerosPerCol.resize(size);
703 
704  ei_declare_aligned_stack_constructed_variable(Index, tags, size, 0);
705
706  for(Index k = 0; k < size; ++k)
707  {
708    /* L(k,:) pattern: all nodes reachable in etree from nz in A(0:k-1,k) */
709    m_parent[k] = -1;             /* parent of k is not yet known */
710    tags[k] = k;                  /* mark node k as visited */
711    m_nonZerosPerCol[k] = 0;      /* count of nonzeros in column k of L */
712    for(typename CholMatrixType::InnerIterator it(ap,k); it; ++it)
713    {
714      Index i = it.index();
715      if(i < k)
716      {
717        /* follow path from i to root of etree, stop at flagged node */
718        for(; tags[i] != k; i = m_parent[i])
719        {
720          /* find parent of i if not yet determined */
721          if (m_parent[i] == -1)
722            m_parent[i] = k;
723          m_nonZerosPerCol[i]++;        /* L (k,i) is nonzero */
724          tags[i] = k;                  /* mark i as visited */
725        }
726      }
727    }
728  }
729 
730  /* construct Lp index array from m_nonZerosPerCol column counts */
731  Index* Lp = m_matrix.outerIndexPtr();
732  Lp[0] = 0;
733  for(Index k = 0; k < size; ++k)
734    Lp[k+1] = Lp[k] + m_nonZerosPerCol[k] + (doLDLT ? 0 : 1);
735
736  m_matrix.resizeNonZeros(Lp[size]);
737 
738  m_isInitialized     = true;
739  m_info              = Success;
740  m_analysisIsOk      = true;
741  m_factorizationIsOk = false;
742}
743
744
745template<typename Derived>
746template<bool DoLDLT>
747void SimplicialCholeskyBase<Derived>::factorize_preordered(const CholMatrixType& ap)
748{
749  eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
750  eigen_assert(ap.rows()==ap.cols());
751  const Index size = ap.rows();
752  eigen_assert(m_parent.size()==size);
753  eigen_assert(m_nonZerosPerCol.size()==size);
754
755  const Index* Lp = m_matrix.outerIndexPtr();
756  Index* Li = m_matrix.innerIndexPtr();
757  Scalar* Lx = m_matrix.valuePtr();
758
759  ei_declare_aligned_stack_constructed_variable(Scalar, y, size, 0);
760  ei_declare_aligned_stack_constructed_variable(Index,  pattern, size, 0);
761  ei_declare_aligned_stack_constructed_variable(Index,  tags, size, 0);
762 
763  bool ok = true;
764  m_diag.resize(DoLDLT ? size : 0);
765 
766  for(Index k = 0; k < size; ++k)
767  {
768    // compute nonzero pattern of kth row of L, in topological order
769    y[k] = 0.0;                     // Y(0:k) is now all zero
770    Index top = size;               // stack for pattern is empty
771    tags[k] = k;                    // mark node k as visited
772    m_nonZerosPerCol[k] = 0;        // count of nonzeros in column k of L
773    for(typename MatrixType::InnerIterator it(ap,k); it; ++it)
774    {
775      Index i = it.index();
776      if(i <= k)
777      {
778        y[i] += internal::conj(it.value());            /* scatter A(i,k) into Y (sum duplicates) */
779        Index len;
780        for(len = 0; tags[i] != k; i = m_parent[i])
781        {
782          pattern[len++] = i;     /* L(k,i) is nonzero */
783          tags[i] = k;            /* mark i as visited */
784        }
785        while(len > 0)
786          pattern[--top] = pattern[--len];
787      }
788    }
789
790    /* compute numerical values kth row of L (a sparse triangular solve) */
791
792    RealScalar d = internal::real(y[k]) * m_shiftScale + m_shiftOffset;    // get D(k,k), apply the shift function, and clear Y(k)
793    y[k] = 0.0;
794    for(; top < size; ++top)
795    {
796      Index i = pattern[top];       /* pattern[top:n-1] is pattern of L(:,k) */
797      Scalar yi = y[i];             /* get and clear Y(i) */
798      y[i] = 0.0;
799     
800      /* the nonzero entry L(k,i) */
801      Scalar l_ki;
802      if(DoLDLT)
803        l_ki = yi / m_diag[i];       
804      else
805        yi = l_ki = yi / Lx[Lp[i]];
806     
807      Index p2 = Lp[i] + m_nonZerosPerCol[i];
808      Index p;
809      for(p = Lp[i] + (DoLDLT ? 0 : 1); p < p2; ++p)
810        y[Li[p]] -= internal::conj(Lx[p]) * yi;
811      d -= internal::real(l_ki * internal::conj(yi));
812      Li[p] = k;                          /* store L(k,i) in column form of L */
813      Lx[p] = l_ki;
814      ++m_nonZerosPerCol[i];              /* increment count of nonzeros in col i */
815    }
816    if(DoLDLT)
817    {
818      m_diag[k] = d;
819      if(d == RealScalar(0))
820      {
821        ok = false;                         /* failure, D(k,k) is zero */
822        break;
823      }
824    }
825    else
826    {
827      Index p = Lp[k] + m_nonZerosPerCol[k]++;
828      Li[p] = k ;                /* store L(k,k) = sqrt (d) in column k */
829      if(d <= RealScalar(0)) {
830        ok = false;              /* failure, matrix is not positive definite */
831        break;
832      }
833      Lx[p] = internal::sqrt(d) ;
834    }
835  }
836
837  m_info = ok ? Success : NumericalIssue;
838  m_factorizationIsOk = true;
839}
840
841namespace internal {
842 
843template<typename Derived, typename Rhs>
844struct solve_retval<SimplicialCholeskyBase<Derived>, Rhs>
845  : solve_retval_base<SimplicialCholeskyBase<Derived>, Rhs>
846{
847  typedef SimplicialCholeskyBase<Derived> Dec;
848  EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs)
849
850  template<typename Dest> void evalTo(Dest& dst) const
851  {
852    dec().derived()._solve(rhs(),dst);
853  }
854};
855
856template<typename Derived, typename Rhs>
857struct sparse_solve_retval<SimplicialCholeskyBase<Derived>, Rhs>
858  : sparse_solve_retval_base<SimplicialCholeskyBase<Derived>, Rhs>
859{
860  typedef SimplicialCholeskyBase<Derived> Dec;
861  EIGEN_MAKE_SPARSE_SOLVE_HELPERS(Dec,Rhs)
862
863  template<typename Dest> void evalTo(Dest& dst) const
864  {
865    dec().derived()._solve_sparse(rhs(),dst);
866  }
867};
868
869} // end namespace internal
870
871} // end namespace Eigen
872
873#endif // EIGEN_SIMPLICIAL_CHOLESKY_H
Note: See TracBrowser for help on using the repository browser.