11#ifndef EIGEN_INCOMPLETE_CHOlESKY_H
12#define EIGEN_INCOMPLETE_CHOlESKY_H
18#include "./InternalHeaderCheck.h"
50template <
typename Scalar,
int UpLo_ = Lower,
typename OrderingType_ = AMDOrdering<
int> >
54 using Base::m_isInitialized;
57 typedef typename NumTraits<Scalar>::Real RealScalar;
58 typedef OrderingType_ OrderingType;
59 typedef typename OrderingType::PermutationType PermutationType;
60 typedef typename PermutationType::StorageIndex StorageIndex;
65 typedef std::vector<std::list<StorageIndex> > VectorList;
66 enum { UpLo = UpLo_ };
67 enum { ColsAtCompileTime =
Dynamic, MaxColsAtCompileTime =
Dynamic };
76 IncompleteCholesky() : m_initialShift(1e-3), m_analysisIsOk(false), m_factorizationIsOk(false) {}
80 template <
typename MatrixType>
82 : m_initialShift(1e-3), m_analysisIsOk(false), m_factorizationIsOk(false) {
87 EIGEN_CONSTEXPR
Index rows() const EIGEN_NOEXCEPT {
return m_L.
rows(); }
90 EIGEN_CONSTEXPR
Index cols() const EIGEN_NOEXCEPT {
return m_L.
cols(); }
101 eigen_assert(m_isInitialized &&
"IncompleteCholesky is not initialized.");
111 template <
typename MatrixType>
114 PermutationType pinv;
115 ord(mat.template selfadjointView<UpLo>(), pinv);
117 m_perm = pinv.inverse();
120 m_L.
resize(mat.rows(), mat.cols());
121 m_analysisIsOk =
true;
122 m_isInitialized =
true;
133 template <
typename MatrixType>
142 template <
typename MatrixType>
149 template <
typename Rhs,
typename Dest>
150 void _solve_impl(
const Rhs& b, Dest& x)
const {
151 eigen_assert(m_factorizationIsOk &&
"factorize() should be called first");
152 if (m_perm.rows() == b.rows())
156 x = m_scale.asDiagonal() * x;
157 x = m_L.template triangularView<Lower>().solve(x);
158 x = m_L.adjoint().template triangularView<Upper>().solve(x);
159 x = m_scale.asDiagonal() * x;
160 if (m_perm.rows() == b.rows()) x = m_perm.inverse() * x;
165 eigen_assert(m_factorizationIsOk &&
"factorize() should be called first");
171 eigen_assert(m_factorizationIsOk &&
"factorize() should be called first");
177 eigen_assert(m_analysisIsOk &&
"analyzePattern() should be called first");
182 RealScalar
shift()
const {
return m_shift; }
187 RealScalar m_initialShift;
189 bool m_factorizationIsOk;
191 PermutationType m_perm;
196 const Index& jk, VectorIx& firstElt, VectorList& listCol);
203template <
typename Scalar,
int UpLo_,
typename OrderingType>
204template <
typename MatrixType_>
205void IncompleteCholesky<Scalar, UpLo_, OrderingType>::factorize(
const MatrixType_& mat) {
207 eigen_assert(m_analysisIsOk &&
"analyzePattern() should be called first");
213 if (m_perm.rows() == mat.rows())
216 FactorType tmp(mat.rows(), mat.cols());
217 tmp = mat.template selfadjointView<UpLo_>().twistedBy(m_perm);
218 m_L.template selfadjointView<Lower>() = tmp.template selfadjointView<Lower>();
220 m_L.template selfadjointView<Lower>() = mat.template selfadjointView<UpLo_>();
227 bool modified =
false;
228 for (Index i = 0; i < mat.cols(); ++i) {
229 bool inserted =
false;
230 m_L.findOrInsertCoeff(i, i, &inserted);
235 if (modified) m_L.makeCompressed();
237 Index n = m_L.cols();
238 Index nnz = m_L.nonZeros();
239 Map<VectorSx> vals(m_L.valuePtr(), nnz);
240 Map<VectorIx> rowIdx(m_L.innerIndexPtr(), nnz);
241 Map<VectorIx> colPtr(m_L.outerIndexPtr(), n + 1);
242 VectorIx firstElt(n - 1);
243 VectorList listCol(n);
244 VectorSx col_vals(n);
245 VectorIx col_irow(n);
246 VectorIx col_pattern(n);
247 col_pattern.fill(-1);
248 StorageIndex col_nnz;
253 for (Index j = 0; j < n; j++)
254 for (Index k = colPtr[j]; k < colPtr[j + 1]; k++) {
255 m_scale(j) += numext::abs2(vals(k));
256 if (rowIdx[k] != j) m_scale(rowIdx[k]) += numext::abs2(vals(k));
259 m_scale = m_scale.cwiseSqrt().cwiseSqrt();
261 for (Index j = 0; j < n; ++j)
262 if (m_scale(j) > (std::numeric_limits<RealScalar>::min)())
263 m_scale(j) = RealScalar(1) / m_scale(j);
270 RealScalar mindiag = NumTraits<RealScalar>::highest();
271 for (Index j = 0; j < n; j++) {
272 for (Index k = colPtr[j]; k < colPtr[j + 1]; k++) vals[k] *= (m_scale(j) * m_scale(rowIdx[k]));
273 eigen_internal_assert(rowIdx[colPtr[j]] == j &&
274 "IncompleteCholesky: only the lower triangular part must be stored");
275 mindiag = numext::mini(numext::real(vals[colPtr[j]]), mindiag);
278 FactorType L_save = m_L;
280 m_shift = RealScalar(0);
281 if (mindiag <= RealScalar(0.)) m_shift = m_initialShift - mindiag;
289 for (Index j = 0; j < n; j++) vals[colPtr[j]] += m_shift;
296 Scalar diag = vals[colPtr[j]];
298 for (Index i = colPtr[j] + 1; i < colPtr[j + 1]; i++) {
299 StorageIndex l = rowIdx[i];
300 col_vals(col_nnz) = vals[i];
301 col_irow(col_nnz) = l;
302 col_pattern(l) = col_nnz;
306 typename std::list<StorageIndex>::iterator k;
308 for (k = listCol[j].begin(); k != listCol[j].end(); k++) {
309 Index jk = firstElt(*k);
310 eigen_internal_assert(rowIdx[jk] == j);
311 Scalar v_j_jk = numext::conj(vals[jk]);
314 for (Index i = jk; i < colPtr[*k + 1]; i++) {
315 StorageIndex l = rowIdx[i];
316 if (col_pattern[l] < 0) {
317 col_vals(col_nnz) = vals[i] * v_j_jk;
318 col_irow[col_nnz] = l;
319 col_pattern(l) = col_nnz;
322 col_vals(col_pattern[l]) -= vals[i] * v_j_jk;
324 updateList(colPtr, rowIdx, vals, *k, jk, firstElt, listCol);
329 if (numext::real(diag) <= 0) {
330 if (++iter >= 10)
return;
333 m_shift = numext::maxi(m_initialShift, RealScalar(2) * m_shift);
335 vals = Map<const VectorSx>(L_save.valuePtr(), nnz);
336 rowIdx = Map<const VectorIx>(L_save.innerIndexPtr(), nnz);
337 colPtr = Map<const VectorIx>(L_save.outerIndexPtr(), n + 1);
338 col_pattern.fill(-1);
339 for (Index i = 0; i < n; ++i) listCol[i].clear();
344 RealScalar rdiag = sqrt(numext::real(diag));
345 vals[colPtr[j]] = rdiag;
346 for (Index k = 0; k < col_nnz; ++k) {
347 Index i = col_irow[k];
349 col_vals(k) /= rdiag;
351 vals[colPtr[i]] -= numext::abs2(col_vals(k));
355 Index p = colPtr[j + 1] - colPtr[j] - 1;
356 Ref<VectorSx> cvals = col_vals.head(col_nnz);
357 Ref<VectorIx> cirow = col_irow.head(col_nnz);
358 internal::QuickSplit(cvals, cirow, p);
361 for (Index i = colPtr[j] + 1; i < colPtr[j + 1]; i++) {
362 vals[i] = col_vals(cpt);
363 rowIdx[i] = col_irow(cpt);
365 col_pattern(col_irow(cpt)) = -1;
369 Index jk = colPtr(j) + 1;
370 updateList(colPtr, rowIdx, vals, j, jk, firstElt, listCol);
374 m_factorizationIsOk =
true;
377 }
while (m_info != Success);
380template <
typename Scalar,
int UpLo_,
typename OrderingType>
381inline void IncompleteCholesky<Scalar, UpLo_, OrderingType>::updateList(Ref<const VectorIx> colPtr,
382 Ref<VectorIx> rowIdx, Ref<VectorSx> vals,
383 const Index& col,
const Index& jk,
384 VectorIx& firstElt, VectorList& listCol) {
385 if (jk < colPtr(col + 1)) {
386 Index p = colPtr(col + 1) - jk;
388 rowIdx.segment(jk, p).minCoeff(&minpos);
390 if (rowIdx(minpos) != rowIdx(jk)) {
392 std::swap(rowIdx(jk), rowIdx(minpos));
393 std::swap(vals(jk), vals(minpos));
395 firstElt(col) = internal::convert_index<StorageIndex, Index>(jk);
396 listCol[rowIdx(jk)].push_back(internal::convert_index<StorageIndex, Index>(col));
Modified Incomplete Cholesky with dual threshold.
Definition IncompleteCholesky.h:51
ComputationInfo info() const
Reports whether previous computation was successful.
Definition IncompleteCholesky.h:100
IncompleteCholesky(const MatrixType &matrix)
Definition IncompleteCholesky.h:81
const VectorRx & scalingS() const
Definition IncompleteCholesky.h:170
const FactorType & matrixL() const
Definition IncompleteCholesky.h:164
EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
Definition IncompleteCholesky.h:87
const PermutationType & permutationP() const
Definition IncompleteCholesky.h:176
void factorize(const MatrixType &mat)
Performs the numerical factorization of the input matrix mat.
IncompleteCholesky()
Definition IncompleteCholesky.h:76
void compute(const MatrixType &mat)
Definition IncompleteCholesky.h:143
EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT
Definition IncompleteCholesky.h:90
void analyzePattern(const MatrixType &mat)
Computes the fill reducing permutation vector using the sparsity pattern of mat.
Definition IncompleteCholesky.h:112
RealScalar shift() const
Definition IncompleteCholesky.h:182
void setInitialShift(RealScalar shift)
Set the initial shift parameter .
Definition IncompleteCholesky.h:107
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:186
A matrix or vector expression mapping an existing expression.
Definition Ref.h:264
A versatible sparse matrix representation.
Definition SparseUtil.h:47
Index cols() const
Definition SparseMatrix.h:161
Index rows() const
Definition SparseMatrix.h:159
void resize(Index rows, Index cols)
Definition SparseMatrix.h:730
A base class for sparse solvers.
Definition SparseSolverBase.h:67
ComputationInfo
Definition Constants.h:438
@ NumericalIssue
Definition Constants.h:442
@ Success
Definition Constants.h:440
Namespace containing all symbols from the Eigen library.
Definition Core:137
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:83
const int Dynamic
Definition Constants.h:25