Skip to content

Commit 3c9dd55

Browse files
committed
update experimental synapse models
1 parent 7fb57de commit 3c9dd55

File tree

5 files changed

+210
-17
lines changed

5 files changed

+210
-17
lines changed

brainpy/__init__.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22

3-
__version__ = "2.3.6"
3+
__version__ = "2.3.7"
44

55

66
# fundamental supporting modules
@@ -61,20 +61,23 @@
6161
experimental,
6262
)
6363
from brainpy._src.dyn.base import not_pass_shared
64-
from brainpy._src.dyn.base import (DynamicalSystem,
65-
DynamicalSystemNS,
64+
from brainpy._src.dyn.base import (DynamicalSystem as DynamicalSystem,
6665
Container as Container,
6766
Sequential as Sequential,
6867
Network as Network,
6968
NeuGroup as NeuGroup,
70-
NeuGroupNS as NeuGroupNS,
7169
SynConn as SynConn,
7270
SynOut as SynOut,
7371
SynSTP as SynSTP,
7472
SynLTP as SynLTP,
7573
TwoEndConn as TwoEndConn,
7674
CondNeuGroup as CondNeuGroup,
7775
Channel as Channel)
76+
from brainpy._src.dyn.base import (DynamicalSystemNS as DynamicalSystemNS,
77+
NeuGroupNS as NeuGroupNS)
78+
from brainpy._src.dyn.synapses_v2.base import (SynOutNS as SynOutNS,
79+
SynSTPNS as SynSTPNS,
80+
SynConnNS as SynConnNS, )
7881
from brainpy._src.dyn.transform import (LoopOverTime as LoopOverTime,)
7982
from brainpy._src.dyn.runners import (DSRunner as DSRunner) # runner
8083
from brainpy._src.dyn.context import share, Delay

brainpy/_src/dyn/synapses_v2/abstract_synapses.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,3 +298,106 @@ def update(self, pre_spike, post_v=None):
298298
return self.out(post_vs, post_v)
299299
else:
300300
return post_vs
301+
302+
303+
class Alpha(DualExponential):
304+
r"""Alpha synapse model.
305+
306+
**Model Descriptions**
307+
308+
The analytical expression of alpha synapse is given by:
309+
310+
.. math::
311+
312+
g_{syn}(t)= g_{max} \frac{t-t_{s}}{\tau} \exp \left(-\frac{t-t_{s}}{\tau}\right).
313+
314+
While, this equation is hard to implement. So, let's try to convert it into the
315+
differential forms:
316+
317+
.. math::
318+
319+
\begin{aligned}
320+
&g_{\mathrm{syn}}(t)= g_{\mathrm{max}} g \\
321+
&\frac{d g}{d t}=-\frac{g}{\tau}+h \\
322+
&\frac{d h}{d t}=-\frac{h}{\tau}+\delta\left(t_{0}-t\right)
323+
\end{aligned}
324+
325+
**Model Examples**
326+
327+
.. plot::
328+
:include-source: True
329+
330+
>>> import brainpy as bp
331+
>>> from brainpy import neurons, synapses, synouts
332+
>>> import matplotlib.pyplot as plt
333+
>>>
334+
>>> neu1 = neurons.LIF(1)
335+
>>> neu2 = neurons.LIF(1)
336+
>>> syn1 = synapses.Alpha(neu1, neu2, bp.connect.All2All(), output=synouts.CUBA())
337+
>>> net = bp.Network(pre=neu1, syn=syn1, post=neu2)
338+
>>>
339+
>>> runner = bp.DSRunner(net, inputs=[('pre.input', 25.)], monitors=['pre.V', 'post.V', 'syn.g', 'syn.h'])
340+
>>> runner.run(150.)
341+
>>>
342+
>>> fig, gs = bp.visualize.get_figure(2, 1, 3, 8)
343+
>>> fig.add_subplot(gs[0, 0])
344+
>>> plt.plot(runner.mon.ts, runner.mon['pre.V'], label='pre-V')
345+
>>> plt.plot(runner.mon.ts, runner.mon['post.V'], label='post-V')
346+
>>> plt.legend()
347+
>>> fig.add_subplot(gs[1, 0])
348+
>>> plt.plot(runner.mon.ts, runner.mon['syn.g'], label='g')
349+
>>> plt.plot(runner.mon.ts, runner.mon['syn.h'], label='h')
350+
>>> plt.legend()
351+
>>> plt.show()
352+
353+
Parameters
354+
----------
355+
conn: optional, ArrayType, dict of (str, ndarray), TwoEndConnector
356+
The synaptic connections.
357+
comp_method: str
358+
The connection type used for model speed optimization. It can be
359+
`sparse` and `dense`. The default is `sparse`.
360+
delay_step: int, ArrayType, Initializer, Callable
361+
The delay length. It should be the value of :math:`\mathrm{delay\_time / dt}`.
362+
tau_decay: float, ArrayType
363+
The time constant of the synaptic decay phase. [ms]
364+
g_max: float, ArrayType, Initializer, Callable
365+
The synaptic strength (the maximum conductance). Default is 1.
366+
name: str
367+
The name of this synaptic projection.
368+
method: str
369+
The numerical integration methods.
370+
371+
References
372+
----------
373+
374+
.. [1] Sterratt, David, Bruce Graham, Andrew Gillies, and David Willshaw.
375+
"The Synapse." Principles of Computational Modelling in Neuroscience.
376+
Cambridge: Cambridge UP, 2011. 172-95. Print.
377+
"""
378+
379+
def __init__(
380+
self,
381+
conn: Union[TwoEndConnector, ArrayType, Dict[str, ArrayType]],
382+
out: Optional[SynOutNS] = None,
383+
stp: Optional[SynSTPNS] = None,
384+
comp_method: str = 'dense',
385+
g_max: Union[float, ArrayType, Initializer, Callable] = 1.,
386+
tau_decay: Union[float, ArrayType] = 10.0,
387+
method: str = 'exp_auto',
388+
389+
# other parameters
390+
name: str = None,
391+
mode: bm.Mode = None,
392+
):
393+
super().__init__(conn=conn,
394+
comp_method=comp_method,
395+
g_max=g_max,
396+
tau_decay=tau_decay,
397+
tau_rise=tau_decay,
398+
method=method,
399+
out=out,
400+
stp=stp,
401+
name=name,
402+
mode=mode)
403+

brainpy/_src/dyn/synapses_v2/base.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
from brainpy.types import ArrayType
1111

1212

13-
class SynConn(DynamicalSystemNS):
13+
class SynConnNS(DynamicalSystemNS):
1414
def __init__(
1515
self,
1616
conn: TwoEndConnector,
17-
out: Optional['SynOut'] = None,
18-
stp: Optional['SynSTP'] = None,
17+
out: Optional['SynOutNS'] = None,
18+
stp: Optional['SynSTPNS'] = None,
1919
name: str = None,
2020
mode: bm.Mode = None,
2121
):
@@ -28,8 +28,8 @@ def __init__(
2828
self.post_size = conn.post_size
2929
self.pre_num = conn.pre_num
3030
self.post_num = conn.post_num
31-
assert out is None or isinstance(out, SynOut)
32-
assert stp is None or isinstance(stp, SynSTP)
31+
assert out is None or isinstance(out, SynOutNS)
32+
assert stp is None or isinstance(stp, SynSTPNS)
3333
self.out = out
3434
self.stp = stp
3535

@@ -118,15 +118,15 @@ def _syn2post_with_dense(self, syn_value, syn_weight, conn_mat):
118118
return post_vs
119119

120120

121-
class SynOut(DynamicalSystemNS):
121+
class SynOutNS(DynamicalSystemNS):
122122
def update(self, post_g, post_v):
123123
raise NotImplementedError
124124

125125
def reset_state(self, batch_size: Optional[int] = None):
126126
pass
127127

128128

129-
class SynSTP(DynamicalSystemNS):
129+
class SynSTPNS(DynamicalSystemNS):
130130
"""Base class for synaptic short-term plasticity."""
131131

132132
def update(self, pre_spike):
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
2+
from typing import Union, Optional
3+
4+
import brainpy.math as bm
5+
from brainpy._src.dyn.base import DynamicalSystemNS
6+
from brainpy._src.dyn.context import share
7+
from brainpy.check import is_float, is_integer
8+
9+
10+
class PoissonInput(DynamicalSystemNS):
11+
"""Poisson Input.
12+
13+
Adds independent Poisson input to a target variable. For large
14+
numbers of inputs, this is much more efficient than creating a
15+
`PoissonGroup`. The synaptic events are generated randomly during the
16+
simulation and are not preloaded and stored in memory. All the inputs must
17+
target the same variable, have the same frequency and same synaptic weight.
18+
All neurons in the target variable receive independent realizations of
19+
Poisson spike trains.
20+
21+
Parameters
22+
----------
23+
num_input: int
24+
The number of inputs.
25+
freq: float
26+
The frequency of each of the inputs. Must be a scalar.
27+
weight: float
28+
The synaptic weight. Must be a scalar.
29+
"""
30+
31+
def __init__(
32+
self,
33+
target_shape,
34+
num_input: int,
35+
freq: Union[int, float],
36+
weight: Union[int, float],
37+
seed: Optional[int] = None,
38+
mode: bm.Mode = None,
39+
name: str = None
40+
):
41+
super(PoissonInput, self).__init__(name=name, mode=mode)
42+
43+
# check data
44+
is_integer(num_input, 'num_input', min_bound=1)
45+
is_float(freq, 'freq', min_bound=0., allow_int=True)
46+
is_float(weight, 'weight', allow_int=True)
47+
assert self.mode.is_parent_of(bm.NonBatchingMode, bm.BatchingMode)
48+
49+
# parameters
50+
self.target_shape = target_shape
51+
self.num_input = num_input
52+
self.freq = freq
53+
self.weight = weight
54+
self.seed = seed
55+
self.rng = bm.random.default_rng(seed)
56+
57+
def update(self):
58+
p = self.freq * share.dt / 1e3
59+
a = self.num_input * p
60+
b = self.num_input * (1 - p)
61+
if isinstance(share.dt, (int, float)): # dt is not in tracing
62+
if (a > 5) and (b > 5):
63+
inp = self.rng.normal(a, b * p, self.target_shape)
64+
else:
65+
inp = self.rng.binomial(self.num_input, p, self.target_shape)
66+
67+
else: # dt is in tracing
68+
inp = bm.cond((a > 5) * (b > 5),
69+
lambda _: self.rng.normal(a, b * p, self.target_shape),
70+
lambda _: self.rng.binomial(self.num_input, p, self.target_shape),
71+
None,
72+
dyn_vars=self.rng)
73+
return inp * self.weight
74+
75+
def __repr__(self):
76+
names = self.__class__.__name__
77+
return f'{names}(shape={self.target_shape}, num_input={self.num_input}, freq={self.freq}, weight={self.weight})'
78+
79+
def reset_state(self, batch_size=None):
80+
pass
81+
82+
def reset(self, batch_size=None):
83+
self.rng.seed(self.seed)
84+
self.reset_state(batch_size)
85+
86+

brainpy/experimental.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
11

2-
from brainpy._src.dyn.synapses_v2.base import (
3-
SynConn as SynConn,
4-
SynOut as SynOut,
5-
SynSTP as SynSTP,
6-
)
72
from brainpy._src.dyn.synapses_v2.syn_plasticity import (
83
STD as STD,
94
STP as STP,
@@ -13,5 +8,11 @@
138
COBA as COBA,
149
)
1510
from brainpy._src.dyn.synapses_v2.abstract_synapses import (
16-
Exponential as Exponential,
11+
Exponential,
12+
DualExponential,
13+
Alpha,
14+
)
15+
from brainpy._src.dyn.synapses_v2.others import (
16+
PoissonInput,
1717
)
18+

0 commit comments

Comments
 (0)