# Source code for integrate_1d

Dear all,

to my great shame I have to admit that I couldn’t find the source code for the integrate_1d function in the stan-dev GitHub repo and I would be really glad if someone could point my to it or just paste it here.

I would like to understand what is going on under the hood, especially how the check for the relative tolerance is implemented, since I want to try out a different integration scheme (Adaptive Gauss Hermite, as taken from Rabe-Hesketh, Skrondal and Pickles (2005)) and want to compare results as equivalently as possible.

Thank you!

2 Likes
5 Likes

Thank you for the quick response, maybe someone can help me clarify one thing. After sifting through this and the boost doc (https://www.boost.org/doc/libs/1_75_0/libs/math/doc/html/math_toolkit/double_exponential.html) and, for example, this post by @bbbales2 (https://github.com/boostorg/math/issues/449), I have a hard time figuring out, what exactly the meaning of “L1” is. In the doc they say

Like the trapezoidal quadrature, the tanh-sinh quadrature produces an estimate of the L1 norm of the integral along with the requested integral. This is to establish a scale against which to measure the tolerance, and to provide an estimate of the condition number of the summation. This can be queried as follows:

But to be precise here, “the integral” is just a number, i.e. its L1-Norm is just its absolute value. Another meaning of “L1 norm” could be “the operator norm of the integration operator I induced by the L1 norm on the space of absolutely integrable functions”, i.e.

\displaystyle || I||_{\infty} = \sup_{f\neq0}\frac{|I(f)|}{||f||_{\infty}},

but this is useless here, since it does not depend on f. Lastly, they could mean the L1 norm of f itself, i.e. \int |f|, which I think is what is being calculated here, since in the boost code we find:

L1_I0 += (abs(yp) + abs(ym))*w; (granted, I don’t understand everything that’s going on before).

Now in the boost doc (https://www.boost.org/doc/libs/1_74_0/libs/math/doc/html/math_toolkit/double_exponential/de_levels.html), it says that we want to compare error*L1 > 0.01.

I understand that we need ||f||_{\infty} to get the condition number, which for integration is given by

\displaystyle\kappa(I(f))=(b-a)\frac{||f||_{\infty}}{|I(f)|},

but why is the error compared to the L1 norm of f and not just the absolute value of the last estimate, i.e. why do we want

\displaystyle |I_n(f) - I_{n+1}(f)| < \mathrm{tol} \cdot ||f||_{\infty} and not
\displaystyle |I_n(f) - I_{n+1}(f)| < \mathrm{tol} \cdot |I_n(f)|?

In my intuitive understanding, we want the change of the estimate, relative to its size, to be small enough (i.e. we don’t get much more information by refining the grid), so if we have a “big” function with ||f||_{\infty}>>0, the integral’s value could still change, but we already reached our exit condition.

1 Like

I think you meant to tag @bbbales2.

1 Like

Yes indeed, I’m sorry, I corrected it above.

Good question. I honestly don’t know the math, I just tried to follow the Boost recommendations.

I downloaded a couple of the references from here, but it wasn’t light reading. Maybe there’s an example integral or something that works better this way than another?

The page here says the Boost developer list can handle implementation questions: https://www.boost.org/doc/libs/1_75_0/libs/math/doc/html/math_toolkit/contact.html .

1 Like

Thank you, I will post on the mailing list. Now that I reread it, I think the phrase an estimate of the L1 norm of the integral is just a typo and should read integrand instead of integral, that would clear up the first confusion, anyway.

2 Likes