brian-team / brian2

Brian is a free, open source simulator for spiking neural networks.
http://briansimulator.org
Other
904 stars 216 forks source link

Access to update_order in Equations #464

Closed dabliss closed 9 years ago

dabliss commented 9 years ago

Hey,

This is a feature request, not a bug report. I'm wondering how you'd feel about giving users easier control over the order of the equations within an Equations object. I'm thinking about giving users the ability to pass an order as a keyword argument (to Equations and possibly also to NeuronGroup). Right now I'm sub-classing Equations and using my own version of _sort_subexpressions. (Is there a reason the update order should always be what the current _sort_subexpressions produces -- aside from the special treatment of dependencies?)

thesamovar commented 9 years ago

We're definitely open to suggestions of this sort and we decide them based on whether there is a general use case, i.e. whether or not it's likely to be useful to more people. So what sort of use cases do you have in mind? As far as I know (Marcel may correct me), the only important thing that sorting the subexpressions does is to get the dependencies in the right order (but this is essential).

dabliss commented 9 years ago

What I noticed is that _sort_subexpressions gets dependencies in the right order only for subexpressions -- not for differential equations. All differential equations are updated at the same step after subexpressions, and parameters follow differential equations.

I have subexpressions -- e.g.,

I_gaba = -G_gaba * s_gaba * (v - E_gaba) --

that are dependent on differential equations -- in this case,

ds_gaba / dt = -s_gaba / t_gaba.

So I'd like the differential equations to be updated before the subexpressions. (I'm assuming that when a differential equation is updated, the variable to which it applies -- here, s_gaba -- is also updated.)

thesamovar commented 9 years ago

Wait, if the dependencies are in the wrong order doesn't that mean it's a bug? If so, it would be really helpful if you could give us a very simple example where the behaviour is wrong.

dabliss commented 9 years ago

I wasn't sure whether that order was unintended. A comment in the body of _sort_subexpressions says,

# i.e. ignore dependencies on parameters and differential equations

So it does what it says it's going to do.

thesamovar commented 9 years ago

Hmm. OK, I'll wait for a comment from @mstimberg on this, I don't remember at the moment.

mstimberg commented 9 years ago

I think there is some misconception about the meaning of update order and subexpressions here. In contrast to Brian 1 (where they were called "static equations"), subexpressions do not correspond to a variable, they are just a tool to structure your code. If the name of a subexpressions is used, you should be able to substitute it with the expression and get the same result. Therefore, if you have something like

...
I_gaba = -G_gaba * s_gaba * (v - E_gaba) ... : amp 
dv/dt = (g_L*(v - E_L) + I_gaba + ...) / Cm : volt
...

then this is equivalent to

...
dv/dt = (g_L*(v - E_L) + -G_gaba * s_gaba * (v - E_gaba) + ...) / Cm : volt
...

Among several differential equations, there is no such thing as an update order, they are all updated simultaneously, using the state variable values from the previous time step, everything else would be mathematically incorrect.

The update order is only important for the code generation related to subexpressions, if you use one subexpression in abstract code that refers to other subexpressions, those other expressions have to be evaluated first.

Hope that makes things clearer. I don't think there's any situation where the user should have to care about the order of equations, the order you use in the equations string should never matter.

dabliss commented 9 years ago

Huh, OK. Thanks a lot for this explanation. I have one lingering question. You say,

Among several differential equations, there is no such thing as an update order, they are all updated simultaneously, using the state variable values from the previous time step, everything else would be mathematically incorrect.

Suppose I have

dv / dt = -G_gaba * s_gaba * (v - E_gaba) / Cm : volt
ds_gaba / dt = -s_gaba / t_gaba.

Is there no way for me to update s_gaba according to the differential equation for s_gaba before I update v according to the differential equation for v? I guess I'm not seeing why this is in all cases mathematically incorrect (given that, for example, brian2 would allow me to achieve this order if I updated s_gaba at the 'start' stage and v at the 'groups' stage).

mstimberg commented 9 years ago

Is there no way for me to update s_gaba according to the differential equation for s_gaba before I update v according to the differential equation for v?

No, this is a system of coupled differential equations, and v and s_gaba are functions of time, you can't "update" them independently of each other if they are part of the same system of equations (which is what putting them in the same Equations object means). As I said before, during the update step, there's no "order", both variables are updated based on the values of the variables at the beginning of the time step, e.g. with the forward Euler method:

>>> eqs = Equations('''
... dv / dt = -G_gaba * s_gaba * (v - E_gaba) / Cm : volt
... ds_gaba / dt = -s_gaba / t_gaba : 1''')
>>> print euler(eqs)
_s_gaba = -dt*s_gaba/t_gaba + s_gaba
_v = v - G_gaba*dt*s_gaba*(-E_gaba + v)/Cm
s_gaba = _s_gaba
v = _v

I'm not quite sure I understand what you want to achieve, but if this is related to the fact that s_gaba is discretely updated for synaptic events then you could work around the restrictions of a single system of coupled equations by describing s_gaba as part of the synaptic model (which will be less efficient because updates will be done once per synapse instead of once per neuron but you can provide an order keyword argument to change when it is updated during the time step).

dabliss commented 9 years ago

Aha, OK, this resolves the issue for me. Thanks for clarifying. It wasn't that I wanted to achieve anything exotic; I just wanted to understand (or, have control over so that I could understand) how the updating was taking place. If it isn't obvious already, I am not all that experienced with neural simulations. I greatly appreciate the help experts like you and Dan give me.

thesamovar commented 9 years ago

No problem! We're happy that you're using Brian. :)

I'm going to close this issue now if there's no further problems.