# 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),
... weight_dependence=AdditiveWeightDependence(w_min=0, w_max=0.02,
... 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.