Reputation: 261
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.
Upvotes: 1
Views: 1048
Reputation: 471
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
Upvotes: 3