stan-dev / stanc3

The Stan transpiler (from Stan to C++ and beyond).
BSD 3-Clause "New" or "Revised" License
139 stars 44 forks source link

[FR] Add `lower_upper` constrain #1438

Open andrjohns opened 1 month ago

andrjohns commented 1 month ago

With the merge of stan-dev/math#3087, the lub_* constrain and free functions now support a single tuple of bounds. It would be great to add the lower_upper bounds type so that both bounds can be specified in a single function call.

Example pseudo-stan:

functions {
  (vector, vector) make_bounds(...) { ... }
}

...

parameters {
  vector<lower_upper = make_bounds(...)> x;
}

This would be great for situations where parameter bounds depend on functions of other parameters, and there is some non-trivial computation shared by both bounds

WardBrian commented 1 month ago

I believe we still need signatures in the serializer/deserializer in the Stan repo, no?

andrjohns commented 1 month ago

I believe we still need signatures in the serializer/deserializer in the Stan repo, no?

Ah good point, will do now

andrjohns commented 1 month ago

@WardBrian having some troubles adding a single tuple overload for read_free_lub, since it results in an ambiguous signature where the first element of the Sizes... is treated as the upper bound.

Would it be safe to add a separate read_free_lub_tuple signature instead (same for write and constrain)?

WardBrian commented 1 month ago

Need to think about the implementation a bit. Might be worth starting in stanc3 and seeing which is more natural:

  1. The naming structure you suggest. The backend will need special logic to make sure this is called
  2. Just generating a temporary auto temp__ = lub; then calling the normal read_free_lub(sizes, get<0>(lub), get<1>(lub)) (this means the function just added to Stan-Math isn't necessary).

I think my preference would be number 1, but happy to discuss either.

andrjohns commented 1 month ago

No worries! I don't really have a preference either way, so I'm happy with whichever option would be easiest on the implementation side