If you can propose new member functions for the C++ model class, that’d be a huge help.
I have only a cursory understanding of how the prob_grad
(i.e., Stan model) class works, but I can take a stab at suggesting a redesign that would serve this long-term goal.
Perhaps the generated parameters block be treated as something similar to the prob_grad
class, except instead of a log_prob
scalar-valued function it would return an vector<__T>
valued-vector containing the transformed parameters. Let’s call such a class the generated_params
class. Every Stan model with a generated model
block would have, as a member, an object of the type generated_params
class. Instead of defining generated values as double
types in the model, it would populate them using semantics similar to how the log_prob
reads from a context using readers and writers.
Specifically, just like log_prob
, the generated_params
class would have a method, say, generate_params
that would take as an argument the vector<T__>& params_r__
vector and read it with a stan::io::reader<T__>
object. Every generated parameter (i.e. parameters declared in the generated parameters
block) would be an attribute of the generated_params
class, just like parameters declared in the parameters
block are declared as parameters of the prob_grad
-derived class. constrained_param_names()
would be replaced with generated_param_names()
.
Very little would have to change in a prob_grad
class. Instead of calculating generated parameters inline, it would calculate them with a generated_params
class method. In order to avoid decoding the stan::io::var_context
twice, you could overload the generate_params()
method to take as an input either a pre-decoded Stan model or a vector vector<T__>& params_r__
. In either case, the generated_params
method would return a vector of generated parameters, whose entries would be enumerated by the generated_param_names()
method.
You could then drop a functor that wraps the generate_params()
function directly into stan::math::jacobian
and get exactly what you need to implement the high-level features I described above.
Note again that, for the full functionality, this would also require that either the unconstrained variables or the constraining functions be made available through the Stan model interface, which is basically the same as them being made available in C++ outside the reader
and writer
classes.
Does that make sense?
I’m assuming you don’t want the whole Jacobian matrix from unconstrained to constrained parameters.
Right, you generally only really want this for specific parameters. That’s why the ability to take the Jacobian of generated parameters, plus access to the constraining funcitons or unconstrained parameters, makes more sense.