1
1
// This file is part of Eigen, a lightweight C++ template library
2
2
// for linear algebra.
4
// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
4
// Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr>
5
5
// Copyright (C) 2009 Keir Mierle <mierle@gmail.com>
6
6
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
8
// Eigen is free software; you can redistribute it and/or
9
// modify it under the terms of the GNU Lesser General Public
10
// License as published by the Free Software Foundation; either
11
// version 3 of the License, or (at your option) any later version.
13
// Alternatively, you can redistribute it and/or
14
// modify it under the terms of the GNU General Public License as
15
// published by the Free Software Foundation; either version 2 of
16
// the License, or (at your option) any later version.
18
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
19
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
21
// GNU General Public License for more details.
23
// You should have received a copy of the GNU Lesser General Public
24
// License and a copy of the GNU General Public License along with
25
// Eigen. If not, see <http://www.gnu.org/licenses/>.
7
// Copyright (C) 2011 Timothy E. Holy <tim.holy@gmail.com >
9
// This Source Code Form is subject to the terms of the Mozilla
10
// Public License v. 2.0. If a copy of the MPL was not distributed
11
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
27
13
#ifndef EIGEN_LDLT_H
28
14
#define EIGEN_LDLT_H
30
18
namespace internal {
31
19
template<typename MatrixType, int UpLo> struct LDLT_Traits;
34
/** \ingroup cholesky_Module
22
/** \ingroup Cholesky_Module
38
26
* \brief Robust Cholesky decomposition of a matrix with pivoting
40
28
* \param MatrixType the type of the matrix of which to compute the LDL^T Cholesky decomposition
29
* \param UpLo the triangular part that will be used for the decompositon: Lower (default) or Upper.
30
* The other triangular part won't be read.
42
32
* Perform a robust Cholesky decomposition of a positive semidefinite or negative semidefinite
43
33
* matrix \f$ A \f$ such that \f$ A = P^TLDL^*P \f$, where P is a permutation matrix, L
48
38
* on D also stabilizes the computation.
50
40
* Remember that Cholesky decompositions are not rank-revealing. Also, do not use a Cholesky
51
* decomposition to determine whether a system of equations has a solution.
41
* decomposition to determine whether a system of equations has a solution.
53
43
* \sa MatrixBase::ldlt(), class LLT
55
/* THIS PART OF THE DOX IS CURRENTLY DISABLED BECAUSE INACCURATE BECAUSE OF BUG IN THE DECOMPOSITION CODE
56
* Note that during the decomposition, only the upper triangular part of A is considered. Therefore,
57
* the strict lower part does not have to store correct values.
59
45
template<typename _MatrixType, int _UpLo> class LDLT
98
84
m_isInitialized(false)
87
/** \brief Constructor with decomposition
89
* This calculates the decomposition for the input \a matrix.
90
* \sa LDLT(Index size)
101
92
LDLT(const MatrixType& matrix)
102
93
: m_matrix(matrix.rows(), matrix.cols()),
103
94
m_transpositions(matrix.rows()),
132
131
/** \returns the coefficients of the diagonal matrix D */
133
inline Diagonal<const MatrixType> vectorD(void) const
132
inline Diagonal<const MatrixType> vectorD() const
135
134
eigen_assert(m_isInitialized && "LDLT is not initialized.");
136
135
return m_matrix.diagonal();
139
138
/** \returns true if the matrix is positive (semidefinite) */
140
inline bool isPositive(void) const
139
inline bool isPositive() const
142
141
eigen_assert(m_isInitialized && "LDLT is not initialized.");
143
142
return m_sign == 1;
197
196
LDLT& compute(const MatrixType& matrix);
198
template <typename Derived>
199
LDLT& rankUpdate(const MatrixBase<Derived>& w,RealScalar alpha=1);
199
201
/** \returns the internal LDLT decomposition matrix
201
203
* TODO: document the storage layout
211
213
inline Index rows() const { return m_matrix.rows(); }
212
214
inline Index cols() const { return m_matrix.cols(); }
216
/** \brief Reports whether previous computation was successful.
218
* \returns \c Success if computation was succesful,
219
* \c NumericalIssue if the matrix.appears to be negative.
221
ComputationInfo info() const
223
eigen_assert(m_isInitialized && "LDLT is not initialized.");
334
// Reference for the algorithm: Davis and Hager, "Multiple Rank
335
// Modifications of a Sparse Cholesky Factorization" (Algorithm 1)
336
// Trivial rearrangements of their computations (Timothy E. Holy)
337
// allow their algorithm to work for rank-1 updates even if the
338
// original matrix is not of full rank.
339
// Here only rank-1 updates are implemented, to reduce the
340
// requirement for intermediate storage and improve accuracy
341
template<typename MatrixType, typename WDerived>
342
static bool updateInPlace(MatrixType& mat, MatrixBase<WDerived>& w, typename MatrixType::RealScalar sigma=1)
344
using internal::isfinite;
345
typedef typename MatrixType::Scalar Scalar;
346
typedef typename MatrixType::RealScalar RealScalar;
347
typedef typename MatrixType::Index Index;
349
const Index size = mat.rows();
350
eigen_assert(mat.cols() == size && w.size()==size);
352
RealScalar alpha = 1;
355
for (Index j = 0; j < size; j++)
357
// Check for termination due to an original decomposition of low-rank
358
if (!(isfinite)(alpha))
361
// Update the diagonal terms
362
RealScalar dj = real(mat.coeff(j,j));
363
Scalar wj = w.coeff(j);
364
RealScalar swj2 = sigma*abs2(wj);
365
RealScalar gamma = dj*alpha + swj2;
367
mat.coeffRef(j,j) += swj2/alpha;
371
// Update the terms of L
373
w.tail(rs) -= wj * mat.col(j).tail(rs);
375
mat.col(j).tail(rs) += (sigma*conj(wj)/gamma)*w.tail(rs);
380
template<typename MatrixType, typename TranspositionType, typename Workspace, typename WType>
381
static bool update(MatrixType& mat, const TranspositionType& transpositions, Workspace& tmp, const WType& w, typename MatrixType::RealScalar sigma=1)
383
// Apply the permutation to the input w
384
tmp = transpositions * w;
386
return ldlt_inplace<Lower>::updateInPlace(mat,tmp,sigma);
322
390
template<> struct ldlt_inplace<Upper>
327
395
Transpose<MatrixType> matt(mat);
328
396
return ldlt_inplace<Lower>::unblocked(matt, transpositions, temp, sign);
399
template<typename MatrixType, typename TranspositionType, typename Workspace, typename WType>
400
static EIGEN_STRONG_INLINE bool update(MatrixType& mat, TranspositionType& transpositions, Workspace& tmp, WType& w, typename MatrixType::RealScalar sigma=1)
402
Transpose<MatrixType> matt(mat);
403
return ldlt_inplace<Lower>::update(matt, transpositions, tmp, w.conjugate(), sigma);
332
407
template<typename MatrixType> struct LDLT_Traits<MatrixType,Lower>
334
typedef TriangularView<MatrixType, UnitLower> MatrixL;
335
typedef TriangularView<typename MatrixType::AdjointReturnType, UnitUpper> MatrixU;
336
inline static MatrixL getL(const MatrixType& m) { return m; }
337
inline static MatrixU getU(const MatrixType& m) { return m.adjoint(); }
409
typedef const TriangularView<const MatrixType, UnitLower> MatrixL;
410
typedef const TriangularView<const typename MatrixType::AdjointReturnType, UnitUpper> MatrixU;
411
static inline MatrixL getL(const MatrixType& m) { return m; }
412
static inline MatrixU getU(const MatrixType& m) { return m.adjoint(); }
340
415
template<typename MatrixType> struct LDLT_Traits<MatrixType,Upper>
342
typedef TriangularView<typename MatrixType::AdjointReturnType, UnitLower> MatrixL;
343
typedef TriangularView<MatrixType, UnitUpper> MatrixU;
344
inline static MatrixL getL(const MatrixType& m) { return m.adjoint(); }
345
inline static MatrixU getU(const MatrixType& m) { return m; }
417
typedef const TriangularView<const typename MatrixType::AdjointReturnType, UnitLower> MatrixL;
418
typedef const TriangularView<const MatrixType, UnitUpper> MatrixU;
419
static inline MatrixL getL(const MatrixType& m) { return m.adjoint(); }
420
static inline MatrixU getU(const MatrixType& m) { return m; }
348
423
} // end namespace internal
445
/** Update the LDLT decomposition: given A = L D L^T, efficiently compute the decomposition of A + sigma w w^T.
446
* \param w a vector to be incorporated into the decomposition.
447
* \param sigma a scalar, +1 for updates and -1 for "downdates," which correspond to removing previously-added column vectors. Optional; default value is +1.
450
template<typename MatrixType, int _UpLo>
451
template<typename Derived>
452
LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::rankUpdate(const MatrixBase<Derived>& w,typename NumTraits<typename MatrixType::Scalar>::Real sigma)
454
const Index size = w.rows();
457
eigen_assert(m_matrix.rows()==size);
461
m_matrix.resize(size,size);
463
m_transpositions.resize(size);
464
for (Index i = 0; i < size; i++)
465
m_transpositions.coeffRef(i) = i;
466
m_temporary.resize(size);
467
m_sign = sigma>=0 ? 1 : -1;
468
m_isInitialized = true;
471
internal::ldlt_inplace<UpLo>::update(m_matrix, m_transpositions, m_temporary, w, sigma);
370
476
namespace internal {
371
477
template<typename _MatrixType, int _UpLo, typename Rhs>
372
478
struct solve_retval<LDLT<_MatrixType,_UpLo>, Rhs>