R - use primitive functions like max(), sum() in Rcpp - c++

The following codes:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector FFF(){
NumericVector LB(3);
LB[0]=Language("max",12.3,1.2,13.3,34,10,12.45).eval();
LB[1]=Language("min",12.31,1.24,13.35,340,109,121.45).eval();
LB[2]=Language("sum",12.37,1.21,13.43,34).eval();
return LB;
}
won't pass the compiler, since "Language("max",12.3,1.2,13.3,34,10,12.45).eval())" returns SEXP object, which doesn't fit LB[0]'s type "double". I really want to directly use max(), min() and sum() from the R base instead of writing additional C++ functions. Do you have any good idea?
Thank you!

This is a perfect use case for Rcpp Sugar
http://dirk.eddelbuettel.com/code/rcpp/Rcpp-sugar.pdf
http://adv-r.had.co.nz/Rcpp.html#rcpp-sugar
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector FFF(){
NumericVector LB(3);
LB[0] = max(NumericVector::create(12.3,1.2,13.3,34,10,12.45));
LB[1] = min(NumericVector::create(12.31,1.24,13.35,340,109,121.45));
LB[2] = sum(NumericVector::create(12.37,1.21,13.43,34));
return LB;
}

I like Eigen:
// [[Rcpp::depends(RcppEigen)]]
#include <RcppEigen.h>
using namespace Rcpp;
using Eigen::Map;
using Eigen::VectorXd;
typedef Map<VectorXd> MapVecd;
// [[Rcpp::export]]
NumericVector RcppEigenFun(NumericVector xx) {
const MapVecd x(as<MapVecd>(xx));
NumericVector LB(3);
LB[0] = x.minCoeff();
LB[1] = x.maxCoeff();
LB[2] = x.sum();
return LB;
}
Using it:
RcppEigenFun(3:7)
#[1] 3 7 25
Here is the corresponding function that uses sugar:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector RcppFun(NumericVector x) {
NumericVector LB(3);
LB[0] = min(x);
LB[1] = max(x);
LB[2] = sum(x);
return LB;
}
Benchmarks:
set.seed(42)
x <- rnorm(1e5)
library(microbenchmark)
microbenchmark(RcppEigenFun(x), RcppFun(x))
#Unit: microseconds
# expr min lq median uq max neval
# RcppEigenFun(x) 101.425 101.807 101.948 102.1785 123.095 100
# RcppFun(x) 1480.187 1480.552 1480.889 1489.0045 1550.173 100

Related

Rcpp - Using the optim function

How to use the varargs functions of the R language, as is the case of the optim function?
Consider the code below where I want to maximize the log-likelihood function verossimilhanca:
#include <Rcpp.h>
#include <RInside.h>
using namespace Rcpp;
// [[Rcpp::export]]
double verossimilhanca(Function pdf, NumericVector par, NumericVector x){
NumericVector log_result = log(pdf(par,x));
double soma =0;
for(int i = 0; i < log_result.size(); i++){
soma += log_result[i];
}
return -1*soma;
}
// [[Rcpp::export]]
List bootC(NumericVector x, NumericVector init_val){
Rcpp::Environment stats("package:stats");
Rcpp::Function optim = stats["optim"];
R["my_objective_fn"] = Rcpp::InternalFunction(&verossimilhanca);
Rcpp::List opt_results = optim(Rcpp::_["par"] = init_val,
Rcpp::_["fn"] = Rcpp::InternalFunction(&verossimilhanca),
Rcpp::_["method"] = "BFGS", x);
return opt_results;
// x is a data vetor.
}
In summary, I have a log-likelihood function and I want to maximize this function and x is my data set. I know that RInside allows me to create instances of R in C++ but I want to solve this problem only by using the Rcpp.h library without resorting to RInside.h.
Replace x with Rcpp::_["x"] = x in the arguments of optim function.
It bothers me too until I find the answer of #coatless.

RcppArmadillo: Lambda expression with each_slice

