MappedSparseMatrix in RcppEigen

2019-03-06 13:46发布

I want to use conjugate gradient algorithm implemented in RcppEigen package for solving large sparse matrices.

Since I am new to Rcpp and C++, I just started with the dense matrices.

    // [[Rcpp::depends(RcppEigen)]]
    #include <Rcpp.h>
    #include <RcppEigen.h>
    #include <Eigen/IterativeLinearSolvers>
    using Eigen::SparseMatrix;
    using Eigen::MappedSparseMatrix;
    using Eigen::Map;
    using Eigen::MatrixXd;
    using Eigen::VectorXd;
    using Rcpp::as;
    using Eigen::ConjugateGradient;
    typedef Eigen::MappedSparseMatrix<double> MSpMat;

    // [[Rcpp::export]]
    VectorXd getEigenValues(SEXP As, SEXP bs) {
    const Map<MatrixXd> A(as<Map<MatrixXd> > (As));
    const Map<VectorXd> b(as<Map<VectorXd> > (bs));
    ConjugateGradient<MatrixXd> cg;
    cg.compute(A);
    VectorXd x=cg.solve(b);
    return x;
    }

This works as expected. Therefore, I thought to extend this to suit to sparse matrices.

   // [[Rcpp::depends(RcppEigen)]]
   #include <Rcpp.h>
   #include <RcppEigen.h>
   #include <Eigen/IterativeLinearSolvers>
   using Eigen::SparseMatrix;
   using Eigen::MappedSparseMatrix;
   using Eigen::Map;
   using Eigen::MatrixXd;
   using Eigen::VectorXd;
   using Rcpp::as;
   using Eigen::ConjugateGradient;
   typedef Eigen::MappedSparseMatrix<double> MSpMat;

   // [[Rcpp::export]]
   VectorXd getEigenValues(SEXP As, SEXP bs) {
   const MSpMat A = as<MSpMat>(As);
   const Map<VectorXd> b(as<Map<VectorXd> > (bs));
   ConjugateGradient<SparseMatrix<double> > cg;
   cg.compute(A);
   VectorXd x=cg.solve(b);
   return x;
   }

However, this tends to give really strange results. The code in itself is also not giving any errors. Hope someone could help me to correct this error.

Thanks.

1条回答
一纸荒年 Trace。
2楼-- · 2019-03-06 14:22

You need to use your Eigen::MappedSparseMatrix type in the Eigen::ConjugateGradient function. Try the following code:

#include <RcppEigen.h>

typedef Eigen::MappedSparseMatrix< double > mappedSparseMatrix ;
typedef Eigen::Map< Eigen::VectorXd > mappedVector ;

// [[Rcpp::depends(RcppEigen)]]
// [[Rcpp::export]]
Eigen::VectorXd cgSparse(
    const mappedSparseMatrix A,
    const mappedVector b
) {
    Eigen::ConjugateGradient< mappedSparseMatrix, Eigen::Lower > cg( A ) ;
    return cg.solve( b ) ;
}

Comparing with R's solve() function:

B <- matrix( c( 1, 2, 0, 2, 5, 0, 0, 0, 3  ), 3, 3, TRUE )
b <- c( 5, 1, 7 )
B %*% solve( B, b )
       [,1]
[1,]    5
[2,]    1
[3,]    7

B %*% cgSparse( as( B, 'dgCMatrix' ), b )
     [,1]
[1,]    5
[2,]    1
[3,]    7
查看更多
登录 后发表回答