【问题标题】:Serializing Decomposed Matrix from eigen (SparseLU object)从特征序列化分解矩阵(SparseLU 对象)
【发布时间】:2014-07-06 05:48:44
【问题描述】:

我正在尝试解决 Ax=b,其中矩阵 A 的大小可能接近 1M x 1M,是稀疏且对称的,但可能未明确定义.

问题是使用 eigen 中的sparseLU object 计算分解可能需要很长时间,并且最好存储 sparseLU 矩阵而不是原始矩阵,这样每当我们执行类似的操作时使用相同的矩阵A,我们可以通过不需要重新计算来加快速度

在stackoverflow上快速搜索,google返回thisthisthis用于特征矩阵序列化的稀疏矩阵。但是,我不确定是否可以将相同的代码应用于 sparseLU 对象。

也许我应该改写我的问题:

如何将分解后的矩阵存储到文件中?

目前的方法都专注于存储原始矩阵,但我想存储分解后的矩阵。有没有办法做到这一点?谢谢。

【问题讨论】:

  • 矩阵有多稀疏?有提到here的选项。
  • 我不确定矩阵的稀疏程度,因为它可能会随着输入的变化而变化。然而,这里的主要问题是是否可以序列化分解后的 sparseLU 对象。当尝试使用我在 sparseLU 对象上提供的链接中给出的方法时,它们都不起作用。
  • 在我提供的链接中,ggael 展示了如果您想滚动自己的序列化,如何访问矩阵的索引和值。
  • 谢谢Avi,我想我现在明白你的意思了。与thisthis 一起,我认为可以序列化sparseLU 然后
  • 现在的问题是以下错误:'class Eigen::SparseLU<:sparsematrix int>, Eigen::COLAMDOrdering>' has no member named 'nonZeros ' 这很奇怪,因为我已经检查过 nonZeros() 绝对是一个成员函数,我不确定这出了什么问题。

标签: c++ sparse-matrix eigen


【解决方案1】:

以下示例应该可以帮助您实现自己的序列化。

编辑更改示例以回答改写后的问题。

#include <Eigen/Dense>
#include <Eigen/Core>
#include <Eigen/Sparse>
#include <Eigen/SparseLU>
#include <iostream>
#include <fstream>

using namespace Eigen;
using namespace std;

typedef Triplet<int> Trip;

template <typename T, int whatever, typename IND>
void Serialize(SparseMatrix<T, whatever, IND>& m) {
    std::vector<Trip> res;
    int sz = m.nonZeros();
    m.makeCompressed();

    fstream writeFile;
    writeFile.open("matrix", ios::binary | ios::out);

    if(writeFile.is_open())
    {
        IND rows, cols, nnzs, outS, innS;
        rows = m.rows()     ;
        cols = m.cols()     ;
        nnzs = m.nonZeros() ;
        outS = m.outerSize();
        innS = m.innerSize();

        writeFile.write((const char *)&(rows), sizeof(IND));
        writeFile.write((const char *)&(cols), sizeof(IND));
        writeFile.write((const char *)&(nnzs), sizeof(IND));
        writeFile.write((const char *)&(outS), sizeof(IND));
        writeFile.write((const char *)&(innS), sizeof(IND));

        writeFile.write((const char *)(m.valuePtr()),       sizeof(T  ) * m.nonZeros());
        writeFile.write((const char *)(m.outerIndexPtr()),  sizeof(IND) * m.outerSize());
        writeFile.write((const char *)(m.innerIndexPtr()),  sizeof(IND) * m.nonZeros());

        writeFile.close();
    }
}

template <typename T, int whatever, typename IND>
void Deserialize(SparseMatrix<T, whatever, IND>& m) {
    fstream readFile;
    readFile.open("matrix", ios::binary | ios::in);
    if(readFile.is_open())
    {
        IND rows, cols, nnz, inSz, outSz;
        readFile.read((char*)&rows , sizeof(IND));
        readFile.read((char*)&cols , sizeof(IND));
        readFile.read((char*)&nnz  , sizeof(IND));
        readFile.read((char*)&outSz, sizeof(IND));
        readFile.read((char*)&inSz , sizeof(IND));

        m.resize(rows, cols);
        m.makeCompressed();
        m.resizeNonZeros(nnz);

        readFile.read((char*)(m.valuePtr())     , sizeof(T  ) * nnz  );
        readFile.read((char*)(m.outerIndexPtr()), sizeof(IND) * outSz);
        readFile.read((char*)(m.innerIndexPtr()), sizeof(IND) * nnz );

        m.finalize();
        readFile.close();

    } // file is open
}


int main(int argc, char *argv[]){
    int rows, cols;
    rows = cols = 6;
    SparseMatrix<double> A(rows,cols), B;

    std::vector<Trip> trp, tmp;

    trp.push_back(Trip(0, 0, rand()));
    trp.push_back(Trip(1, 1, rand()));
    trp.push_back(Trip(2, 2, rand()));
    trp.push_back(Trip(3, 3, rand()));
    trp.push_back(Trip(4, 4, rand()));
    trp.push_back(Trip(5, 5, rand()));
    trp.push_back(Trip(2, 4, rand()));
    trp.push_back(Trip(3, 1, rand()));

    A.setFromTriplets(trp.begin(), trp.end());
    cout << A.nonZeros() << endl;   // Prints 8
    cout << A.size() << endl;       // Prints 36
    cout << A << endl;              // Prints the matrix along with the sparse matrix stuff

    Serialize(A);

    Deserialize(B);

    cout << B.nonZeros() << endl;   // Prints 8
    cout << B.size() << endl;       // Prints 36
    cout << B << endl;              // Prints the reconstructed matrix along with the sparse matrix stuff


    SparseLU<SparseMatrix<double>, COLAMDOrdering<int> > solver;
    solver.isSymmetric(true);
    solver.compute(A);  // Works...
    /*
    ...
    */

    return 0;
}

另外,nonZerosMatrix 的成员,而不是 SparseLU

【讨论】:

  • 嗨,Avi,非常感谢您的帮助。我最近收到了来自 ggael 的reply,说我无法保存 SparseLU 对象,我必须“破解”sparseLU 对象类才能执行序列化。非常感谢您的帮助!!
  • @Sam 我现在才意识到您想要保存SparseLU 对象而不是SparseMatrix。如果 ggael 说你必须自己保存/加载方法,那就去吧。
  • 谢谢,删除评论!
猜你喜欢
  • 2019-06-29
  • 1970-01-01
  • 1970-01-01
  • 2011-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-04
  • 1970-01-01
相关资源
最近更新 更多