Lemon Graph Library on R using Rcpp - r

I think that this answer is a bit complex because it involves several things.
I want to do high performance computations with R particularly with graphs (networks). As a R package igraph is very nice. But R is slow, so I want to code the computationally expensive routines in C++ (maybe in C). I take a look at the igraph C library and I found it a little messy to work with. I also look at the Boost Graph Library and I read about it that it is difficult to learn. So I eventually found Lemon Graph Library. It is in C++ and seems very nice to work with.
So I installed the Lemon Graph Library as recommended in the official page. Then using the Rcpp and inline packages I manage myself to run Lemon Graph C++ code from R. Here I write in detail what I had made. But basically I put this:
inc <- '
#include <lemon/list_graph.h>
using namespace lemon ;
'
src <- '
int xx = Rcpp::as<int>(x);
int res = xx + 1;
ListDigraph g;
ListDigraph::Node u = g.addNode();
ListDigraph::Node v = g.addNode();
ListDigraph::Arc a = g.addArc(u, v);
int i = countNodes(g);
int j = countArcs(g);
Rprintf("num nodes is %d , and num edges is %d \\n",i,j);
return Rcpp::wrap(res);
'
fun <- cxxfunction( signature(x="numeric"), body=src,include=inc, plugin="Rcpp")
in a myexample_inline.R file and then run a R console and write:
> library("inline")
> library("Rcpp")
> source("myexample_inline.R")
> fun(1)
num nodes is 2 , and num edges is 1
[1] 2
So it works !!! But now I have the following problem. If I make a C++ function (say double func1(g)) that for example calculates some property to some Lemon graph object. How I call that function from the inlined code? I must made func1() as a template function and put it in the include field of cxxfunction()?
Basically: I can't figure out how to call a C++ function inlined in R from another C++ function also inlined in R. Is it possible? Is there another way that do not uses inline code?
Maybe I can do it using Rcpp modules but I couldn't (still) figure out how to do this.
I'm having problems with making modules work. I will keep trying with this, but maybe I can get some kind of hint from here.
I also thought about the possibility to develop (my first) a package. But I had the problem that the Lemon Graph C++ code call the headers in this way (for example):
#include <iostream>
#include <lemon/list_graph.h>
So it means (at least I believe this) that I can not avoid the installation of the Lemon Graph Library. If I want to make a R package of the Lemon Graph Library I have to "rewrite" all the code again !!! So this is not my main option.
Best Regards

