Eigen线性代数求解器(分解类)
1. 核心分解类概览
Eigen 提供多种矩阵分解方法,适用于不同矩阵类型(稠密/稀疏、正定/非正定等):
分解类 | 适用矩阵类型 | 分解形式 | 典型应用场景 |
---|---|---|---|
PartialPivLU | 方阵(可逆) | A=PLUA=PLU | 通用线性方程组求解 |
FullPivLU | 任意矩阵 | A=P−1LUQ−1A=P−1LUQ−1 | 高稳定性求解(计算成本高) |
HouseholderQR | 任意矩阵(列满秩) | A=QRA=QR | 最小二乘问题(快速但不稳定) |
ColPivHouseholderQR | 任意矩阵 | A=QRA=QR(列主元) | 稳定的最小二乘解 |
FullPivHouseholderQR | 任意矩阵 | A=QRA=QR(完全主元) | 高稳定性(计算成本最高) |
LLT | 正定矩阵 | A=LLTA=LLT | Cholesky 分解(快速) |
LDLT | 半正定/正定矩阵 | A=LDLTA=LDLT | 带对角调整的 Cholesky |
2. 通用方法与属性
所有分解类均继承自 Eigen::SolverBase
,提供以下统一接口:
核心方法
方法 | 参数说明 | 返回值/功能 | 示例 |
---|---|---|---|
compute(const MatrixType& A) | A : 待分解矩阵 | 无(更新分解状态) | lu.compute(A); |
solve(const MatrixType& b) | b : 右侧矩阵/向量 | 解 Ax=bAx=b | VectorXf x = lu.solve(b); |
matrixLU() | 无 | 返回 LU 分解后的矩阵 | MatrixXd LU = lu.matrixLU(); |
info() | 无 | 返回计算状态(Success /NumericalIssue ) | if (lu.info() != Success) { /* error */ } |
属性
属性 | 说明 |
---|---|
rows() , cols() | 返回分解矩阵的行数/列数 |
rank() | 返回矩阵的秩(仅 FullPiv* 类支持) |
3. 各分解类详解
(1) PartialPivLU
(部分主元 LU 分解)
-
适用场景:通用方阵求解(推荐默认使用)。
-
特有方法:
cpp
PermutationMatrix P = lu.permutationP(); // 返回排列矩阵 P MatrixXd L = lu.matrixLU().triangularView<UnitLower>(); // 提取 L MatrixXd U = lu.matrixLU().triangularView<Upper>(); // 提取 U
(2) HouseholderQR
与 ColPivHouseholderQR
-
区别:后者通过列主元提高稳定性,但稍慢。
-
特有方法:
cpp
MatrixXd Q = qr.householderQ(); // 获取 Q 矩阵(需显式计算) VectorXd hCoeffs = qr.hCoeffs(); // 返回 Householder 系数 // 仅 ColPivHouseholderQR: PermutationMatrix P = qr.colsPermutation(); // 列排列矩阵
(3) LLT
与 LDLT
(Cholesky 分解)
-
要求:矩阵必须正定(
LLT
)或半正定(LDLT
)。 -
特有方法:
cpp
MatrixXd L = llt.matrixL(); // 获取下三角矩阵 L(LLT) VectorXd D = ldlt.vectorD(); // 获取对角矩阵 D(LDLT)
4. 稀疏矩阵分解类
类名 | 适用场景 | 关键方法 |
---|---|---|
SimplicialLLT | 稀疏正定矩阵 | analyzePattern() , factorize() |
SparseLU | 通用稀疏方阵 | solve() 支持多右手边 |
ConjugateGradient | 稀疏对称正定矩阵(迭代) | setTolerance() , compute() |
5. 代码示例
稠密矩阵求解
cpp
#include <Eigen/Dense>
using namespace Eigen;Matrix3f A;
Vector3f b;
A << 1, 2, 3, 4, 5, 6, 7, 8, 10;
b << 3, 3, 4;// PartialPivLU 分解(推荐默认)
PartialPivLU<Matrix3f> lu(A);
Vector3f x = lu.solve(b); // 解 Ax = b// Cholesky 分解(正定矩阵)
LLT<Matrix3f> llt(A.transpose() * A); // A^T A 正定
Vector3f y = llt.solve(A.transpose() * b); // 解正规方程
稀疏矩阵求解
cpp
#include <Eigen/Sparse>
SparseMatrix<double> mat(100, 100);
VectorXd b = VectorXd::Random(100);// SimplicialLLT 分解
SimplicialLLT<SparseMatrix<double>> solver;
solver.compute(mat);
VectorXd x = solver.solve(b);
6. 选择分解方法的准则
矩阵类型 | 推荐分解类 | 原因 |
---|---|---|
通用稠密方阵 | PartialPivLU | 平衡速度与稳定性 |
最小二乘问题(非对称) | ColPivHouseholderQR | 稳定性优于 HouseholderQR |
正定稠密矩阵 | LLT | 最快(约 2 倍加速) |
稀疏对称正定矩阵 | SimplicialLLT | 内存高效 |
注意事项
-
分解重用:若矩阵不变,可先调用
compute(A)
再多次solve(b)
提高效率。 -
数值稳定性:对于病态矩阵,优先选择
FullPivLU
或ColPivHouseholderQR
。 -
稀疏矩阵:分解前需调用
analyzePattern()
优化内存分配。
通过合理选择分解类,可以显著提升计算性能!更多细节见 Eigen 文档。