如何使用自定义预处理与Eigen

How to use custom preconditioner with Eigen

本文关键字:Eigen 预处理 自定义 何使用      更新时间:2023-10-16

我正在尝试使用一个自定义预条件与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)实际上会导致共轭梯度(实际上是IterativeSolverBase)在其前置条件上调用compute(参见IterativeSolverBase.h的1.111节,本章3.2.9节):

m_preconditioner.compute(*mp_matrix);

即基于均值矩阵的预条件被新矩阵的Cholesky分解所取代,因此CG解在1次迭代中收敛。相反,我想保持相同的预条件(平均矩阵的Cholesky分解,在循环之前一次性计算),并使用预条件CG求解不同的矩阵。

是否有一种简单的方法来实现我想做的事情?

提前感谢您的帮助!我希望这是有意义的。如果没有,请不要犹豫,让我澄清。

一种方法是围绕CholmodSupernodalLLT编写一个小包装器,显示所需的预调节器API,其compute()方法将是no-op。这可以从identitypreconditioning中获得灵感,在10-15行代码中完成。唯一需要更改的是存储CholmodSupernodalLLT对象(或引用)并实现solve以返回m_llt.solve(b);