Rcpp中同时使用mlpack与SuperLU时spsolve报错的解决求助
问题解决:引入mlpack后Armadillo spsolve报错"需启用SuperLU"
问题背景
编写Rcpp代码时,引入mlpack库后调用spsolve()函数出现错误:spsolve(): use of SuperLU must be enabled。但代码中已定义ARMA_USE_SUPERLU 1,且eigs_sym()函数可正常运行;移除mlpack相关引用后问题消失。需要在保留mlpack及boost库的前提下解决该问题。
原代码片段
#include <RcppArmadillo.h> #define _USE_MATH_DEFINES #include<cmath> #include <boost/math/special_functions/bessel.hpp> #include <mlpack.h> #include <mlpack/methods/kmeans.hpp> // [[Rcpp::depends(RcppEnsmallen)]] // [[Rcpp::depends(mlpack)]] // [[Rcpp::plugins(cpp17)]] // [[Rcpp::depends(RcppArmadillo)]] // [[Rcpp::plugins(openmp)]] // [[Rcpp::depends(BH)]] using namespace arma; using namespace Rcpp; #define ARMA_USE_ARPACK 1 #define ARMA_USE_SUPERLU 1 // ... 其余代码
错误输出
flag eig Error: spsolve(): use of SuperLU must be enabled
解决方案
1. 调整宏定义顺序
Armadillo的功能宏定义必须在任何Armadillo头文件(包括被mlpack间接引入的)之前声明。原代码中宏定义放在#include <RcppArmadillo.h>和mlpack头文件之后,mlpack内部会先引入Armadillo,导致宏定义未生效。
修改方法:把ARMA_USE_SUPERLU和ARMA_USE_ARPACK移到所有#include之前:
#define ARMA_USE_ARPACK 1 #define ARMA_USE_SUPERLU 1 #define _USE_MATH_DEFINES #include <RcppArmadillo.h> #include<cmath> #include <boost/math/special_functions/bessel.hpp> #include <mlpack.h> #include <mlpack/methods/kmeans.hpp> // ... 其余depends和plugins声明
2. 确认编译时链接SuperLU
确保编译环境正确链接SuperLU库。可在代码中添加显式链接声明:
// [[Rcpp::linkingTo(RcppArmadillo, SuperLU)]]
或在项目的Makevars文件中补充链接参数:
PKG_LIBS += $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) -lsuperlu
3. 替换求解器参数为枚举值(可选)
原代码中用字符串"superlu"指定求解器,可替换为Armadillo内置的枚举值superlu,避免字符串解析冲突:
bool status = spsolve(mu_f, B, y, superlu, opts);
修改后的完整代码
#define ARMA_USE_ARPACK 1 #define ARMA_USE_SUPERLU 1 #define _USE_MATH_DEFINES #include <RcppArmadillo.h> #include<cmath> #include <boost/math/special_functions/bessel.hpp> #include <mlpack.h> #include <mlpack/methods/kmeans.hpp> // [[Rcpp::depends(RcppEnsmallen)]] // [[Rcpp::depends(mlpack)]] // [[Rcpp::plugins(cpp17)]] // [[Rcpp::depends(RcppArmadillo)]] // [[Rcpp::plugins(openmp)]] // [[Rcpp::depends(BH)]] using namespace arma; using namespace Rcpp; #define tolr 1e-5 #define crossprod(x) symmatu((x).t() * (x)) #define tcrossprod(x) symmatu((x) * (x).t()) #define pi_sq 9.869604401089358 // [[Rcpp::export]] Rcpp::List NNGP_fit(const int n){ sp_mat A = sprandu<sp_mat>(n, n, 0.1); sp_mat B = A.t()*A; vec eigval; mat eigvec; eigs_sym(eigval, eigvec, B, n-1); // find n-1 eigenvalues/eigenvectors Rcpp::Rcout<<"flag eig"<<endl; superlu_opts opts; opts.symmetric = true; opts.equilibrate =true; vec mu_f, y(n, fill::randn); bool status = spsolve(mu_f,B, y, superlu,opts); Rcpp::Rcout<<"status= "<<status<<endl; return Rcpp::List::create(Rcpp::Named("covmat") =wrap(B), Rcpp::Named("eigval") =wrap(eigval), Rcpp::Named("eigvec") =wrap(eigvec), Rcpp::Named("y") =wrap(y), Rcpp::Named("mu_f") =wrap(mu_f) ); }
内容的提问来源于stack exchange,提问作者noirritchandra
相关产品推荐
相关产品推荐

