[Eigen中文文档] 稀疏矩阵快速参考指南

简介: 本页面简要介绍了类SparseMatrix中可用的主要操作。在处理稀疏矩阵时,重要的一点是要了解它们的存储方式:即行优先或列优先,Eigen默认为列优先。对稀疏矩阵进行的大多数算术操作都会默认它们具有相同的存储顺序。

文档总目录

英文原文(Quick reference guide for sparse matrices)

本页面简要介绍了类SparseMatrix中可用的主要操作。首先,建议先阅读介绍性教程《稀疏矩阵操作》。在处理稀疏矩阵时,重要的一点是要了解它们的存储方式:即行优先或列优先,Eigen默认为列优先。对稀疏矩阵进行的大多数算术操作都会默认它们具有相同的存储顺序。

稀疏矩阵初始化

构造

SparseMatrix<double> sm1(1000,1000); 
SparseMatrix<std::complex<double>, RowMajor> sm2;

默认为列优先。

重置大小/预分配内存空间

sm1.resize(m,n);      // Change sm1 to a m x n matrix. 
sm1.reserve(nnz);     // Allocate room for nnz nonzeros elements.

请注意,调用 Reserve() 时,不需要 nnz 是最终矩阵中非零元素的确切数量。通过给出一个精确的估计值可以避免在插入阶段进行多次重新分配内存。

赋值

SparseMatrix<double,Colmajor> sm1;
// Initialize sm2 with sm1.
SparseMatrix<double,Rowmajor> sm2(sm1), sm3;        
// Assignment and evaluations modify the storage order.
sm3 = sm1;

拷贝构造函数可用于从一种存储顺序转换为另一种存储顺序。

逐元素插入

// Insert a new element; 
sm1.insert(i, j) = v_ij;  

// Update the value v_ij
sm1.coeffRef(i,j) = v_ij;
sm1.coeffRef(i,j) += v_ij;
sm1.coeffRef(i,j) -= v_ij;

insert() 函数假设该元素在矩阵中不存在;如果该元素已经存在,请使用 coeffRef() 函数。

批量插入

std::vector< Eigen::Triplet<double> > tripletList;
tripletList.reserve(estimation_of_entries);
// -- Fill tripletList with nonzero elements...
sm1.setFromTriplets(TripletList.begin(), TripletList.end());

Triplet Insertion 提供了完整的示例。

指定位置或随机插入

sm1.setZero();

删除所有非零系数。

矩阵属性

除了基本函数 rows()cols() 之外,还有一些有用的函数可用于从矩阵中获取一些信息。

sm1.rows();         // Number of rows
sm1.cols();         // Number of columns 
sm1.nonZeros();     // Number of non zero values   
sm1.outerSize();    // Number of columns (resp. rows) for a column major (resp. row major )
sm1.innerSize();    // Number of rows (resp. columns) for a row major (resp. column major)
sm1.norm();         // Euclidian norm of the matrix
sm1.squaredNorm();  // Squared norm of the matrix
sm1.blueNorm();
sm1.isVector();     // Check if sm1 is a sparse vector or a sparse matrix
sm1.isCompressed(); // Check if sm1 is in compressed form
...

算术运算

只要矩阵的维度合适并且矩阵具有相同的存储顺序,就可以轻松地在稀疏矩阵上执行算术运算。请注意,始终可以在具有不同存储顺序的矩阵中进行计算或处理数学表达式或函数。在下面的文本中,sm 表示稀疏矩阵,dm 表示密集矩阵,dv 表示密集向量。

加减

sm3 = sm1 + sm2; 
sm3 = sm1 - sm2;
sm2 += sm1; 
sm2 -= sm1;

sm1sm2应该有相同的存储顺序。

标量积

sm3 = sm1 * s1;   sm3 *= s1; 
sm3 = s1 * sm1 + s2 * sm2; sm3 /= s1;

如果尺寸和存储顺序一致,则可以进行多种计算组合。

稀疏矩阵乘积

sm3 = sm1 * sm2;
dm2 = sm1 * dm1;
dv2 = sm1 * dv1;

转置/伴随

sm2 = sm1.transpose();
sm2 = sm1.adjoint();

请注意,转置会更改存储顺序。不支持 transposeInPlace()

排列

perm.indices();      // Reference to the vector of indices
sm1.twistedBy(perm); // Permute rows and columns
sm2 = sm1 * perm;    // Permute the columns
sm2 = perm * sm1;    // Permute the columns

组件级操作

sm1.cwiseProduct(sm2);
sm1.cwiseQuotient(sm2);
sm1.cwiseMin(sm2);
sm1.cwiseMax(sm2);
sm1.cwiseAbs();
sm1.cwiseSqrt();

sm1sm2 应该有相同的存储顺序。

其他支持的操作

子矩阵

