Skip to content

Commit 89dc9d6

Browse files
authored
Merge pull request #108 from PKU-NIP-Lab/V2.1.1
release V2.1.1
2 parents e28ff0a + 830b112 commit 89dc9d6

File tree

4 files changed

+197
-30
lines changed

4 files changed

+197
-30
lines changed

brainpy/dyn/neurons/fractional_models.py

Lines changed: 170 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,196 @@
11
# -*- coding: utf-8 -*-
22

3+
from typing import Union, Sequence
4+
35
import brainpy.math as bm
46
from brainpy.dyn.base import NeuGroup
57
from brainpy.integrators.fde import CaputoL1Schema
8+
from brainpy.integrators.fde import GLShortMemory
69
from brainpy.integrators.joint_eq import JointEq
710
from brainpy.tools.checking import check_float, check_integer
11+
from brainpy.types import Parameter, Shape
812

913
__all__ = [
10-
'FractionalFHN',
14+
'FractionalFHR',
1115
'FractionalIzhikevich',
1216
]
1317

1418

15-
class FractionalFHN(NeuGroup):
16-
"""
19+
class FractionalNeuron(NeuGroup):
20+
"""Fractional-order neuron model."""
21+
pass
22+
23+
24+
class FractionalFHR(FractionalNeuron):
25+
r"""The fractional-order FH-R model [1]_.
26+
27+
FitzHugh and Rinzel introduced FH-R model (1976, in an unpublished article),
28+
which is the modification of the classical FHN neuron model. The fractional-order
29+
FH-R model is described as
30+
31+
.. math::
32+
33+
\begin{array}{rcl}
34+
\frac{{d}^{\alpha }v}{d{t}^{\alpha }} & = & v-{v}^{3}/3-w+y+I={f}_{1}(v,w,y),\\
35+
\frac{{d}^{\alpha }w}{d{t}^{\alpha }} & = & \delta (a+v-bw)={f}_{2}(v,w,y),\\
36+
\frac{{d}^{\alpha }y}{d{t}^{\alpha }} & = & \mu (c-v-dy)={f}_{3}(v,w,y),
37+
\end{array}
38+
39+
where :math:`v, w` and :math:`y` represent the membrane voltage, recovery variable
40+
and slow modulation of the current respectively.
41+
:math:`I` measures the constant magnitude of external stimulus current, and :math:`\alpha`
42+
is the fractional exponent which ranges in the interval :math:`(0 < \alpha \le 1)`.
43+
:math:`a, b, c, d, \delta` and :math:`\mu` are the system parameters.
44+
45+
The system reduces to the original classical order system when :math:`\alpha=1`.
1746
47+
:math:`\mu` indicates a small parameter that determines the pace of the slow system
48+
variable :math:`y`. The fast subsystem (:math:`v-w`) presents a relaxation oscillator
49+
in the phase plane where :math:`\delta` is a small parameter.
50+
:math:`v` is expressed in mV (millivolt) scale. Time :math:`t` is in ms (millisecond) scale.
51+
It exhibits tonic spiking or quiescent state depending on the parameter sets for a fixed
52+
value of :math:`I`. The parameter :math:`a` in the 2D FHN model corresponds to the
53+
parameter :math:`c` of the FH-R neuron model. If we decrease the value of :math:`a`,
54+
it causes longer intervals between two burstings, however there exists :math:`a`
55+
relatively fixed time of bursting duration. With the increasing of :math:`a`, the
56+
interburst intervals become shorter and periodic bursting changes to tonic spiking.
57+
58+
Examples
59+
--------
60+
61+
- [(Mondal, et, al., 2019): Fractional-order FitzHugh-Rinzel bursting neuron model](https://brainpy-examples.readthedocs.io/en/latest/neurons/2019_Fractional_order_FHR_model.html)
62+
63+
64+
Parameters
65+
----------
66+
size: int, sequence of int
67+
The size of the neuron group.
68+
alpha: float, tensor
69+
The fractional order.
70+
num_memory: int
71+
The total number of the short memory.
1872
1973
References
2074
----------
2175
.. [1] Mondal, A., Sharma, S.K., Upadhyay, R.K. *et al.* Firing activities of a fractional-order FitzHugh-Rinzel bursting neuron model and its coupled dynamics. *Sci Rep* **9,** 15721 (2019). https://doi.org/10.1038/s41598-019-52061-4
2276
"""
23-
def __init__(self, size, alpha, num_step,
24-
a=0.7, b=0.8, c=-0.775, d=1., delta=0.08, mu=0.0001):
25-
super(FractionalFHN, self).__init__(size)
2677

78+
def __init__(self,
79+
size: Shape,
80+
alpha: Union[float, Sequence[float]],
81+
num_memory: int = 1000,
82+
a: Parameter = 0.7,
83+
b: Parameter = 0.8,
84+
c: Parameter = -0.775,
85+
d: Parameter = 1.,
86+
delta: Parameter = 0.08,
87+
mu: Parameter = 0.0001,
88+
Vth: Parameter = 1.8,
89+
name: str = None):
90+
super(FractionalFHR, self).__init__(size, name=name)
91+
92+
# fractional order
2793
self.alpha = alpha
28-
self.num_step = num_step
94+
check_integer(num_memory, 'num_memory', allow_none=False)
2995

96+
# parameters
3097
self.a = a
3198
self.b = b
3299
self.c = c
33100
self.d = d
34101
self.delta = delta
35102
self.mu = mu
103+
self.Vth = Vth
36104

105+
# variables
37106
self.input = bm.Variable(bm.zeros(self.num))
38-
self.v = bm.Variable(bm.ones(self.num) * 2.5)
107+
self.V = bm.Variable(bm.ones(self.num) * 2.5)
39108
self.w = bm.Variable(bm.zeros(self.num))
40109
self.y = bm.Variable(bm.zeros(self.num))
110+
self.spike = bm.Variable(bm.zeros(self.num, dtype=bool))
111+
self.t_last_spike = bm.Variable(bm.ones(self.num) * -1e7)
41112

42-
self.integral = CaputoL1Schema(self.derivative,
43-
alpha=alpha,
44-
num_step=num_step,
45-
inits=[self.v, self.w, self.y])
113+
# integral function
114+
self.integral = GLShortMemory(self.derivative,
115+
alpha=alpha,
116+
num_memory=num_memory,
117+
inits=[self.V, self.w, self.y])
46118

47-
def dv(self, v, t, w, y):
48-
return v - v ** 3 / 3 - w + y + self.input
119+
def dV(self, V, t, w, y):
120+
return V - V ** 3 / 3 - w + y + self.input
49121

50-
def dw(self, w, t, v):
51-
return self.delta * (self.a + v - self.b * w)
122+
def dw(self, w, t, V):
123+
return self.delta * (self.a + V - self.b * w)
52124

53-
def dy(self, y, t, v):
54-
return self.mu * (self.c - v - self.d * y)
125+
def dy(self, y, t, V):
126+
return self.mu * (self.c - V - self.d * y)
55127

56128
@property
57129
def derivative(self):
58-
return JointEq([self.dv, self.dw, self.dy])
130+
return JointEq([self.dV, self.dw, self.dy])
59131

60132
def update(self, _t, _dt):
61-
v, w, y = self.integral(self.v, self.w, self.y, _t, _dt)
62-
self.v.value = v
133+
V, w, y = self.integral(self.V, self.w, self.y, _t, _dt)
134+
self.spike.value = bm.logical_and(V >= self.Vth, self.V < self.Vth)
135+
self.t_last_spike.value = bm.where(self.spike, _t, self.t_last_spike)
136+
self.V.value = V
63137
self.w.value = w
64138
self.y.value = y
65139
self.input[:] = 0.
66140

141+
def set_init(self, values: dict):
142+
for k, v in values.items():
143+
if k not in self.integral.inits:
144+
raise ValueError(f'Variable "{k}" is not defined in this model.')
145+
variable = getattr(self, k)
146+
variable[:] = v
147+
self.integral.inits[k][:] = v
148+
149+
150+
class FractionalIzhikevich(FractionalNeuron):
151+
r"""Fractional-order Izhikevich model [10]_.
152+
153+
The fractional-order Izhikevich model is given by
154+
155+
.. math::
156+
157+
\begin{aligned}
158+
&\tau \frac{d^{\alpha} v}{d t^{\alpha}}=\mathrm{f} v^{2}+g v+h-u+R I \\
159+
&\tau \frac{d^{\alpha} u}{d t^{\alpha}}=a(b v-u)
160+
\end{aligned}
161+
162+
where :math:`\alpha` is the fractional order (exponent) such that :math:`0<\alpha\le1`.
163+
It is a commensurate system that reduces to classical Izhikevich model at :math:`\alpha=1`.
67164
68-
class FractionalIzhikevich(NeuGroup):
69-
"""Fractional-order Izhikevich model [10]_.
165+
The time :math:`t` is in ms; and the system variable :math:`v` expressed in mV
166+
corresponds to membrane voltage. Moreover, :math:`u` expressed in mV is the
167+
recovery variable that corresponds to the activation of K+ ionic current and
168+
inactivation of Na+ ionic current.
169+
170+
The parameters :math:`f, g, h` are fixed constants (should not be changed) such
171+
that :math:`f=0.04` (mV)−1, :math:`g=5, h=140` mV; and :math:`a` and :math:`b` are
172+
dimensionless parameters. The time constant :math:`\tau=1` ms; the resistance
173+
:math:`R=1` Ω; and :math:`I` expressed in mA measures the injected (applied)
174+
dc stimulus current to the system.
175+
176+
When the membrane voltage reaches the spike peak :math:`v_{peak}`, the two variables
177+
are rest as follow:
178+
179+
.. math::
180+
181+
\text { if } v \geq v_{\text {peak }} \text { then }\left\{\begin{array}{l}
182+
v \leftarrow c \\
183+
u \leftarrow u+d
184+
\end{array}\right.
185+
186+
we used :math:`v_{peak}=30` mV, and :math:`c` and :math:`d` are parameters expressed
187+
in mV. When the spike reaches its peak value, the membrane voltage :math:`v` and the
188+
recovery variable :math:`u` are reset according to the above condition.
189+
190+
Examples
191+
--------
192+
193+
- [(Teka, et. al, 2018): Fractional-order Izhikevich neuron model](https://brainpy-examples.readthedocs.io/en/latest/neurons/2018_Fractional_Izhikevich_model.html)
70194
71195
72196
References
@@ -77,9 +201,21 @@ class FractionalIzhikevich(NeuGroup):
77201
78202
"""
79203

80-
def __init__(self, size, num_step, alpha=0.9,
81-
a=0.02, b=0.20, c=-65., d=8., f=0.04,
82-
g=5., h=140., tau=1., R=1., V_th=30., name=None):
204+
def __init__(self,
205+
size: Shape,
206+
alpha: Union[float, Sequence[float]],
207+
num_step: int,
208+
a: Parameter = 0.02,
209+
b: Parameter = 0.20,
210+
c: Parameter = -65.,
211+
d: Parameter = 8.,
212+
f: Parameter = 0.04,
213+
g: Parameter = 5.,
214+
h: Parameter = 140.,
215+
tau: Parameter = 1.,
216+
R: Parameter = 1.,
217+
V_th: Parameter = 30.,
218+
name: str = None):
83219
# initialization
84220
super(FractionalIzhikevich, self).__init__(size=size, name=name)
85221

@@ -131,3 +267,11 @@ def update(self, _t, _dt):
131267
self.u.value = bm.where(spikes, u + self.d, u)
132268
self.spike.value = spikes
133269
self.input[:] = 0.
270+
271+
def set_init(self, values: dict):
272+
for k, v in values.items():
273+
if k not in self.integral.inits:
274+
raise ValueError(f'Variable "{k}" is not defined in this model.')
275+
variable = getattr(self, k)
276+
variable[:] = v
277+
self.integral.inits[k][:] = v

brainpy/integrators/fde/GL.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ def __init__(self, f, alpha, num_memory, inits, dt=None, name=None):
123123
super(GLShortMemory, self).__init__(f=f, alpha=alpha, dt=dt, name=name)
124124

125125
# fractional order
126-
if not jnp.all(jnp.logical_and(self.alpha < 1, self.alpha > 0)):
126+
if not jnp.all(jnp.logical_and(self.alpha <= 1, self.alpha > 0)):
127127
raise UnsupportedError(f'Only support the fractional order in (0, 1), '
128128
f'but we got {self.alpha}.')
129129

@@ -132,11 +132,11 @@ def __init__(self, f, alpha, num_memory, inits, dt=None, name=None):
132132
self.num_memory = num_memory
133133

134134
# initial values
135-
inits = check_inits(inits, self.variables)
135+
self.inits = check_inits(inits, self.variables)
136136

137137
# delays
138138
self.delays = {}
139-
for key, val in inits.items():
139+
for key, val in self.inits.items():
140140
delay = bm.Variable(bm.zeros((self.num_memory,) + val.shape, dtype=bm.float_))
141141
delay[0] = val
142142
self.delays[key] = delay

changelog.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,28 @@ brainpy 2.x (LTS)
66
*****************
77

88

9+
Version 2.1.1 (2022.03.18)
10+
==========================
11+
12+
This release continues to update the functionality of BrainPy. Core changes include
13+
14+
- numerical solvers for fractional differential equations
15+
- more standard ``brainpy.nn`` interfaces
16+
17+
18+
New Features
19+
~~~~~~~~~~~~
20+
21+
- Numerical solvers for fractional differential equations
22+
- ``brainpy.fde.CaputoEuler``
23+
- ``brainpy.fde.CaputoL1Schema``
24+
- ``brainpy.fde.GLShortMemory``
25+
- Fractional neuron models
26+
- ``brainpy.dyn.FractionalFHR``
27+
- ``brainpy.dyn.FractionalIzhikevich``
28+
- support ``shared_kwargs`` in `RNNTrainer` and `RNNRunner`
29+
30+
931
Version 2.1.0 (2022.03.14)
1032
==========================
1133

docs/index.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ high-performance Brain Dynamics Programming (BDP). Among its key ingredients, Br
77
- **JIT compilation** and **automatic differentiation** for class objects.
88
- **Numerical methods** for ordinary differential equations (ODEs),
99
stochastic differential equations (SDEs),
10-
delay differential equations (DDEs), etc.
10+
delay differential equations (DDEs),
11+
fractional differential equations (FDEs), etc.
1112
- **Dynamics simulation** tools for various brain objects, like
1213
neurons, synapses, networks, soma, dendrites, channels, and even more.
1314
- **Dynamics training** tools with various machine learning algorithms,

0 commit comments

Comments
 (0)