This probably was discussed before but I can’t find anything. Does it make sense to allow undefined high order functions? Something like:
functions{
matrix foo(func bar, vector x);
matrix bar(vector x);
#include "foobar_impl.hpp" // let's assume we can include hpp
}
model {
vector b;
matrix a = foo(bar, b);
}
It implies we need to
- allow including hpp like what one can do in rstan
- allow new type “func”
I think doing this helps when someone wants to retrofit sophisticated c/c++ functions and use them in Stan.
3 Likes
I agree that better support for including external functions.
The support rstan offers is what I think we want to support everywhere with a more general approach.
CmdStan’s approach is much less useful and more or less not transfarable as shareing and including a C++ function (regardless if its a HOF or not) in different models is impossible without always touching the C++ code.
The related issues are support arbitrary data type in function block's function signatures · Issue #2572 · stan-dev/stan · GitHub and Including .hpp files and namespaces · Issue #712 · stan-dev/stanc3 · GitHub.
The stanc3 issue would have to be done first. The easiest solution would be that if the compiler sees #include ".../file.hpp"
it would simply paste that include to the generated code. This is what rstan does just on the already generated C++ code which works but inserting stuff in generated code is not something we want interfaces doing.
Then we can figure out how to support arbitrary C++ external functions.
Would this similarly allow functions to be defined with gradients?
In C++? Yes.
For gradients in written in Stan thats a different story that is also circling around.
1 Like
Thanks, I wasn’t aware of the 2nd thread. No surprise this has a bigger scope of package system. In that regard, perhaps we can do a better job than #include
. I like the option suggested in the thread that we can do
import FooPackage // equal to #include <FooPackage.hpp>
functions{
matrix FooPackage::foo(func bar, vector x);
matrix FooPackage::bar(vector x);
}
as it gives us chance to allow
import FooPackage // equal to #include <FooPackage.hpp>
import BarPackage // when we have package system ready, BarPackage would be a Stan package.
functions{
matrix FooPackage::foo(func bar, vector x); // we may not even need to declare foo or bar.
matrix BarPackage::bar(vector x);
}
Then the syntax would be consistent.
For that to work, first we have to go extra mile beyond rstan, to add keyword import
& ::
in stanc3.
EDIT: related conversion Helpful function repository , in particular Helpful function repository - #7 by bbbales2
1 Like
Cross-posting from github, to support namespace token ::
in Stan lang. At this point it’s intended to allow user to stick in a c++ function without declaring it in function block. For user’s c++ function used this way there comes no semantic checks.
Example:
data {
int<lower=0> N;
int<lower=0,upper=1> y[N];
}
parameters {
real<lower=0,upper=1> theta;
}
transformed parameters {
real a = 1;
real b = foo::bar::baz(a);
}
model {
theta ~ beta(b,1);
y ~ bernoulli(theta);
}
And in .hpp file foo::bar::baz
is literally transpiled into c++ style call
b = foo::bar::baz(a);
with user defined baz
namespace foo {
namespace bar {
template<typename T>
T baz(const T& x) {
//...
}
}
}
To try it, use GitHub - stan-dev/stanc3 at namespaced_fn branch and rebuilt stanc3.
1 Like