How to use "integrate_1d"

Hi,

I would like to use the recently added “integrate_1d” function in stan (I am using Rstan and have only limited background in using C++). However, I have some trouble in understanding how to use this function. I would have expected something like

integrate_1d(f,a,b),

wherein a and b denote the limits of integration and wherein f denotes a
previously defined function. However, from the manual I gather the following:
"The integrate_1dfunction requires

  • its first argument to refer to a function wth signature(real, real, real[],real[], int[]) : real,
  • the remaining six arguments are assignable to types real,real,real[],real[],andint[], and
  • the fourth and fifth arguments must be expressions not containing any variablesnot originating in the data or transformed data blocks."

I do not understand this specification. What is the meaning of the arguments in the signature(real, real, real[],real[], int[])?

Perhaps a small toy example would settle my questions.
Thanks for your help!

See here: https://mc-stan.org/docs/2_19/reference-manual/argument-types-and-qualifiers.html

Thank you very much. But as far as I noticed, the manual speaks about matrices/arrays/int-variables. What I have difficulties with is not the formal type specification, but to know how the arguments in the signature relate to the concrete problem of implementing the integral of a function, e.g… which argument(s) represent the bounds of integration? Where and how do I reference the function which has to be integrated?

Ah, I see. A few minutes ago, I tried to find that information myself, but had no luck. It’s not even in the Stan Functions reference, which is where it should be.

It is given more detail in the Math library API mc-stan.org/math I just wasn’t sure if the information there necessarily helps @pasjor.

Unfortunately, the API documentation doesn’t help much. The catch is that the mapping of C++ arguments to Stan arguments is not one-to-one. Stan functions obviously do not have arguments of the std::ostream& type, and since the last argument in the Stan function integrate_1d is of type int[], it obviously does not correspond to the last argument in the C++ function integrate_1d, which is of type double.

1 Like

My thoughts exactly.

integrate_1d is a functional that behaves in the same was as integrate_ode and algebra_solver with the target functor defined in the functions block. Consequently you can follow the pattern for ordinary differential equations and algebraic systems that are well documented in the manual.

The basic structure for the algebraic solver, for example, is given by

functions {
  vector objective_function(vector y, vector theta, real[] x_r, int[] x_i) {
    // compute objective function and return output values
  }
}

transformed data {
  vector[1] y_guess;
  vector[1] theta;
  vector[1] y;
  real x_r[0];
  int x_i[0];

  y = algebra_solver(objective_function, y_guess, theta, x_r, x_i);
}

The biggest change you’ll have to make is the exact signature of the function defined in the functions block to match that required by the integrate_1d functional.

1 Like

Here’s the function signature of integrate_ode_rk45:

real[ , ] integrate_ode_rk45(function ode, real[] initial_state, real initial_time, real[] times, real[] theta, real[] x_r, int[] x_i)

Here’s the apparent function signature of integrate_1d:

real integrate_1d(function foo, real, real, real[], real[], int[])

Given how different these function signatures are, it is clear that integrate_1d does not behave like integrate_ode except in the broadest strokes.

Thank you all very much!

I will examine the integrate_ode function closer. This could solve my problem. However, as I also gather from some of the objections, the signature of the integrate_1d function is somewhat different. It was also helpful to look at the link with the underlying C++ code and documentation. However, I understand that there is still a difference from the C++ signature to the stan-signature. I hope that I can cope with the necessary translation from one language into the other.

I think example code of a small application of the integrate_1d function (e.g. computing the integral of 2*x+1 over the interval from -1 to +1) would be most helpful in gaining a quick understanding of the function.

For what it’s worth, in my personal opinion, if a function is poorly documented, that may be a sign that it isn’t ready for prime time. It certainly means that if something goes wrong when using the function, you will have more difficulty debugging.

1 Like

@jjramsey thanks, you’re right that integrate_1d() isn’t documented properly. I tried to find it in the functions reference and I couldn’t either. I’m not sure how it got into the language without documentation. That shouldn’t happen.

I just opened an issue on GitHub:

1 Like