As a part of utilizing network data drawn at random before further processing, I am trying to call a couple of functions from the igraph package at the beginning of each iteration. The code I use is as follows:
#define ARMA_64BIT_WORD
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::plugins(cpp11)]]
using namespace Rcpp;
using arma::sp_mat;
// [[Rcpp::export]]
sp_mat adj_mat(int n, double p) {
Environment igraph("package:igraph");
Function game_er = igraph["erdos.renyi.game"];
Function get_adjacency = igraph["get.adjacency"];
List g = game_er(Named("n", n), Named("p", p));
NumericMatrix A_m = get_adjacency(Named("g", g));
sp_mat A = as<sp_mat>(A_m);
return A;
}
/*** R
set.seed(20130810)
library(igraph)
adj_mat(100, 0.5)
*/
So, while the C++ compiles without warnings, the following error is thrown:
> sourceCpp("Hooking-R-in-cpp.cpp")
> set.seed(20130810)
> library(igraph)
> adj_mat(100, 0.5)
Error in adj_mat(100, 0.5) :
Not compatible with requested type: [type=S4; target=double].
From the error it looks like I am passing a S4 class to a double? Where is the error?
You were imposing types in the middle of your C++ functions that did not correspond to the representation, so you got run-time errors trying to instantiate them.
The version below works. I don't know igraph well enough to suggest what else you use to store the first return; for the S4 you can use the dgCMatrix matrix but S4 is an ok superset.
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::plugins(cpp11)]]
using namespace Rcpp;
using arma::sp_mat;
// [[Rcpp::export]]
sp_mat adj_mat(int n, double p) {
Environment igraph("package:igraph");
Function game_er = igraph["erdos.renyi.game"];
Function get_adjacency = igraph["get.adjacency"];
SEXP g = game_er(Named("n", n), Named("p", p));
S4 A_m = get_adjacency(Named("g", g));
sp_mat A = as<sp_mat>(A_m);
return A;
}
/*** R
set.seed(20130810)
library(igraph)
adj_mat(100, 0.5)
*/
Related
I'm working on a package that requires some very fast matrix multiplication so looking to use RcppEigen. For a variety of reasons though having to do with the need for multidimensional arrays, I need to convert a created object of class Eigen::MatrixXd to class Rcpp::NumericMatrix.
I tried reversing the steps listed in RcppEigen::FastLm.cpp, but that doesn't seem to work
e.g. instead of using
const Map<MatrixXd> X(as<Map<MatrixXd> >(Xs));
I tried
Rcpp:NumericMatrix X(as<Rcpp::NumericMatrix>(Xs));
where Xs is a matrix of class Eigen::MatrixXd but that didn't seem to work:" error: no matching function for call to 'as'
return Rcpp::asRcpp::NumericMatrix(z);"
If this isn't at all possible I can try another direction.
Basically what I need to do in R speak is
a = matrix(1, nrow = 10, ncol = 10)
b = array(0, c(10,10,10))
b[,,1] = a
To give a clearer starting example
How would I go about storing an object of class MatrixXd in an object of class NumericMatrix?
#include <Rcpp.h>
#include <RcppEigen.h>
using namespace Rcpp;
using namespace Eigen;
// [[Rcpp::export]]
NumericMatrix sample_problem() {
Eigen::MatrixXd x(2, 2); x << 1,1,2,2;
Eigen::MatrixXd z(2, 2);
Eigen::MatrixXd y(2,2); y << 3,3,4,4;
z = x * y; // do some eigen matrix multiplication
Rcpp::NumericMatrix w(2,2);
// what I'd like to be able to do somehow:
// store the results of the eigen object z in
// a NumericMatrix w
// w = z;
return w;
}
Thanks for posting code! It makes everything easier. I just rearranged you code the tiniest bit.
The key changes is to "explicitly" go back from the Eigen representation via an RcppEigen helper to a SEXP, and to then instantiate the matrix. Sometimes ... the compiler needs a little nudge.
Code
#include <Rcpp.h>
#include <RcppEigen.h>
// [[Rcpp::depends(RcppEigen)]]
// [[Rcpp::export]]
Rcpp::NumericMatrix sample_problem() {
Eigen::MatrixXd x(2, 2), y(2, 2);
x << 1,1,2,2;
y << 3,3,4,4;
// do some eigen matrix multiplication
Eigen::MatrixXd z = x * y;
// what I'd like to be able to do somehow:
// store the results of the eigen object z in
// a NumericMatrix w
// w = z;
SEXP s = Rcpp::wrap(z);
Rcpp::NumericMatrix w(s);
return w;
}
/*** R
sample_problem()
*/
Demo
R> sourceCpp("demo.cpp)
R> sample_problem()
[,1] [,2]
[1,] 7 7
[2,] 14 14
R>
With g++-9 I need -Wno-ignored-attributes or I get screens and screens of warnings...
I need to involve variable from arma::in my Rcpp code. But I ran into a problem when trying to use the sugar function pnorm. Here is a demo:
#include <RcppArmadillo.h>
#include <RcppArmadilloExtensions/sample.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;
// [[Rcpp::export]]
double pget(NumericVector x, NumericVector beta) {
arma::colvec xx = Rcpp::as<arma::colvec>(x) ;
arma::colvec bb = Rcpp::as<arma::colvec>(beta) ;
double tt = as_scalar( arma::trans(xx) * bb);
double temp = Rcpp::pnorm(tt);
return temp;
}
Then I got an error: no matching function for call to 'pnorm5'
Does that mean I cannot use Rcpp::pnorm???
The Rcpp sugar functions are meant for vector type arguments like Rcpp::NumericVector. For scalar arguments you can use the functions in the R namespace:
#include <RcppArmadillo.h>
#include <RcppArmadilloExtensions/sample.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;
// [[Rcpp::export]]
double pget(NumericVector x, NumericVector beta) {
arma::colvec xx = Rcpp::as<arma::colvec>(x) ;
arma::colvec bb = Rcpp::as<arma::colvec>(beta) ;
double tt = as_scalar( arma::trans(xx) * bb);
double temp = R::pnorm(tt, 0.0, 1.0, 1, 0);
return temp;
}
/*** R
x <- rnorm(5)
beta <- rnorm(5)
pget(x, beta)
*/
BTW, here two variants. First variant uses arma instead of Rcpp vectors as arguments. Since these are const references, no data is copied. In addition, arma::dot is used:
// [[Rcpp::export]]
double pget2(const arma::colvec& xx, const arma::colvec& bb) {
double tt = arma::dot(xx, bb);
return R::pnorm(tt, 0.0, 1.0, 1, 0);
}
The second variant calculates the scalar product without resorting to Armadillo:
// [[Rcpp::export]]
double pget3(NumericVector x, NumericVector beta) {
double tt = Rcpp::sum(x * beta);
return R::pnorm(tt, 0.0, 1.0, 1, 0);
}
I'm much less of an expert than #RalfStubner at Rcpp, so I had to hack around (with help from StackOverflow and the Rcpp cheat sheat) to get the following code. Instead of using the R-namespace versions on scalars, I converted back to a NumericVector ... this can almost certainly be done more efficiently/skipping a few steps by someone who actually knows what they're doing ... e.g. it's possible that the arma-to-NumericVector conversion could be done directly without going through as_scalar ... ?
#include <RcppArmadillo.h>
#include <RcppArmadilloExtensions/sample.h>
#include <Rcpp.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;
using namespace arma;
// [[Rcpp::export]]
NumericVector pget(NumericVector x, NumericVector beta) {
colvec xx = as<colvec>(x) ;
colvec bb = as<colvec>(beta) ;
double tt = as_scalar(trans(xx) * bb);
NumericVector tt2 = NumericVector::create( tt );
NumericVector temp = Rcpp::pnorm(tt2);
return temp;
}
I have a very large binary big.matrix and also a vector of class assignment (same length as number of rows of big.matrix).
I want to be able to loop through each column of the big.matrix and output the p value for each fisher.test.
With a normal matrix object, I can do the following, but converting my big.matrix into a matrix takes up over 5 gb of ram.
p.value <- unlist(
lapply(
lapply(as.data.table(binarymatrix),
fisher.test,
y = class
), function(x) x$p.value
)
)
How can I do this without converting into a matrix object? As I understand it, accessing elements of a big.matrix requires C++ code, but I am not familiar with this at all.
Here it shows how to do fisher.test in Rcpp Rcpp: Is there an implementation fisher.test() in Rcpp but I am not sure how to input each column of a matrix into this.
An example big.matrix would look like
library(bigmemory)
matrix <- matrix(sample(0:1, 100 * 10000, replace = TRUE), 100 , 10000)
bigmatrix <- as.big.matrix(matrix)
And my class variable looks like:
class <- sample( LETTERS[1:2], 100, replace=TRUE)
Thanks!
EDIT:
Here is the Rcpp code I have right now. If someone could help me figure out the issue I would really appreciate it.
// [[Rcpp::depends(RcppEigen, RcppArmadillo, bigmemory, BH)]]
#include <RcppArmadillo.h>
#include <RcppEigen.h>
#include <bigmemory/BigMatrix.h>
#include <bigmemory/MatrixAccessor.hpp>
using namespace Rcpp;
using namespace arma;
using namespace Eigen;
using namespace std;
// [[Rcpp::plugins(cpp11)]]
// [[Rcpp::export]]
ListOf<IntegerVector> AccessVector(SEXP pBigMat, int j, vector<int> status) {
XPtr<BigMatrix> xpMat(pBigMat);
MatrixAccessor<int> macc(*xpMat);
int n = xpMat->nrow();
// Bigmemory
cout << "Bigmemory:";
for (int i = 0; i < n; i++) {
cout << macc[j][i] << ' ';
}
cout << endl;
// STD VECTOR
vector<int> stdvec(macc[j], macc[j] + n);
// Obtain environment containing function
Rcpp::Environment base("package:stats");
// Make function callable from C++
Rcpp::Function fisher_test = base["fisher.test"];
// Call the function and receive its list output
Rcpp::List test_out = fisher_test(Rcpp::_["x"] = stdvec, Rcpp::_["y"] = status);
// Return test object in list structure
return test_out;
}
Ideally I want to be able to loop through each of the columns in C++ itself, and just output the p-values to R.
I am trying to rewrite into (R)cpp an original R function that makes use of the gamma function (from double input). Below the original source. When comping with sourceCpp the following error is raised "no matching function for call to 'gamma(Rcpp::traits::storage_type(<14>:.type)'"
The gamma function should has been put within sugar (as the mean below use) so I expect there should be easily called.
#include <Rcpp.h>
#include <math.h>
using namespace Rcpp;
// original R function
// function (y_pred, y_true)
// {
// eps <- 1e-15
// y_pred <- pmax(y_pred, eps)
// Poisson_LogLoss <- mean(log(gamma(y_true + 1)) + y_pred -
// log(y_pred) * y_true)
// return(Poisson_LogLoss)
// }
// [[Rcpp::export]]
double poissonLogLoss(NumericVector predicted, NumericVector actual) {
NumericVector temp, y_pred_new;
double out;
const double eps=1e-15;
y_pred_new=pmax(predicted,eps);
long n = predicted.size();
for (long i = 0; i < n; ++i) {
temp[i] = log( gamma(actual[i]+1)+y_pred_new[i]-log(y_pred_new[i])*actual[i]);
}
out=mean(temp); // using sugar implementation
return out;
}
You are making this too complicated as the point of Rcpp Sugar is work vectorized. So the following compiles as well:
#include <Rcpp.h>
#include <math.h>
using namespace Rcpp;
// [[Rcpp::export]]
double poissonLogLoss(NumericVector predicted, NumericVector actual) {
NumericVector temp, y_pred_new;
double out;
const double eps=1e-15;
y_pred_new=pmax(predicted,eps);
temp = log(gamma(actual + 1)) + y_pred_new - log(y_pred_new)*actual;
out=mean(temp); // using sugar implementation
return out;
}
Now, you didn't supply any test data so I do not know if this computes correctly or not. Also, because your R expression is already vectorized, this will not be much faster.
Lastly, your compile error is likely due to the Sugar function gamma() expecting an Rcpp object whereas you provided a double.
I am trying to duplicate the R vectorised sum in Rcpp
I first try the following trouble-free code:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
double call(NumericVector x){
return sum(x);
}
Type call(Time)
> call(Time)
[1] 1919853
Then an environment version, also works well,
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
double call(){
Environment env = Environment::global_env();
NumericVector Time = env["Time"];
return sum(Time);
}
Type call()
> call()
[1] 1919853
Now I am trying something weird as following,
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
double call(){
Environment base("package:base");
Function sumc = base["sum"];
Environment env = Environment::global_env();
NumericVector Time = env["Time"];
double res = sumc(Time);
return res;
}
This time I got a error message:
trycpp.cpp:10:25: error: cannot convert ‘SEXP {aka SEXPREC*}’ to ‘double’ in initialization
double res = sumc(Time);
Any idea what's going wrong ?
You cannot call an R function (ie sumc() on one of Rcpp's vectors. Do this:
// [[Rcpp::export]]
double mycall(){
Environment base("package:base");
Function sumc = base["sum"];
Environment env = Environment::global_env();
NumericVector Time = env["Time"];
double res = sum(Time);
return res;
}
Here sum() is the Rcpp sugar function.