refactor coupled_ode_system to use ode_system

53 views
Skip to first unread message

Sebastian Weber

unread,
Aug 4, 2016, 4:25:01 PM8/4/16
to stan development mailing list
Hi!

I intend to refactor the current coupled ode system object. For one reason I would like to align ODE codes (rk45 and bdf) and for two I would like to route execution through the ode_system object. The reason to do so is that we can plug into the system analytic Jacobians of the ODE wrt to states and parameters using partial template specialization's.

To illustrate what I mean, I prepared a "test" which has the sole purpose to show the execution time for the two cases (with AD and without AD):

https://github.com/stan-dev/math/blob/feature/issue-310-coupled_ode_system-refactor-only/test/unit/math/rev/mat/functor/integrate_ode_rk45_noAD_test.cpp

The speed gain for the specific case is close to 2x. This always depends on the ODE system, parameters, etc.. the speed gain will be larger for stiffer systems and for ODE systems with many states (this is my personal guess; the cases with many Jacobian evaluations). Applying this during model inference gave me 2-3x speedups.

Supplying the analytic Jacobians won't be something regular users will, rather only advanced users. Making this user friendly is a different topic (I can share some R codes which help already a lot).

I hold on for the moment with a pull request until the design is settled.

Best,
Sebastian

Daniel Lee

unread,
Aug 5, 2016, 9:42:15 AM8/5/16
to stan-dev mailing list
Hi Sebastian,

I think I see what's going on. Let me try to get everyone on board.

These are the three relevant files to look at:
  • oral_2cmt.hpp 
    The functor defined here is very close to what would be translated from Stan to C++.
  • ode_system.hpp
    The first functor is passed into this class, ode_system, to calculate Jacobians. Jacobians are required by CVODES. ode_system takes the functor and uses automatic differentiation to compute Jacobians. 
  • oral_2cmt_jacobian.hpp
    This is a template specialization of the second file, ode_system, but for the oral_2cmt functor. Here, the Jacobians are known analytically so they're computed using doubles and without automatic differentiation.
    This is a specialization for just that particular functor and is written in C++. This is currently not generated from the Stan language. In order to write analytic Jacobians in this way, a user needs to perform surgery on the generated code, but it can be done.
Some comments in no particular order:
  • I'm really pleased that autodiff is only 2x as long as putting in analytic gradients! That's awesome! I know this is a simpler example, but still... that's really rad.
  • I think there are changes we can make to ode_system to make things a lot better:
    • Rename. It's not an ode system. It's the Jacobians of an ode system. There are three functions exposed:
      1. A function to calculate the value of the ode at the time and state provided.
      2. A function to calculate the Jacobian of the RHS with respect to y.
      3. A function to calculate the Jacobians of the RHS with respect to y and the RHS with respect to theta.
    • Clean up the interface. I don't think it needs to be this complicated. For example, here are the three function signatures I would provide:
      std::vector<double> operator()(double t, const std::vector<double>& y). returns dy_dt.
      For the two Jacobian functions, I would simplify a lot and just use Eigen::Matrix<double, Dynamic, Dynamic> (or whatever the right type is). Having the indirection of Eigen::MatrixBase<Derived1> where Derived1 is a template parameter isn't helping. These things are double based containers and it would help a lot if it weren't overengineered. Unless there's a use-case that I'm missing. It doesn't look like there is, though.
    • I'd rethink cvodes_ode_data.hpp. I don't understand the naming. Now that I look at it, why aren't the functions in the existing ode_system.hpp renamed to rhs_sens() and dense_jacobian()? Would that be more descriptive?
  • What are your use cases for having people specify analytic Jacobians? (I guess CVODES is calling them sensitivities and dense Jacobians.)
    • If the goal is to have a user be able to hack the C++, I think it's sufficient to rename and clean up ode_system. And possibly cvodes_ode_data as well.
    • If the goal is to have people write sensitivities and dense Jacobians in the Stan language, then what do you expect it to generate? Right now, we don't even allow users to specify gradients on their own functions and I think this is a good thing. Experts will be able to get into the C++ directly. I think it's hard to implement gradients correctly and not allowing users to try has saved us a lot of effort.

I think I understand the tangle of ode classes now. I think it's much too complicated and that's why I was struggling with it. I'm sure we can simplify, if you want to go through with it.

