如何在 Eigen 中使用自定义预处理器

How to use custom preconditioner with Eigen

我正在尝试将自定义预条件器用于带有 Eigen 的迭代求解器(例如 CG)。具体来说,我必须多次解决类似的问题:矩阵略有变化但保持接近均值矩阵。我想计算均值矩阵的 Cholesky 分解,然后将其用作预条件子。

我的想法是这样的:

ConjugateGradient< SparseMatrix<double>, Lower, CholmodSupernodalLLT<SparseMatrix<double>> > solver(meanMatrix);
solver.preconditioner().compute(meanMatrix);
// Loop on n similar matrices
for(int i = 0; i < n; i++){
  // create matrix: it is similar (in structure and in values) to meanMatrix
  SparseMatrix<double> matrix = ...;
  // create right-hand-side
  VectorXd rhs = ...;
  // update matrix reference for solver
  solver.compute(matrix);
  // solve using the preconditioned CG
  solver.solve(rhs);
}

问题是调用 solver.compute(matrix) 实际上会导致 ConjugateGradient(实际上是 IterativeSolverBase)调用 compute它的预条件子(参见 l. 111 of IterativeSolverBase.h, Eigen 3.2.9):

m_preconditioner.compute(*mp_matrix);

换句话说,基于均值矩阵的预条件被新矩阵的Cholesky分解所取代,因此CG求解在1次迭代中收敛。相反,我想保留 相同的预条件 (均值矩阵的 Cholesky 分解,在循环之前一劳永逸地计算),并使用预条件求解不同的矩阵CG.

有没有一种简单的方法可以实现我想要做的事情?

非常感谢您的帮助!我希望这是有道理的。如果没有,请不要犹豫,让我澄清一下。

一种方法是围绕 CholmodSupernodalLLT 编写一个小包装器,展示所需的预调节器 API 并且其 compute() 方法将是空操作。这可以在 10-15 行代码中完成,灵感来自 IdentityPreconditioner。 唯一需要的更改是存储一个 CholmodSupernodalLLT 对象(或引用)并实现 solve 到 return m_llt.solve(b);.