将稀疏矩阵分解的结果存储在本征中的预定存储位置中

时间:2018-07-20 11:11:40

标签: sparse-matrix eigen

我正在尝试编写一个函数来使用Eigen库执行稀疏的Cholesky分解,在该函数中,我将指向输入矩阵数据的指针和指向要存储输出矩阵的指针都传递给了

该程序当前为

#include <iostream>
#include <Eigen/Dense>
#include <Eigen/SparseCore>
#include <Eigen/SparseCholesky>

using namespace std;
using namespace Eigen;


struct CSC {
    int *indptr;
    int *indices;
    double *data;
    int nnz;
};

int cholesky_sparse_d_c(struct CSC *A, struct CSC *L,
        int rows, int cols, int nnz) {
    // Find sparse Cholesky factorisation of matrix A and store in triangular
    // matrix L i.e A = L L.T.
    // First we must build the sparse matrix A.
    Map<SparseMatrix <double> > A_sp(rows, cols, nnz,
            A->indptr, A->indices, A->data);
    cout << "A: " << endl << A_sp << endl;

    // Now compute the sparse Cholesky decomposition.
    SimplicialLLT<SparseMatrix<double> > SLLT;
    SLLT.compute(A_sp);
    if (SLLT.info() != Success) {
      cout << "Decomposition failed";
      return -1;
    }
    cout << "Sparse lower factor of A:" << endl << SLLT.matrixL()
         << endl;

    // Put the values back into L. Note I am not sure if we need to create a
    // `temp` variable here, as the call `.matrixL()` may be free.
    SparseMatrix<double > temp(SLLT.matrixL());
    L->indptr = (int *) temp.outerIndexPtr();
    L->indices = (int *) temp.innerIndexPtr();
    L->data = (double *) temp.valuePtr();
    L->nnz = (int) temp.nonZeros();
    Map<SparseMatrix <double> > L_sp(rows, cols, L->nnz,
            L->indptr, L->indices, L->data);
    cout << "L: " << endl << L_sp << endl;

    return 0;
}

int main() {
    struct CSC A;
    int A_indptr[] = {0, 1, 2};
    int A_indices[] = {0, 1};
    double A_data[] = {1.1, 2.2};
    A.indptr = A_indptr;
    A.indices = A_indices;
    A.data = A_data;

    struct CSC L;

    cholesky_sparse_d_c(&A, &L, 2, 2, 2);

    cout << L.indptr[0] << L.indptr[1] << L.indptr[2] << endl;
    cout << L.indices[0] << L.indices[1] << L.indices[2] << endl;
    cout << L.data[0] << L.data[1] << L.data[2] << endl;
}

如代码中所述,我不确定temp变量是否是必需的

    L_indptr = SLLT.matrixL().outerIndexPtr();
    L_indices = SLLT.matrixL().innerIndexPtr();
    L_data = SLLT.matrixL().valuePtr();

可能很好(我不确定matrixL()是否是免费操作)。

无论如何,当此函数退出L指针所指向的内存时,现在将被释放。我可以复制内存,但这是不必要的且效率低下。我理想地希望做的是告诉SLLT不要为其创建新的指针

  • .outerIndexPtr()
  • .innerIndexPtr()
  • .valuePtr()

但要使用提供的L结构中的指针。

有没有办法做到这一点?

1 个答案:

答案 0 :(得分:0)

如果您坚持要保存副本(与分解相比,它应该非常便宜),那么最简单,最安全的方法就是让SLLT保持生存状态,直到您的L为止,例如创建一个存储两个对象的小型结构,并负责破坏它们。

否则,您可以想象将移动 SLLT.matrixL()L中,但是您将不得不释放分配的内存,但是由于您不知道如何操作而无法它被分配了。要为自己分配L并将其传递给SLLT,您需要一种方法来确切知道L中非零的数量。实际上,此信息是通过analyzePattern步骤计算出来的,但是此方法还预先分配了SLLT.matrixL(),所以为时已晚。