Just to be clear, this change you're proposing has no affect on existing timing. It just allows you, an expert that's willing to hack the C++, to write analytic sensitivities and Jacobians, which, in this case, is a 2x speedup. (Or... does this speed up all of the odes in general? if so, I missed it and would like to know how / why.)



Daniel




--
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.
For more options, visit https://groups.google.com/d/optout.

Daniel Lee

unread,
Aug 5, 2016, 9:44:54 AM8/5/16
to stan-dev mailing list
I guess one other use case I forgot about until now was:

do you plan on providing a handful of ode systems that provide analytic sensitivities and dense Jacobians? And have that exposed through the Stan language? If so, what would it look like from Stan? How would you construct such a thing? How would you use it?



Daniel

Ben Goodrich

unread,
Aug 5, 2016, 11:46:51 AM8/5/16
to stan development mailing list
On Friday, August 5, 2016 at 9:42:15 AM UTC-4, Daniel Lee wrote:
  • If the goal is to have people write sensitivities and dense Jacobians in the Stan language, then what do you expect it to generate? Right now, we don't even allow users to specify gradients on their own functions and I think this is a good thing. Experts will be able to get into the C++ directly. I think it's hard to implement gradients correctly and not allowing users to try has saved us a lot of effort.
I would place zero weight on the problems of users who specify their own gradients incorrectly, but I think we need to provide mechanisms to do this (correctly). Now there are more and more packages that do like rstanarm and provide a set of pre-compiled models or do like brms and generate Stan code that could benefit from something like this. Hacking the C++ in those cases is not a good option because it would have to be done programatically.

Another thing that ties into this is the Stan requirement that user-defined functions be defined. If you declare a function in the functions block but don't define it, then the parser throws an error even though the pre-processor would be perfectly happy to find it in another .cpp file or the linker would be perfectly happy to find it in a shared object. If the parser would just delete that check, then it would be a lot easier to utilize custom C++ that might accumulate analytical gradients or whatever.

Ben

Sebastian Weber

unread,
Aug 6, 2016, 3:25:23 AM8/6/16
to stan...@googlegroups.com
Hi Daniel,

My main goal is to have ODEs in Stan at maximum speed. I fully agree that AD is amazingly fast! However, in my field (any I guess many others as well) I need to solve essentially the same ODE in many projects such that it is very reasonable to work out Jacobians for those often used ODE systems. For the current stage I just would like to have an easy C++ way to make the analytic Jacobians possible for ODEs. It is in fact not so magic to do this - there are lots of tools out there to do automatic code generation already. So it comes down to knowing these tools and a bit of copy and paste. No magic. That does not mean this should be worked on in the future, i.e. having some Stan language features which help users with this, but we need to go in steps here.

The change I have put up does two things:

1. Use the ode_system for calculating the Jacobians. Doing so enables that specifying analytic Jacobians once will be beneficial for bdf and rk45 integrators in Stan

2. I made the coupled_ode_system work with an unshifted sensitivity system. Up to now the shifting was done whenever the initials vary. However, this is not needed at all and I aligned this with the CVODES code. This may lead to a minor speedup, not sure.

To be clear on this - yes there is no speed gain of the rk45 integrator by now using the ode_system (if at all only a very minor).

