【问题标题】:For Eigen SparseMatrix, what does innerIndexPtr() and outerIndexPtr() exactly represent?对于 Eigen SparseMatrix,innerIndexPtr() 和 outerIndexPtr() 究竟代表什么?
【发布时间】:2019-08-06 08:38:51
【问题描述】:

我正在使用 Eigen::SparseMatrix,但我无法理解 innerIndexPtrouterIndexPtr 的含义。 the official page 的解释对我来说非常模糊。直观地说,我认为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

谁能给我解释一下innerIndexPtrouterIndexPtr 究竟代表什么?

【问题讨论】:

    标签: c++ eigen eigen3


    【解决方案1】:

    你的矩阵看起来像这样:

        (0) (1) (2)
    (0)  10   0   0
    (1)   0   0   0
    (2)  11   0   0
    

    在内部,一个稀疏数组由四个紧凑数组组成:

    • Values:存储非零的系数值。
    • InnerIndices:存储非零的行(列)索引。
    • OuterStarts:为每一列(相应的行)存储前两个数组中第一个非零的索引。
    • InnerNNZs:存储每列(相应行)的非零数。单词 inner 指的是一个内部向量,它是一个列 列主矩阵,或行主矩阵的行。外字 指另一个方向。

    (见Sparse matrix manipulations

    您的矩阵存储为:

          Values: 10 11
    InnerIndices:  0  2
    
     OuterStarts:  0  2  2
       InnerNNZs:  2  0  0
    

    引用手册:

    低级 API

    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 的解释有点误导。将“非零的拳头”视为过去的元素。

    【讨论】:

    • 根据您对OuterStarts 的解释,不应该是0 null null 吗?第 1 列和第 2 列中没有非零。或者我还没有完全理解它......
    • 抱歉,我不明白3 与解释为什么outerIndexPtr 不是0 null null 有什么关系。
    • @user3667089 抱歉,我之前的评论搞砸了。查看更新的答案。
    【解决方案2】:

    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)
    }
    

    以上所有内容都是针对列主要存储的,这是 Eigen 中的默认设置。对于row-major,交换上面描述中的row column。

    【讨论】:

      猜你喜欢
      • 2021-07-19
      • 1970-01-01
      • 2017-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多