0

I am trying to solve Ax=b where the matrix A can be big close to 1M x 1M in size, is sparse and symmetric but might not be positively defined.

Problem is that it might take a long time to compute the decomposition using the sparseLU object in eigen and it will be idea for one to store the sparseLU matrix instead of the original matrix such that whenever we perform similar operation using the same matrix A, we can speed things up by not needing to re-compute the

A quick search on stackoverflow and google returned this, this and this for sparse matrix for the serialization of eigen matrix. However, I am not sure if the same code can be apply for the sparseLU object.

Maybe I should rephrase my question:

How can I store the decomposed matrix into a file?

The current methods all focus on storing the original matrix but I want to store the decomposed matrix. Is there any way to do that? Thank you.

Community
  • 1
  • 1
Sam
  • 16
  • 2
  • How sparse is the matrix? There is the option mentioned [here](https://forum.kde.org/viewtopic.php?f=74&t=94420). – Avi Ginsburg Jul 06 '14 at 06:35
  • I am not sure how sparse the matrix are as that might change from input to input. However, the main problem here is whether if one can serialize the decomposed sparseLU object. When trying to use the method given from links I provided on the sparseLU object, none of them works. – Sam Jul 06 '14 at 06:49
  • In the link I provided, ggael shows how to access the indices and the values of the matrix if you would like to roll your own serialization. – Avi Ginsburg Jul 06 '14 at 07:07
  • Thanks Avi, I think I understand what you mean now. Together with [this](http://stackoverflow.com/questions/13094372/extract-a-block-from-a-sparse-matrix-as-another-sparse-matric) and then [this](http://josiahmanson.com/prose/eigen_linear_solver/), I think it is possible for one to serialize the sparseLU then – Sam Jul 06 '14 at 08:47
  • The problem now is the following error: ‘class Eigen::SparseLU, Eigen::COLAMDOrdering >’ has no member named ‘nonZeros’ which is strange as I have checked that nonZeros() is definitely a member function, I am not sure what went wrong with that. – Sam Jul 06 '14 at 08:57
  • I've changed my example to write/read to/from a file. – Avi Ginsburg Jul 06 '14 at 19:04

1 Answers1

2

The following example should help you implement your own serialization.

EDIT Changed the example to answer the reworded question.

#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;
}

Also, nonZeros is a member of Matrix, not SparseLU.

Bar
  • 2,736
  • 3
  • 33
  • 41
Avi Ginsburg
  • 10,323
  • 3
  • 29
  • 56
  • Hi Avi, thank you very much for your help. I have recently received the [reply](https://forum.kde.org/viewtopic.php?f=74&t=121894&sid=ddab9a774830dbce0ca85b5c6f1de547) from ggael that it is not possible for me to save the SparseLU object and I will have to "hack" the sparseLU object class in order for me to perform the serialization. Thank you very much for your help!! – Sam Jul 08 '14 at 08:38
  • @Sam I only just now realized that you wanted to save the `SparseLU` object and not the `SparseMatrix`. If ggael says you'd have to the save/load methods yourself, then go for it. – Avi Ginsburg Jul 08 '14 at 11:32
  • Thanks, removed the comment! – Bar Sep 04 '18 at 18:48