# Changing weights during a run when an event occurred

**URL:** <https://brian.discourse.group/t/changing-weights-during-a-run-when-an-event-occurred/635>\
**Category:** Support\
**Tags:** synapses\
**Created:** [20 March 2022 22:29 UTC](https://brian.discourse.group/t/changing-weights-during-a-run-when-an-event-occurred/635 "2022-03-20T22:29:23Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![RRHHAAWW](https://yyz2.discourse-cdn.com/free1/user_avatar/brian.discourse.group/rrhhaaww/32/281_2.png) [@RRHHAAWW](https://brian.discourse.group/u/RRHHAAWW)\
**Post date:** [20 March 2022 22:29 UTC](https://brian.discourse.group/t/changing-weights-during-a-run-when-an-event-occurred/635/1 "2022-03-20T22:29:23Z")

</div>

# Description of problem

How to change the weights to other neurons when a neuron fired?  
The [event-driven example](https://brian2.readthedocs.io/en/stable/user/synapses.html#event-driven-updates) on the Synapses page changes the weight of the neuron that fired, but not the weight to other neurons.

# Minimal code to reproduce problem

So far I was able to achieve a similar goal by breaking down the simulation into smaller segments, and update the weight if the spike\_mon detected spikes. But this is inaccurate and not event-driven.

```auto
from brian2 import *

eqs = '''
dv/dt = (I-v)/tau : 1
I : 1
tau : second
'''

G = NeuronGroup(3, eqs, threshold='v>1', reset='v = 0', method='exact')
G.I = [2, 0, 0]
G.tau = [10]*ms

S = Synapses(G, G, model='w : 1', on_pre='v_post += w')
S.connect(i=0,j=[1,2])
S.w = [0.5,1]
S.delay = [1, 0]*ms # add a delay to demonstrate the issue

state_mon = StateMonitor(G,'v', record=True)
spike_mon = SpikeMonitor(G)

net = Network(collect())
net.add(S)
net.add(state_mon)
net.add(spike_mon)

#total run=50ms, but break the run into 10ms segment
for seg in range(5):
    net.run(10*ms)
    # check if a neuron fired every 10ms
    if(spike_mon.count[1] != 0 or spike_mon.count[2] != 0):
        # if a neuron fired, set the other neuron's weight to 0
        if(spike_mon.count[1] > spike_mon.count[2]):
            S.w = [1,0]
        else:
            S.w = [0,1]

plt.figure(1)
plt.subplot(311)
plot(state_mon.t/ms, state_mon.v[0], label='Neuron 0')
ylim([0,1.5])
ylabel('Neuron_0')

plt.subplot(312)
plot(state_mon.t/ms, state_mon.v[1], label='Neuron 1')
ylim([0,1.5])
ylabel('Neuron_1')

plt.subplot(313)
plot(state_mon.t/ms, state_mon.v[2], label='Neuron 2')
ylim([0,1.5])
ylabel('Neuron_2')
xlabel('Time (ms)')
show()

```

# What you have already tried

I was thinking to add a backward synapse (blue arrow in the figure) to trigger the neuron in blue to update the weight. But I couldn’t figure out what syntax I should put for the `model`

 ![STDP](https://global.discourse-cdn.com/free1/uploads/brian/original/1X/f9bdce0723250f10951f5e9f75bf7ab7d9809770.png)

# Expected output (if relevant)

 ![02](https://global.discourse-cdn.com/free1/uploads/brian/original/1X/0b2422795f8b078676e6a632e75469fc95c8eecd.png)

# Actual output (if relevant)

 ![01](https://global.discourse-cdn.com/free1/uploads/brian/original/1X/15c70e7844afc1bef28f8aefd05aff160d7e8bcd.png)

# Full traceback of error (if relevant)

---

<div class="post-metadata">

**Author:** ![mstimberg](https://yyz2.discourse-cdn.com/free1/user_avatar/brian.discourse.group/mstimberg/32/11_2.png) [@mstimberg](https://brian.discourse.group/u/mstimberg)\
**Post date:** [22 March 2022 11:14 UTC](https://brian.discourse.group/t/changing-weights-during-a-run-when-an-event-occurred/635/2 "2022-03-22T11:14:30Z")

</div>

Hi @RRHHAAWW,  
you can implement this by having another “synapse”, that goes from the neurons to the actual synapses. When a neuron spikes, it can change the weight of the targeted synapse. When you set this up you have to be careful, since the target index `j`, corresponds to the index of the _synapse_ (i.e. 0 is the first synapse that was created, 1 is the second synapse that was created). In your example, this index is very easy to figure out, but for more complex connection patterns it is less straightforward. With this `i=[1, 2], j=[1, 0]` setup, neuron 1 is connected to the synapse with index 1, i.e. the 0→2 connection, and neuron 2 is connected to the synapse with index 0, i.e. the 0→1 connection. Here’s the full adapted example:

```nohighlight
from brian2 import *

eqs = '''
dv/dt = (I-v)/tau : 1
I : 1
tau : second
'''

G = NeuronGroup(3, eqs, threshold='v>1', reset='v = 0', method='exact')
G.I = [2, 0, 0]
G.tau = [10]*ms

S = Synapses(G, G, model='w : 1', on_pre='v_post += w')
S.connect(i=0,j=[1,2])
S.w = [0.5,1]
S.delay = [1, 0]*ms # add a delay to demonstrate the issue

# Change weights of the synapse to the other neuron if a neuron spikes
S_suppress = Synapses(G, S, on_pre='w_post = 0')
S_suppress.connect(i=[1, 2], j=[1, 0]) # note that the j values are *synapse indices*

state_mon = StateMonitor(G,'v', record=True)
spike_mon = SpikeMonitor(G)

net = Network(collect())

net.run(50*ms)

plt.figure(1)
plt.subplot(311)
plot(state_mon.t/ms, state_mon.v[0], label='Neuron 0')
ylim([0,1.5])
ylabel('Neuron_0')

plt.subplot(312)
plot(state_mon.t/ms, state_mon.v[1], label='Neuron 1')
ylim([0,1.5])
ylabel('Neuron_1')

plt.subplot(313)
plot(state_mon.t/ms, state_mon.v[2], label='Neuron 2')
ylim([0,1.5])
ylabel('Neuron_2')
xlabel('Time (ms)')
show()

```

```auto

```

---

<div class="post-metadata">

**Author:** ![RRHHAAWW](https://yyz2.discourse-cdn.com/free1/user_avatar/brian.discourse.group/rrhhaaww/32/281_2.png) [@RRHHAAWW](https://brian.discourse.group/u/RRHHAAWW)\
**Post date:** [23 March 2022 04:24 UTC](https://brian.discourse.group/t/changing-weights-during-a-run-when-an-event-occurred/635/3 "2022-03-23T04:24:38Z")

</div>

This is what I was looking for. Thank you.  
In my project, there are around 65000 synapses. This method almost triples the connection and the time it takes to create synapses seems to be O(n^2) or even longer. Right now the synapses are created in loops. I’m wondering if using a flat array to create synapses makes it faster?

---

<div class="post-metadata">

**Author:** ![mstimberg](https://yyz2.discourse-cdn.com/free1/user_avatar/brian.discourse.group/mstimberg/32/11_2.png) [@mstimberg](https://brian.discourse.group/u/mstimberg)\
**Post date:** [23 March 2022 09:30 UTC](https://brian.discourse.group/t/changing-weights-during-a-run-when-an-event-occurred/635/4 "2022-03-23T09:30:11Z")

</div>

It is definitely much faster to make less `connect` calls with bigger arrays. One main reason is that each of the `connect` call will generate some Cython/C++ code that needs to get compiled. This is faster than creating the synapses in Python, but is only really worth it for big arrays (and in general probably not worth it at all for `connect` calls with indices instead of string expressions). A quick workaround could be to set `prefs.codegen.target = 'numpy'` before creating the synapses and switching it back to `prefs.codegen.target = 'cython'` before the start of the simulation.
