Allow undefined high order function

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