/* cuba_stdp.sli Copyright (C) 2004 The NEST Initiative This file 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. This file 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 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ /* The fifth simulator review benchmark is implemented as a variation of the * Brunel Network * (from the docu of brunel.sli) The SLI code in this file creates a sparsely coupled network of excitatory and inhibitory neurons. Connections within and across both populations are created at random. Both neuron populations receive Poissonian background input. The spike output of 1000 neurons are recorded. Neurons are modeled as leaky integrate-and-fire neurons with current-injecting synapses (exp functions). Excitatory-excitatory synapses implement multiplicative STDP. Marc-Oliver Gewaltig, Abigail Morrison, Wiebke Potjans, Tobias Potjans Usage: This file (cuba_stdp.sli) is used on its own, e.g. nest cuba_stdp.sli If virtual_processes is set to a value greater than one, the benchmarks can will be run with that number of virtual processes. If you do not use MPI, each virtual process is mapped to one POSIX thread. You should not use more POSIX threads per machine than there are processor cores. If you use MPI, you can run the benchmark in a distributed fashion using mpirun, e.g. mpirun -np 2 nest cuba_stdp.sli In this case, the number of MPI processes must divide the number of virtual processes without remainder. You could, e.g. use 4 virtual processes on a mini-cluster of 2 machines with 2 CPUs each. */ %%% PARAMETER SECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % define all relevant parameters: changes should be made here % all data is place in the userdict dictionary % A dictionary is a list of name value pairs, enclosed in << and >> % Here we use dictionaries to encapsulate the parameters for the different % benchmarks /plastic_brunel_params << /virtual_processes 1 % number of virtual processes to use /simtime 2000.0 ms % simulated time /dt 0.1 ms % simulation step /NE 9000 % number of excitatory neurons /NI 2250 % number of inhibitory neurons /model /iaf_psc_exp % the neuron model to use /model_params << % Set variables for iaf_psc_exp /E_L 0.0 mV % Resting membrane potential [mV] /V_m 0.0 mV % Initial membrane potential [mV] /V_th 20.0 mV % Threshold [mV] /V_reset 0.0 mV % Reset Potential [mV] /C_m 250.0 pF % Capacity of the membrane [pF] /tau_m 20.0 ms % Membrane time constant [ms] % V randomly initialized see below >> /mean_potential 7.0 mV /sigma_potential 5.0 mV /epsilon 0.1 % Connection probability /delay 1.5 ms % synaptic delay, static connections [ms] /JE 35.0 pA % peak amplitude of PSC [pA] /g 5.0 % relative strength of inhib. connections /plastic_synapses true /stdp_params << /delay 1.5 ms /alpha 1.05 %STDP asymmetry parameter >> /sigma_w 3.0 %initial standard dev. of E->E synapses [pA] /stimulus /poisson_generator /stimulus_params << /rate 900.0 4.5 mul Hz % rate of inital poisson stimulus >> /detector /spike_detector /detector_params << /withtime true /withgid true /to_file true /label (cuba_stdp) >> /Nrec 500 % number of neurons per population to record from >> def % Here we resolve parameter dependencies, by making the independent % values visible plastic_brunel_params dup using << /E_synapse_params << /weight JE % excitatory synaptic conductance >> /I_synapse_params << /weight JE g mul -1.0 mul % inhibitory synaptic current [pA] >> >> join stdp_params << /weight JE /Wmax 2.0 JE mul %max strength of E->E synapses [pA] >> join % create one single random number generator rngdict /knuthlfg get 238 CreateRNG /myrng Set % normal distribution to draw several quantities from myrng rdevdict /normal_clipped_right get CreateRDV /normal_dv Set normal_dv << /mu mean_potential /std sigma_potential /max model_params /V_th get >> SetStatus %%% FUNCTION SECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Take spike detector, find total number of spikes registered, % return average rate per neuron in Hz. % NOTE: If you are running with several MPI processes, this % function only gives an approximation to the true rate. % % spike_det ComputeRate -> rate /ComputeRate { GetStatus /n_events get /nspikes Set % We need to guess how many neurons we record from. % This assumes an even distribution of nodes across % processes, as well as homogeneous activity in the % network. This is ok for this type of symmetric % network but should not be considered a general % solution. plastic_brunel_params /Nrec get cvd NumProcesses div /nnrn Set nspikes nnrn plastic_brunel_params /simtime get mul div 1000 mul % convert from mHz to Hz, leave on stack end } bind % optional, improves performance def /BuildNetwork { tic % start timer on construction % set global kernel parameters 0 << /resolution dt /total_num_virtual_procs virtual_processes /overwrite_files true >> SetStatus model model_params SetDefaults M_INFO (BuildNetwork) (Creating excitatory population.) message % show message /E_net model [ NE ] LayoutNetwork def M_INFO (BuildNetwork) (Creating inhibitory population.) message % show message /I_net model [ NI ] LayoutNetwork def M_INFO (BuildNetwork) (Creating excitatory stimulus generator.) message /E_stimulus stimulus Create def E_stimulus stimulus_params SetStatus /I_stimulus stimulus Create def I_stimulus stimulus_params SetStatus % one detector would in principle be enough, % but by recording the populations separately, % we save ourselves a lot of sorting work later M_INFO (BuildNetwork) (Creating excitatory spike detector.) message /E_detector detector Create def E_detector detector_params SetStatus M_INFO (BuildNetwork) (Creating inhibitory spike detector.) message /I_detector detector Create def I_detector detector_params SetStatus % some connecting functions need lists (arrays) over all % neurons they should work on, so we need to extract these % lists from the subnetworks % obtain array with GIDs of all excitatory neurons /E_neurons E_net GetLocalNodes def % obtain array with GIDs of all inhibitory neurons /I_neurons I_net GetLocalNodes def % all neurons /allNeurons E_neurons I_neurons join def /N allNeurons length def /CE NE epsilon mul iround def %number of incoming excitatory connections /CI NI epsilon mul iround def %number of incomining inhibitory connections M_INFO (BuildNetwork) (Configuring neuron parameters.) message allNeurons { << /V_m normal_dv Random >> SetStatus } forall % Create custom synapse types with appropriate values for % our excitatory and inhibitory connections /static_synapse << /delay delay >> SetDefaults /static_synapse /syn_ex E_synapse_params CopyModel /static_synapse /syn_in I_synapse_params CopyModel /stdp_synapse stdp_params SetDefaults plastic_synapses { /synapse_model /stdp_synapse def% plastic } { /synapse_model /syn_ex def } ifelse % create a dictionary containing the initialization function % InitSynapse, which will be called by RandomConvergentConnect % before each connection to be established. /init_dict << % call: i InitSynapse /InitSynapse { /i Set synapse_model << /weight weights i get % weights will be added to the dict later >> SetDefaults } >> def M_INFO (BuildNetwork) (Connecting stimulus generators.) message % Connect Poisson generator to neuron E_stimulus E_neurons /syn_ex DivergentConnect I_stimulus I_neurons /syn_ex DivergentConnect M_INFO (BuildNetwork) (Connecting excitatory -> excitatory population.) message E_neurons { /target Set % create an array of CE elements and store it in 'rnd_weights'; % each element is chosen from a normal distribution with mean % value JE and standard deviation sigma_w, add to init dictionary CE array { ; normal_dv Random sigma_w mul JE add } Map /rnd_weights Set init_dict cvo << /weights rnd_weights >> SetStatus % E -> E connections E_neurons % source population [we pick from this] target % target neuron CE % number of source neurons to pick init_dict % initialization dictionary synapse_model RandomConvergentConnect } bind forall M_INFO (BuildNetwork) (Connecting excitatory -> inhibitory population.) message I_neurons { /target Set E_neurons target CE /syn_ex RandomConvergentConnect } bind forall M_INFO (BuildNetwork) (Connecting inhibitory -> excitatory population.) message E_neurons { /target Set % I -> E connections % as above, but on a single line I_neurons target CI /syn_in RandomConvergentConnect } bind forall M_INFO (BuildNetwork) (Connecting inhibitory -> inhibitory population.) message I_neurons { /target Set I_neurons target CI /syn_in RandomConvergentConnect } bind forall % Spike detectors are connected to the first Nrec neurons in each % population. Since neurons are equal and connectivity is homogeneously % randomized, this is equivalent to picking Nrec neurons at random % from each population M_INFO (BuildNetwork) (Connecting spike detectors.) message E_neurons Nrec Take E_detector ConvergentConnect I_neurons Nrec Take I_detector ConvergentConnect % read out time used for building toc /BuildCPUTime Set } def % end of buildnetwork { ResetKernel M_INFO setverbosity BuildNetwork tic simtime Simulate toc /SimCPUTime Set % number of synapses---just so we know /Nsyn CE CI add % internal synapses N mul Nrec 2 mul % "synapses" to spike detectors add N add % "synapses" from poisson generator def (\nBrunel Network Simulation) = (Building time : ) =only BuildCPUTime =only ( s) = (Simulation time : ) =only SimCPUTime =only ( s\n) = (Number of Neurons : ) =only N = (Number of Synapses: ) =only Nsyn = (Excitatory rate : ) =only E_detector ComputeRate =only ( Hz) = (Inhibitory rate : ) =only I_detector ComputeRate =only ( Hz) = } exec