我正在使用 Eigen::SparseMatrix,但我无法理解innerIndexPtr和 的含义outerIndexPtr。官方页面的解释对我来说非常模糊。直观上,我认为innerIndexPtr是非零元素的行索引,outerIndexPtr是非零元素的列索引,但显然情况并非如此。请看下面的例子,
std::vector<Eigen::Triplet<double>> triplet;
triplet.emplace_back(0, 0, 10);
triplet.emplace_back(2, 0, 11);
Eigen::SparseMatrix<double> A(3, 3);
A.setFromTriplets(triplet.begin(), triplet.end());
std::cout << A.innerIndexPtr()[0] << std::endl; // prints 0
std::cout << A.innerIndexPtr()[1] << std::endl; // prints 2
std::cout << std::endl;
std::cout << A.outerIndexPtr()[0] << std::endl; // prints 0
std::cout << A.outerIndexPtr()[1] << std::endl; // prints 2, but I thought it should print 0
std::cout << std::endl;
std::cout << A.valuePtr()[0] << std::endl; // prints 10
std::cout << A.valuePtr()[1] << std::endl; // prints 11
Run Code Online (Sandbox Code Playgroud)
有人可以向我解释一下innerIndexPtr和outerIndexPtr到底代表什么吗?
你的矩阵看起来像这样:
(0) (1) (2)
(0) 10 0 0
(1) 0 0 0
(2) 11 0 0
Run Code Online (Sandbox Code Playgroud)
在内部,稀疏数组由四个紧凑数组组成:
Values:存储非零的系数值。InnerIndices:存储非零的行(或列)索引。OuterStarts:为每列(或行)存储前两个数组中第一个非零的索引。InnerNNZs:存储每列(或行)的非零数。单词“内部”指的是内部向量,对于列主矩阵来说它是列,对于行主矩阵来说它是行。“外”这个词指的是另一个方向。
(参见稀疏矩阵操作)
您的矩阵存储为:
Values: 10 11
InnerIndices: 0 2
OuterStarts: 0 2 2
InnerNNZs: 2 0 0
Run Code Online (Sandbox Code Playgroud)
引用手册:
低级API
Run Code Online (Sandbox Code Playgroud)sm1.valuePtr(); // Pointer to the values sm1.innerIndexPtr(); // Pointer to the indices. sm1.outerIndexPtr(); // Pointer to the beginning of each inner vector
因此,valuePtr()返回[10, 11]、innerIndexPtr()返回[0, 2]和outerIndexPtr()返回[0, 2, 2]。这应该可以解释您观察到的结果。
关于数组的一些解释OuterStarts:编号为 1 和 2 的列由零组成。这不会影响外部索引。编号为 1 的列从位置 2 开始,到位置 2 结束。编号为 2 的列也从位置 2 开始,到位置 2 结束。它们完全由零组成的事实意味着它们的大小为零。我同意手册中的解释OuterStarts有点误导。将“第一个非零”视为超越终点的元素。
Eigen 使用 CSC(压缩稀疏列)格式(另请参阅https://en.wikipedia.org/wiki/Sparse_matrix#Compressed_sparse_row_(CSR,_CRS_or_Yale_format))。
outerIndexPtr()[i]指示第 i 列开始的其他数组的索引。它结束于outerIndexPtr()[i+1],即下一列的开始处。如果这两个索引彼此相等,则该列为空。
innerIndexPtr()是元素行索引的数组,valuePtr()是对应值的数组。
因此,为了说明这一点,此代码迭代第 i 列
int k_start = A.outerIndexPtr()[i];
int k_end = A.outerIndexPtr()[i+1];
for (k = k_start; k < k_end; k++) {
int j = A.innerIndexPtr()[k];
double v = A.valuePtr()[k];
// v is value of the element at position (j,i)
}
Run Code Online (Sandbox Code Playgroud)
以上都是针对列主存储,这是 Eigen 中默认的。对于行优先,交换上面描述中的行 <-> 列。
| 归档时间: |
|
| 查看次数: |
1792 次 |
| 最近记录: |