In brief, I’m trying to write a custom c++ function that takes a vector of reals and returns an array of counts given some parameters for data binning (start, end, bin-width). I’m new to c++ and to Stan and will be using rstan to implement various models that will make use of this counting function. In part, I’m also just using this task as a way to learn rstan/Stan/c++ and build experience designing highly customized Stan models. I’m now encountering a parsing error that I can’t figure out and I would appreciate some help (and any suggestions for improvements on any of the code below).
To begin, the error. In an R session I’m calling a script (see below) that builds a Stan model in order to simply test a custom c++ function (also below). The R code is stored in “count2stan.R”, and the c++ function definition is in “stancount.cpp”. When called, the R script produces the following error:
source(“./count2stan.R”)
SYNTAX ERROR, MESSAGE(S) FROM PARSER:
error in ‘model10333a7f6ac4fb_counting’ at line 3, column 4
1:
2: functions {
3: array[] int count( vector somereals,
^
4: real minimum,
PARSER EXPECTED: “}”
Error in stanc(file = file, model_code = model_code, model_name = model_name, :
failed to parse Stan model ‘counting’ due to the above error.
Now the relevant code (though, see attached for files so you don’t have to copy-n-paste).
count2stan.R (1.1 KB)
stancount.cpp (722 Bytes)
R script:
library(rstan)
model_code <-
'
functions {
array[] int count( vector somereals,
real minimum,
real maximum,
real delta );
}
data {
int N;
int Nbins;
vector[N] somereals;
real minimum;
real maximum;
real delta;
}
model {}
generated quantities {
int y[Nbins] = count(somereals, minimum, maximum, delta);
}
'
somereals = c(1, 2, 3.5, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14.99, 15.7, 16, 17, 24, 26)
N = length(somereals)
minimum = 5
maximum = 25
delta = 5
Nbins = floor((maximum - minimum) / delta)
mydata <- list(
somereals = somereals,
N = N,
minimum = minimum,
maximum = maximum,
delta = delta,
Nbins = Nbins
)
stancount = stan_model(model_code = model_code,
model_name = "counting",
allow_undefined = TRUE,
includes = paste0('\n#include "',
file.path(getwd(), 'stancount.cpp'),
'"\n'))
fit <- sampling(stancount, data = mydata)
#try(readLines(stanc(model_code=model_code, allow_undefined=T)$cppcode))
And CPP:
#include <stan/math.hpp>
Eigen::Matrix<typename boost::math::tools::promote_args<T0__, T1__, T2__, T3__>::type, Eigen::Dynamic, 1>
count(const Eigen::Matrix<T0__, Eigen::Dynamic, 1>& invec,
const T1__& minimum,
const T2__& maximum,
const T3__& delta, std::ostream* pstream__)
{
int invec_size = invec.size();
int cntvec_size = floor((maximum - minimum) / delta);
Eigen::VectorXi cntvec(cntvec_size) = Eigen::VectorXi::Zero(); //vector<int> cntvec(cntvec_size, 0);
for(int i=0; i<invec_size; i++){
if(invec[i] >= minimum && invec[i] < maximum){
int idx = floor((invec[i] - minimum) / delta);
cntvec[idx]++;
}
}
return cntvec;
}
The parser accepts the Stan function declaration if I use “vector” or “int” as the return type, but throws the aforementioned error when using “array int”. With “vector” as the return type, I was able to call the following in order to see the c++ code generated and try to match my custom function signature to Stan’s c++ code,
try(readLines(stanc(model_code=model_code, allow_undefined=T)$cppcode))
I got this from “Interfacing with External C++ Code • rstan” and have been trying to follow that guide.
Any help here would be greatly appreciated!
Operating System: Ubuntu 20.04
Interface Version: latest rstan
Compiler/Toolkit: gcc
Sincerely,
Chris