Eigen稀疏矩阵类 (SparseMatrix)
1. SparseMatrix
核心属性与初始化
模板参数
cpp
SparseMatrix<Scalar, Options, StorageIndex>
-
Scalar
:数据类型(如double
,float
)。 -
Options
:存储格式(默认ColMajor
,可选RowMajor
)。 -
StorageIndex
:索引类型(通常为int
)。
关键属性
属性 | 说明 | 示例 |
---|---|---|
rows() | 矩阵行数 | int rows = mat.rows(); |
cols() | 矩阵列数 | int cols = mat.cols(); |
nonZeros() | 非零元素数量 | int nnz = mat.nonZeros(); |
isCompressed() | 是否为压缩格式(CRS/CCS) | bool compressed = mat.isCompressed(); |
初始化方式
方法 | 示例 | 说明 |
---|---|---|
直接构造 | SparseMatrix<double> mat(100, 100); | 空矩阵(100x100) |
三重态列表(Triplet) | 见下文 | 逐元素填充 |
从稠密矩阵转换 | SparseMatrix<double> sp = dense.sparseView(); | 自动过滤零值 |
2. 核心方法
(1) 元素插入与访问
方法 | 参数说明 | 功能 | 示例 |
---|---|---|---|
insert(i, j, value) | i : 行索引,j : 列索引,value : 值 | 插入非零元素(若存在则覆盖) | mat.insert(0, 1) = 3.14; |
coeffRef(i, j) | 同上 | 访问/修改元素(若不存在则插入) | mat.coeffRef(1, 2) += 1.0; |
makeCompressed() | 无 | 压缩存储(CRS/CCS格式) | mat.makeCompressed(); (此后无法插入新元素) |
valuePtr() , innerIndexPtr() , outerIndexPtr() | 无 | 获取压缩格式的底层数组指针 | 用于直接操作底层数据(高级用法) |
(2) 矩阵操作
方法 | 参数说明 | 功能 | 示例 |
---|---|---|---|
reserve(Size) | Size : 预估非零元素数 | 预分配内存 | mat.reserve(1000); |
prune(Scalar, RealScalar) | 阈值和参考值 | 删除绝对值小于阈值的元素 | mat.prune(1e-5, 0.0); |
transpose() | 无 | 返回转置矩阵(视图) | SparseMatrix<double> matT = mat.transpose(); |
sum() | 无 | 所有元素求和 | double total = mat.sum(); |
(3) 块操作与迭代
方法 | 参数说明 | 功能 | 示例 |
---|---|---|---|
block(startRow, startCol, rows, cols) | 起始位置和块大小 | 返回子矩阵(视图) | auto submat = mat.block(10, 10, 5, 5); |
innerVector(outer) | outer : 列号(ColMajor) | 返回列/行向量(视图) | SparseVector<double> col = mat.innerVector(0); |
迭代器(InnerIterator ) | 无 | 遍历非零元素 | 见下方代码示例 |
3. 辅助类:Triplet
用于高效构建稀疏矩阵(先收集非零元素,再一次性填充):
cpp
#include <Eigen/SparseCore>
using namespace Eigen;std::vector<Triplet<double>> triplets;
triplets.push_back(Triplet<double>(0, 1, 3.0)); // (i, j, value)
triplets.push_back(Triplet<double>(1, 2, 4.0));SparseMatrix<double> mat(3, 3);
mat.setFromTriplets(triplets.begin(), triplets.end());
4. 稀疏矩阵分解与求解
求解器类
类名 | 适用场景 | 关键方法 |
---|---|---|
SimplicialLLT | 对称正定矩阵 | compute(mat) + solve(b) |
SparseLU | 通用方阵 | analyzePattern() + factorize() |
ConjugateGradient | 对称正定矩阵(迭代法) | setTolerance() + compute() |
求解示例
cpp
SparseMatrix<double> A;
VectorXd b, x;// 使用 SimplicialLLT 分解
SimplicialLLT<SparseMatrix<double>> solver;
solver.compute(A);
if (solver.info() == Success) {x = solver.solve(b);
}// 使用迭代法(如共轭梯度)
ConjugateGradient<SparseMatrix<double>> cg;
cg.setTolerance(1e-6);
cg.compute(A);
x = cg.solve(b);
5. 代码示例
遍历非零元素
cpp
for (int k = 0; k < mat.outerSize(); ++k) {for (SparseMatrix<double>::InnerIterator it(mat, k); it; ++it) {std::cout << "(" << it.row() << "," << it.col() << ") = " << it.value() << std::endl;}
}
矩阵运算
cpp
SparseMatrix<double> A, B;
A.resize(100, 100);
B.resize(100, 100);
// ... 填充 A 和 B ...// 稀疏矩阵加法
SparseMatrix<double> C = A + B;// 稀疏矩阵乘法
SparseMatrix<double> D = A * B;// 标量乘法
SparseMatrix<double> E = 2.5 * A;
6. 性能优化技巧
-
预分配内存:通过
reserve()
或Triplet
避免多次扩容。 -
压缩存储:操作完成后调用
makeCompressed()
提升计算效率。 -
选择合适的求解器:
-
对称正定矩阵:优先用
SimplicialLLT
或ConjugateGradient
。 -
非对称矩阵:使用
SparseLU
或BiCGSTAB
。
-
7. 常见问题
-
插入效率:未压缩模式下插入更快,但计算前需压缩。
-
内存占用:稀疏矩阵内存 ≈
(2 * nnz + cols + 1) * sizeof(Index) + nnz * sizeof(Scalar)
。
掌握这些方法后,可高效处理大规模稀疏线性代数问题!更多细节见 Eigen SparseMatrix 文档。