[Eigen中文文档] 求解稀疏线性系统

文档总目录

英文原文(Solving Sparse Linear Systems)

在Eigen中,有多种方法可用于求解稀疏系数矩阵的线性系统。由于此类矩阵的特殊表示,必须特别小心以获得良好的性能。有关Eigen中稀疏矩阵的详细介绍,请参见“[稀疏矩阵操作](#5.1 稀疏矩阵操作)”。本页列出了Eigen中可用的稀疏求解器。还介绍了所有这些线性求解器共同的主要步骤。根据矩阵的属性、所需的准确度,最终用户可以调整这些步骤以提高其代码的性能。请注意,并不需要深入了解这些步骤背后的内容:最后一节介绍了一个基础例程,可轻松使用以获取所有可用求解器的性能洞察。

稀疏求解器列表

Eigen 目前提供了一组广泛的内置求解器,以及外部求解器库的包装器。它们总结在下表中:

内置直接求解器
类及头文件求解器种类矩阵种类与性能相关的功能备注
SimplicialLLT
#include<Eigen/SparseCholesky>
直接LLt分解对称正定(SPD)通过对矩阵的重排列、消元等操作,来减少生成的新元素,以减少计算时间和空间。(Fill-in reducing)SimplicLDLT 通常更可取
SimplicialLDLT
#include<Eigen/SparseCholesky>
直接 LDLt 分解对称正定(SPD)Fill-in reducing推荐用于非常稀疏且不太大的问题(例如,2D 泊松方程)
SparseLU
#include<Eigen/SparseLU>
LU 分解方阵快速的密集代数运算,包括基于GPU的加速、多线程优化、并行计算等。(Leverage fast dense algebra)、Fill-in reducing针对不规则模式的大小问题进行了优化
SparseQR
#include<Eigen/SparseQR>
QR 分解矩形阵Fill-in reducing推荐用于最小二乘问题,具有基本的秩显示特性。
内置迭代求解器
类及头文件求解器种类矩阵种类默认支持的预处理器备注
ConjugateGradient
#include<Eigen/IterativeLinearSolvers>
经典共轭梯度法(CG)SPD IdentityPreconditioner, [DiagonalPreconditioner], IncompleteCholesky推荐用于大型对称问题(例如 3D 泊松方程)
LeastSquaresConjugateGradient
#include<Eigen/IterativeLinearSolvers>
矩形阵最小二乘问题的 CG矩形阵 IdentityPreconditioner, [LeastSquareDiagonalPreconditioner]求解 $min
BiCGSTAB
#include<Eigen/IterativeLinearSolvers>
迭代稳定双共轭梯度方阵IdentityPreconditioner, [DiagonalPreconditioner], IncompleteLUT要加速收敛,请尝试使用 IncompleteLUT 预调节器。
  • 共轭梯度法:(Conjugate Gradient method,简称CG),它是一种迭代求解线性方程组的方法。CG方法通常用于解决大规模稀疏对称正定线性方程组,具有高效、收敛快等优点。在Classic iterative CG中,每次迭代会得到一个新的解向量,同时利用前一次的残差和搜索方向来求解下一次的迭代解。
  • 稳定双共轭梯度法:是求解非对称矩阵线性方程组(Ax = b)的迭代算法。与传统的共轭梯度法不同,稳定双共轭梯度法可以处理非对称矩阵的情况,并且在求解过程中,该方法可以保持数值稳定性,避免出现数值震荡等问题。该方法的主要思路是采用两条共轭的方向(与传统共轭梯度法相同)来求解线性方程组,但在每次迭代过程中,引入了一个稳定因子,该稳定因子的作用是保持迭代过程的数值稳定性。该稳定因子可以通过计算残差向量和搜索方向向量之间的内积来确定。
外部求解器的包装器
模块求解器类型矩阵类型与性能相关的功能依赖/证书备注
PastixLLT
PastixLDLT
PastixLU
PaStiXSupportDirect LLt, LDLt, LU factorizationsSPD
SPD
方阵
Fill-in reducing, Leverage fast dense algebra, MultithreadingRequires the PaStiX package, CeCILL-C针对棘手问题和对称模式进行了优化
CholmodSupernodalLLTCholmodSupportDirect LLt factorizationSPDFill-in reducing, Leverage fast dense algebraRequires the SuiteSparse package, GPL
UmfPackLU UmfPackSupportDirect LU factorization方阵Fill-in reducing, Leverage fast dense algebraRequires the SuiteSparse package, GPL
KLU KLUSupportDirect LU factorization方阵Fill-in reducing, suitted for circuit simulationRequires the SuiteSparse package, GPL
SuperLUSuperLUSupportDirect LU factorization方阵Fill-in reducing, Leverage fast dense algebraRequires the SuperLU library, (BSD-like)
SPQR SPQRSupportQR factorization矩形阵fill-in reducing, multithreaded, fast dense algebraRequires the SuiteSparse package, GPL推荐用于最小二乘问题,具有基本的秩显示特性。
PardisoLLT
PardisoLDLT
PardisoLU
PardisoSupportDirect LLt, LDLt, LU factorizationsSPD
SPD
方阵
Fill-in reducing, Leverage fast dense algebra, MultithreadingRequires the Intel MKL package, Proprietary针对棘手问题模式进行了优化,另请参阅将 MKL 与 Eigen 结合使用
AccelerateLLT
AccelerateLDLT
AccelerateQR
AccelerateSupportDirect LLt, LDLt, QR factorizationsSPD
SPD
方阵
Fill-in reducing, Leverage fast dense algebra, MultithreadingRequires the Apple Accelerate package, Proprietary

这里SPD的意思是对称正定。

稀疏求解器概念

所有这些求解器都遵循相同的一般概念。这是一个典型且普遍的例子:

#include <Eigen/RequiredModuleName>
// ...
SparseMatrix<double> A;
// fill A
VectorXd b, x;
// fill b
// solve Ax = b
SolverClassName<SparseMatrix<double> > solver;
solver.compute(A);
if(solver.info()!=Success) {
  // decomposition failed
  return;
}
x = solver.solve(b);
if(solver.info()!=Success) {
  // solving failed
  return;
}
// solve for another right hand side:
x1 = solver.solve(b1);

对于 SPD 求解器,第二个可选模板参数允许指定使用哪个三角形部分,例如:

#include <Eigen/IterativeLinearSolvers>
 
ConjugateGradient<SparseMatrix<double>, Eigen::Upper> solver;
x = solver.compute(A).solve(b);

在上面的例子中,仅考虑输入矩阵A的上三角部分进行求解。相反的三角形可能为空,也可能包含任意值。

如果必须解决具有相同稀疏模式的多个问题,则“计算”步骤可以分解如下:

SolverClassName<SparseMatrix<double> > solver;
solver.analyzePattern(A);  // for this step the numerical values of A are not used
solver.factorize(A);
x1 = solver.solve(b1);
x2 = solver.solve(b2);
...
// modify the values of the nonzeros of A, the nonzeros pattern must stay unchanged
A = ...; 
solver.factorize(A);
x1 = solver.solve(b1);
x2 = solver.solve(b2);
...

compute() 方法相当于同时调用 analyzePattern()factorize()

每个求解器都提供一些特定的功能,例如行列式、对因子的访问、迭代的控制等。更多详细信息可在相应类的文档中找到。

最后,大多数迭代求解器也可以在无矩阵上下文中使用,请参阅以下示例。

计算步骤

solve() 函数计算具有一个或多个右侧的线性系统的解。

X = solver.solve(B);

在这里,B可以是一个向量或一个矩阵,其中列组成不同的右侧。solve() 函数也可以被多次调用,例如当所有的右侧不是一次性提供的时候。

x1 = solver.solve(b1);
// Get the second right hand side b2
x2 = solver.solve(b2); 
//  ...

对于直接方法,解是以机器精度计算的。有时候,解不需要太精确。在这种情况下,迭代方法更加适用,并且可以在解步骤之前使用setTolerance()设置所需的精度。有关所有可用函数,请参阅迭代求解器模块的文档。

基准测试例程

大多数情况下,只需要知道求解系统需要多长时间,以及希望使用哪种最适合的求解器。在Eigen中,提供了一个可用于此目的的基准测试例程。在构建目录中,切换到 bench/spbench 并通过键入 make spbenchsolver 来编译该例程。使用 --help 选项运行它以获取所有可用选项的列表。基本上,要测试的矩阵应该遵循 MatrixMarket 坐标格式,并且该例程返回Eigen中所有可用求解器的统计信息。

要以 MatrixMarket 格式导出矩阵和右侧向量,可以使用不受支持的 SparseExtra 模块:

#include <unsupported/Eigen/SparseExtra>
...
Eigen::saveMarket(A, "filename.mtx");
Eigen::saveMarket(A, "filename_SPD.mtx", Eigen::Symmetric); // if A is symmetric-positive-definite
Eigen::saveMarketVector(B, "filename_b.mtx");

下表给出了来自几个 Eigen 内置和外部求解器的 XML 统计信息的示例:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万俟淋曦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值