I have managed to success to this problem. Here you can find a detailed explanation about what I have done. Maybe, it is trivial to most of the people here, but it may be a good starting point for someone that is in the same position that I was. I will post a resume here of what I done.
First I installed the Lemon Graph (C++) Library (LGL). I just downloaded the LGL from its home page (from here). Then I proceed:
$ tar xvzf lemon-1.2.tar.gz
$ cd lemon-1.2
$ ./configure
$ make
$ make check # This is optional, but recommended. It runs a bunch of tests.
$ sudo make install
Then check if it works. So in a file named mycode.cc I put:
#include <iostream>
#include <lemon/list_graph.h>
using namespace lemon;
using namespace std;
int main()
{
ListDigraph g;
ListDigraph::Node u = g.addNode();
ListDigraph::Node v = g.addNode();
ListDigraph::Arc a = g.addArc(u, v);
cout << "Hello World! This is LEMON library here." << endl;
cout << "We have a directed graph with " << countNodes(g) << " nodes "
<< "and " << countArcs(g) << " arc." << endl;
return 0;
}
Then I compile and run it:
$ g++ -O2 mycode.cc -lemon
... BLA BLA BLA ...
$./a.out
Hello World! This is LEMON library here.
We have a directed graph with 2 nodes and 1 arc.
So it works. Now, the idea is to integrate that code into R via Rcpp. So in some directory I open a R console and I do:
> require("Rcpp")
Loading required package: Rcpp
> Rcpp.package.skeleton("pkgwithlgl")
Creating directories ...
Creating DESCRIPTION ...
Creating NAMESPACE ...
Creating Read-and-delete-me ...
Saving functions and data ...
Making help files ...
Done.
Further steps are described in './pkgwithlgl/Read-and-delete-me'.
Adding Rcpp settings
>> added Depends: Rcpp
>> added LinkingTo: Rcpp
>> added useDynLib directive to NAMESPACE
>> added Makevars file with Rcpp settings
>> added Makevars.win file with Rcpp settings
>> added example header file using Rcpp classes
>> added example src file using Rcpp classes
>> added example R file calling the C++ example
>> added Rd file for rcpp_hello_world
So, in this way I just created a new Rcpp based source package named pkgwithlgl. Now inside the pkgwithlgl directory (which is the source of the package that I want to modify and install) there is a directory named src. Inside it there are the files with the C++ code of the package. In particular there is one named *rcpp_hello_world.cpp* which contains:
#include "rcpp_hello_world.h"
SEXP rcpp_hello_world(){
using namespace Rcpp ;
CharacterVector x = CharacterVector::create( "foo", "bar" ) ;
NumericVector y = NumericVector::create( 0.0, 1.0 ) ;
List z = List::create( x, y ) ;
return z ;
}
Now, I modify it so it becomes:
#include "rcpp_hello_world.h"
#include <lemon/list_graph.h>
using namespace lemon ;
SEXP rcpp_hello_world(){
using namespace Rcpp ;
int res = 1;
ListDigraph g;
ListDigraph::Node u = g.addNode();
ListDigraph::Node v = g.addNode();
ListDigraph::Arc a = g.addArc(u, v);
int i = countNodes(g);
int j = countArcs(g);
Rprintf("num nodes is %d , and num edges is %d \n",i,j);
return wrap(res) ;
}
Then, from the linux console in the container directory of the source package I write:
$ R CMD INSTALL pkgwithlgl
which returns:
* installing to library ‘/home/juan/R/x86_64-pc-linux-gnu-library/2.12’
* installing *source* package ‘pkgwithlgl’ ...
** libs
g++ -I/usr/share/R/include -I"/usr/local/lib/R/site-library/Rcpp/include" -fpic -O3 -pipe -g -c rcpp_hello_world.cpp -o rcpp_hello_world.o
g++ -shared -o pkgwithlgl.so rcpp_hello_world.o -L/usr/local/lib/R/site-library/Rcpp/lib -lRcpp -Wl,-rpath,/usr/local/lib/R/site-library/Rcpp/lib -L/usr/lib64/R/lib -lR
installing to /home/juan/R/x86_64-pc-linux-gnu-library/2.12/pkgwithlgl/libs
** R
** preparing package for lazy loading
** help
Warning: /home/juan/Desktop/facu/investigacion_ensayos/Cosas_crudas/programming_coding/R-work- space/integrating_R_with_cpp_via_Rcpp/using_packages/pkgwithlgl/man/pkgwithlgl- package.Rd:32: All text must be in a section
Warning: /home/juan/Desktop/facu/investigacion_ensayos/Cosas_crudas/programming_coding/R-work- space/integrating_R_with_cpp_via_Rcpp/using_packages/pkgwithlgl/man/pkgwithlgl- package.Rd:33: All text must be in a section
*** installing help indices
converting help for package ‘pkgwithlgl’
finding HTML links ... done
pkgwithlgl-package html
rcpp_hello_world html
** building package indices ...
** testing if installed package can be loaded
* DONE (pkgwithlgl)
So the package is installed (the warnings has to do with the fact that I don't filled in the right way the .Rd file, ie, the files that contains the helps about the package). The I open a R console and write:
> require("pkgwithlgl")
Loading required package: pkgwithlgl
Loading required package: Rcpp
> rcpp_hello_world()
num nodes is 2 , and num edges is 1
[1] 1
so it works !!! That is all.
But hey !!! What happens if I build this package and upload it into (forexample) CRAN (I will not do it). If some one install this package from CRAN, will it work for him? Even if it does not install the LGL package?
Best Regards

Howdy, and thanks for your interest in Rcpp.
To bind calls between different library functions, you may want to look into building a package. There are now twenty packages using Rcpp as listed on the Rcpp page on CRAN so you have examples to copy from. At a first appromixation,. this is no different from writing a normal program and Rcpp simply helps you getting it to R.
If you have more questions, please feel free to bring them to the rcpp-devel list.

Related

Exporting C++ code from an R package with Rcpp::interfaces(r, cpp) throws error `PACKAGE_RcppExport_registerCCallable" not available for .Call()`

I'm trying to export C++ functions from my R package 'TreeTools' so they can be called from a different package. I've added the line
// [[Rcpp::interfaces(r, cpp)]]
to src/renumber_tree.cpp, per [https://dirk.eddelbuettel.com/code/rcpp/Rcpp-attributes.pdf / http://r-pkgs.had.co.nz/src.html] and when I compileAttributes() and document() the package, there are indicators that the export has been acknowledged:
Relevant header files are added to inst/includes;
#include "../inst/include/TreeTools.h" is added to the start of RcppExports.cpp
A function RcppExport SEXP _TreeTools_RcppExport_registerCCallable() is added to the end of RcppExports.cpp
Compliation nevertheless fails with
Error in .Call("_TreeTools_RcppExport_registerCCallable", PACKAGE = "TreeTools") :
"_TreeTools_RcppExport_registerCCallable" not available for .Call() for package "TreeTools"
Can anyone help me to debug this error?
Could it be related to the fact that I have a manually-generated PACKAGE-init.c file?
Thanks, Dirk, for pointing me in the right direction.
To TreeTools-init.C, I needed to add
extern SEXP _TreeTools_RcppExport_registerCCallable();
and
static const R_CallMethodDef callMethods[] = {
&_TreeTools_RcppExport_registerCCallable, 0},
{NULL, NULL, 0}
};
In RcppExports.R, I saw
# Register entry points for exported C++ functions
methods::setLoadAction(function(ns) {
.Call('_TreeTools_RcppExport_registerCCallable', PACKAGE = 'TreeTools')
})
Replacing the straight quotes around '_TreeTools_RcppExport_registerCCallable' with backticks, i.e.
`_TreeTools_RcppExport_registerCCallable`
allowed the package to load.
Of course, these are replaced with straight quotes whenever compileAttributes() is run, so this doesn't feel like a complete solution...

Rcpp functions undefined when used alongside Stan

I have an R package that uses Rcpp for some internal functions. These functions are not exported for the user to access directly (see minimally reproducible example in the rcpptest repository).
I am now attempting to add Stan code to the src/ directory to be compiled when the package is installed (reproducible example in the rcppstan repository). However, when I modify the package to work with Stan, I get the following error in R CMD CHECK:
#> ❯ checking R code for possible problems ... NOTE
#> meanC: no visible binding for global variable ‘_rcppstan_meanC’
#> Undefined global functions or variables:
#> _rcppstan_meanC
And indeed, when I try to call the R function that uses the meanC function, I get an error saying Error in meanC(x) : object '_rcppstan_meanC' not found.
From what I can tell, here is what is changing when I modify the package to work with rstan, and thus the likely cause.
When only using Rcpp, the following is in the src/RcppExports.cpp:
static const R_CallMethodDef CallEntries[] = {
{"_rcpptest_timesTwo", (DL_FUNC) &_rcpptest_timesTwo, 1},
{NULL, NULL, 0}
};
RcppExport void R_init_rcpptest(DllInfo *dll) {
R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
R_useDynamicSymbols(dll, FALSE);
}
When Stan is incorporated, that code is no longer generated in the src/RcppExports.cpp file. Instead, it appears that this is being handles by the src/init.cpp file created by the rstantools package. The relevant chunk from that file is here:
static const R_CallMethodDef CallEntries[] = {
{NULL, NULL, 0}
};
void attribute_visible R_init_rcppstan(DllInfo *dll) {
// next line is necessary to avoid a NOTE from R CMD check
R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
R_useDynamicSymbols(dll, TRUE); // necessary for .onLoad() to work
}
Why does the code in src/init.cpp make the Rcpp functions undefined? Conversely, is there a way to edit src/init.cpp so that the Stan models are able to compile and be accessed correctly, while still allowing the Rcpp functions to be defined?
The init.cpp takes of registering methods and Makevars inhibits compilation of the cpp files. With the following changes in Makevars (and Makevars.win) I got it to compile:
diff --git a/src/Makevars b/src/Makevars
index 7aedc5b..3ea312e 100644
--- a/src/Makevars
+++ b/src/Makevars
## -1,8 +1,9 ##
STANHEADERS_SRC = `"$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" --vanilla -e "cat(system.file('include', 'src', package = 'StanHeaders'))"`
PKG_CPPFLAGS = -I"../inst/include" -I"$(STANHEADERS_SRC)" -DBOOST_RESULT_OF_USE_TR1 -DBOOST_NO_DECLTYPE -DBOOST_DISABLE_ASSERTS -DEIGEN_NO_DEBUG -DBOOST_MATH_OVERFLOW_ERROR_POLICY=errno_on_error
-SOURCES = $(wildcard stan_files/*.stan)
-OBJECTS = $(SOURCES:.stan=.o) init.o
+CPP_SOURCES = $(wildcard *.cpp)
+STAN_SOURCES = $(wildcard stan_files/*.stan)
+OBJECTS = $(STAN_SOURCES:.stan=.o) $(CPP_SOURCES:.cpp=.o)
all: $(SHLIB)
#if test -e "/usr/bin/install_name_tool" && test -e "/usr/local/clang4/lib/libc++.1.dylib" && test -e "/usr/lib/libc++.1.dylib"; then /usr/bin/install_name_tool -change /usr/local/clang4/lib/libc++.1.dylib /usr/lib/libc++.1.dylib $(SHLIB); fi
After calling Rcpp::compileAttributes() the method registration was again present in RcppExports.cpp. When I tried R CMD INSTALL, I got an error from .onLoad(), c.f. https://github.com/stan-dev/rstanarm/issues/190. Using the workaround from there, i.e. R CMD INSTALL --preclean solved the issue first, but was not reliable. What solved the issue for me was to change
R_useDynamicSymbols(dll, FALSE);
into
R_useDynamicSymbols(dll, TRUE);
in RcppExports.cpp. That is of course problematic, since that file might be overwritten, in particular when RStudio/devtools is used. A rather hacky solution would be to add
RcppExports.o: patch
patch:
sed -i 's/R_useDynamicSymbols(dll, FALSE)/R_useDynamicSymbols(dll, TRUE)/' RcppExports.cpp
.phony: all clean patch
in the Makevars(.win). But in the end the problem seems to be that C++ code for Rcpp modules is generated during package installation in a subdirectory of src. Therefore Rcpp::compileAttributes() cannot include the corresponding methofs in the list of registered methods. I do not see a good solution for that.
Now the package builds, checks and installs with two NOTEs:
N checking installed package size
installed size is 7.8Mb
sub-directories of 1Mb or more:
libs 7.7Mb
N checking for GNU extensions in Makefiles
GNU make is a SystemRequirements.

Source build of Rquantlib fails

I'm building Rquantlib from source and I recently have been encountering this issue:
Error in .Call("RQuantLib_setEvaluationDate", PACKAGE = "RQuantLib", evalDate) :
"RQuantLib_setEvaluationDate" not available for .Call() for package "RQuantLib"
Error : unable to load R code in package ‘RQuantLib’
R version 3.2.3 (2015-12-10)
Rcpp version 0.12.4
I have checked and setEvaluationDate() is there with appropriate rcpp tags, so not sure what's changed. I have not edited the file. It seems to be an inline version, wheras the github version is an actual call:
My rcpp generated inlcude verion for the function:
inline bool setEvaluationDate(QuantLib::Date evalDate) {
typedef SEXP(*Ptr_setEvaluationDate)(SEXP);
static Ptr_setEvaluationDate p_setEvaluationDate = NULL;
}
From github:
bool setEvaluationDate(QuantLib::Date evalDate);
static SEXP RQuantLib_setEvaluationDate_try(SEXP evalDateSEXP) {
BEGIN_RCPP
Rcpp::RObject __result;
Rcpp::traits::input_parameter< QuantLib::Date >::type evalDate(evalDateSEXP);
__result = Rcpp::wrap(setEvaluationDate(evalDate));
return __result;
END_RCPP_RETURN_ERROR
}
You need to recompile all dependents of Rcpp after major upgrades.
Eg when we went from Ubuntu 15.04 to 15.10 which changed the compiler to g++-5 with its new ABI, ran this this script to rebuild everything from the local repo:
#!/usr/bin/env r
## installed packages
IP <- installed.packages()
## all local packages
AP <- available.packages(contrib.url(getOption("repos")[["local"]]))
## all packages known to us
allAP <- available.packages()
pkgs <- "Rcpp"
deps <- tools::package_dependencies(packages=pkgs, db=IP, reverse=TRUE)
## set of dependencies
alldeps <- unique(sort(do.call(c, deps)))
cat("Installing these:\n")
print(alldeps)
## this makes sense on Debian where no packages touch /usr/local
libloc <- Sys.getenv("LIBLOC", unset="/usr/local/lib/R/site-library")
install.packages(alldeps, lib=libloc)
It is similar when something in Rcpp changes, though we've been pretty good about not changing interfaces. But when in doubt, rebuild. Also re-run compileAttributes() if in doubt but little changed there.
Edit: I just (re-)installed without a glitch on two systems too.
Edit 2: It also works directly at the R prompt:
## what follows was one line in R and just broken up for display
R> cppFunction("bool mySetEvalDate(QuantLib::Date d) "
"{ QuantLib::Settings::instance().evaluationDate() = d;"
" return true; }", depends="RQuantLib")
R> mySetEvalDate( Sys.Date() )
[1] TRUE
R>
Now, if your intent was to call setEvaluationDate() from C++ then you need to look at the discussion about exporting to R and C++ in the Rcpp Attributes vignettes. The code in src/daycounter.cpp is meant for R.

Rcpp: Include header from package into cppFunction

I have a package that uses Rcpp. It has different C++ function defined int src/testr.h. Now at some point I need to generate Rcpp functions (using cppFunction or cxxfunction) that use things defined in src/testr.h. How can I do that?
I tried,
> cxxfunction(signature(x="list") includes = c('#include "testr.h"'), body=sprintf(template, name, name))
> Rcpp::cppFunction(depends = "testr", includes = c('#include "src/testr.h"'), sprintf(template, name, name))
But
file7086270f0da.cpp:7:10: fatal error: 'testr.h' file not found
#include "testr.h"
^
Quick suggestion:
Move the header to inst/include/testr.h;
This requires a src/Makevars entry such as PKG_CPPFLAGS = -I../inst/include to have the compilation look there.
Now with the package installed as, say, mypkg, you can add a depends="mypkg" and R will know to set a -I... for you.
We use the same trick all the time in e.g. BH and various Rcpp* packages.

Rcpp inline package error in compileCode

I have R installed along with these two packages Rcpp and inline. (I am doing a project that consists of speeding up a painfully slow program in R and I decided to use Rcpp)...I know I am doing something wrong...probably missing a step but i cannot figure it out. Props to Dirk if you're reading this! Thanks for Rcpp and the brand new inline package pdf but...it's still not running.
Please note that I'm a newbie. As stated before I cleaned out all other packages and only R is installed with Rcpp and inline (of course I have c++ installed as well).
library(Rcpp)
library(inline)
x<-as.numeric(1:10)
n<-as.integer(10)
code<-"
integer i
do 1 i=1, n(1)
1 x(i)=x(i)**3
"
cubefn<- cfunction(signature(n="integer",x="numeric"),code,convention=".Fortran")
ERROR(s) during compilation: source code errors or compiler configuration errors!
Program source:
1: #include <R.h>
2:
3:
4: extern "C" {
5: void filef2424e34d61 ( int * n, double * x );
6: }
7:
8: void filef2424e34d61 ( int * n, double * x ) {
9:
10: integer i
11: do 1 i=1, n(1)
12: 1 x(i)=x(i)**3
13:
14: }
Error in compileCode(f, code, language, verbose) :
Compilation ERROR, function(s)/method(s) not created!
In addition: Warning message:
running command 'C:/R/R-2.15.2/bin/x64/R CMD SHLIB filef2424e34d61.cpp 2> filef2424e34d61.cpp.err.txt' had status 1
If it is the construction of a package skeleton missing: i tried the simple rcpp_hello_world() example:
rcpp_hello_world <- function(){
.Call( "rcpp_hello_world", PACKAGE = "mypackage" )
}
Folder PATH listing for volume OS
Volume serial number is 769C-A616
C:.
The rest was a long list of odd symbols but what I could read was the name of c++ projects I have, I didn't include them as it would be too lengthy
rcpp_hello_world <-function(){
.Call("rcpp_hello_world",PACKAGE="mypackage")
}
rcpp_hello_world()
Error in .Call("rcpp_hello_world", PACKAGE = "mypackage") :
"rcpp_hello_world" not available for .Call() for package "mypackage"
Anything would help please, also I have linux installed as well so if that is a better option please do tell. I am open to anything right now, the slightest progress makes is a delight
Do you actually have a Fortran compiler installed?
If you don't, or you don't know, try your Linux box. R on Windows must be able to compile source packages if you want to build with Rcpp and inline. A good quick test is to try something like
R> myroot <- cppFunction('double myroot(double x) { return ::sqrt(x); }')
R> myroot(16)
[1] 4
R>
or equivalently via inline (where rcpp is a wrapper for the cxxfunction(..., plugin="Rcpp") call, you need the most recent inline package for that)
R> myroot2 <- rcpp(signature(xs="numeric"),
+ body='double x=as<double>(xs); return wrap(::sqrt(x));')
R> myroot2(16)
[1] 4
R>
If this does not work, read up on the R basics of installing Rtools for Windows etc. We have a few additional notes in the Rcpp FAQ as well.

Resources