Search code examples
integrationstanrstan

`integrate_1d` syntax and interactively debugging it


I am a first-time rstan/Stan user trying to set up a custom likelihood and integrate it using integrate_1d. Based on the documentation, I set up my integrand function as follows:

// internal function to integrate over z 
// integrate_1d is super picky: the argument types need to be real, real, 
    real[], real[], int[]
// e.g., cannot use vectors in place of real[] or int[]

real integrand( real x,  // the observed Z-stat; value at which to evaluate integral
              real xc,
              real[] theta,
              real[] x_r,
              int[] x_i ){

    // separate the parameters
    real zeta = theta[1];
    real eta = theta[2];
    real vi = theta[3];

    // significance indicator
    int signif; 
    signif = fabs(x) > 1.96;

    return( (1/eta) * (1 - signif) + signif ) * exp( normal_lpdf( x | zeta, sqrt(vi) ) );
  }

I am trying to test and debug this function because it ultimately causes errors in evaluating the log-likelihood when I run my model. To this end, I want to be able to run the function interactively, passing arguments of my own choosing. I am trying to use rstan's expose_stan_functions to do this:

code = "functions{

  real integrand( real x,  // the observed Z-stat
                  real xc,
                  real[] theta,
                  real[] x_r,
                  int[] x_i ){

    // separate the parameters
    real zeta = theta[1];
    real eta = theta[2];
    real vi = theta[3];

    // significance indicator
    int signif; 
    signif = fabs(x) > 1.96;

    return( (1/eta) * (1 - signif) + signif ) * exp( normal_lpdf( x | zeta, sqrt(vi) ) );
  }
}"

expose_stan_functions(stanc(model_code = code))

integrand(1, {1,1,1}, real[], int[], 1e-8)

integrate_1d( integrand, negative_infinity(), positive_infinity(), {1, 1, 1}, real[], int[], 1e-8 )

but the calls to integrand and integrate_1d each throw error

Error: unexpected ','

as if I am calling the functions with fundamentally incorrect syntax. (In the call to integrate_1d, I wasn't quite sure what to do about xc. I omitted it because the documentation (Section 9.3.2.4) seems to suggest it should be NaN for an indefinite integral.)

I also welcome completely different suggestions for interactively debugging integrand if expose_stan_functions is not the ideal way to go.


Solution

  • The integrate_1d function is a Stan / C++ function, so if you want to call it from R, you need to specify another function that calls it. In your case, you could do

    code = "functions{
    
      real integrand( real x,  // the observed Z-stat
                      real xc,
                      real[] theta,
                      real[] x_r,
                      int[] x_i ){
    
        // separate the parameters
        real zeta = theta[1];
        real eta = theta[2];
        real vi = theta[3];
    
        // significance indicator
        int signif; 
        signif = fabs(x) > 1.96;
    
        return( (1/eta) * (1 - signif) + signif ) * exp( normal_lpdf( x | zeta, sqrt(vi) ) );
      }
    
      real area(real[] theta, data real[] x_r) {
        int x_i[0];
        return integrate_1d(integrand, negative_infinity(), positive_infinity(),
                            theta, x_r, x_i, 1e-8);
      }
    }"
    
    library(rstan)
    expose_stan_functions(stanc(model_code = code))
    area(theta = rep(1, 3), x_r = double()) # yields 1