neurophysik / jitcode

Just-in-Time Compilation for Ordinary Differential Equations
Other
62 stars 9 forks source link

condition on state variable, reset if reach to a threshold #36

Closed Ziaeemehr closed 2 years ago

Ziaeemehr commented 2 years ago

I am wondering if it's possible to set a condition on the state variable if it reached a threshold reset it (at the definition of derivative). This is quite common in neural dynamics.

if I try to do this get the following error:

def derivative():
    if # condition on y(0) :
        y(0) = 0.0
    yield  # some code

SyntaxError: cannot assign to function call
``
Wrzlprmft commented 2 years ago

Quick answer: Please have a look at this. If this doesn’t solve your problem, please describe in more detail what you want to achieve.

Ziaeemehr commented 2 years ago

yes, I have seen and used it #35.

For example, if membrane potential reaches a threshold, it needs to be reset to zero at LIF neuron, if I use a condition like the link above, and return 0 for that component,

def derivative():
    if  y(0) > threshold:
        yield 0 # for dv
    else:
        yield 1/tau * ...
    yield ... # for other components

this does not reset the membrane potential (right?) because y_i = y_i + dv * dt y_i still has nonzero value.

is that make sense or is this too obvious and I am missing something?

Ziaeemehr commented 2 years ago

I need this for the specific example of the Montbrio model.

This is the implementation of Heun stochastic in C++:

        derivative(y, k1, t);     // k1 is the slope and being updated in place by reference
        for (size_t i = 0; i < nn; ++i)
                tmp[i] = y[i] + dt * k1[i] + rNoise * rand();
        derivative(tmp, k2, t+dt); // k2 is the slope (derivative) and is updated in place by reference
        for (size_t i = 0; i < nn; ++i)
        {
                y[i] += 0.5 * dt * (k1[i] + k2[i]) + rNoise * rand();
                if (y[i] < 0)    // reset the value of r if negative  (I just simplified the code, it has some more code to seperate the r component)
                    y[i] = 0.0;
        }
                else
                    y[i] += 0.5 * dt * (k1[i] + k2[i]) + vNoise * dist(mt_rand);
        }

I have set the value of one of the components to zero if it becomes negative. this is the main part of the derivative just for completing the code but it does not matter,

    for (size_t i = 0; i < N; ++i)
        {
            double coupling_term = 0;
            for (size_t j = 0; j < adjlist[i].size(); ++j)
            {
                int k = adjlist[i][j];
                coupling_term += adj[i][k] * x[k];
            }
            dxdt[i] = 1.0 / tau * (delta / (tau * M_PI) + 2 * x[i] * x[i + N]);
            dxdt[i + N] = 1.0 / tau * (x[i + N] * x[i + N] + eta + iapp + J * tau * x[i] - (M_PI * M_PI * tau * tau * x[i] * x[i]) + G * coupling_term);
        }

I need to do the same thing in jitcsde.

because I get this behavior in C++ code: rv (1) and this one from jitcsde:

01_sde_montbrio_2 000

however it seems r never touches negative values, but this is the only difference I could found that may be the source of the difference.

Wrzlprmft commented 2 years ago

Such discontinuous changes of dynamical variables are not possible in JiTC*DE. I don’t see a way to change this because the integrators, error estimators, etc. inherently rely on continuity for many features.

I see two ways for you to work around this: