Passing Argument with higher-order function

This is a bug on Torsten.

I exposed higher-order functions, following closely what was done with integrate_ode_*. These functions act as wrappers around numerical ODE integrators to handle the event schedule of clinical trials. The code can be found at https://github.com/charlesm93/math/tree/torsten-develop and at https://github.com/charlesm93/stan/tree/torsten-develop.

The functions, generalOdeModel_*, take in the relative and absolute tolerances, and the max number of steps, but these get ignored. Instead the default values, specified in the function, get passed. I noticed this because of an error message which stated the max number of steps, 1E8, had been exceeded, when I had set max_num_steps = 10E6.

I confirmed this issue occurred for all the tuning parameters, but none of the other arguments, by adding std::cout statements in the integrate_ode_rk45 function.

If I run the unit tests on math, the function works fine and the tuning parameters specified by the users get passed. This leads me to think there is an error in the changes I made to the grammar files.

I look at the hpp file produced by the parser and the translation looks right. I get:

stan::math::assign(x, generalOdeModel_rk45(twoCptModelODE_functor__(), 3,
time, amt, rate, ii, evid, cmt, addl, ss, theta, biovar, tlag,
0.0001, 9.9999999999999995e-07, 1000000.0));

These are the arguments I specified. (although, I used 1e-06 for abs tol not 9.99e-07). Maybe something is off with stan::math::assign? No, the C++ unit tests work fine with stan::math::assign.

I removed the default values but then compilation of the model doesn’t occur - no error, the compiler just keeps running and never stops (I let it run in the background for 30+ minutes).

I’m trying to think about where things could have gone wrong. Any guidance would be welcome. I also want to design a unit test in Stan to catch these kinds of errors.

Sorry—missed this because I didn’t realize that new topics didn’t count as unread in my buffer.

Is there something like a pull request where I can look at the diffs?

Hi Bob,

This is the pull request: https://github.com/charlesm93/stan/pull/4.

Unfortunately, I updated the Stan version I used for Torsten (a dev version posterior to 2.12) to 2.14 and updated torsten’s higher-order functions accordingly in one commit. So the diff is very long, and does not focus on torsten’s higher-order functions.

A solution would be to look at the differences between the grammar files in Stan’s release version (2.14) and Torsten’s grammar files.

Hi Bob,

I created a dummy pull request (and closed it) to show the differences between the grammar files in Stan 2.14 and Stan 2.14 augmented with Torsten 0.82. Hope this helps!

@Bob_Carpenter Per our discussion at last Thursday’s meeting, I put together some code to expose the bug. It’s a bit of a hack but it works.

You can download Stan + Torsten using the bash script setupTorsten-dev on the issue-1-ode-tuning branch: https://github.com/charlesm93/example-models/tree/issue-1-ode-tuning/PKPD/torsten

Under the math directory (cmdStan/stan_2.14.0/lib/stan_math_2.14.0/) you can run a unit test:
./runTests.py test/unit/math/torsten/generalOdeModel_test.cpp. I edited integrate_ode_rk45.hpp so that it prints the tuning parameters. The expected value should be 1e-8 for the relative and absolute tolerances, and 1e+8 for the max number of steps, which is what you get with this unit test.

More interestingly, here’s the stan code that causes the bug (doing everything in C++ doesn’t cause the error): https://github.com/charlesm93/example-models/tree/issue-1-ode-tuning/PKPD/torsten/GenTwoCptModel

I’d think this would be best managed on the issue tracker for Torsten.

Is there a way to just set up a branch where I clone Torsten, checkout the branch, and run a unit test? Or do I need to be running bash scripts and looking at output visually?

It looks like you’re forking Stan for Torsten if you’re modifying the grammars. Is this something you think will go into Stan itself at some point? I’m just worried about code bases diverging.

There is an issue on Torsten: Tuning Parameters don't get passed for ODE integrator · Issue #6 · charlesm93/stan · GitHub

Is there a way to just set up a branch where I clone Torsten, checkout the branch, and run a unit test? Or do I need to be running bash scripts and looking at output visually?

I could add an EXPECT_EQ statement inside integrate_ode_* that verifies the tuning parameters are the ones specified by the user in the Stan model. This is far from ideal, because the expected value would be predefined and the user would have to pass that expected value in the Stan model. Plus, we can’t keep an EXPECT_EQ statement inside a Stan function. I also need to edit the makefile when the Stan model gets compiled to include the gtest library. Using a print statement was more straightforward.

It looks like you’re forking Stan for Torsten if you’re modifying the grammars. Is this something you think will go into Stan itself at some point? I’m just worried about code bases diverging.

I don’t expect this will go into Stan itself. The generalOdeModel_* functions are too specialized and pharma specific. Since we haven’t gotten a mechanism for adding a C++ extension (with higher-order functions) in place, this is the best alternative I came up with.

I think I found a fix. See https://github.com/charlesm93/math/pull/27.