现实中的大矩阵往往大部分元素是 0比如社交网络、物理仿真。存一堆 0 太浪费稀疏矩阵只存非零元素省内存、算得快。本章讲怎么构建和使用稀疏矩阵。33.1 为什么需要稀疏矩阵一个 1000×1000 的稠密矩阵要存 100 万个元素约 8 MB。但如果它只有 1000 个非零元素其余都是 0稠密存储就浪费了 99.9% 的空间。稀疏矩阵只存非零元素能把内存和计算量降几个数量级。稠密MatrixXd稀疏SparseMatrix存储所有元素只存非零元素适用大部分非零大部分是 0非零 ~10%大小适合小矩阵适合超大稀疏矩阵33.2 用 Triplet 构建稀疏矩阵稀疏矩阵不能像稠密那样填值要用三元组Triplet(行, 列, 值)的列表。#includeEigen/Sparse#includeiostream#includevectorintmain(){// 1. 收集三元组 (行, 列, 值)std::vectorEigen::Tripletdoubletriplets;triplets.push_back({0,0,1.0});triplets.push_back({0,1,0.5});triplets.push_back({1,1,2.0});triplets.push_back({2,2,3.0});triplets.push_back({2,4,0.3});triplets.push_back({3,3,4.0});triplets.push_back({4,4,5.0});// 2. 创建 5x5 稀疏矩阵填入三元组Eigen::SparseMatrixdoubleS(5,5);S.setFromTriplets(triplets.begin(),triplets.end());// 3. 转成稠密矩阵打印std::coutEigen::MatrixXd(S)std::endl;std::cout非零元素个数 S.nonZeros()std::endl;// 7return0;}运行结果1 0.5 0 0 0 0 2 0 0 0 0 0 3 0 0.3 0 0 0 4 0 0 0 0 0 5 非零元素个数 7要点Eigen::Tripletdouble(行, 列, 值)描述一个非零元素S.setFromTriplets(begin, end)批量填入用Eigen::MatrixXd(S)转成稠密矩阵查看33.3 稀疏矩阵的基本操作S.rows();S.cols();// 尺寸S.nonZeros();// 非零元素个数S.coeff(i,j);// 读元素慢别在循环里频繁用S.insert(i,j)value;// 插入单个元素稀疏矩阵读单个元素用coeff()不是()且遍历效率低尽量用三元组批量构建。33.4 用稀疏求解器解方程稀疏矩阵配合稀疏求解器能高效解大规模方程组#includeEigen/Sparse#includeiostream#includevectorintmain(){constintn5;// 构建稀疏矩阵主对角线 2上下对角线 -1对称正定std::vectorEigen::Tripletdoubletriplets;for(inti0;in;i){triplets.push_back({i,i,2.0});// 主对角线if(i1n){triplets.push_back({i1,i,-1.0});// 下对角线triplets.push_back({i,i1,-1.0});// 上对角线保持对称}}Eigen::SparseMatrixdoubleS(n,n);S.setFromTriplets(triplets.begin(),triplets.end());Eigen::VectorXdb(n);b1.5,2,3.3,4,5;// 稀疏求解器SimplicialLDLT 适合对称正定Eigen::SimplicialLDLTEigen::SparseMatrixdoublesolver;solver.compute(S);if(solver.info()Eigen::Success){Eigen::VectorXd xsolver.solve(b);std::cout解 x.transpose()std::endl;std::cout残差 (S*x-b).norm()std::endl;}else{std::cout分解失败std::endl;}return0;}运行结果数值请以上面程序在你机器上的输出为准浮点末位可能有微小差异解 6.4 11.3 14.2 13.8 9.4 残差 2.66454e-15残差是 1e-15 量级也就是实际上等于 0——不要指望它打印成0浮点运算总会留下这种极小的尾巴第 29 章的残差同理。稀疏求解器有SimplicialLDLT/SimplicialLLT对称正定SparseLU一般方阵ConjugateGradient/BiCGSTAB迭代法超大矩阵33.5 稀疏 vs 稠密怎么选矩阵大部分是 0非零 ~10%且很大 → 稀疏 SparseMatrix 矩阵比较稠密或尺寸小 → 稠密 MatrixXd经验小矩阵几百以内用稠密就行几万×几万的稀疏矩阵才需要 SparseMatrix。稀疏矩阵有额外开销小矩阵用它反而慢。33.6 小结稀疏矩阵只存非零元素省内存、算得快。用Triplet行、列、值批量构建setFromTriplets填入。稀疏求解器SimplicialLDLT对称正定、SparseLU一般、迭代法超大。非零占比低 矩阵大才用稀疏。下一章学习性能优化与别名陷阱——避开 Eigen 最经典的坑。练习题用 Triplet 构建一个 3×3 的稀疏单位矩阵转成稠密打印。构建一个对角稀疏矩阵统计它的 nonZeros。用稀疏求解器解一个稀疏方程组。说说什么时候该用稀疏矩阵、什么时候用稠密矩阵。稀疏矩阵读单个元素用什么方法