I have a three dimensional array with positive definite matrices and I would like to obtain an array of the same size with the Cholesky factors of all matrices. I am using the Armadillo library and the cube type, for which there is the convenient function each_slice which I'm trying to use. But I am not getting the lambda expression to work correctly, so hopefully someone can help me and point out my mistake.
Here is a minimal example:
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
// [[Rcpp::export]]
arma::cube chol_array(arma::cube Sigma) {
arma::cube Sigma_chol = Sigma;
Sigma_chol.each_slice([](arma::mat X) {return arma::chol(X);});
return Sigma_chol;
}
// [[Rcpp::export]]
arma::cube chol_array2(arma::cube Sigma) {
arma::cube Sigma_chol(size(Sigma));
for (arma::uword i = 0; i < Sigma.n_slices; i++) {
Sigma_chol.slice(i) = arma::chol(Sigma.slice(i));
}
return Sigma_chol;
}
/*** R
Sigma <- array(crossprod(matrix(rnorm(9), 3, 3)), dim = c(3, 3, 2))
chol_array(Sigma)
chol_array2(Sigma)
*/
The function chol_array2 does the job, but chol_array just returns the original matrices. What am I missing?
The issue here is the lack of references in the .each_slice() call. Armadillo's use of lambda expressions require references to update the object and not a return statement. In particular, we have:
For form 3:
apply the given lambda_function to each slice; the function must accept a reference to a Mat object with the same element type as the underlying cube
So, change:
Sigma_chol.each_slice([](arma::mat X) {return arma::chol(X);});
to:
Sigma_chol.each_slice([](arma::mat& X) {X = arma::chol(X);});
Fixed Code
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
// Enable lambda expressions....
// [[Rcpp::plugins(cpp11)]]
// [[Rcpp::export]]
arma::cube chol_array(arma::cube Sigma) {
arma::cube Sigma_chol = Sigma;
// NOTE: the '&' and saving _back_ into the object are crucial
Sigma_chol.each_slice( [](arma::mat& X) { X = arma::chol(X); } );
return Sigma_chol;
}
Test code
set.seed(1113)
Sigma = array(crossprod(matrix(rnorm(9), 3, 3)), dim = c(3, 3, 2))
all.equal(chol_array(Sigma), chol_array2(Sigma))
# [1] TRUE

RcppParallel and C++. Inconsistent results

