对于Eigen SparseMatrix,innerIndexPtr()和outerIndexPtr()到底代表什么?

use*_*089 4 c++ eigen eigen3

我正在使用 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)

有人可以向我解释一下innerIndexPtrouterIndexPtr到底代表什么吗?

L. *_* F. 5

你的矩阵看起来像这样:

    (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

sm1.valuePtr();      // Pointer to the values
sm1.innerIndexPtr(); // Pointer to the indices.
sm1.outerIndexPtr(); // Pointer to the beginning of each inner vector
Run Code Online (Sandbox Code Playgroud)

因此,valuePtr()返回[10, 11]innerIndexPtr()返回[0, 2]outerIndexPtr()返回[0, 2, 2]。这应该可以解释您观察到的结果。


关于数组的一些解释OuterStarts:编号为 1 和 2 的列由零组成。这不会影响外部索引。编号为 1 的列从位置 2 开始,到位置 2 结束。编号为 2 的列也从位置 2 开始,到位置 2 结束。它们完全由零组成的事实意味着它们的大小为零。我同意手册中的解释OuterStarts有点误导。将“第一个非零”视为超越终点的元素。


Ily*_*pov 5

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 中默认的。对于行优先,交换上面描述中的行 <-> 列。