/*
* test_stdp_synapse.sli
*
* This file is part of NEST.
*
* Copyright (C) 2004 The NEST Initiative
*
* NEST is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* NEST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NEST. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* BeginDocumentation
Name: testsuite::test_stdp_synapse - basic test of stdp_synapse
Synopsis: (test_stdp_synapse) run
Description:
A parrot_neuron that repeats the spikes from a poisson generator is
connected to an iaf_psc_alpha that is driven by inh. and exc. poisson input.
The synapse is an stdp_synapse. After the simulation, we go through the pre-
and postsyn. spike-trains spike by spike and try to reproduce the STDP
results. The final weight obtained after simulation is compared to the final
weight obtained from the test.
Author: Kunkel, Nov 2010
*/
/unittest (8831) require
/unittest using
ResetKernel
/resolution 0.1 def %1.0 def %2.0 -4 pow def % simulation step size
0 << /resolution resolution >> SetStatus %/tics_per_ms 10000.0 >> SetStatus
%%% input parameters %%%
/K_exc 8000.0 def % number of exc. inputs
/K_inh 2000.0 def % number of inh. inputs
/nu 10.0 def % equil. firing rate
/nu_x 1.7 def % external rate
/w_exc 45.0 def % strength of exc. connections
/w_inh w_exc -5.0 mul def % strength of inh. connections
/delay 1.0 def % synaptic transmission delay
/axonal_delay 0.0 def
/backpr_delay delay axonal_delay sub def
%%% STDP parameters %%%
/alpha 1.1 def
/lambda 0.01 def
/tau_plus 20.0 def
/tau_minus 30.0 def
/mu_plus 1.0 def % multiplicative
/mu_minus 1.0 def % multiplicative
/w_max w_exc 2.0 mul def
%%% create poisson generators, neurons and spike detector %%%
/pg_exc /poisson_generator << /rate K_exc nu nu_x add mul >> Create def
/pg_inh /poisson_generator << /rate K_inh nu mul >> Create def
/pg_pre /poisson_generator << /rate nu >> Create def
/parrot /parrot_neuron Create def
/neuron /iaf_psc_alpha << /tau_minus tau_minus >> Create def
/spike_detector << /to_file false
/to_memory true
/precision 15
>> SetDefaults
/sd_pre /spike_detector Create def
/sd_post /spike_detector Create def
%%% connect %%%
/stdp_synapse << /alpha alpha
/lambda lambda
/tau_plus tau_plus
/mu_plus mu_plus
/mu_minus mu_minus
/Wmax w_max
>> SetDefaults
pg_exc neuron w_exc delay Connect
pg_inh neuron w_inh delay Connect
pg_pre parrot w_exc delay Connect
parrot neuron w_exc delay /stdp_synapse Connect
parrot sd_pre Connect
neuron sd_post Connect
%%% simulate and get data %%%
10000.0 Simulate
/pre_spikes sd_pre GetStatus /events get /times get cva { axonal_delay add } Map def
/post_spikes sd_post GetStatus /events get /times get cva { backpr_delay add } Map def
/final_weight << /source parrot /target neuron >> FindConnections 0 get /weight get def
%%% check final weight %%%
cout 15 setprecision
/K_plus 0.0 def
/K_minus 0.0 def
/last_pre 0 def
/last_post 0 def
/j 0 def
/i 0 def
/post_spike post_spikes i get def
/pre_spike pre_spikes j get def
/w w_exc w_max div def
/update_K_plus
{
last_pre pre_spike sub tau_plus div exp K_plus mul 1.0 add /K_plus Set
}
def
/update_K_minus
{
last_post post_spike sub tau_minus div exp K_minus mul 1.0 add /K_minus Set
}
def
/next_pre_spike
{
j 1 add /j Set
pre_spike /last_pre Set
pre_spikes j get /pre_spike Set
}
def
/next_post_spike
{
i 1 add /i Set
post_spike /last_post Set
post_spikes i get /post_spike Set
}
def
/facilitate
{
( w + lambda * (1.0-w)**mu_plus * K_plus * exp((last_pre-post_spike)/tau_plus) ) ExecMath
dup 1.0 lt { /w Set } { pop 1.0 /w Set } ifelse
%(facilitation) =only (\t) =only last_pre =only (\t) =only post_spike =only (\t) =only w w_max mul =
}
def
/depress
{
( w - lambda * alpha * w**mu_minus * K_minus * exp((last_post-pre_spike)/tau_minus) ) ExecMath
dup 0.0 gt { /w Set } { pop 0.0 /w Set } ifelse
%(depression) =only (\t) =only last_post =only (\t) =only pre_spike =only (\t) =only w w_max mul =
}
def
{
pre_spike post_spike eq
{ % pre- and post-syn. spike at the same time
last_post post_spike neq { facilitate } if
last_pre pre_spike neq { depress } if
%(pre == post) =only (\t) =only pre_spike =only (\t) =only post_spike =only (\t) =only w w_max mul =
j 1 add pre_spikes length lt
{
update_K_plus
next_pre_spike
i 1 add post_spikes length lt
{
update_K_minus
next_post_spike
}
if
}
{
exit
}
ifelse
}
{
pre_spike post_spike lt
{ % next spike is a pre-syn. spike
depress
update_K_plus
j 1 add pre_spikes length lt
{
next_pre_spike
}
{
%(last presyn spike) =
% we don't consider the post-syn. spikes after the last pre-syn. spike
exit
}
ifelse
}
{ % next spike is a post-syn. spike
facilitate
update_K_minus
i 1 add post_spikes length lt
{
next_post_spike
}
{
%(last postsyn spike) =
% we DO consider the pre-syn. spikes after the last post-syn. spike
post_spike /last_post Set
pre_spikes dup length 1 sub get resolution add /post_spike Set % to make sure we don't come here again
}
ifelse
}
ifelse
}
ifelse
}
loop
%final_weight w w_max mul sub abs dup = 1e-13 leq =
final_weight w w_max mul sub abs 1e-13 leq assert_or_die