# Synaptic plasticity¶

The default type of synaptic connection in PyNN is static, with fixed synaptic weights. To model dynamic synapses, for which the synaptic weight (and possibly other properties, such as rise-time) varies depending on the recent history of post- and/or pre-synaptic activity, we use the same idea as for neurons, of standardized, named models that have the same interface and behaviour across simulators, even if the underlying implementation may be very different.

Where the approach for dynamic synapses differs from that for neurons is that we attempt a greater degree of compositionality, i.e. we decompose models into a number of components, for example for short-term and long-term dynamics, or for the timing-dependence and the weight-dependence of STDP rules, that can then be composed in different ways.

The advantage of this is that if we have n differerent models for component ‘’A’’ and m models for component ‘’B’‘, then we require only n + m models rather than n x m, which had advantages in terms of code-simplicity and in shorter model names. The disadvantage is that not all combinations may exist, if the underlying simulator implements composite models rather than using components itself: in this situation, PyNN checks whether a given composite model AB exists for a given simulator and raises an Exception if it does not.

The composite approach may be extended to neuron models in future versions of the PyNN interface depending on the experience with composite synapse models.

To set the model of synapse dynamics to use for the connections of a given Projection, we pass a SynapseDynamics object as the synapse_dynamics keyword argument to the Projection constructor.

The SynapseDynamics object is simply a container that has attributes fast, which, if set, is an instance of a subclass of the abstract class ShortTermPlasticityMechanism, and slow, which is an instance of a subclass of the abstract class STDPMechanism.

Only a single subclass of ShortTermPlasticityMechanism is currently available in PyNN: TsodkysMarkramMechanism.

STDPMechanism objects are further decomposed into components for the timing-dependence, weight-dependence and post-synaptic voltage-dependence of the mechanism.

An example of defining a Projection with depressing synapses, but no long-term plasticity:

>>> pre = post = Population(50, IF_cond_exp)

>>> params = {'U': 0.5, 'tau_rec': 100.0, 'tau_facil': 0.0}
>>> depressing_syn = SynapseDynamics(fast=TsodyksMarkramMechanism(**params))
>>> prj = Projection(pre, post, AllToAllConnector(),
...                  synapse_dynamics = depressing_syn)


and one with long-term plasticity, using a spike-pair rule and with additive weight updates (i.e. the weight change is independent of the current weight value):

>>> stdp_model = STDPMechanism(
...    timing_dependence=SpikePairRule(tau_plus=20.0, tau_minus=20.0),
...                                               A_plus=0.01, A_minus=0.012)
... )
>>> prj2 = Projection(pre, post, FixedProbabilityConnector(p_connect=0.1),
...                   synapse_dynamics=SynapseDynamics(slow=stdp_model))


Just as with synaptic weights and delays for static synapses, the parameters of dynamic synapses can be obtained and set with the getSynapseDynamics(), setSynapseDynamics() and randomizeSynapseDynamics() methods of the Projection class:

>>> prj.setSynapseDynamics('tau_rec', 50.0)
>>> prj.getSynapseDynamics('tau_rec')[:5]
[50.0, 50.0, 50.0, 50.0, 50.0]
>>> from pyNN.random import RandomDistribution
>>> distr = RandomDistribution('normal', [0.02, 0.05])
>>> prj2.randomizeSynapseDynamics('w_max', distr)
>>> prj2.getSynapseDynamics('w_max')[:5]
[-0.056605932509016577, 0.063197908706714212, 0.034940801886916589, 0.010755581262934901, 0.011700727992415299]


There are a number of examples of networks using synaptic plasticity in the examples directory of the source distribution.