Var Context Return Types

28 views
Skip to first unread message

Michael Betancourt

unread,
Jun 25, 2015, 5:27:54 AM6/25/15
to stan...@googlegroups.com
In trying to refactor everything I’ve realized that the current var_context
implementation is awkward because it’s sort of in the middle of two
functionalities. On one hand you could imagine the var_context just
returning an unstructured array of values corresponding to a variable
name, and on the other you could imagine the var_context returning
a properly formatted type. For example, calling

Eigen::VectorXd v = context.get_vals_r(“vector_name”);

would be incredibly useful to the internal code.

But right now var_context does something in between. It returns
a set of unstructured values but does know something about its
structure which is partially validated (namely the dims). This then
requires that the client know what type to be expecting, which is
fine for the generator but not for user-facing code.

Is there a pattern that would allow us to implement dynamic return types?
I can imagine metaprograms that properly map a block of vector data
in the var_context into the appropriate output (instead of having a dims
vector we’d have a type class which would not only contain the dim
information but also the type information) but I don’t see how we could
get dynamic return types with a single function signature.

Or should the user have to specify the type for validation? i.e.

template <typename T>
T var_context::get_vars_r(std::string& name) {
if (! contains_r(name))
throw unknown variable exception;
if (! T == type(name) )
throw type mismatch exception;

return convert<T>(vals_r(name);
}

In this case, how could the types be checked for equality dynamically?

Allen B. Riddell

unread,
Jun 25, 2015, 7:29:53 AM6/25/15
to stan...@googlegroups.com
What about keeping the contract between the client interface (RStan,
PyStan, etc.) and Stan as simple as possible? Could one allow Stan to
pass error messages if something goes wrong? Perhaps we could just reuse
here whatever pattern we're going to use with error handling for the
sampler arguments?

(Why can't one use functions like `contains_r_only` to check types?)

Best,

-a

p.s. "client interface" is a reasonable generic term for RStan, PyStan,
etc., right?
> --
> You received this message because you are subscribed to the Google Groups "stan development mailing list" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to stan-dev+u...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Ben Goodrich

unread,
Jun 25, 2015, 5:20:30 PM6/25/15
to stan...@googlegroups.com, betan...@gmail.com
On Thursday, June 25, 2015 at 5:27:54 AM UTC-4, Michael Betancourt wrote:
Is there a pattern that would allow us to implement dynamic return types?
I can imagine metaprograms that properly map a block of vector data
in the var_context into the appropriate output (instead of having a dims
vector we’d have a type class which would not only contain the dim
information but also the type information) but I don’t see how we could
get dynamic return types with a single function signature.

Assuming C++11 in the future, we could store output in an Eigen::Tensor

http://eigen.tuxfamily.org/dox-devel/unsupported/classEigen_1_1Tensor.html#details

whose template parameter only requires the number of dimensions.

So, if the Eigen::Tensor in the var_context were set up with the correct dimensions and the function reading it knew how many dimensions to expect, then it could just extract it when necessary and query its .dimensions(). But if we are assuming C++11, then wouldn't

auto v = context.get_vals_r("vector_name");

work also?

Ben

Michael Betancourt

unread,
Jun 25, 2015, 5:35:44 PM6/25/15
to stan...@googlegroups.com
I don’t think auto will work here because the type isn’t static
but depends on the dynamics argument.  

Michael Betancourt

unread,
Jun 25, 2015, 5:38:17 PM6/25/15
to stan...@googlegroups.com

> What about keeping the contract between the client interface (RStan,
> PyStan, etc.) and Stan as simple as possible?

The contract will be pretty simple — the question is how much duplication
we require of the user or how much type information we utilize in the var
context.

> Could one allow Stan to
> pass error messages if something goes wrong? Perhaps we could just reuse
> here whatever pattern we're going to use with error handling for the
> sampler arguments?

Right now it’s all exceptions that get caught and turned into error messages
by the model class.

> (Why can't one use functions like `contains_r_only` to check types?)

That just checks reals vs ints. I’m thinking about checking vectors vs
matrices vs scalars.

> p.s. "client interface" is a reasonable generic term for RStan, PyStan,
> etc., right?

I think RStan etc are just referred to as “clients" of the Stan API.

Ben Goodrich

unread,
Jun 25, 2015, 5:57:25 PM6/25/15
to stan...@googlegroups.com, betan...@gmail.com
On Thursday, June 25, 2015 at 5:35:44 PM UTC-4, Michael Betancourt wrote:
I don’t think auto will work here because the type isn’t static
but depends on the dynamics argument.  

If context.get_vals_r("foo") were an Eigen::Tensor<double, D>, where D is known at compile time, regardless of that type of thing "foo" is in the .stan program, isn't that static enough for the compiler to infer?

Ben

Michael Betancourt

unread,
Jun 25, 2015, 6:14:01 PM6/25/15
to stan...@googlegroups.com
If D were known at compile time, sure.  But we read in data/inits/etc dynamically.

Ben Goodrich

unread,
Jun 25, 2015, 6:57:41 PM6/25/15
to stan...@googlegroups.com, betan...@gmail.com
On Thursday, June 25, 2015 at 6:14:01 PM UTC-4, Michael Betancourt wrote:
If D were known at compile time, sure.  But we read in data/inits/etc dynamically.

The values and the dimensions of the data, inits, samples, ... are dynamic but stanc could be capable of substituting a number for D (the number of dimensions) in the C++ code given the .stan program. So if the .stan program is

data {
 
int<lower=1> N;
 
int<lower=1> K;
 
...
}
parameters
{
  matrix
[N,K] theta;
}

and you need the initial values for theta or whatever the generated C++ code could read

Eigen::Tensor<double,2> theta_inits = var_context.inits("theta");

or I would think just auto if the compiler knows that var_context is holding an Eigen::Tensor<double,2>.

Ben

On Jun 25, 2015, at 10:57 PM, Ben Goodrich <goodri...@gmail.com> wrote:
On Thursday, June 25, 2015 at 5:35:44 PM UTC-4, Michael Betancourt wrote:
I don’t think auto will work here because the type isn’t static
but depends on the dynamics argument.  

If context.get_vals_r("foo") were an Eigen::Tensor<double, D>, where D is known at compile time, regardless of that type of thing "foo" is in the .stan program, isn't that static enough for the compiler to infer?

Ben

--
You received this message because you are subscribed to the Google Groups "stan development mailing list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to stan-dev+unsubscribe@googlegroups.com.

Bob Carpenter

unread,
Jun 25, 2015, 8:48:46 PM6/25/15
to stan...@googlegroups.com

> On Jun 25, 2015, at 5:20 PM, Ben Goodrich <goodri...@gmail.com> wrote:
>
> On Thursday, June 25, 2015 at 5:27:54 AM UTC-4, Michael Betancourt wrote:
> Is there a pattern that would allow us to implement dynamic return types?
> I can imagine metaprograms that properly map a block of vector data
> in the var_context into the appropriate output (instead of having a dims
> vector we’d have a type class which would not only contain the dim
> information but also the type information) but I don’t see how we could
> get dynamic return types with a single function signature.
>
> Assuming C++11 in the future, we could store output in an Eigen::Tensor

I don't think we can assume C++11. We have too many legacy compilers
and systems like R that won't work with C++11 yet, so we're
going to trash a whole bunch of users if we assume C++11 any
time soon (by which I mean in the next year or more).

We don't need Eigen tensors, though --- we can just use something
like Boost arrays if we really need more generality.

- Bob

Bob Carpenter

unread,
Jun 25, 2015, 8:48:51 PM6/25/15
to stan...@googlegroups.com
I'm all in favor of returning structured results for
all of our types.

No need for template polymorphism then.

- Bob
> --
> You received this message because you are subscribed to the Google Groups "stan development mailing list" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to stan-dev+u...@googlegroups.com.

Michael Betancourt

unread,
Jun 26, 2015, 3:59:19 AM6/26/15
to stan...@googlegroups.com
You mean like

vector_t var_context::get_vector_vals(“name”)?

Michael Betancourt

unread,
Jun 26, 2015, 8:16:10 AM6/26/15
to stan...@googlegroups.com
I think I have a pattern but it will take me a bit
to plumb through everything for a prototype.

On Jun 26, 2015, at 12:31 AM, Bob Carpenter <ca...@alias-i.com> wrote:

Allen B. Riddell

unread,
Jun 26, 2015, 9:10:53 AM6/26/15
to stan...@googlegroups.com
I agree it would be great to avoid templates wherever possible on the
client-facing code because it seems like supporting templates in C++
glue packages has proven hard in the past. For example, it was a very
late addition to Cython.

Bob Carpenter

unread,
Jun 26, 2015, 9:13:46 AM6/26/15
to stan...@googlegroups.com
Exactly. The trick is going to be specifying
arrays of things, like arrays of covariance matrices.
It'd be easy to move that functionality into the reader
where it belongs and out of the actual code generation.

I think I made some poor decisions in the first go-round in
factoring this code. But I have to admit I haven't thought
through all the ramifications of changing it.

- Bob

Bob Carpenter

unread,
Jun 26, 2015, 9:14:41 AM6/26/15
to stan...@googlegroups.com
I don't think this should need to be templated at all.
We just need to specify type + dimensions + array dimensions.
Or maybe we can just read the types and make reading an
array of them external?

- Bob
Reply all
Reply to author
Forward
0 new messages