Stan Integral Example

I copied an example from Stan’s user guide pdf, pages 177 and 178 (Stan User Guide).

functions{
  real normal_density(real x, // Function argument
                      real xc, // Complement of function argument
                               // on the domain (defined later)
                      real[] theta, // parameters
                      real[] x_r, // data (real)
                      int[] x_i){ // data (integer)
                      
  real mu = theta[1];
  real sigma = theta[2];
  return 1 / (sqrt(2 * pi()) * sigma) * exp(-0.5 * ((x - mu) / sigma)^2);
  }
}
data {
  int N;
  real y[N];
}
transformed data {
  real x_r[0];
  int x_i[0];
}
parameters {
  real mu;
  real<lower = 0.0> sigma;
  real left_limit;
}
model {
  mu ~ normal(0, 1);
  sigma ~ normal(0, 1);
  left_limit ~ normal(0, 1);
  target += normal_lpdf(y | mu, sigma);
  target += log(integrate_1d(normal_density,
                left_limit,
                positive_infinity(),
                { mu, sigma }, x_r, x_i));
}

I tried to run this example and I received an error

SYNTAX ERROR, MESSAGE(S) FROM PARSER:

variable "normal_density" does not exist.

Can anyone see why normal_density does not exist according to Stan?

The error message is not that helpful but

I tried adding in the relative tolerance, but the same error message is shown.

model {
  mu ~ normal(0, 1);
  sigma ~ normal(0, 1);
  left_limit ~ normal(0, 1);
  target += normal_lpdf(y | mu, sigma);
  target += log(integrate(normal_density,
                left_limit,
                positive_infinity(),
                { mu, sigma }, x_r, x_i, 
                sqrt(machine_precision())));
}

According to 1D Integrator, in order to use relative_tolerance as an argument, I need to use integrate\_1d, but Stan does not seem to like this function. I receive an error message when trying to use integrate\_1d

SYNTAX ERROR, MESSAGE(S) FROM PARSER:

variable "integrate" does not exist.

It is integrate_1d. The slash was a unnecessary \LaTeX-ism

Okay. But

model {
  mu ~ normal(0, 1);
  sigma ~ normal(0, 1);
  left_limit ~ normal(0, 1);
  target += normal_lpdf(y | mu, sigma);
  target += log(integrate(normal_density,
                left_limit,
                positive_infinity(),
                { mu, sigma }, x_r, x_i, 
                sqrt(machine_precision())));
}

Still gives an error.

Does target += log(integrate_1d(normal_density, ...?

Yes, that also gives the same error.

This parses for me

functions{
  real normal_density(real x, // Function argument
                      real xc, // Complement of function argument
                               // on the domain (defined later)
                      real[] theta, // parameters
                      real[] x_r, // data (real)
                      int[] x_i){ // data (integer)
                      
  real mu = theta[1];
  real sigma = theta[2];
  return 1 / (sqrt(2 * pi()) * sigma) * exp(-0.5 * ((x - mu) / sigma)^2);
  }
}
data {
  int N;
  real y[N];
}
transformed data {
  real x_r[0];
  int x_i[0];
}
parameters {
  real mu;
  real<lower = 0.0> sigma;
  real left_limit;
}
model {
  mu ~ normal(0, 1);
  sigma ~ normal(0, 1);
  left_limit ~ normal(0, 1);
  target += normal_lpdf(y | mu, sigma);
  target += log(integrate_1d(normal_density,
                left_limit,
                positive_infinity(),
                { mu, sigma }, x_r, x_i, 1e-8));
}
N = 100
y = rnorm(N, 0, 1)

stan_list = list(N=N, y=y)

library(rstan)
rstan_options(auto_write = TRUE)
options(mc.cores = parallel::detectCores())

int_model = stan("int.stan", data=stan_list, iter = 200, seed = 1, chains = 4)

I am running the code from RStudio with the Stan code saved in a file called int.stan. Does Stan need something in order to know what x_r and x_i are?

It is fine to define them as empty arrays in the transformed data block. I didn’t compile or run that code; I was just saying I didn’t get a parser error from it.

Okay. I will rewrite this “by hand”. I pasted the code from the Stan user guide and I may have accidentally copied something from the pdf that does not compile well in R.

Update: I just ran two Stan codes, both have a functions block defined. The scripts both use integrate_1d and both give an error message saying that the variable (which is actually a function, so Stan is confusing the function for a variable) does not exist. E.g.

SYNTAX ERROR, MESSAGE(S) FROM PARSER:

variable "normal_density" does not exist.
  error in 'modeldd88ab7bd6_example' at line 26, column 43
  -------------------------------------------------
    24:   left_limit ~ normal(0,1);
    25:   target+= normal_lpdf(y | mu, sigma);
    26:   target+= log(integrate_1d(normal_density, left_limit, positive_infinity(), {mu, sigma}, x_r, x_i, 1e-8));
                                                  ^
    27: }
  -------------------------------------------------

What is packageVersion("rstan") for you?

2.18.2.

I think you need to upgrade rstan.

Good spot. I will do that; and then confirm if the code works.

It works! Thank you! I accepted the solution.