压缩稀疏行转置

qwe*_*ers 4 compression transpose row matrix sparse-matrix

如您所知,我们可以在压缩行存储(CRS)(或者压缩稀疏行(CSR))中写入稀疏矩阵。设 A 为 mn 矩阵。A 的转置是一个 nxm 矩阵 A',对于所有 0 <= i < n 且 0 <= j < m,A'(i; j) = A(j; i)。

我需要编写用于转置 CRS 表示形式的矩阵的算法。我该如何解决这个问题?

Mar*_*rko 7

我正在寻找类似的东西。这是我的算法。我不知道它是否是最快的,但我认为它相当不错。

编辑:本质上在scipy的 C++ 模块中实现了相同的算法。

假设矩阵由以下结构表示:

struct CRSMatrix
{
    int n; // number of rows
    int m; // number of columns
    int nz; // number of non-zero elements
    std::vector<double> val; // non-zero elements
    std::vector<int> colIndex; // column indices
    std::vector<int> rowPtr; // row ptr
};
Run Code Online (Sandbox Code Playgroud)

这个函数的作用是:

CRSMatrix sparse_transpose(const CRSMatrix& input) {
    CRSMatrix res{
        input.m,
        input.n,
        input.nz,
        std::vector<double>(input.nz, 0.0),
        std::vector<int>(input.nz, 0),
        std::vector<int>(input.m + 2, 0) // one extra
    };

    // count per column
    for (int i = 0; i < input.nz; ++i) {
        ++res.rowPtr[input.colIndex[i] + 2];
    }

    // from count per column generate new rowPtr (but shifted)
    for (int i = 2; i < res.rowPtr.size(); ++i) {
        // create incremental sum
        res.rowPtr[i] += res.rowPtr[i - 1];
    }

    // perform the main part
    for (int i = 0; i < input.n; ++i) {
        for (int j = input.rowPtr[i]; j < input.rowPtr[i + 1]; ++j) {
            // calculate index to transposed matrix at which we should place current element, and at the same time build final rowPtr
            const int new_index = res.rowPtr[input.colIndex[j] + 1]++;
            res.val[new_index] = input.val[j];
            res.colIndex[new_index] = i;
        }
    }
    res.rowPtr.pop_back(); // pop that one extra

    return res;
}
Run Code Online (Sandbox Code Playgroud)

  • 对于试图理解 `res.rowPtr` 是什么的人:您需要一个数据结构来回答一个简单的查询“在这个元素之前放置了多少个元素?”,所以如果您仔细查看 `res.rowPtr` 您会看到对于“colIndex[i]”(转置的行索引),答案放置在“colIndex[I]+1”中。并且 `res.rowPtr.pop_back();` 可以发生在主循环之前。 (2认同)