Compilation error in one dimensional integration in Rstan

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?

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__.

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?

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)

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"

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)

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

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.

1 Like

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.

Yes, here the function test1 passes the message stream.

For the rest of the error Google provided me with this: Error in dyn.load(libLFile): unable to load shared object Ā· Issue #448 Ā· stan-dev/rstan Ā· GitHub

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?

Hi, do you know how to unload older DLLs?

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

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

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?

2 Likes

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

1 Like

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

2 Likes

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.

Which compiler are you using?

% 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.