sm1.block(startRow, startCol, rows, cols); 
sm1.block(startRow, startCol); 
sm1.topLeftCorner(rows, cols); 
sm1.topRightCorner(rows, cols);
sm1.bottomLeftCorner( rows, cols);
sm1.bottomRightCorner( rows, cols);

与稠密矩阵相反,这里所有方法都是只读的。 有关读写子矩阵,请参阅块操作及下文。

范围操作

sm1.innerVector(outer);           // RW
sm1.innerVectors(start, size);    // RW
sm1.leftCols(size);               // RW
sm2.rightCols(size);              // RO because sm2 is row-major
sm1.middleRows(start, numRows);   // RO because sm1 is column-major
sm1.middleCols(start, numCols);   // RW
sm1.col(j);                       // RW

内部向量可以是行(对于行优先)或列(对于列优先)。 如前所述,对于读写子矩阵(RW),可以在具有不同存储顺序的矩阵中进行。

三角形和自伴随视图

sm2 = sm1.triangularview<Lower>();
sm2 = sm1.selfadjointview<Lower>();

三角形视图和块视图之间的多种组合是可能的。

三角形求解

dv2 = sm1.triangularView<Upper>().solve(dv1);
dv2 = sm1.topLeftCorner(size, size).triangularView<Lower>().solve(dv1);

对于一般稀疏矩阵求解,请使用 求解稀疏线性系统 中描述的合适的模块。

低级API

sm1.valuePtr();      // Pointer to the values
sm1.innerIndexPtr();  // Pointer to the indices.
sm1.outerIndexPtr(); // Pointer to the beginning of each inner vector

如果矩阵不是压缩形式,应在调用这些函数之前使用 makeCompressed() 函数进行压缩。 请注意,这些函数主要提供与外部库的互操作性。更好地访问矩阵的值是通过使用InnerIterator类来完成的,如 Tutorial Sparse 部分所述。

映射外部缓冲区

innerIndices[nnz];
double values[nnz];
Map<SparseMatrix<double> > sm1(rows,cols,nnz,outerIndexPtr, // read-write
                               innerIndices,values);
Map<const SparseMatrix<double> > sm2(...);                  // read-only

对于稠密矩阵,类 Map<SparseMatrixType> 可用于将外部缓冲区视为 Eigen 的 SparseMatrix 对象。

相关文章
|
并行计算 算法 测试技术
[Eigen中文文档] 稠密分解方法目录
本文介绍了 Eigen 提供的处理稠密矩阵分解方法的目录。
137 0
|
缓存 测试技术 编译器
[Eigen中文文档] 稠密矩阵分解函数对比
本文介绍了 Eigen 为各种方阵和过约束问题提供的稠密矩阵分解的速度比较。
133 0
|
存储 算法 NoSQL
[Eigen中文文档] 存储顺序
矩阵和二维数组有两种不同的存储顺序:列优先和行优先。本节解释了这些存储顺序以及如何指定应该使用哪一种。
175 0
|
存储 算法 NoSQL
[Eigen中文文档] 稀疏矩阵操作
在许多应用中(例如,有限元方法),通常要处理非常大的矩阵,其中只有少数系数不为零。在这种情况下,可以通过使用仅存储非零系数的特殊表示来减少内存消耗并提高性能。这样的矩阵称为稀疏矩阵。
468 0
|
存储
[Eigen中文文档] 就地矩阵分解
从 Eigen 3.3 开始,LU、Cholesky 和 QR 分解可以就地操作,即直接在给定的输入矩阵内操作。当处理大矩阵时,或者当可用内存非常有限(嵌入式系统)时,此功能特别有用。
111 0
|
存储 C语言 C++
|
存储 索引
[Eigen中文文档] 扩展/自定义Eigen(三)
本页面针对非常高级的用户,他们不害怕处理一些Eigen的内部细节。在大多数情况下,可以通过使用自定义一元或二元函数避免使用自定义表达式,而极其复杂的矩阵操作可以通过零元函数(nullary-expressions)来实现,如前一页所述。 本页面通过示例介绍了如何在Eigen中实现新的轻量级表达式类型。它由三个部分组成:表达式类型本身、包含有关表达式编译时信息的特性类和评估器类,用于将表达式评估为矩阵。
141 1
|
安全 编译器 C++
[Eigen中文文档] 矩阵与向量运算
本文章旨在提供有关如何使用 Eigen 在矩阵、向量和标量之间执行算术操作的概述和一些详细信息。
400 0
|
存储 NoSQL API
[Eigen中文文档] Matrix类
在Eigen中,所有矩阵和向量都是Matrix模板类的对象。向量只是行数或者列数为1的特殊矩阵。
408 1
[Eigen中文文档] 固定大小的可向量化Eigen对象
本文主要解释 固定大小可向量化 的含义。
115 0