You appear to be very confused by the naming of ode_system - we did have a discussion on stab-dev about this (https://groups.google.com/forum/m/?fromgroups#!searchin/stan-dev/ode_system$20name/stan-dev/Bi4D_2YSrjI). Bob and Michael supported the name for it. The design of the ode_system object was aligned with Bob who suggested to use function name overloading. I myself like the ode_system name - it does reflect that this is the ODE plus needed facilities which is the Jacobian in this case.

Now, ode_system should really only provide the Jacobian and not the sensitivity system. The reason is that with the Jacobian it is straightforward to generate the sensitivity system which is needed (which depends on the case var/double and var/double for inits and parameters). Moreover, the CVODES code needs the Jacobian wrt to the states to do its stiff integration. I am not sure if renaming to dense_jacobian makes sense for a Stan object. I mean CVODES makes the distinction between sparse and dense jacobians while Stan always gives you a dense version of it as far as I am aware. So changing to dense_jacobian the function calls - I don’t know.

Moreover, the need to use the MatrixBase Eigen functionality is coming from the fact that I can then pass into the function Matrix and Map objects. The Map functionality enables to write directly into memory chunks, this is used here:


or here:


If you require a Matrix to be passed around then this leads to extra copies which have to be created. From my experience this leads to a ~2-5% performance degradation.

So here is what I would suggest to do:

1. We move the coupled_ode_system to use the ode_system AND to not anymore do a shifting operation (which is on the branch for feature 310)

2. We make cvodes_ode_data use the couple_ode_system which would then be possible as no more shifting is done. Now, this will lead to a minor performance hit for the bdf integrator whenever users supply the analytic Jacobians. The reason is that then the coupled_ode_system cannot be instructed to calculate only the sensitivity system, but not evaluate the function itself. As this is not the major use case of coupled_ode_system and probably the performance hit is not too large, this would be ok. This would lead to a removal of all the rhs_sens function floating around in cvodes_ode_data.

However, we will still need the cvodes_ode_data object around as this is needed for the CVODES integrator for the static callback. The name of the object stems from the CVODES notion here which refers to this callback „thing“ as user data.

Best,
Sebastian

You received this message because you are subscribed to a topic in the Google Groups "stan development mailing list" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/stan-dev/vjM5siFfxwY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to stan-dev+u...@googlegroups.com.

Daniel Lee

unread,
Aug 6, 2016, 9:43:39 AM8/6/16
to stan-dev mailing list
On Sat, Aug 6, 2016 at 3:25 AM, Sebastian Weber <sdw....@gmail.com> wrote:
Hi Daniel,

My main goal is to have ODEs in Stan at maximum speed. I fully agree that AD is amazingly fast! However, in my field (any I guess many others as well) I need to solve essentially the same ODE in many projects such that it is very reasonable to work out Jacobians for those often used ODE systems. For the current stage I just would like to have an easy C++ way to make the analytic Jacobians possible for ODEs. It is in fact not so magic to do this - there are lots of tools out there to do automatic code generation already. So it comes down to knowing these tools and a bit of copy and paste. No magic. That does not mean this should be worked on in the future, i.e. having some Stan language features which help users with this, but we need to go in steps here.

The change I have put up does two things:

1. Use the ode_system for calculating the Jacobians. Doing so enables that specifying analytic Jacobians once will be beneficial for bdf and rk45 integrators in Stan

2. I made the coupled_ode_system work with an unshifted sensitivity system. Up to now the shifting was done whenever the initials vary. However, this is not needed at all and I aligned this with the CVODES code. This may lead to a minor speedup, not sure.

To be clear on this - yes there is no speed gain of the rk45 integrator by now using the ode_system (if at all only a very minor).

And there's no speed gain for the BDF integrator also. Unless someone writes custom Jacobians. That's a good use case, this doesn't actually affect the existing code base in speed.
 

You appear to be very confused by the naming of ode_system - we did have a discussion on stab-dev about this (https://groups.google.com/forum/m/?fromgroups#!searchin/stan-dev/ode_system$20name/stan-dev/Bi4D_2YSrjI). Bob and Michael supported the name for it. The design of the ode_system object was aligned with Bob who suggested to use function name overloading. I myself like the ode_system name - it does reflect that this is the ODE plus needed facilities which is the Jacobian in this case.

Here's the thread (the last link didn't go anywhere): 

I just looked at the thread again and I think it's a lot clearer now. I still don't like "ode_system" because I don't think "system" conveys the right information. I believe the original use of "coupled_ode_system" came from a the terminology used in odes, "system of equations" -- so the coupled ode system was not just the original ode system of equations, but now a new ode system of equations with the initial conditions and parameters coupled into the system.

I would think F is the ode_system and what you're describing is a way to wrap F and get sensitivities. So I'd just prefer a much more descriptive name that doesn't overload what we take to be the existing ode_system.
 

Now, ode_system should really only provide the Jacobian and not the sensitivity system. The reason is that with the Jacobian it is straightforward to generate the sensitivity system which is needed (which depends on the case var/double and var/double for inits and parameters). Moreover, the CVODES code needs the Jacobian wrt to the states to do its stiff integration. I am not sure if renaming to dense_jacobian makes sense for a Stan object. I mean CVODES makes the distinction between sparse and dense jacobians while Stan always gives you a dense version of it as far as I am aware. So changing to dense_jacobian the function calls - I don’t know.

Then why do we have both?
In the integrator we have now, do we ever use both?
Do the "sparse Jacobians" and "dense Jacobians" line up with CVODES calls to rhs_sens() and dense_jacobian()? Or are they different?

(those are actual questions.... not sure what the answers are and if I'm missing something)
 

Moreover, the need to use the MatrixBase Eigen functionality is coming from the fact that I can then pass into the function Matrix and Map objects. The Map functionality enables to write directly into memory chunks, this is used here:


or here:


If you require a Matrix to be passed around then this leads to extra copies which have to be created. From my experience this leads to a ~2-5% performance degradation.


Ok. That makes sense. I stop doing Eigen Matrix stuff for a few weeks and I forgot how messy it looks. 

 
So here is what I would suggest to do:

1. We move the coupled_ode_system to use the ode_system AND to not anymore do a shifting operation (which is on the branch for feature 310)

I don't understand what this means. What is a "shifting operator"?

What part of the coupled_ode_system needs to use the ode_system?

Can we add a step 0 and rename ode_system? (Either that or give me a good name for the functor F, the system of ordinary differential equations.... if you tell me that's called something else in the literature, then I'll start referring to that as something else and we can leave this is "ode_system.")
 

2. We make cvodes_ode_data use the couple_ode_system which would then be possible as no more shifting is done. Now, this will lead to a minor performance hit for the bdf integrator whenever users supply the analytic Jacobians. The reason is that then the coupled_ode_system cannot be instructed to calculate only the sensitivity system, but not evaluate the function itself. As this is not the major use case of coupled_ode_system and probably the performance hit is not too large, this would be ok. This would lead to a removal of all the rhs_sens function floating around in cvodes_ode_data.

However, we will still need the cvodes_ode_data object around as this is needed for the CVODES integrator for the static callback. The name of the object stems from the CVODES notion here which refers to this callback „thing“ as user data.


Sorry -- I couldn't follow along since I don't understand what shifting is.

Before you go forward, mind putting out a design first? I hate to say it, but UML or a flowchart might be helpful. I've had to use pen and paper multiple times to get a handle on how things get called. (I get it... you think it's all straightforward, but to me it isn't. I'm usually ok bouncing functionality between 2 classes... when it gets beyond that, it starts becoming a lot of effort.)

Alternatively, we could design the whole thing top-down leaving all the user-facing interfaces intact. We can write out the requirements (things we must have) and work from there.




Daniel

 

Best,
Sebastian

To unsubscribe from this group and all its topics, send an email to stan-dev+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Bob Carpenter

unread,
Aug 6, 2016, 2:38:02 PM8/6/16
to stan...@googlegroups.com
The only issue with users specifying wrong gradients is that
they'll get lots of divergences and either live with the wrong
answer or clog our mailing lists. We do have checks that they've
defined it properly, but they're slow.

We could remove the requirement that functions are defined if
they are declared, but then there would be Stan programs that
translate to C++ but don't link. I don't know how to catch the
error at that point and do something reasonable for the user.

I do want to support some kind of user-defined C++ extensions
for functions.

- Bob


> On Aug 5, 2016, at 11:46 AM, Ben Goodrich <goodri...@gmail.com> wrote:
>
> On Friday, August 5, 2016 at 9:42:15 AM UTC-4, Daniel Lee wrote:
> • If the goal is to have people write sensitivities and dense Jacobians in the Stan language, then what do you expect it to generate? Right now, we don't even allow users to specify gradients on their own functions and I think this is a good thing. Experts will be able to get into the C++ directly. I think it's hard to implement gradients correctly and not allowing users to try has saved us a lot of effort.

> I would place zero weight on the problems of users who specify their own gradients incorrectly,

They'll get frustrated and blame us and clog our mailing list.
I don't want to make a policy of don't post X or Y. So it's
going to cause work. I could live with that, though.

> but I think we need to provide mechanisms to do this (correctly). Now there are more and more packages that do like rstanarm and provide a set of pre-compiled models or do like brms and generate Stan code that could benefit from something like this. Hacking the C++ in those cases is not a good option because it would have to be done programatically.
>
> Another thing that ties into this is the Stan requirement that user-defined functions be defined. If you declare a function in the functions block but don't define it, then the parser throws an error even though the pre-processor would be perfectly happy to find it in another .cpp file or the linker would be perfectly happy to find it in a shared object. If the parser would just delete that check, then it would be a lot easier to utilize custom C++ that might accumulate analytical gradients or whatever.

We could delete that check easily enough, but then what

>
> 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+u...@googlegroups.com.

Ben Goodrich

unread,
Aug 6, 2016, 2:57:10 PM8/6/16
to stan development mailing list
On Saturday, August 6, 2016 at 2:38:02 PM UTC-4, Bob Carpenter wrote:
The only issue with users specifying wrong gradients is that
they'll get lots of divergences and either live with the wrong
answer or clog our mailing lists.  We do have checks that they've
defined it properly, but they're slow.

I agree that is the cost, but it is a self-inflicted cost for people who do not even bother to ever run it with test_gradient = TRUE. Morally, I don't think that should keep us from implementing something that responsible people would find useful or perhaps essential in some cases.
 
We could remove the requirement that functions are defined if
they are declared, but then there would be Stan programs that
translate to C++ but don't link.  I don't know how to catch the
error at that point and do something reasonable for the user.

Linker errors don't bother me as much as wrong gradients that compile. If it doesn't link, it is pretty obvious what the problem is. It is only non-obvious for someone who meant to define the user-defined function in the Stan program but forgot.

Ben

Bob Carpenter

unread,
Aug 6, 2016, 3:05:55 PM8/6/16
to stan...@googlegroups.com

> On Aug 6, 2016, at 2:57 PM, Ben Goodrich <goodri...@gmail.com> wrote:
>
> On Saturday, August 6, 2016 at 2:38:02 PM UTC-4, Bob Carpenter wrote:
> The only issue with users specifying wrong gradients is that
> they'll get lots of divergences and either live with the wrong
> answer or clog our mailing lists. We do have checks that they've
> defined it properly, but they're slow.
>
> I agree that is the cost, but it is a self-inflicted cost for people who do not even bother to ever run it with test_gradient = TRUE. Morally, I don't think that should keep us from implementing something that responsible people would find useful or perhaps essential in some cases.

I think we should make user-defined gradients avaialable.
I just dont think it'll be without user headaches.

> We could remove the requirement that functions are defined if
> they are declared, but then there would be Stan programs that
> translate to C++ but don't link. I don't know how to catch the
> error at that point and do something reasonable for the user.
>
> Linker errors don't bother me as much as wrong gradients that compile. If it doesn't link, it is pretty obvious what the problem is. It is only non-obvious for someone who meant to define the user-defined function in the Stan program but forgot.

I'm not that bothered either way because I know C++.
But ordinary users are going to be confused by the spew from
the compiler/linker. But maybe it won't happen that much.

- Bob

Sebastian Weber

unread,
Aug 8, 2016, 3:48:35 AM8/8/16
to stan development mailing list
Hi Daniel,

With the shifting operation I am referring to the process of setting initials to zero which is done in the coupled_ode_system whenever the initials vary. This is why this add_initals function was needed during decoupling of the ODE states. This shifting operation is not needed if you just setup the initial values of the sensitivity states a bit differently.

How about we call the functor F simply ode_rhs - with the understanding that this refers to the bare base system only. The ode_system is then the ode_rhs together with the Jacobians.

I have never used UML, so it would be very hard to me to layout the design using UML from scratch. Chances are better if I modify an existing UML for the current rk45 design. Does that exist? Is there a UML flowchart for any of the Stan sub-systems?

As a first step we could write on a wiki page definitions of things - or could we make the PDF I have written a while ago (under the link you quoted) sticky in the wiki?

Sebastian
> I'm really pleased that autodiff is only 2x as long as putting in analytic gradients! That's awesome! I know this is a simpler example, but still... that's really rad.I think there are changes we can make to ode_system to make things a lot better:Rename. It's not an ode system. It's the Jacobians of an ode system. There are three functions exposed:
> 1. A function to calculate the value of the ode at the time and state provided.
> 2. A function to calculate the Jacobian of the RHS with respect to y.
> 3. A function to calculate the Jacobians of the RHS with respect to y and the RHS with respect to theta.Clean up the interface. I don't think it needs to be this complicated. For example, here are the three function signatures I would provide:
> std::vector<double> operator()(double t, const std::vector<double>& y). returns dy_dt.
> For the two Jacobian functions, I would simplify a lot and just use Eigen::Matrix<double, Dynamic, Dynamic> (or whatever the right type is). Having the indirection of Eigen::MatrixBase<Derived1> where Derived1 is a template parameter isn't helping. These things are double based containers and it would help a lot if it weren't overengineered. Unless there's a use-case that I'm missing. It doesn't look like there is, though.
> I'd rethink cvodes_ode_data.hpp. I don't understand the naming. Now that I look at it, why aren't the functions in the existing ode_system.hpp renamed to rhs_sens() and dense_jacobian()? Would that be more descriptive?What are your use cases for having people specify analytic Jacobians? (I guess CVODES is calling them sensitivities and dense Jacobians.)If the goal is to have a user be able to hack the C++, I think it's sufficient to rename and clean up ode_system. And possibly cvodes_ode_data as well.If the goal is to have people write sensitivities and dense Jacobians in the Stan language, then what do you expect it to generate? Right now, we don't even allow users to specify gradients on their own functions and I think this is a good thing. Experts will be able to get into the C++ directly. I think it's hard to implement gradients correctly and not allowing users to try has saved us a lot of effort.
>
>
> I think I understand the tangle of ode classes now. I think it's much too complicated and that's why I was struggling with it. I'm sure we can simplify, if you want to go through with it.
>
>
> Just to be clear, this change you're proposing has no affect on existing timing. It just allows you, an expert that's willing to hack the C++, to write analytic sensitivities and Jacobians, which, in this case, is a 2x speedup. (Or... does this speed up all of the odes in general? if so, I missed it and would like to know how / why.)
>
>
>
>
>
>
> Daniel
>
>
>
>
>
>
> On Thu, Aug 4, 2016 at 4:25 PM, Sebastian Weber <sdw....@gmail.com> wrote:
> Hi!
>
> I intend to refactor the current coupled ode system object. For one reason I would like to align ODE codes (rk45 and bdf) and for two I would like to route execution through the ode_system object. The reason to do so is that we can plug into the system analytic Jacobians of the ODE wrt to states and parameters using partial template specialization's.
>
> To illustrate what I mean, I prepared a "test" which has the sole purpose to show the execution time for the two cases (with AD and without AD):
>
> https://github.com/stan-dev/math/blob/feature/issue-310-coupled_ode_system-refactor-only/test/unit/math/rev/mat/functor/integrate_ode_rk45_noAD_test.cpp
>
> The speed gain for the specific case is close to 2x. This always depends on the ODE system, parameters, etc.. the speed gain will be larger for stiffer systems and for ODE systems with many states (this is my personal guess; the cases with many Jacobian evaluations). Applying this during model inference gave me 2-3x speedups.
>
> Supplying the analytic Jacobians won't be something regular users will, rather only advanced users. Making this user friendly is a different topic (I can share some R codes which help already a lot).
>
> I hold on for the moment with a pull request until the design is settled.
>
> Best,
> Sebastian
>
> --
> 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.
>
>
>
> -- 
> You received this message because you are subscribed to a topic in the Google Groups "stan development mailing list" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/stan-dev/vjM5siFfxwY/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to stan-dev+u...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>
>
>
>
>
>
>
> --
>
> 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.

Bob Carpenter

unread,
Aug 8, 2016, 10:04:34 PM8/8/16
to stan...@googlegroups.com
I don't know about adding to the Wiki.

We don't need UML per se, but just want to know what
the classes are going to be, what data/references
they're going to hold and what its type is, and what
the inheritance (if any) looks like.

I have no idea about PDFs. I'd rather stick to
Wiki pages because they're easy to edit.

- Bob

Daniel Lee

unread,
Aug 8, 2016, 10:15:52 PM8/8/16
to stan-dev mailing list
I'm also happy with the wiki. And I'm completely agreed on not needing UML or any other formal standard (I know... I suggested it, but it was in hopes that you had seen it or known at least what it's designed to express).

+1 to Bob's list:
- what the classes are going to be
- what data/references they're going to hold; what type each data/reference is
- what the inheritance (if any) looks like


Daniel
 

> To unsubscribe from this group and stop receiving emails from it, send an email to stan-dev+unsubscribe@googlegroups.com.

> For more options, visit https://groups.google.com/d/optout.

--
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,
Aug 8, 2016, 10:17:39 PM8/8/16
to stan...@googlegroups.com
And which methods they define (non-statics). The static stuff
probably shouldn't be in classes, but I drop it there sometimes
if I know it'll only be used in the class.

- Bob
> > 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.
>
> --
> 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.
>
>
> --
> You received this message because you are subscribed to the Google Groups "stan development mailing list" group.
Reply all
Reply to author
Forward
0 new messages