While using RcppArmadillo::sample function I discovered that using a large input vector causes RStudio to crash. I provide the entire code below:
#include<iostream>
#include <armadillo>
#include <RcppArmadilloExtensions/sample.h>
//[[Rcpp::depends(RcppArmadillo)]]
using namespace std;
using namespace Rcpp;
using namespace arma;
//[[Rcpp::export]]
IntegerVector test_func(int N) {
IntegerVector frame = Range(1, N);
NumericVector wts = runif(N, 0, 1);
NumericVector Wts = wts / sum(wts);
IntegerVector y = RcppArmadillo::sample(frame, N,TRUE, Wts );
return y;
}
Calling test_func(N=100) produces the right results. But N greater that 200, for instance test_func(N=210), crashes RStudio as well as RConsole. Is there a mistake I am making?
I cannot replicate this. On either a straight R ression or inside RStudio it just works for me.
I made small corrections to your code:
// the following header also include Rcpp and Armadillo headers
#include <RcppArmadilloExtensions/sample.h>
//[[Rcpp::depends(RcppArmadillo)]]
//[[Rcpp::export]]
Rcpp::IntegerVector test_func(int N) {
Rcpp::IntegerVector frame = Rcpp::Range(1, N);
Rcpp::NumericVector wts = Rcpp::runif(N, 0.0, 1.0);
return Rcpp::RcppArmadillo::sample(frame, N, true, wts / Rcpp::sum(wts));
}
but none of these should be material.
Note how the code of the sample() function throws an excpetion if N gets big:
if (walker_test < 200) {
ProbSampleReplace<IntegerVector>(index, nOrig, size, prob);
} else {
throw std::range_error("Walker Alias method not implemented. [...]");
}
so I think you may be seeing a garden variety error of a mismatch between R, Rcpp, RcppArmadillo. What platform are you on? For it is Linux where packages are recompiled.
Related
I'm quite new to Rcpp. Sorry If I'm missing something obvious.
but when I try to use an igraph function in Rcpp I face the following obvious error on the left:
"Cannot initialize a Variable of type 'RCPP:Environment' (aka,'int') with an lvalue of type 'const char[15]'
Here is the code
#include <Rcpp.h>
// [[Rcpp::plugins(cpp11)]]
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector insideOfCommEdgeIdsCpp(CharacterVector g, CharacterVector v) {
Environment igraph("package:igraph");
Function game_er = igraph["erdos.renyi.game"];
Function get_adjacency = igraph["get.adjacency"];
}
A few small errors in your file:
declared as NumericVector but nothing is returned
Environment igraph not set up correctly.
A corrected version is below. And it it worth repeating this: Any R functions called from C++ are still R functions that run at the speed of R functions.
Corrected code
#include <Rcpp.h>
// [[Rcpp::plugins(cpp11)]]
using namespace Rcpp;
// [[Rcpp::export]]
void insideOfCommEdgeIdsCpp(CharacterVector g, CharacterVector v) {
Environment igraph = Environment("package:igraph");
Function game_er = igraph["erdos.renyi.game"];
Function get_adjacency = igraph["get.adjacency"];
}
I commonly work with a short Rcpp function that takes as input a matrix where each row contains K probabilities that sum to 1. The function then randomly samples for each row an integer between 1 and K corresponding to the provided probabilities. This is the function:
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadilloExtensions/sample.h>
using namespace Rcpp;
// [[Rcpp::export]]
IntegerVector sample_matrix(NumericMatrix x, IntegerVector choice_set) {
int n = x.nrow();
IntegerVector result(n);
for ( int i = 0; i < n; ++i ) {
result[i] = RcppArmadillo::sample(choice_set, 1, false, x(i, _))[0];
}
return result;
}
I recently updated R and all packages. Now I cannot compile this function anymore. The reason is not clear to me. Running
library(Rcpp)
library(RcppArmadillo)
Rcpp::sourceCpp("sample_matrix.cpp")
throws the following error:
error: call of overloaded 'sample(Rcpp::IntegerVector&, int, bool, Rcpp::Matrix<14>::Row)' is ambiguous
This basically tells me that my call to RcppArmadillo::sample() is ambiguous. Can anyone enlighten me as to why this is the case?
There are two things happening here, and two parts to your problem and hence the answer.
The first is "meta": why now? Well we had a bug let in the sample() code / setup which Christian kindly fixed for the most recent RcppArmadillo release (and it is all documented there). In short, the interface for the very probability argument giving you trouble here was changed as it was not safe for re-use / repeated use. It is now.
Second, the error message. You didn't say what compiler or version you use but mine (currently g++-9.3) is actually pretty helpful with the error. It is still C++ so some interpretative dance is needed but in essence it clearly stating you called with Rcpp::Matrix<14>::Row and no interface is provided for that type. Which is correct. sample() offers a few interface, but none for a Row object. So the fix is, once again, simple. Add a line to aid the compiler by making the row a NumericVector and all is good.
Fixed code
#include <RcppArmadillo.h>
#include <RcppArmadilloExtensions/sample.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;
// [[Rcpp::export]]
IntegerVector sample_matrix(NumericMatrix x, IntegerVector choice_set) {
int n = x.nrow();
IntegerVector result(n);
for ( int i = 0; i < n; ++i ) {
Rcpp::NumericVector z(x(i, _));
result[i] = RcppArmadillo::sample(choice_set, 1, false, z)[0];
}
return result;
}
Example
R> Rcpp::sourceCpp("answer.cpp") # no need for library(Rcpp)
R>
I am considering calling a R function from c++ via environment, but I got an error, here is what I did
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector call(NumericVector x){
Environment env = Environment::global_env();
Function f = env["fivenum"];
NumericVector res = f(x);
return res;
}
Type call(x), this is what I got,
Error: cannot convert to function
I know I can do it right in another way,
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector callFunction(NumericVector x, Function f) {
NumericVector res = f(x);
return res;
}
and type
callFunction(x,fivenum)
But still wondering why first method failed.
fivenum function is not defined in the global environment but in the stats package enviroment, so you should get it from that:
...
Environment stats("package:stats");
Function f = stats["fivenum"];
...
In addition to #digEmAll's answer, I would like to mention a more general approach, which mimics R's packagename::packagefunctionX(...) approach.
The advantage is that you don't have to call library("dependend_library"), i.e., in this case, library(stats). That is useful when you call a function from your package, without previously calling library.
// [[Rcpp::export]]
Rcpp::NumericVector five_nums(Rcpp::NumericVector x){
Rcpp::Environment stats = Rcpp::Environment::namespace_env("stats");
Rcpp::Function f = stats["fivenum"];
return Rcpp::NumericVector(f(x));
}
/*** R
five_nums(stats::rnorm(25, 2, 3))
*/
I am considering calling a R function from c++ via environment, but I got an error, here is what I did
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector call(NumericVector x){
Environment env = Environment::global_env();
Function f = env["fivenum"];
NumericVector res = f(x);
return res;
}
Type call(x), this is what I got,
Error: cannot convert to function
I know I can do it right in another way,
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector callFunction(NumericVector x, Function f) {
NumericVector res = f(x);
return res;
}
and type
callFunction(x,fivenum)
But still wondering why first method failed.
fivenum function is not defined in the global environment but in the stats package enviroment, so you should get it from that:
...
Environment stats("package:stats");
Function f = stats["fivenum"];
...
In addition to #digEmAll's answer, I would like to mention a more general approach, which mimics R's packagename::packagefunctionX(...) approach.
The advantage is that you don't have to call library("dependend_library"), i.e., in this case, library(stats). That is useful when you call a function from your package, without previously calling library.
// [[Rcpp::export]]
Rcpp::NumericVector five_nums(Rcpp::NumericVector x){
Rcpp::Environment stats = Rcpp::Environment::namespace_env("stats");
Rcpp::Function f = stats["fivenum"];
return Rcpp::NumericVector(f(x));
}
/*** R
five_nums(stats::rnorm(25, 2, 3))
*/
I am basically trying to translate some R code into cpp using Rcpp. I got the following errors in the code below:
error: cannot convert ‘Rcpp::sugar::Plus_Vector_Primitive<14, true, Rcpp::stats::D2<14, true, Rcpp::Vector<14, Rcpp::PreserveStorage> > >’ to ‘Rcpp::traits::storage_type<14>::type {aka double}’ in assignment
Here is the code
#include <RcppArmadillo.h>
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export(".loop_exp")]]
void mm_mult(const arma::vec& helpa, const arma::mat& helpb, const arma::vec& helpc,
const Rcpp::NumericVector& t1, const arma::vec& t2, int J, Rcpp::NumericVector& prob)
{
int j;
for (j = 1; J <= J; j++)
{
arma::mat t = (helpb.row(j)).t() * (t2);
double tt = t[0,0];
prob[j] = (helpa[j] + dnorm(t1, tt, helpc[j])); <---- here is the error
}
return;
}
I guess this is a type casting error, but basically I cannot find a good reference.. Could anyone give me some help on this issue? Thanks a lot!
The reason is that the dnorm "syntaxic sugar" has a signature NumericVector dnorm( NumericVector, double, double ).
As it returns a NumericVector, you have to convert it to a double value yourself.
A quick and easy (and not very robust) way is to subset the returned vector to get only its first element. In your example:
prob[j] = (helpa[j] + dnorm(t1, tt, helpc[j])[0]); // Note the "[0]"
Otherwise, there are a couple of other potential problems in your code: you shouldn't #include <Rcpp.h> as it is already done with #include <RcppArmadillo.h> --- also, your loop ending condition, J <= J, looks suspicious to me...
Hope this helps :)