brainstate 0.0.2.post20241009__py2.py3-none-any.whl → 0.1.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- brainstate/__init__.py +31 -11
- brainstate/_state.py +760 -316
- brainstate/_state_test.py +41 -12
- brainstate/_utils.py +31 -4
- brainstate/augment/__init__.py +40 -0
- brainstate/augment/_autograd.py +608 -0
- brainstate/augment/_autograd_test.py +1193 -0
- brainstate/augment/_eval_shape.py +102 -0
- brainstate/augment/_eval_shape_test.py +40 -0
- brainstate/augment/_mapping.py +525 -0
- brainstate/augment/_mapping_test.py +210 -0
- brainstate/augment/_random.py +99 -0
- brainstate/{transform → compile}/__init__.py +25 -13
- brainstate/compile/_ad_checkpoint.py +204 -0
- brainstate/compile/_ad_checkpoint_test.py +51 -0
- brainstate/compile/_conditions.py +259 -0
- brainstate/compile/_conditions_test.py +221 -0
- brainstate/compile/_error_if.py +94 -0
- brainstate/compile/_error_if_test.py +54 -0
- brainstate/compile/_jit.py +314 -0
- brainstate/compile/_jit_test.py +143 -0
- brainstate/compile/_loop_collect_return.py +516 -0
- brainstate/compile/_loop_collect_return_test.py +59 -0
- brainstate/compile/_loop_no_collection.py +185 -0
- brainstate/compile/_loop_no_collection_test.py +51 -0
- brainstate/compile/_make_jaxpr.py +756 -0
- brainstate/compile/_make_jaxpr_test.py +134 -0
- brainstate/compile/_progress_bar.py +111 -0
- brainstate/compile/_unvmap.py +159 -0
- brainstate/compile/_util.py +147 -0
- brainstate/environ.py +408 -381
- brainstate/environ_test.py +34 -32
- brainstate/{nn/event → event}/__init__.py +6 -6
- brainstate/event/_csr.py +308 -0
- brainstate/event/_csr_test.py +118 -0
- brainstate/event/_fixed_probability.py +271 -0
- brainstate/event/_fixed_probability_test.py +128 -0
- brainstate/event/_linear.py +219 -0
- brainstate/event/_linear_test.py +112 -0
- brainstate/{nn/event → event}/_misc.py +7 -7
- brainstate/functional/_activations.py +521 -511
- brainstate/functional/_activations_test.py +300 -300
- brainstate/functional/_normalization.py +43 -43
- brainstate/functional/_others.py +15 -15
- brainstate/functional/_spikes.py +49 -49
- brainstate/graph/__init__.py +33 -0
- brainstate/graph/_graph_context.py +443 -0
- brainstate/graph/_graph_context_test.py +65 -0
- brainstate/graph/_graph_convert.py +246 -0
- brainstate/graph/_graph_node.py +300 -0
- brainstate/graph/_graph_node_test.py +75 -0
- brainstate/graph/_graph_operation.py +1746 -0
- brainstate/graph/_graph_operation_test.py +724 -0
- brainstate/init/_base.py +28 -10
- brainstate/init/_generic.py +175 -172
- brainstate/init/_random_inits.py +470 -415
- brainstate/init/_random_inits_test.py +150 -0
- brainstate/init/_regular_inits.py +66 -69
- brainstate/init/_regular_inits_test.py +51 -0
- brainstate/mixin.py +236 -244
- brainstate/mixin_test.py +44 -46
- brainstate/nn/__init__.py +26 -51
- brainstate/nn/_collective_ops.py +199 -0
- brainstate/nn/_dyn_impl/__init__.py +46 -0
- brainstate/nn/_dyn_impl/_dynamics_neuron.py +290 -0
- brainstate/nn/_dyn_impl/_dynamics_neuron_test.py +162 -0
- brainstate/nn/_dyn_impl/_dynamics_synapse.py +320 -0
- brainstate/nn/_dyn_impl/_dynamics_synapse_test.py +132 -0
- brainstate/nn/_dyn_impl/_inputs.py +154 -0
- brainstate/nn/{_projection/__init__.py → _dyn_impl/_projection_alignpost.py} +6 -13
- brainstate/nn/_dyn_impl/_rate_rnns.py +400 -0
- brainstate/nn/_dyn_impl/_rate_rnns_test.py +64 -0
- brainstate/nn/_dyn_impl/_readout.py +128 -0
- brainstate/nn/_dyn_impl/_readout_test.py +54 -0
- brainstate/nn/_dynamics/__init__.py +37 -0
- brainstate/nn/_dynamics/_dynamics_base.py +631 -0
- brainstate/nn/_dynamics/_dynamics_base_test.py +79 -0
- brainstate/nn/_dynamics/_projection_base.py +346 -0
- brainstate/nn/_dynamics/_state_delay.py +453 -0
- brainstate/nn/_dynamics/_synouts.py +161 -0
- brainstate/nn/_dynamics/_synouts_test.py +58 -0
- brainstate/nn/_elementwise/__init__.py +22 -0
- brainstate/nn/_elementwise/_dropout.py +418 -0
- brainstate/nn/_elementwise/_dropout_test.py +100 -0
- brainstate/nn/_elementwise/_elementwise.py +1122 -0
- brainstate/nn/_elementwise/_elementwise_test.py +171 -0
- brainstate/nn/_exp_euler.py +97 -0
- brainstate/nn/_exp_euler_test.py +36 -0
- brainstate/nn/_interaction/__init__.py +32 -0
- brainstate/nn/_interaction/_connections.py +726 -0
- brainstate/nn/_interaction/_connections_test.py +254 -0
- brainstate/nn/_interaction/_embedding.py +59 -0
- brainstate/nn/_interaction/_normalizations.py +388 -0
- brainstate/nn/_interaction/_normalizations_test.py +75 -0
- brainstate/nn/_interaction/_poolings.py +1179 -0
- brainstate/nn/_interaction/_poolings_test.py +219 -0
- brainstate/nn/_module.py +328 -0
- brainstate/nn/_module_test.py +211 -0
- brainstate/nn/metrics.py +309 -309
- brainstate/optim/__init__.py +14 -2
- brainstate/optim/_base.py +66 -0
- brainstate/optim/_lr_scheduler.py +363 -400
- brainstate/optim/_lr_scheduler_test.py +25 -24
- brainstate/optim/_optax_optimizer.py +103 -176
- brainstate/optim/_optax_optimizer_test.py +41 -1
- brainstate/optim/_sgd_optimizer.py +950 -1025
- brainstate/random/_rand_funs.py +3269 -3268
- brainstate/random/_rand_funs_test.py +568 -0
- brainstate/random/_rand_seed.py +149 -117
- brainstate/random/_rand_seed_test.py +50 -0
- brainstate/random/_rand_state.py +1360 -1318
- brainstate/random/_random_for_unit.py +13 -13
- brainstate/surrogate.py +1262 -1243
- brainstate/{nn/_projection/_utils.py → transform.py} +1 -2
- brainstate/typing.py +157 -130
- brainstate/util/__init__.py +52 -0
- brainstate/util/_caller.py +100 -0
- brainstate/util/_dict.py +734 -0
- brainstate/util/_dict_test.py +160 -0
- brainstate/util/_error.py +28 -0
- brainstate/util/_filter.py +178 -0
- brainstate/util/_others.py +497 -0
- brainstate/util/_pretty_repr.py +208 -0
- brainstate/util/_scaling.py +260 -0
- brainstate/util/_struct.py +524 -0
- brainstate/util/_tracers.py +75 -0
- brainstate/{_visualization.py → util/_visualization.py} +16 -16
- {brainstate-0.0.2.post20241009.dist-info → brainstate-0.1.0.dist-info}/METADATA +11 -11
- brainstate-0.1.0.dist-info/RECORD +135 -0
- brainstate/_module.py +0 -1637
- brainstate/_module_test.py +0 -207
- brainstate/nn/_base.py +0 -251
- brainstate/nn/_connections.py +0 -686
- brainstate/nn/_dynamics.py +0 -426
- brainstate/nn/_elementwise.py +0 -1438
- brainstate/nn/_embedding.py +0 -66
- brainstate/nn/_misc.py +0 -133
- brainstate/nn/_normalizations.py +0 -389
- brainstate/nn/_others.py +0 -101
- brainstate/nn/_poolings.py +0 -1229
- brainstate/nn/_poolings_test.py +0 -231
- brainstate/nn/_projection/_align_post.py +0 -546
- brainstate/nn/_projection/_align_pre.py +0 -599
- brainstate/nn/_projection/_delta.py +0 -241
- brainstate/nn/_projection/_vanilla.py +0 -101
- brainstate/nn/_rate_rnns.py +0 -410
- brainstate/nn/_readout.py +0 -136
- brainstate/nn/_synouts.py +0 -166
- brainstate/nn/event/csr.py +0 -312
- brainstate/nn/event/csr_test.py +0 -118
- brainstate/nn/event/fixed_probability.py +0 -276
- brainstate/nn/event/fixed_probability_test.py +0 -127
- brainstate/nn/event/linear.py +0 -220
- brainstate/nn/event/linear_test.py +0 -111
- brainstate/random/random_test.py +0 -593
- brainstate/transform/_autograd.py +0 -585
- brainstate/transform/_autograd_test.py +0 -1181
- brainstate/transform/_conditions.py +0 -334
- brainstate/transform/_conditions_test.py +0 -220
- brainstate/transform/_error_if.py +0 -94
- brainstate/transform/_error_if_test.py +0 -55
- brainstate/transform/_jit.py +0 -265
- brainstate/transform/_jit_test.py +0 -118
- brainstate/transform/_loop_collect_return.py +0 -502
- brainstate/transform/_loop_no_collection.py +0 -170
- brainstate/transform/_make_jaxpr.py +0 -739
- brainstate/transform/_make_jaxpr_test.py +0 -131
- brainstate/transform/_mapping.py +0 -109
- brainstate/transform/_progress_bar.py +0 -111
- brainstate/transform/_unvmap.py +0 -143
- brainstate/util.py +0 -746
- brainstate-0.0.2.post20241009.dist-info/RECORD +0 -87
- {brainstate-0.0.2.post20241009.dist-info → brainstate-0.1.0.dist-info}/LICENSE +0 -0
- {brainstate-0.0.2.post20241009.dist-info → brainstate-0.1.0.dist-info}/WHEEL +0 -0
- {brainstate-0.0.2.post20241009.dist-info → brainstate-0.1.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,346 @@
|
|
1
|
+
# Copyright 2024 BDP Ecosystem Limited. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
# ==============================================================================
|
15
|
+
from __future__ import annotations
|
16
|
+
|
17
|
+
from typing import Union, Callable
|
18
|
+
|
19
|
+
from brainstate._state import State
|
20
|
+
from brainstate.mixin import AlignPost, ParamDescriber, BindCondData, JointTypes
|
21
|
+
from brainstate.nn._collective_ops import call_order
|
22
|
+
from brainstate.nn._module import Module
|
23
|
+
from brainstate.util._others import get_unique_name
|
24
|
+
from ._dynamics_base import Dynamics, maybe_init_prefetch, Prefetch, PrefetchDelayAt
|
25
|
+
from ._synouts import SynOut
|
26
|
+
|
27
|
+
__all__ = [
|
28
|
+
'AlignPostProj',
|
29
|
+
'DeltaProj',
|
30
|
+
'CurrentProj',
|
31
|
+
]
|
32
|
+
|
33
|
+
|
34
|
+
class Interaction(Module):
|
35
|
+
__module__ = 'brainstate.nn'
|
36
|
+
|
37
|
+
|
38
|
+
def _check_modules(*modules):
|
39
|
+
# checking modules
|
40
|
+
for module in modules:
|
41
|
+
if not callable(module) and not isinstance(module, State):
|
42
|
+
raise TypeError(
|
43
|
+
f'The module should be a callable function or a brainstate.State, but got {module}.'
|
44
|
+
)
|
45
|
+
return tuple(modules)
|
46
|
+
|
47
|
+
|
48
|
+
def call_module(module, *args, **kwargs):
|
49
|
+
if callable(module):
|
50
|
+
return module(*args, **kwargs)
|
51
|
+
elif isinstance(module, State):
|
52
|
+
return module.value
|
53
|
+
else:
|
54
|
+
raise TypeError(
|
55
|
+
f'The module should be a callable function or a brainstate.State, but got {module}.'
|
56
|
+
)
|
57
|
+
|
58
|
+
|
59
|
+
def is_instance(x, cls) -> bool:
|
60
|
+
return isinstance(x, cls)
|
61
|
+
|
62
|
+
|
63
|
+
def get_post_repr(syn, out):
|
64
|
+
return f'{syn.identifier} // {out.identifier}'
|
65
|
+
|
66
|
+
|
67
|
+
def align_post_add_bef_update(
|
68
|
+
syn_desc: ParamDescriber[AlignPost],
|
69
|
+
out_desc: ParamDescriber[BindCondData],
|
70
|
+
post: Dynamics,
|
71
|
+
proj_name: str
|
72
|
+
):
|
73
|
+
# synapse and output initialization
|
74
|
+
_post_repr = get_post_repr(syn_desc, out_desc)
|
75
|
+
if not post._has_before_update(_post_repr):
|
76
|
+
syn_cls = syn_desc()
|
77
|
+
out_cls = out_desc()
|
78
|
+
|
79
|
+
# synapse and output initialization
|
80
|
+
post.add_current_input(proj_name, out_cls)
|
81
|
+
post._add_before_update(_post_repr, _AlignPost(syn_cls, out_cls))
|
82
|
+
syn = post._get_before_update(_post_repr).syn
|
83
|
+
out = post._get_before_update(_post_repr).out
|
84
|
+
return syn, out
|
85
|
+
|
86
|
+
|
87
|
+
class _AlignPost(Module):
|
88
|
+
def __init__(
|
89
|
+
self,
|
90
|
+
syn: Dynamics,
|
91
|
+
out: BindCondData
|
92
|
+
):
|
93
|
+
super().__init__()
|
94
|
+
self.syn = syn
|
95
|
+
self.out = out
|
96
|
+
|
97
|
+
def update(self, *args, **kwargs):
|
98
|
+
self.out.bind_cond(self.syn(*args, **kwargs))
|
99
|
+
|
100
|
+
|
101
|
+
class AlignPostProj(Interaction):
|
102
|
+
"""
|
103
|
+
Full-chain synaptic projection with the align-post reduction and the automatic synapse merging.
|
104
|
+
|
105
|
+
The ``full-chain`` means that the model needs to provide all information needed for a projection,
|
106
|
+
including ``pre`` -> ``delay`` -> ``comm`` -> ``syn`` -> ``out`` -> ``post``.
|
107
|
+
|
108
|
+
The ``align-post`` means that the synaptic variables have the same dimension as the post-synaptic neuron group.
|
109
|
+
|
110
|
+
The ``merging`` means that the same delay model is shared by all synapses, and the synapse model with same
|
111
|
+
parameters (such like time constants) will also share the same synaptic variables.
|
112
|
+
|
113
|
+
All align-post projection models prefer to use the event-driven computation mode. This means that the
|
114
|
+
``comm`` model should be the event-driven model.
|
115
|
+
|
116
|
+
Moreover, it's worth noting that ``FullProjAlignPost`` has a different updating order with all align-pre
|
117
|
+
projection models. The updating order of align-post projections is ``spikes`` -> ``comm`` -> ``syn`` -> ``out``.
|
118
|
+
While, the updating order of all align-pre projection models is usually ``spikes`` -> ``syn`` -> ``comm`` -> ``out``.
|
119
|
+
|
120
|
+
|
121
|
+
# brainstate.nn.AlignPostProj(
|
122
|
+
# LIF().prefetch('V').delay.at('I'), bst.surrogate.ReluGrad(), comm, syn, out, post
|
123
|
+
# )
|
124
|
+
|
125
|
+
Args:
|
126
|
+
pre: The pre-synaptic neuron group.
|
127
|
+
delay: The synaptic delay.
|
128
|
+
comm: The synaptic communication.
|
129
|
+
syn: The synaptic dynamics.
|
130
|
+
out: The synaptic output.
|
131
|
+
post: The post-synaptic neuron group.
|
132
|
+
"""
|
133
|
+
__module__ = 'brainstate.nn'
|
134
|
+
|
135
|
+
def __init__(
|
136
|
+
self,
|
137
|
+
*modules,
|
138
|
+
comm: Callable,
|
139
|
+
syn: Union[ParamDescriber[AlignPost], AlignPost],
|
140
|
+
out: Union[ParamDescriber[SynOut], SynOut],
|
141
|
+
post: Dynamics,
|
142
|
+
):
|
143
|
+
super().__init__(name=get_unique_name(self.__class__.__name__))
|
144
|
+
|
145
|
+
# checking modules
|
146
|
+
self.modules = _check_modules(*modules)
|
147
|
+
|
148
|
+
# checking communication model
|
149
|
+
if not callable(comm):
|
150
|
+
raise TypeError(
|
151
|
+
f'The communication should be an instance of callable function, but got {comm}.'
|
152
|
+
)
|
153
|
+
|
154
|
+
# checking synapse and output models
|
155
|
+
if is_instance(syn, ParamDescriber[AlignPost]):
|
156
|
+
if not is_instance(out, ParamDescriber[SynOut]):
|
157
|
+
raise TypeError(
|
158
|
+
f'The output should be an instance of describer {ParamDescriber[SynOut]} when '
|
159
|
+
f'the synapse is a describer, but we got {out}.'
|
160
|
+
)
|
161
|
+
merging = True
|
162
|
+
else:
|
163
|
+
if not is_instance(out, SynOut):
|
164
|
+
raise TypeError(
|
165
|
+
f'The output should be an instance of {SynOut} when the synapse is '
|
166
|
+
f'not a describer, but we got {out}.'
|
167
|
+
)
|
168
|
+
merging = False
|
169
|
+
self.merging = merging
|
170
|
+
|
171
|
+
# checking post model
|
172
|
+
if not is_instance(post, Dynamics):
|
173
|
+
raise TypeError(
|
174
|
+
f'The post should be an instance of {Dynamics}, but got {post}.'
|
175
|
+
)
|
176
|
+
|
177
|
+
if merging:
|
178
|
+
# synapse and output initialization
|
179
|
+
syn, out = align_post_add_bef_update(syn_desc=syn, out_desc=out, post=post, proj_name=self.name)
|
180
|
+
else:
|
181
|
+
post.add_current_input(self.name, out)
|
182
|
+
|
183
|
+
# references
|
184
|
+
self.comm = comm
|
185
|
+
self.syn: JointTypes[Dynamics, AlignPost] = syn
|
186
|
+
self.out: BindCondData = out
|
187
|
+
self.post: Dynamics = post
|
188
|
+
|
189
|
+
@call_order(2)
|
190
|
+
def init_state(self, *args, **kwargs):
|
191
|
+
for module in self.modules:
|
192
|
+
maybe_init_prefetch(module, *args, **kwargs)
|
193
|
+
|
194
|
+
def update(self, *args):
|
195
|
+
# call all modules
|
196
|
+
for module in self.modules:
|
197
|
+
x = call_module(module, *args)
|
198
|
+
args = (x,)
|
199
|
+
# communication module
|
200
|
+
x = self.comm(*args)
|
201
|
+
# add synapse input
|
202
|
+
self.syn.add_delta_input(self.name, x)
|
203
|
+
if not self.merging:
|
204
|
+
# synapse and output interaction
|
205
|
+
conductance = self.syn()
|
206
|
+
self.out.bind_cond(conductance)
|
207
|
+
|
208
|
+
|
209
|
+
class DeltaProj(Interaction):
|
210
|
+
"""Full-chain of the synaptic projection for the Delta synapse model.
|
211
|
+
|
212
|
+
The synaptic projection requires the input is the spiking data, otherwise
|
213
|
+
the synapse is not the Delta synapse model.
|
214
|
+
|
215
|
+
The ``full-chain`` means that the model needs to provide all information needed for a projection,
|
216
|
+
including ``pre`` -> ``delay`` -> ``comm`` -> ``post``.
|
217
|
+
|
218
|
+
**Model Descriptions**
|
219
|
+
|
220
|
+
.. math::
|
221
|
+
|
222
|
+
I_{syn} (t) = \sum_{j\in C} g_{\mathrm{max}} * \delta(t-t_j-D)
|
223
|
+
|
224
|
+
where :math:`g_{\mathrm{max}}` denotes the chemical synaptic strength,
|
225
|
+
:math:`t_j` the spiking moment of the presynaptic neuron :math:`j`,
|
226
|
+
:math:`C` the set of neurons connected to the post-synaptic neuron,
|
227
|
+
and :math:`D` the transmission delay of chemical synapses.
|
228
|
+
For simplicity, the rise and decay phases of post-synaptic currents are
|
229
|
+
omitted in this model.
|
230
|
+
|
231
|
+
# brainstate.nn.DeltaInteraction(
|
232
|
+
# LIF().prefetch('V'), bst.surrogate.ReluGrad(), comm, post
|
233
|
+
# )
|
234
|
+
|
235
|
+
Args:
|
236
|
+
pre: The pre-synaptic neuron group.
|
237
|
+
delay: The synaptic delay.
|
238
|
+
comm: DynamicalSystem. The synaptic communication.
|
239
|
+
post: DynamicalSystem. The post-synaptic neuron group.
|
240
|
+
"""
|
241
|
+
|
242
|
+
__module__ = 'brainstate.nn'
|
243
|
+
|
244
|
+
def __init__(self, *modules, comm: Callable, post: Dynamics, label=None):
|
245
|
+
super().__init__(name=get_unique_name(self.__class__.__name__))
|
246
|
+
|
247
|
+
self.label = label
|
248
|
+
|
249
|
+
# checking modules
|
250
|
+
self.modules = _check_modules(*modules)
|
251
|
+
|
252
|
+
# checking communication model
|
253
|
+
if not callable(comm):
|
254
|
+
raise TypeError(
|
255
|
+
f'The communication should be an instance of callable function, but got {comm}.'
|
256
|
+
)
|
257
|
+
self.comm = comm
|
258
|
+
|
259
|
+
# post model
|
260
|
+
if not isinstance(post, Dynamics):
|
261
|
+
raise TypeError(
|
262
|
+
f'The post should be an instance of {Dynamics}, but got {post}.'
|
263
|
+
)
|
264
|
+
self.post = post
|
265
|
+
|
266
|
+
@call_order(2)
|
267
|
+
def init_state(self, *args, **kwargs):
|
268
|
+
for module in self.modules:
|
269
|
+
maybe_init_prefetch(module, *args, **kwargs)
|
270
|
+
|
271
|
+
def update(self, *x):
|
272
|
+
for module in self.modules:
|
273
|
+
x = (call_module(module, *x),)
|
274
|
+
assert len(x) == 1, f'The output of the modules should be a single value, but got {x}.'
|
275
|
+
x = self.comm(x[0])
|
276
|
+
self.post.add_delta_input(self.name, x, label=self.label)
|
277
|
+
|
278
|
+
|
279
|
+
class CurrentProj(Interaction):
|
280
|
+
"""
|
281
|
+
Full-chain synaptic projection with the align-pre reduction and delay+synapse updating and merging.
|
282
|
+
|
283
|
+
The ``full-chain`` means that the model needs to provide all information needed for a projection,
|
284
|
+
including ``pre`` -> ``delay`` -> ``syn`` -> ``comm`` -> ``out`` -> ``post``.
|
285
|
+
Note here, compared to ``FullProjAlignPreSD``, the ``delay`` and ``syn`` are exchanged.
|
286
|
+
|
287
|
+
The ``align-pre`` means that the synaptic variables have the same dimension as the pre-synaptic neuron group.
|
288
|
+
|
289
|
+
The ``delay+synapse updating`` means that the projection first delivers the pre neuron output (usually the
|
290
|
+
spiking) to the delay model, then computes the synapse states, and finally computes the synaptic current.
|
291
|
+
|
292
|
+
The ``merging`` means that the same delay model is shared by all synapses, and the synapse model with same
|
293
|
+
parameters (such like time constants) will also share the same synaptic variables.
|
294
|
+
|
295
|
+
Neither ``FullProjAlignPreDS`` nor ``FullProjAlignPreSD`` facilitates the event-driven computation.
|
296
|
+
This is because the ``comm`` is computed after the synapse state, which is a floating-point number, rather
|
297
|
+
than the spiking. To facilitate the event-driven computation, please use align post projections.
|
298
|
+
|
299
|
+
# bint.CurrentInteraction(
|
300
|
+
# LIF().align_pre(bst.nn.Expon.desc()).prefetch('g'), comm, out, post
|
301
|
+
# )
|
302
|
+
|
303
|
+
Args:
|
304
|
+
prefetch: The synaptic dynamics.
|
305
|
+
comm: The synaptic communication.
|
306
|
+
out: The synaptic output.
|
307
|
+
post: The post-synaptic neuron group.
|
308
|
+
"""
|
309
|
+
__module__ = 'brainstate.nn'
|
310
|
+
|
311
|
+
def __init__(
|
312
|
+
self,
|
313
|
+
prefetch: Union[Prefetch, PrefetchDelayAt],
|
314
|
+
comm: Callable,
|
315
|
+
out: SynOut,
|
316
|
+
post: Dynamics,
|
317
|
+
):
|
318
|
+
super().__init__(name=get_unique_name(self.__class__.__name__))
|
319
|
+
|
320
|
+
# pre-synaptic neuron group
|
321
|
+
if not isinstance(prefetch, (Prefetch, PrefetchDelayAt)):
|
322
|
+
raise TypeError(f'The pre should be a Prefetch or PrefetchDelayAt, but got {prefetch}.')
|
323
|
+
self.prefetch = prefetch
|
324
|
+
|
325
|
+
# check out
|
326
|
+
if not isinstance(out, SynOut):
|
327
|
+
raise TypeError(f'The out should be a SynOut, but got {out}.')
|
328
|
+
self.out = out
|
329
|
+
|
330
|
+
# check post
|
331
|
+
if not isinstance(post, Dynamics):
|
332
|
+
raise TypeError(f'The post should be a Dynamics, but got {post}.')
|
333
|
+
self.post = post
|
334
|
+
post.add_current_input(self.name, out)
|
335
|
+
|
336
|
+
# output initialization
|
337
|
+
self.comm = comm
|
338
|
+
|
339
|
+
@call_order(2)
|
340
|
+
def init_state(self, *args, **kwargs):
|
341
|
+
maybe_init_prefetch(self.prefetch, *args, **kwargs)
|
342
|
+
|
343
|
+
def update(self, *x):
|
344
|
+
x = self.prefetch(*x)
|
345
|
+
x = self.comm(x)
|
346
|
+
self.out.bind_cond(x)
|