how to get the determinant of a matrix using RcppEigen - c++

I am brand new to Rcpp. I am trying to using the R package RcppEigen to get the determinant of a matrix. The following code is saved in a file and I use sourceCpp to use it. There is no compilation error when I use sourceCpp. When using getDeterminant(A) in R, A is a matrix. It always complains the following error.
"Error: could not find function "getDeterminant""
However, the getEigenValues works well.
I appreciate a lot if anybody is happy to help me with this.
Thanks a lot!
#include <RcppEigen.h>
// [[Rcpp::depends(RcppEigen)]]
using Eigen::Map; // 'maps' rather than copies
using Eigen::MatrixXd; // variable size matrix, double precision
using Eigen::VectorXd; // variable size vector, double precision
using Eigen::SelfAdjointEigenSolver; // one of the eigenvalue solvers
using Eigen::MatrixXi;
using Eigen::MatrixBase;
// [[Rcpp::export]]
VectorXd getEigenValues(Map<MatrixXd> M) {
SelfAdjointEigenSolver<MatrixXd> es(M);
return es.eigenvalues();
}
// [[Rcpp:export]]
double getDeterminant(Map<MatrixXd> AA){
return AA.determinant();
}

You are missing a : in the second Rcpp Attributes tag: Rcpp::export is the form the regular expression looks for.
If you add it, the functions becomes accessible:
R> Rcpp::sourceCpp("/tmp/crystal.cpp")
R> M <- matrix(1:9,3,3)*1.0
R> getEigenValues(M)
[1] 2.80689e-16 6.99265e-01 1.43007e+01
R> getDeterminant(M)
[1] 0
R>

Related

Rcpp: confusion about the base operation of assignment

Recently, I am trying to work on the Rcpp package to improve efficiency of computation in my work. However,I am not deep knowledged about C++, there are some strange behavoirs I can not understand. The below example show a simple tasks about derving weight of NumericVector, there are several questions:
When I use WAP=rev(WAP), it results in an incorrect output, I have to introduce a new variable to store the result so that I get the right output. I do not know why, should it NEVER use a 'x=f(x)' operation in C++ and Rcpp (must copy by clone instead) ?
About the CharacterVector method="eq", exactly I want to use a char or string type, however, it does not work with strncmp function (now I have to use method[0]), but I do not know how to look up the API of Rcpp functions in Rstudio?
I wonder whether there is a R-style grep, tolower function for conditions in Rcpp, I do not know which document I should refer to except for Rcpp suger, so that I can find the availiable base functions. Otherwise, I am thinking about calling R functions with Rcpp::function R_grep("grep"), but I do know whether this is the best way and recommended.
Any suggestions would be greatly appreciated.
#include <Rcpp.h>
#include <string>
#include <math.h>
#include <algorithm>
using namespace std;
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector cppweight(int N, CharacterVector method="eq", const bool reverse=false, const bool test=false){
NumericVector W(N);
NumericVector WAP(N);
NumericVector revWAP(N);
//method=tolower(method); //function not exists
if(strncmp(method[0],"eq",2)==0){
W=rep(1,N)/1.0*N;//convert int to float by multiplying 1.0
WAP=W/sum(W);
Rcout<< sum(W) << "\n";
} else if(strncmp(method[0],"ln",2)==0){
W=rev(seq(1,N))/1.0*N;
WAP=W/sum(W);
}
if(reverse){
if(test){
WAP=rev(WAP);//Why this result in incorrect result
revWAP=WAP;
}else{
revWAP=rev(WAP);
}
}else{
revWAP=WAP;
}
return(round(revWAP,3));
}
/*** R
cppweight(6,"ln",reverse=F,test=F)
cppweight(6,"ln",reverse=T,test=F)
cppweight(6,"ln",reverse=T,test=T)
*/

Rcpp: ambiguous overload for 'operator=' Matrix and List

