[Rcpp-devel] Named vectors
Andrew Redd
amredd at gmail.com
Thu Sep 9 22:05:10 CEST 2010
Thank you all for the comments. They are very helpful as I'm just
trying to get on board with Rcpp.
My next problem with this is compiling and linking to the library in
the package pomp. I'll include the whole file here and hope that it
does not offend anyone for being too big.
----------
library("inline")
library("Rcpp")
library("pomp")
registerPlugin(name="pomp",function(){
Rcpp<-getPlugin("Rcpp")
modifyList(Rcpp,list(
LinkingTo=c('pomp',"Rcpp"),
includes=paste(Rcpp$includes,"#include <pomp.h>",'\n'),
Depends = c("pomp","Rcpp"),
Makvars = 'PKG_LIBS = $(shell
"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e "Rcpp:::LdFlags()")
$(shell "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e
"tools:::file_path_as_absolute(base:::system.file("lib/pomp.so",package="pomp"))")',
Makvars.Win = 'PKG_LIBS = $(shell
"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e "Rcpp:::LdFlags()")
$(shell "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e
"tools:::file_path_as_absolute(base:::system.file("libs/pomp.dll",package="pomp"))")',
env=modifyList(Rcpp$env,list(PKG_LIBS = paste(Rcpp$env$PKG_LIBS,
paste("-lpomp -L",tools:::file_path_as_absolute(base:::system.file("libs",package="pomp")),sep=''))))
))
})
CppColonized<-cxxfunction(
sig=signature(x="numeric", t="numeric", params="numeric", dt="numeric"),
plugin='pomp',includes = sprintf("#include <Rmath.h>\n#include
<math.h>\n#include\"%s\"",tools:::file_path_as_absolute(base:::system.file("include/pomp.h",package="pomp"))),
body='
GetRNGstate();
enum Xind{C, S}; // X indices
Rcpp::NumericVector X(x);
double T = REAL(t)[1];
Rcpp::List P(params);
Rcpp::NumericVector D(dt);
Rcpp::Environment global = Rcpp::Environment::global_env();
Rcpp::NumericVector Admissions = global[\"Admissions\"];
Rcpp::NumericVector Discharge = global[\"Discharge\"];
int N = X[C] + X[S];
double mu = P["mu"];
double trans=0;
double rate = 1/(1+exp(-mu))*X[C]/N;
reulermultinom(1 , X[S], &rate, D[0], &trans);
double nu = P["nu"];
double import = Rf_rbinom(Admissions[T+1], 1/(1+exp( -nu)));
double ColDis = floor(X[C]*Discharge[T+1]/N);
std::map<std::string,double> updated;
updated["C"] = X[C] + trans + import - ColDis;
updated["S"] = X[S] - trans + Admissions[T+1] - import -
Discharge[T+1] + ColDis;
PutRNGstate();
return wrap(updated);
',verbose=T)
Admissions = rpois(1,10000)
Discharge = rpois(1,10000)
params=c(mu=log(0.02/0.98), nu=log(0.04/0.96), p=0, S.0=18000, C.0=1500)
CppColonized(x=c(C=100,S=1000),t=1,params,dt=1)
-----------
When I run this command I get the error that
undefined reference to `reulermultinom(int, double, double*,
double, double*)
But it should is defined in the pomp.dll. The compiling commands look
as if they should work.
g++ -I"C:/PROGRA~1/R/R-211~1.1/include"
-I"C:/PROGRA~1/R/R-211~1.1/library/pomp/include"
-I"C:/PROGRA~1/R/R-211~1.1/library/Rcpp/include" -O2 -Wall -c
file678418be.cpp -o file678418be.o
g++ -shared -s -static-libgcc -o file678418be.dll tmp.def
file678418be.o C:/PROGRA~1/R/R-211~1.1/library/Rcpp/lib/libRcpp.a
-lpomp -LC:/PROGRA~1/R/R-211~1.1/library/pomp/libs
-LC:/PROGRA~1/R/R-211~1.1/bin -lR
I hope that by including the whole code it will be obvious to someone
what my problem is.
Thanks again,
Andrew
On Thu, Sep 9, 2010 at 12:20 PM, Romain Francois
<romain at r-enthusiasts.com> wrote:
> Le 09/09/10 18:09, Dirk Eddelbuettel a écrit :
>>
>> On 9 September 2010 at 08:52, Andrew Redd wrote:
>> | What is the appropriate way to use/convert named vectors in C++ with
>> | Rcpp. Basically I have a named vector of parameters that pass into
>> | the function. I cannot be certain of their order, so would like to
>> | extract them by name. For those initialized in C++ a
>> | std:map<std::string, double> should work, but how do declare one from
>> | a SEXP pointer that is passed in? For example:
>> |
>> | draw<- cxxfunction(signature(A="numeric",t="numeric",
>> params="numeric"),body="
>> | SEXP draw( SEXP A, SEXP t, SEXP params){
>> | Rcpp::NumericVector Admissions(A);
>> | Rcpp::NumericVector T(t);
>> | std::map<std::string, double> Params(params);
>> | std::vector<double> draws;
>> | for(int i=0;i<params[\"n\"];i++){
>> |
>> draws.pushback(rbinom(Admissions[T[i]+1,2], 1/(1+exp(-params[\"nu\"])))));
>> | }
>> | return wrap(draws);
>> | }
>> | ",plugin='Rcpp')
>> | This of course does not compile because of std::map<std::string,
>> | double> Params(params); is not valid. But is shows more of less what
>> | I'm trying to do.
>>
>> There were numerous other errors I fixed:
>>
>> 1) Do not add a function header as inline does that for you.
>>
>> 2) Do not add a final } either.
>>
>> 3) Your Params can be passed to a list as I showed.
>>
>> 4) I do not understand what Admissions[T[i]+1,2] could possible do for a
>> NumericVector Admissions. Did you mean a matrix? Changed to vector.
>>
>> 5) rbinom is now defined in SVN (wait for 0.8.6 "soon"). I presume you
>> meant
>> the function from R itself returning a double so I changed that with
>> explicit prefixes.
>>
>> So this now builds for me:
>>
>>
>>
>>> draw<- cxxfunction(signature(A="numeric",t="numeric",
>>> params="numeric"),body="
>>
>> + Rcpp::NumericVector Admissions(A);
>> + Rcpp::NumericVector T(t);
>> + Rcpp::List Params(params);
>> + int len = Rcpp::as<int>(Params[\"n\"]);
>> + Rcpp::NumericVector draws(len);
>> + for(int i=0; i<len; i++){
>> + draws[i] = ::Rf_rbinom(Admissions[T[i]],
>> 1/(1+exp(-Rcpp::as<double>(Params[\"nu\"]))));
>> + }
>> + return draws;
>> + ",plugin='Rcpp')
>>>
>>
>> We don;t need the Rcpp:: prefixes but I like'em too.
>
> Same with Rcpp::NumericVector instead of Rcpp::List, which spares one call
> to "as.list".
>
> Also : 'x[i,j]' is not legal C++ code. So if Admissions really is a matrix,
> you could use the "(" instead of "[" :
>
> Admissions( T[i+1], 2 )
>
> but given you always use the second column, maybe something like this would
> work for you:
>
> draw <- cxxfunction(signature(A="numeric",t="numeric",
> params="numeric"),body='
> NumericMatrix Admissions(A);
> NumericMatrix::Column col2 = Admissions.column(2) ;
>
> NumericVector T(t);
> NumericVector Params(params);
> int n = static_cast<int>( Params["n"] ) ;
> NumericVector draws( n ) ;
> double nu = Params["nu"] ;
> for(int i=0;i<n;i++){
> draws[i] = ::Rf_rbinom( col2[i], 1/(1+exp(-nu)) ) ;
> }
> return draws;
> ',plugin='Rcpp')
>
> Perhaps also taking ' 1/(1+exp(-nu)) ' out of the loop since it does not
> change.
>
> Romain
>
>> From your next mail:
>>
>> On 9 September 2010 at 09:43, Andrew Redd wrote:
>> | That is good to know, and if it were up to me I would be using lists
>> | or environments. Unfortunately, I'm working with writing compiled code
>> | for use with the pomp package that has the constraint that model
>> | parameters are only passed on as a named numeric vector. So a way to
>> | convert the named vector into an equivalent structure would be
>> | helpful.
>>
>> a) I'd write a quick utility function to convert.
>>
>> b) You could try as.list() as well.
>>
>>
>> Hth, Dirk
>>
>>
>>
>
>
> --
> Romain Francois
> Professional R Enthusiast
> +33(0) 6 28 91 30 30
> http://romainfrancois.blog.free.fr
> |- http://bit.ly/bzoWrs : Rcpp svn revision 2000
> |- http://bit.ly/b8VNE2 : Rcpp at LondonR, oct 5th
> `- http://bit.ly/aAyra4 : highlight 0.2-2
>
>
>
More information about the Rcpp-devel
mailing list