I've been playing around with RcppParallel and coded up a fairly simple example to figure out how things work. The code is displayed below.
The function float pdf(double x, double sigma) calculates a scaled version of a Gaussian distribution with mean 0 and standard deviation sigma.
Struct_1 is a struct that creates a worker to perform some calculations. I populate a matrix to figure out why certain things are not working correctly.
void Struct_check() performs the calculations.
The function seems to work but every now and again it does not work as expected. I think that it has to do with the types used to perform the calculations in the function pdf!
An example run is displayed below the code.
I would appreciate any help help!
#include <RcppParallel.h>
#include <RcppArmadillo.h>
#include <RcppArmadilloExtensions/sample.h>
#include <math.h>
#define pi 3.14159265358979323846 /* pi */
using namespace arma;
using namespace Rcpp;
using namespace R;
using namespace sugar;
using namespace std;
using namespace RcppParallel;
// Enable C++11 via this plugin (Rcpp 0.10.3 or later)
// [[Rcpp::plugins(cpp11)]]
// [[Rcpp::depends(RcppParallel)]]
// Returns the probability of x, given the distribution described by mu and sigma.
float pdf(double x, double sigma)
{
return exp( -1 * x * x / (2 * sigma * sigma)) / sigma;
}
struct Struct_1 : public Worker
{
arma::vec wr;
arma::vec sr;
NumericVector w2;
// source matrix
const RVector<double> input;
// destination matrix
RMatrix<double> output;
// initialize with source and destination
Struct_1(const NumericMatrix input, NumericMatrix output)
: input(input), output(output) {}
//what is done.
void operator()(std::size_t begin, std::size_t end) {
for (std::size_t i=begin; i<end; i++){ //the processor loop!
NumericVector w2(3);
for (int comp_j=0; comp_j<3; ++comp_j){
w2(comp_j) = wr(comp_j) * pdf( input[i], sr(comp_j) ) ;
}
double sw1 = sum(w2);
output(i,0) = w2(0);
output(i,1) = w2(1);
output(i,2) = w2(2);
output(i,3) = sw1;
w2 = w2/sw1;
output(i,4) = w2(0);
output(i,5) = w2(1);
output(i,6) = w2(2);
double sw2 = sum(w2);
output(i,7) = sw2;
}//end of i loop
}//end of operator
};
// [[Rcpp::depends("RcppArmadillo")]]
// [[Rcpp::export]]
void Struct_check(){
//Some vecs defined
arma::vec wr = {0.2522, 0.58523, 0.16257};
arma::vec s2r = {1.2131, 2.9955, 7.5458};
arma::vec sr = sqrt(s2r);
//an arma mat that will be used in the struct
arma::mat arb_mat;
arb_mat.randn(20);
Rcout<<"Arb_mat=\n"<<arb_mat<<endl;
NumericMatrix r_i_x_NM = as<NumericMatrix>(wrap( arb_mat )); //convert to NumericMatrix
NumericMatrix output( r_i_x_NM.nrow() , 8 ); //define the output matrix
Struct_1 struct_1( r_i_x_NM , output);
struct_1.wr = wr;
struct_1.sr = sr;
Rcout<<"nrow output = "<<output.nrow()<<endl;
Rcout<<"ncol output = "<<output.ncol()<<endl;
parallelFor(0, r_i_x_NM.length(), struct_1);
Rcout<<"completed Parallell calculations"<<endl;
Rcout<<"output = \n"<<output<<endl;
}
Run from within Rstudio. I am running OS X El Capitan if that matter.
Struct_check()
Arb_mat=
-0.4539
0.7915
0.2581
1.5917
0.3718
0.4452
0.1230
-1.4719
0.0024
2.6166
-0.4839
-1.2865
2.0492
-1.5980
-0.7531
-0.7312
-1.4482
0.0202
0.4434
-0.0224
nrow output = 20
ncol output = 8
completed Parallell calculations
output =
0.210336 0.326704 0.0583792 0.595419 0.353256 0.548696 0.0980473 1.00000
0.176872 0.304564 0.0567753 0.538211 0.328629 0.565882 0.105489 1.00000
0.222778 0.334398 0.0589211 0.616097 0.361596 0.542768 0.0956361 1.00000
0.0805904 0.221529 0.0500356 0.352155 0.228849 0.629067 0.142084 1.00000
0.216296 0.330423 0.0586421 0.605361 0.357301 0.545827 0.0968712 1.00000
0.211018 0.327133 0.0584096 0.596561 0.353724 0.548365 0.0979106 1.00000
0.227556 0.337284 0.0591224 0.623962 0.364695 0.540551 0.0947533 1.00000
0.0937487 0.235521 0.0512670 0.380537 0.246359 0.618918 0.134723 1.00000
0.228979 0.338136 0.0591817 0.626297 0.365608 0.539897 0.0944947 1.00000
0.0136216 0.107837 0.0375975 0.159056 0.0856401 0.677981 0.236379 1.00000
0.207911 0.325174 0.0582705 0.591355 0.351584 0.549879 0.0985372 1.00000
0.115751 0.256513 0.0530344 0.425298 0.272164 0.603137 0.124699 1.00000
0.0405607 0.167755 0.0448066 0.253123 0.160241 0.662743 0.177015 1.00000
0.0799309 0.220793 0.0499695 0.350694 0.227922 0.629590 0.142488 1.00000
0.181248 0.307594 0.0569989 0.545841 0.332053 0.563523 0.104424 1.00000
0.183689 0.309265 0.0571216 0.550075 0.333934 0.562222 0.103843 1.00000
**0.228941 0.338113 0.0591801 0.618557 0.591026 0.872861 0.152777 1.61666**
0.228941 0.338113 0.0591801 0.626234 0.365583 0.539915 0.0945016 1.61666
0.211153 0.327218 0.0584156 0.596786 0.353816 0.548300 0.0978837 1.00000
0.228932 0.338108 0.0591798 0.626220 0.365578 0.539919 0.0945032 1.00000
The error occurs when -1.4482 is evaluated to produce the following line 0.228941 0.338113 0.0591801 0.618557 0.591026 0.872861 0.152777 1.61666
In R - checking I get :
wr <- c(0.2522, 0.58523, 0.16257)
s2r <- c(1.2131, 2.9955, 7.5458)
sr <- sqrt(s2r)
w<-NULL
for (i in 1:3){
w[i] = wr[i]*exp( -0.5*((-1.4482/sr[i])^ 2))/(sr[i])
}
w
[1] 0.09646706 0.23826346 0.05150315
sum(w)
[1] 0.3862337
w = w/sum(w)
w
[1] 0.2497635 0.6168894 0.1333471

RcppExports.R not being modified