The following Rcpp code is the minimal reproducible example for a much larger code that generates the identical compilation error. It seems that I cannot asign a numeric matrix to a list and the list then again to another matrix.
#include <Rcpp.h>
using namespace Rcpp;
//[[Rcpp::export]]
List return_a(NumericMatrix a, NumericMatrix b){
//the function only returns the input matrix a
List result(1);
result(0) = a;
return(result);
}
//[[Rcpp::export]]
List wrapper_cpp(NumericMatrix a, NumericMatrix b){
//the function is a dummy wrapper for much more code
List Step1(1);
List results(1);
Step1 = return_a(a,b);
a = Step1(0);
results(0) = a;
return(results);
}
The code above gives the following compilation error that I shortened:
error: ambiguous overload for 'operator=' (operand types are 'Rcpp::NumericMatrix {aka Rcpp::Matrix<14>}' and 'Rcpp::Vector<19>::Proxy ...
a = Step1(0);
My real function is much more complex. I need to manipulate matrices in several loops and in each step the matrices are returned by each function within a list. I then need to extract these lists to manipulate the matrices further. How can this be done?
Besides the error that #Ralf already mentioned, you were simply trying too much. Sometimes we need an intermediate step as the template magic is ... finicky. The following works.
Code
#include <Rcpp.h>
using namespace Rcpp;
//[[Rcpp::export]]
List return_a(NumericMatrix a, NumericMatrix b){
//the function only returns the input matrix a
List result(1);
result(0) = a;
return(result);
}
//[[Rcpp::export]]
List wrapper_cpp(NumericMatrix a, NumericMatrix b){
//the function is a dummy wrapper for much more code
List results(1);
List Step1 = return_a(a,b);
NumericMatrix tmp = Step1(0);
results(0) = tmp;
return(results);
}
Output
R> Rcpp::sourceCpp("~/git/stackoverflow/54771818/answer.cpp")
R> wrapper_cpp(matrix(1:4,2,2), matrix(4:1,2,2))
[[1]]
[,1] [,2]
[1,] 1 3
[2,] 2 4
R>

Vectorized log1p() in RcppArmadillo

What is the appropriate way to apply log1p() to an entire arma::vec? It seems that there are vectorized versions of log() and exp(), but not log1p(). I found that there's syntactic sugar for NumericVector, so I end up converting arma::vec to NumericVector, applying log1p(), then converting back:
#include <RcppArmadillo.h>
using namespace Rcpp;
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::vec test_log1p( arma::vec v )
{
// arma::vec res = log1p(v); // results in a compilation error
NumericVector v1 = log1p( wrap(v) );
arma::vec res = as<arma::vec>(v1);
return res;
}
Is there a more elegant way of doing this?
The devil is, once again, in the detail.
For starters, RcppArmadillo does not have 'Sugar' so your reasoning is flawed--you can't just look at the Rcpp Sugar functions that are working on Rcpp::NumericVector.
Then again, one can convert as you did. But you chose an expensive conversion. Look into the advanced constructors explicitly reusing memory -- no copies needed.
A much simpler and more direct (yet local) approach would just be to add a little local inlined function. That's what I would do :) Done in a few minutes.
Lastly, we have some sibbling projects that generalized Rcpp Sugar over anything that can take iterators. That is "the high road" and it could do with some fresh development. Maybe start at this repo.
Use the .transform() or .for_each() facilities available for Armadillo vectors and matrices. Example:
v.transform( [](double val) { return log1p(val); } );
or
v.for_each( [](double& val) { val = log1p(val); } ); // note the & character
You may need to use the std prefix: std::log1p() instead of log1p().

Eigen: Flat view of Matrix in Templated Function

For 1D resizing, the Eigen documentation suggests I use the following method to resize an array:
using Eigen;
MatrixXf X(2,2) << 1,2,3,4;
Map<RowVectorXf> v1(X.data(), X.size());
Except I have a templated vector, and can't use RowVectorXf
using Eigen;
template<class num>
void my_func(){
Matrix<num,Dynamic,Dynamic> X(2,2) << 1,2,3,4;
Map<Matrix<num,Dynamic,Dynamic>> unraveled(X.data(),X.size());
}
The example above fails with the following message:
error: static assertion faild: YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX
How do I obtain a flat view of an eigen matrix in a templated function?
The issue is that the Map is 2D and not 1D as you really want:
Map<Matrix<num,Dynamic,1>> unraveled(X.data(),X.size());
Then now it's a vector operation on your original X matrix.

How can I initialize a SparseVector in Eigen

How can I initialize a SparseVector in Eigen ? The following code:
#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
#include <Eigen/Sparse>
using namespace Eigen;
SparseVector<float> vec(3);
main()
{
vec(0)=1.0;
}
gives me the following error
error: call of an object of a class type without appropriate operator() or conversion functions to pointer-to-function type
vec(0)=1.0;
by the way, vec[0]=1.0 doesn't work either.
Looking at the documentation I noticed Scalar& coeffRef(Index i), and it says:
Returns a reference to the coefficient value at given index i. This operation involes a log(rho*size) binary search. If the coefficient does not exist yet, then a sorted insertion into a sequential buffer is performed. (This insertion might be very costly if the number of nonzeros above i is large.)
So the following should work:
#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
#include <Eigen/Sparse>
using namespace Eigen;
SparseVector<float> vec(3);
main()
{
vec.coeffRef(0)=1.0;
}
Not sure why they did it that way instead of using array overloading. Perhaps when it becomes IS_STABLE then they'll do it in a more typical C++ way?