Compilation error in one dimensional integration in Rstan


#1

I was trying to do one dimensional integration in Rstan using external C++ code. I looked at the posts: 1D integration and integration-in-stan . I wrote the header file test.hpp as follows


When including Stan code in your post it really helps if you make it as readable as possible by using Stan code chunks (```stan) with clear spacing and indentation. For example, use

#ifndef test_hpp
#define test_hpp

#include <stan/math.hpp>
#include <vector>
#include <iostream>
#include <limits>
#include <sstream>


template <typename T0__, typename T1__,typename T2__>

typename boost::math::tools::promote_args<T0__, T1__,T2__>::type

integral_GK(const T0__& ll, const T1__& ul,const T2__& nu, std::ostream* pstream__) {
   auto f1 = [&](double x) {
        return std::exp(x);
    };
    double error;
    double ll_new=ll * nu;
    double ul_new=ul * nu;
    double Q = stan::math::integrate_1d(f1, ll_new, ul_new, {}, {}, {},&error)/nu;
    return Q;
}

And run the Stan code :


mc2="
functions { real integral_GK(real ll, real ul, real nu); }
model {} // use the integral_GK() function somehow
"

, it works fine!!! But when I have another code in the header file “test.hpp”:


template <typename T0__, typename T1__,typename T2__>
typename boost::math::tools::promote_args<T0__, T1__,T2__>::type
test1(const T0__& ll, const T1__& ul,const T2__& beta, const T2__& M0, std::ostream* pstream__) {

  auto f2 = [&](double x) {
        return std::exp(-beta*(x-M0));
    };
    
    std::vector<double> theta={beta,M0};
    double error;
    double ll_new=ll;
    double ul_new=ul;
    
    
    double Q = stan::math::integrate_1d(f2, ll_new, ul_new, theta, {},{}, &error);
    return Q;
}

    

and run the Stan code


test2="functions{
    
    real test1(  real lower, real upper, real beta,
                         real M0);
    
    real logL (int N, real[] m, real beta, real M0){
        
        real temp=0.0;
        for (i in 1:N){
            temp += beta*exp(-beta*(m[i]-M0));
        }
        return (temp);
    }
    
    
    }
data{
    int <lower=0> N;
    real<lower=0> m[N];
    real<lower=0> M0;
    real<lower=0> lower;
    real<lower=0> upper;
}

parameters{
    real<lower=0> beta;
}

model{
    
    //priors
    beta~exponential (1);
    
    //likelihood
    target +=logL(N,m,beta,M0) - test1( 
                                                 lower,  upper, beta, M0);
} 
"

, I get the following COMPILATION error:


In file included from file23582db6d7ac.cpp:91:
/Users/Lulu /Desktop/test.hpp:50:16: error: no matching function for call to 'integrate_1d'
    double Q = stan::math::integrate_1d(f2, ll_new, ul_new, theta, {},{}, &error);
               ^~~~~~~~~~~~~~~~~~~~~~~~

. Why is this happening? Any idea? Could anyone help me with this?


#2

There’s something that I find suspicious about this code:

auto f2 = [&](double x) {
        return std::exp(-beta*(x-M0));
    };
    
    std::vector<double> theta={beta,M0};

It looks to me like you may be expecting that the beta and M0 in the variable theta that you pass to stan::math::integrate_1d will be passed to f2, but that’s just not how C++ works. Inside the stan::math::integrate_1d function, theta is just a vector with a bunch of numbers in it; the variable names beta and M0 are not attached to those numbers. See https://mc-stan.org/math/d4/d84/namespacestan_1_1math.html#ad0325b6d2efb9873cb8a7383ffcb7359 for what the signature of f2 should look like.

Also, passing &error to stan::math::integrate is wrong. That argument is supposed to be a reference to a std::ostream object. If your C++ compiler didn’t catch that, it may be too lenient (perhaps because it’s too old?). That may also be why your use of f1 in your first test header appeared to work. You should probably replace &error with *pstream__.


#3

Hi @jjramsey; using the following templated function in the header file leads to the same error:


template <typename T0__, typename T1__,typename T2__,typename T3__>
typename boost::math::tools::promote_args<T0__, T1__, T2__, T3__>::type
test1(const T0__& ll, const T1__& ul,const T2__& beta, const T3__& M0, std::ostream* pstream__) {
    
  
    
    
    auto f2 = [&](double x, std::vector<double> theta) {
        return std::exp(- theta[0]*(x-theta[1]));
    };
    

   
    double ll_new=ll;
    double ul_new=ul;
    
    
    double Q = stan::math::integrate_1d(f2, ll_new, ul_new, {beta,M0}, {},{}, pstream__);
    return Q;
}

My question to you is that=

  1. I found from the Stan math library that the arguments for the integrate_1d function is as follows:

template <typename F>
 inline double integrate_1d(
      const F& f, const double a, const double b,
     const std::vector<double>& theta, const std::vector<double>& x_r,
      const std::vector<int>& x_i, std::ostream& msgs,
    const double tolerance
      = std::sqrt(std::numeric_limits<double>::epsilon()))

. What will be the substitute for "std::ostream& msgs " in my function?

  1. How would I create a vector of parameters then?

#4

That’s not surprising. Your new f2 still doesn’t have the signature that was specified in the stan::math::integrate_1d documentation. To quote the documentation:

The signature for f should be: double foo(double x, double xc, std::vector<double> theta, std::vector<double> x_r, std::vector<int> x_i, std::ostream& msgs)


#5

But when I use :



    double f2 (double& x, double& xc,  std::vector<double>& theta, std::vector<double>& x_r, std::vector<int>& x_i,  std::ostream& msgs) {
        return std::exp(- theta[0]*(x-theta[1]));
    };

I get the error along with the previous one:


no function definition is allowed here

. But if I use the code to define f2 as-



    auto f2= [&](double& x, double& xc,  std::vector<double>& theta, std::vector<double>& x_r, std::vector<int>& x_i,  std::ostream& msgs) {
        return std::exp(- theta[0]*(x-theta[1]));
    };

I get the error:


: error: no matching function for call to 'integrate_1d'

.
Another thing is that, whenever I use the “integrate_1d” function as-


 double Q = stan::math::integrate_1d(f2, ll_new, ul_new, {beta,M0}, {},{}, msgs)

I get the error:


undeclared identifier "msgs"


#6

msgs is the print stream for error messages.

What happens if you use

 double Q = stan::math::integrate_1d(f2, ll_new, ul_new, {beta,M0}, {},{}, std::ostream msgs)

or even

 double Q = stan::math::integrate_1d(f2, ll_new, ul_new, {beta,M0}, {},{}, NULL)

#7

Hi @increasechief, I tried both but gave me same error. However, if I use the following code in my header file; I get no compilation error but it shows error in loading object as Symbol not found. The code in the header file which shows NO COMPILATION error (but some warnings):


template <typename T0__, typename T1__,typename T2__>
typename boost::math::tools::promote_args<T0__, T1__, T2__>::type
test1(const T0__& ll, const T1__& ul,const T2__& beta, const T2__& M0, std::ostream& msgs) {
    
  
    
    
    auto f2= [&](double& x, double& xc,  std::vector<double>& theta, std::vector<double>& x_r, std::vector<int>& x_i,  std::ostream& msgs) {
        return std::exp(- theta[0]*(x-theta[1]));
    };
    

   
    double ll_new=ll;
    double ul_new=ul;
    double betan= beta;
    double M0n= M0;
    
    
    double Q = stan::math::integrate_1d(f2, ll_new, ul_new, {betan,M0n}, {},{}, msgs);
    return Q;
}

But the error is:


Error in dyn.load(libLFile) : 
  unable to load shared object '/var/folders/4w/v4pl36r9475cb2fkspc3qxkm0000gp/T//RtmpYMEu3o/file235821cc62f3.so':
  dlopen(/var/folders/4w/v4pl36r9475cb2fkspc3qxkm0000gp/T//RtmpYMEu3o/file235821cc62f3.so, 6): Symbol not found: __ZN36model23585cd2e591_external_namespace5test1IddN4stan4math3varEdEEN5boost4math5tools12promote_argsIT_T0_T1_T2_ffE4typeERKS8_RKS9_RKSA_RKSB_PNSt3__113basic_ostreamIcNSM_11char_traitsIcEEEE
  Referenced from: /var/folders/4w/v4pl36r9475cb2fkspc3qxkm0000gp/T//RtmpYMEu3o/file235821cc62f3.so
  Expected in: flat namespace
 in /var/folders/4w/v4pl36r9475cb2fkspc3qxkm0000gp/T//RtmpYMEu3o/file235821cc62f3.so


#8

I already told you to use *pstream__.

I’m not quite sure why that is. I would suggest, though, that in your definition for f2 that you replace double & x with double x, double & xc with double xc, and std::vector<double>& with const std::vector<double>&. Whether or not that would help isn’t clear to me, but it’s worth a shot.

Also, what do you know about C++? It doesn’t look like you’re familiar with it, and C++ can be a rather unforgiving and treacherous language even for those who are familiar with it.


#9

Hi, Using the corrections (*pstream__, double x, double xc, const std::vector) did not help me. I still get the same error. However, if you see my previous comment; if I use that code; I do not get any compilation error but I get error for loading object.


#10

Yes, here the function test1 passes the message stream.

For the rest of the error Google provided me with this: https://github.com/stan-dev/rstan/issues/448


#11

Hi @jjramsey; ignore my previous reply. I tried your code again, this time I did not get compilation error but I get this error:


Error in dyn.load(libLFile) : 
  unable to load shared object '/var/folders/4w/v4pl36r9475cb2fkspc3qxkm0000gp/T//RtmpYMEu3o/file2358332bd675.so':
  dlopen(/var/folders/4w/v4pl36r9475cb2fkspc3qxkm0000gp/T//RtmpYMEu3o/file2358332bd675.so, 6): Symbol not found: __ZN36model23586b9f9c36_external_namespace5test1IddN4stan4math3varEdEEN5boost4math5tools12promote_argsIT_T0_T1_T2_ffE4typeERKS8_RKS9_RKSA_RKSB_PNSt3__113basic_ostreamIcNSM_11char_traitsIcEEEE
  Referenced from: /var/folders/4w/v4pl36r9475cb2fkspc3qxkm0000gp/T//RtmpYMEu3o/file2358332bd675.so
  Expected in: flat namespace
 in /var/folders/4w/v4pl36r9475cb2fkspc3qxkm0000gp/T//RtmpYMEu3o/file2358332bd675.so

. Could you tell me how to resolve this?


#12

Hi, do you know how to unload older DLLs?


#13

https://www.rdocumentation.org/packages/base/versions/3.5.2/topics/library.dynam


#14

But in my case, the error message is: SYMBOL NOT FOUND. I do not understand which symbol did they not find. And how to resolve this


#15

It is telling you it cannot find a function specialization for

boost::math::tools::promote_args<double, double, stan::math::var, double, float, float>::type 
model*_namespace::test1<double, double, stan::math::var, double>(
double const&, double const&, stan::math::var const&, double const&, std::basic_ostream<char, std::char_traits<char> >*
)

I believe this is because you are returning a double for Q even though it should be of type stan::math::var if any of the arguments to the function is of type stan::math::var.

Perhaps more importantly why are you doing numerical integration of e^{-\theta_0 \left(x - \theta_1\right)}, which has an analytical solution?


#16

Just to test if I can really export external C++ function; before applying it on a much complicated model. So it’s a test case for me


#17

The integrate_1d function got merged into the Stan language today, so you might as well just install the development versions of stuff with

source("https://raw.githubusercontent.com/stan-dev/rstan/develop/StanHeaders/install-github.R", echo = TRUE)
remotes::install_github("stan-dev/rstan", ref = "develop", subdir = "rstan/rstan")

and then do like


1d integration in STAN language--timeline?
#18

I get

Error: package or namespace load failed for ‘rstan’ in dyn.load(file, DLLpath = DLLpath, ...):
 unable to load shared object '/u/77/ave/unix/R/x86_64-pc-linux-gnu-library/3.5/rstan/libs/rstan.so':
  /u/77/ave/unix/R/x86_64-pc-linux-gnu-library/3.5/rstan/libs/rstan.so: undefined symbol: _ZNK4stan4lang14local_var_type10array_lensEv
Error: loading failed
Execution halted

I’ve tried some other ways to install, too, but with the same error (or with _ZNK4stan4lang14base_expr_type11is_int_typeEv) and I haven’t been able to figure out how to fix this.


#19

Which compiler are you using?


#20

% g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
Copyright © 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.