I am building an R package with Rcpp. I have included roxygen2 style comments in the source cpp file but those comments are not reflected in R/RcppExports.R and src/RcppExports.cpp after building the package and devtools::document().
#include <RcppArmadillo.h>
#include <Rcpp.h>
using namespace Rcpp;
//' #title Linearc
//' #description Computes the linear regression coefficient estimates
(ridge-penalization and weights, optional)
//' #param X matrix
//' #param y matrix
//' #param lam optional tuning parameter for ridge regularization term.
Defaults to 'lam = 0'
//' #param weights optional vector of weights for weighted least squares
//' #param intercept add column of ones if not already present. Defaults to
TRUE
//' #param kernel use linear kernel to compute ridge regression
coefficeients. Defaults to true when p >> n
//' #return returns the coefficient estimates
//' #export
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
List linearrc(const arma::mat& X, const arma::colvec& y, double lam = 0,
arma::colvec weights = 0, bool intercept = true, bool kernel = false) {
...
No modifications in R/RcppExports.R:
# Generated by using Rcpp::compileAttributes() -> do not edit by hand
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393
linearrc <- function(X, y, lam = 0, weights = 0L, intercept = TRUE, kernel =
FALSE) {
.Call('statr_linearrc', PACKAGE = 'statr', X, y, lam, weights, intercept,
kernel)
}
No modifications in src/RcppExports.cpp:
// Generated by using Rcpp::compileAttributes() -> do not edit by hand
// Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393
#include <RcppArmadillo.h>
#include <Rcpp.h>
using namespace Rcpp;
// linearrc
List linearrc(const arma::mat& X, const arma::colvec& y, double lam,
arma::colvec weights, bool intercept, bool kernel);
RcppExport SEXP statr_linearrc(SEXP XSEXP, SEXP ySEXP, SEXP lamSEXP, SEXP
weightsSEXP, SEXP interceptSEXP, SEXP kernelSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< const arma::mat& >::type X(XSEXP);
Rcpp::traits::input_parameter< const arma::colvec& >::type y(ySEXP);
Rcpp::traits::input_parameter< double >::type lam(lamSEXP);
Rcpp::traits::input_parameter< arma::colvec >::type weights(weightsSEXP);
Rcpp::traits::input_parameter< bool >::type intercept(interceptSEXP);
Rcpp::traits::input_parameter< bool >::type kernel(kernelSEXP);
rcpp_result_gen = Rcpp::wrap(linearrc(X, y, lam, weights, intercept,
kernel));
return rcpp_result_gen;
END_RCPP
}
I have included #' #useDynLib <pkg-name> and #' #importFrom Rcpp sourceCpp in a random .R file in the package. I am using latest version of Rstudio and Roxygen2.
Also, the linearrc function does not appear in the NAMESPACE in the form export(linearrc) either...
Thanks!

R interacting with c++ by means of Rcpp to solve large ODE systems

I'm trying to speedup my R code performing some computationally expensive task with C++ and Rcpp. My problem involves approximately a system of 100 equations, so any hint to speed up the computation is welcome.
What I need is to import a matrix MX created in R into a C++ script. The C++ script have to use rows of MX as x0 (x initial values) in a systems of ODE.
To simplify the explanation of my problem, the code below is based on the Lorenz systems.
As it is clear from the quality of my code, I'm new to C++ (and Rcpp).
For clarity, I don't post all my test code that are terrible, bu I really need your help to try solve this problem.
Any help will be really, really appreciated!
Thanks in advance.
#include <boost/array.hpp>
#include <boost/numeric/odeint.hpp>
#include <Rcpp.h>
// [[Rcpp::depends(BH)]]
// [[Rcpp::plugins(cpp11)]]
using namespace std;
using namespace boost::numeric::odeint;
double theta [] = {10.000,28,2.5};
typedef boost::array< double , 3 > state_type;
void lorenz( const state_type &x , state_type &dxdt , double t ) {
dxdt[0] = theta[0] * ( x[1] - x[0] );
dxdt[1] = theta[1] * x[0] - x[1] - x[0] * x[2];
dxdt[2] = -theta[2] * x[2] + x[0] * x[1];
}
struct foo { std::vector<double> a, b, c; };
struct foo f;
//observer should be a function that append a single output row for each input row of mx corresponding to the last integration step.
void append_lorenz(const state_type &x , const double t ) {
f.a.push_back(x[0]);
f.b.push_back(x[1]);
f.c.push_back(x[2]);
}
using namespace Rcpp;
// [[Rcpp::export]]
DataFrame callMain(NumericMatrix mx){
int n = mx.nrow();
NumericMatrix total(mx);
for(int i = 0; i < n; ++i) {
// state_type x should be mx rows
state_type x = total.row(i); // initial conditions
const double dt =0.1;
integrate(lorenz , x , 0.0 , 1.0 , dt , append_lorenz );
}
return DataFrame::create(Named("a") = f.a, Named("b") = f.b, Named("c") = f.c);
}
/*** R
mx=matrix(1:9,3,3)
res <- callMain(mx)
print((res))
*/
the error I get is:
error: conversion from ‘Rcpp::Matrix<14>::Row {aka Rcpp::MatrixRow<14>}’ to non-scalar type ‘state_type {aka boost::array}’ requested
state_type x = total.row(i); // initial conditions
I think the error message is clear enough.
state_type x = total.row(i);
There is no conversion between Rcpp object and boost::array, you need to develop your own.