# Would numerical approximation of log-likelihood prevent the autodifferentiation of Stan from working?

A term in my log-likelihood can only be numerically approximated. To approximate this term, Brent’s root-finding method (which corresponds to function `uniroot` in base R) needs to be used. Since the Stan Math library does not have the counterpart of `uniroot`, I am planning to use an external C++ function that is not in the Stan Math library to perform the root-finding step.

My questions are :

a. Would numerical approximation of the term using a root-finding method prevent the autodifferentiation of Stan from working?

b. How should I import the external C++ function that is not in the Stan Math library? Do I simply follow the steps in interfacing with external C++ code (https://cran.r-project.org/web/packages/rstan/vignettes/external.html)?

Thank you!

1 Like

Numerical methods are fine, but the root is an implicit function. So, you have to use the implicit function theorem to get the correct derivatives with respect to the unknown parameters. I would start with `algebraic_solver` in Stan before trying to use `toms_748` from Boost, but if you were to use `toms_748`, it would be like in that vignette.

3 Likes

Thank you for your prompt response. I used `algebra_solver` as you suggested to define the following function to compute one term in my log likelihood function. Unfortunately, I ran into a parser error that says PARSER EXPECTED: “,”. I understand it is caused by not passing function arguments x_r and x_i, so I attempted to add line a and b (see the commented code below) and pass x_r and x_i to the function (see line c). Then the parser says “fourth argument to algebra_solver must be data only (cannot reference parameters).have to be data (not parameters)." In my case, data is not necessary to solve the equation. I am not sure how to handle this?

Below is the relevant code:

``````real cal_some_term(vector gam, vector lam) {
real res;
int p = num_elements(gam);
vector[p] lam2 = lam;
// line a: real x_r;
// line b:  int x_i;
// some other code
vector[2*p] theta;
vector guess;
theta = append_row(gam, lam2);
guess = (low + up) / 2.0;
tau = algebra_solver(system, guess, theta);
// line c: tau = algebra_solver(system, guess, theta, x_r, x_i);
// code to calculate res as a function of tau
return res;
}
``````

Thank you!

You need to specify `x_r` and `x_i` even if they are of size zero and not used by your `system` function. Nevertheless, the `system` function must accept those two arguments.

1 Like

So is it sufficient to put `x_r` and `x_i` as dummy data in the data section? e.g.

``````data {
int<lower=0> N;
int<lower=0> K;
vector[K] y[N];
real x_r;
int x_i;
}
``````

and pass any value to `x_r` and `x_i`.

Almost – you just need to move the empty arrays into the `transformed data` block,

``````data {
...
}

transformed data {
real x_r;
int x_i;
}

parameters {
...
}
``````
2 Likes