NEST  2.6.0,not_revisioned_source_dir@0
stdp_dopa_connection.h
Go to the documentation of this file.
1 /*
2  * stdp_dopa_connection.h
3  *
4  * This file is part of NEST.
5  *
6  * Copyright (C) 2004 The NEST Initiative
7  *
8  * NEST is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * NEST is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with NEST. If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 #ifndef STDP_DOPA_CONNECTION_H
24 #define STDP_DOPA_CONNECTION_H
25 
26 /* BeginDocumentation
27 
28  Name: stdp_dopamine_synapse - Synapse type for dopamine-modulated spike-timing dependent plasticity.
29 
30  Description:
31  stdp_dopamine_synapse is a connection to create synapses with
32  dopamine-modulated spike-timing dependent plasticity (used as a
33  benchmark model in [1], based on [2]). The dopaminergic signal is a
34  low-pass filtered version of the spike rate of a user-specific pool
35  of neurons. The spikes emitted by the pool of dopamine neurons are
36  delivered to the synapse via the assigned volume transmitter. The
37  dopaminergic dynamics is calculated in the synapse itself.
38 
39  Examples:
40  /volume_transmitter Create /vol Set
41  /iaf_neuron Create /pre_neuron Set
42  /iaf_neuron Create /post_neuron Set
43  /iaf_neuron Create /neuromod_neuron Set
44  /stdp_dopamine_synapse << /vt vol >> SetDefaults
45  neuromod_neuron vol Connect
46  pre_neuron post_neuron /stdp_dopamine_synapse Connect
47 
48  Parameters:
49  vt long - ID of volume_transmitter collecting the spikes from the pool of
50  dopamine releasing neurons and transmitting the spikes
51  to the synapse. If no volume transmitter has been
52  assigned, a value of -1 is returned when the synapse is
53  asked for its defaults.
54  A_plus double - Amplitude of weight change for facilitation
55  A_minus double - Amplitude of weight change for depression
56  tau_plus double - STDP time constant for facilitation in ms
57  tau_c double - Time constant of eligibility trace in ms
58  tau_n double - Time constant of dopaminergic trace in ms
59  b double - Dopaminergic baseline concentration
60  Wmin double - Minimal synaptic weight
61  Wmax double - Maximal synaptic weight
62 
63  References:
64  [1] Potjans W, Morrison A and Diesmann M (2010). Enabling
65  functional neural circuit simulations with distributed
66  computing of neuromodulated plasticity.
67  Front. Comput. Neurosci. 4:141. doi:10.3389/fncom.2010.00141
68  [2] Izhikevich, E.M. (2007). Solving the distal reward problem
69  through linkage of STDP and dopamine signaling. Cereb. Cortex,
70  17(10), 2443-2452.
71 
72  Transmits: SpikeEvent
73 
74  Author: Susanne Kunkel
75  Remarks:
76  - based on an earlier version by Wiebke Potjans
77  - major changes to code after code revision in Apr 2013
78 
79  SeeAlso: volume_transmitter
80 */
81 
82 #include "connection.h"
83 #include "volume_transmitter.h"
84 #include "spikecounter.h"
85 #include "numerics.h"
86 
87 namespace nest
88 {
89 
94  {
95  public:
96 
102 
106  void get_status(DictionaryDatum& d) const;
107 
111  void set_status(const DictionaryDatum& d, ConnectorModel& cm);
112 
113  Node* get_node();
114 
115  long_t get_vt_gid() const;
116 
126  };
127 
128  inline
130  {
131  if(vt_!= 0)
132  return vt_->get_gid();
133  else
134  return -1;
135  }
136 
141  template<typename targetidentifierT>
142  class STDPDopaConnection : public Connection<targetidentifierT>
143  {
144 
145  public:
146 
149 
155 
161 
162  // Explicitly declare all methods inherited from the dependent base ConnectionBase.
163  // This avoids explicit name prefixes in all places these functions are used.
164  // Since ConnectionBase depends on the template parameter, they are not automatically
165  // found in the base class.
170 
174  void get_status(DictionaryDatum& d) const;
175 
179  void set_status(const DictionaryDatum& d, ConnectorModel& cm);
180 
185  void send(Event& e, thread t, double_t, const STDPDopaCommonProperties& cp);
186 
187  void trigger_update_weight(thread t, const vector<spikecounter>& dopa_spikes, double_t t_trig, const STDPDopaCommonProperties& cp);
188 
190  {
191  public:
192  // Ensure proper overriding of overloaded virtual functions.
193  // Return values from functions are ignored.
196  };
197 
198  /*
199  * This function calls check_connection on the sender and checks if the receiver
200  * accepts the event type and receptor type requested by the sender.
201  * Node::check_connection() will either confirm the receiver port by returning
202  * true or false if the connection should be ignored.
203  * We have to override the base class' implementation, since for STDP
204  * connections we have to call register_stdp_pl_connection on the target neuron
205  * to inform the Archiver to collect spikes for this connection.
206  * Further, the STDP dopamine synapse requires a volume transmitter to be set before
207  * any simulation is performed. Checking this satisfies ticket #926.
208  *
209  * \param s The source node
210  * \param r The target node
211  * \param receptor_type The ID of the requested receptor type
212  * \param t_lastspike last spike produced by presynaptic neuron (in ms)
213  */
214  void check_connection(Node & s, Node & t, rport receptor_type, double_t t_lastspike, const CommonPropertiesType & cp)
215  {
216  if(cp.vt_==0)
217  throw BadProperty("No volume transmitter has been assigned to the dopamine synapse.");
218 
219  ConnTestDummyNode dummy_target;
220  ConnectionBase::check_connection_(dummy_target, s, t, receptor_type);
221 
222  t.register_stdp_connection(t_lastspike - get_delay());
223  }
224 
226 
227  private:
228 
229  // update dopamine trace from last to current dopamine spike and increment index
230  void update_dopamine_(const vector<spikecounter>& dopa_spikes, const STDPDopaCommonProperties& cp);
231 
232  void update_weight_(double_t c0, double_t n0, double_t minus_dt, const STDPDopaCommonProperties& cp);
233 
234  void process_dopa_spikes_(const vector<spikecounter>& dopa_spikes, double_t t0, double_t t1, const STDPDopaCommonProperties& cp);
235  void facilitate_(double_t kplus, const STDPDopaCommonProperties& cp);
236  void depress_(double_t kminus, const STDPDopaCommonProperties& cp);
237 
238  // data members of each connection
243 
244  // dopa_spikes_idx_ refers to the dopamine spike that has just been processes
245  // after trigger_update_weight a pseudo dopamine spike at t_trig is stored at index 0 and dopa_spike_idx_ = 0
247 
248  // time of last update, which is either time of last presyn. spike or time-driven update
250  };
251 
252  //
253  // Implementation of class STDPDopaConnection.
254  //
255 
256  template<typename targetidentifierT>
258  ConnectionBase(),
259  weight_(1.0),
260  Kplus_(0.0),
261  c_(0.0),
262  n_(0.0),
263  dopa_spikes_idx_(0),
264  t_last_update_(0.0)
265  {}
266 
267  template<typename targetidentifierT>
269  ConnectionBase(rhs),
270  weight_(rhs.weight_),
271  Kplus_(rhs.Kplus_),
272  c_(rhs.c_),
273  n_(rhs.n_),
274  dopa_spikes_idx_(rhs.dopa_spikes_idx_),
275  t_last_update_(rhs.t_last_update_)
276  {}
277 
278  template<typename targetidentifierT>
280  {
281 
282  // base class properties, different for individual synapse
283  ConnectionBase::get_status(d);
284  def<double_t>(d, names::weight, weight_);
285 
286  // own properties, different for individual synapse
287  def<double_t>(d, "c", c_);
288  def<double_t>(d, "n", n_);
289  }
290 
291  template<typename targetidentifierT>
293  {
294  // base class properties
295  ConnectionBase::set_status(d, cm);
296  updateValue<double_t>(d, names::weight, weight_);
297 
298  updateValue<double_t>(d, "c", c_);
299  updateValue<double_t>(d, "n", n_);
300  }
301 
302  template<typename targetidentifierT>
303  inline
304  void STDPDopaConnection<targetidentifierT>::update_dopamine_(const vector<spikecounter>& dopa_spikes, const STDPDopaCommonProperties& cp)
305  {
306  double_t minus_dt = dopa_spikes[dopa_spikes_idx_].spike_time_ - dopa_spikes[dopa_spikes_idx_+1].spike_time_;
307  ++dopa_spikes_idx_;
308  n_ = n_ * std::exp( minus_dt / cp.tau_n_ ) + dopa_spikes[dopa_spikes_idx_].multiplicity_ / cp.tau_n_;
309  }
310 
311  template<typename targetidentifierT>
312  inline
314  {
315  const double_t taus_ = ( cp.tau_c_ + cp.tau_n_ ) / ( cp.tau_c_ * cp.tau_n_ );
316  weight_ = weight_ - c0 * ( n0 / taus_ * numerics::expm1( taus_ * minus_dt ) - cp.b_ * cp.tau_c_ * numerics::expm1( minus_dt / cp.tau_c_ ) );
317 
318  if ( weight_ < cp.Wmin_ )
319  weight_ = cp.Wmin_;
320  if ( weight_ > cp.Wmax_ )
321  weight_ = cp.Wmax_;
322  }
323 
324  template<typename targetidentifierT>
325  inline
326  void STDPDopaConnection<targetidentifierT>::process_dopa_spikes_(const vector<spikecounter>& dopa_spikes,
327  double_t t0, double_t t1, const STDPDopaCommonProperties& cp)
328  {
329  // process dopa spikes in (t0, t1]
330  // propagate weight from t0 to t1
331  if ( ( dopa_spikes.size() > dopa_spikes_idx_+1 ) && ( dopa_spikes[dopa_spikes_idx_+1].spike_time_ <= t1 ) )
332  {
333  // there is at least 1 dopa spike in (t0, t1]
334  // propagate weight up to first dopa spike and update dopamine trace
335  // weight and eligibility c are at time t0 but dopamine trace n is at time of last dopa spike
336  double_t n0 = n_ * std::exp( ( dopa_spikes[dopa_spikes_idx_].spike_time_ - t0 ) / cp.tau_n_ ); // dopamine trace n at time t0
337  update_weight_(c_, n0, t0 - dopa_spikes[dopa_spikes_idx_+1].spike_time_, cp);
338  update_dopamine_(dopa_spikes, cp);
339 
340  // process remaining dopa spikes in (t0, t1]
341  double_t cd;
342  while ( ( dopa_spikes.size() > dopa_spikes_idx_+1 ) && ( dopa_spikes[dopa_spikes_idx_+1].spike_time_ <= t1 ) )
343  {
344  // propagate weight up to next dopa spike and update dopamine trace
345  // weight and dopamine trace n are at time of last dopa spike td but eligibility c is at time t0
346  cd = c_ * std::exp( ( t0 - dopa_spikes[dopa_spikes_idx_].spike_time_ ) / cp.tau_c_ ); // eligibility c at time of td
347  update_weight_(cd, n_, dopa_spikes[dopa_spikes_idx_].spike_time_ - dopa_spikes[dopa_spikes_idx_+1].spike_time_, cp);
348  update_dopamine_(dopa_spikes, cp);
349  }
350 
351  // propagate weight up to t1
352  // weight and dopamine trace n are at time of last dopa spike td but eligibility c is at time t0
353  cd = c_ * std::exp( ( t0 - dopa_spikes[dopa_spikes_idx_].spike_time_ ) / cp.tau_c_ ); // eligibility c at time td
354  update_weight_(cd, n_, dopa_spikes[dopa_spikes_idx_].spike_time_ - t1, cp);
355  }
356  else
357  {
358  // no dopamine spikes in (t0, t1]
359  // weight and eligibility c are at time t0 but dopamine trace n is at time of last dopa spike
360  double_t n0 = n_ * std::exp( ( dopa_spikes[dopa_spikes_idx_].spike_time_ - t0 ) / cp.tau_n_ ); // dopamine trace n at time t0
361  update_weight_(c_, n0, t0 - t1, cp);
362  }
363 
364  // update eligibility trace c for interval (t0, t1]
365  c_ = c_ * std::exp( ( t0 - t1 ) / cp.tau_c_ );
366  }
367 
368  template<typename targetidentifierT>
369  inline
371  {
372  c_ += cp.A_plus_ * kplus;
373  }
374 
375  template<typename targetidentifierT>
376  inline
378  {
379  c_ -= cp.A_minus_ * kminus;
380  }
381 
388  template<typename targetidentifierT>
389  inline
391  {
392  // t_lastspike_ = 0 initially
393 
394  Node *target = get_target(t);
395 
396  // purely dendritic delay
397  double_t dendritic_delay = get_delay();
398 
400 
401  // get history of dopamine spikes
402  const vector<spikecounter>& dopa_spikes = cp.vt_->deliver_spikes();
403 
404  // get spike history in relevant range (t_last_update, t_spike] from post-synaptic neuron
405  std::deque<histentry>::iterator start;
406  std::deque<histentry>::iterator finish;
407  target->get_history(t_last_update_ - dendritic_delay, t_spike - dendritic_delay, &start, &finish);
408 
409  // facilitation due to post-synaptic spikes since last update
410  double_t t0 = t_last_update_;
411  double_t minus_dt;
412  while ( start != finish )
413  {
414  process_dopa_spikes_(dopa_spikes, t0, start->t_ + dendritic_delay, cp);
415  t0 = start->t_ + dendritic_delay;
416  minus_dt = t_last_update_ - t0;
417  if ( start->t_ < t_spike ) // only depression if pre- and postsyn. spike occur at the same time
418  facilitate_(Kplus_ * std::exp( minus_dt / cp.tau_plus_ ), cp);
419  ++start;
420  }
421 
422  // depression due to new pre-synaptic spike
423  process_dopa_spikes_(dopa_spikes, t0, t_spike, cp);
424  depress_(target->get_K_value(t_spike - dendritic_delay), cp);
425 
426  e.set_receiver(*target);
427  e.set_weight(weight_);
428  e.set_delay(get_delay_steps());
429  e.set_rport(get_rport());
430  e();
431 
432  Kplus_ = Kplus_ * std::exp( ( t_last_update_ - t_spike ) / cp.tau_plus_) + 1.0;
433  t_last_update_ = t_spike;
434  }
435 
436  template<typename targetidentifierT>
437  inline
438  void STDPDopaConnection<targetidentifierT>::trigger_update_weight(thread t, const vector<spikecounter>& dopa_spikes, const double_t t_trig,
439  const STDPDopaCommonProperties& cp)
440  {
441  // propagate all state variables to time t_trig
442  // this does not include the depression trace K_minus, which is updated in the postsyn. neuron
443 
444  // purely dendritic delay
445  double_t dendritic_delay = get_delay();
446 
447  // get spike history in relevant range (t_last_update, t_trig] from postsyn. neuron
448  std::deque<histentry>::iterator start;
449  std::deque<histentry>::iterator finish;
450  get_target(t)->get_history(t_last_update_ - dendritic_delay, t_trig - dendritic_delay, &start, &finish);
451 
452  // facilitation due to postsyn. spikes since last update
453  double_t t0 = t_last_update_;
454  double_t minus_dt;
455  while ( start != finish )
456  {
457  process_dopa_spikes_(dopa_spikes, t0, start->t_ + dendritic_delay, cp);
458  t0 = start->t_ + dendritic_delay;
459  minus_dt = t_last_update_ - t0;
460  facilitate_(Kplus_ * std::exp( minus_dt / cp.tau_plus_ ), cp);
461  ++start;
462  }
463 
464  // propagate weight, eligibility trace c, dopamine trace n and facilitation trace K_plus to time t_trig
465  // but do not increment/decrement as there are no spikes to be handled at t_trig
466  process_dopa_spikes_(dopa_spikes, t0, t_trig, cp);
467  n_ = n_ * std::exp( ( dopa_spikes[dopa_spikes_idx_].spike_time_ - t_trig ) / cp.tau_n_ );
468  Kplus_ = Kplus_ * std::exp( ( t_last_update_ - t_trig ) / cp.tau_plus_);
469 
470  t_last_update_ = t_trig;
471  dopa_spikes_idx_ = 0;
472  }
473 
474 } // of namespace nest
475 
476 #endif // of #ifndef STDP_DOPA_CONNECTION_H
size_t index
Unsigned long type for enumerations.
Definition: nest.h:109
Connection< targetidentifierT > ConnectionBase
Definition: stdp_dopa_connection.h:148
void check_connection(Node &s, Node &t, rport receptor_type, double_t t_lastspike, const CommonPropertiesType &cp)
Definition: stdp_dopa_connection.h:214
void set_rport(rport p)
Set the receiver port number (r-port).
Definition: event.h:817
void set_receiver(Node &)
Change pointer to receiving Node.
Definition: event.h:708
const Name receptor_type("receptor_type")
Connection parameters.
Definition: nest_names.h:240
void set_status(const DictionaryDatum &d, ConnectorModel &cm)
Set properties from the values given in dictionary.
Definition: stdp_dopa_connection.cpp:69
index get_gid() const
Return global Network ID.
Definition: node.h:753
const Name d("d")
Specific to Izhikevich 2003.
Definition: nest_names.h:83
virtual double_t get_K_value(double_t t)
return the Kminus value at t (in ms).
Definition: node.cpp:273
double_t weight_
Definition: stdp_dopa_connection.h:239
long_t get_delay_steps() const
Return the delay of the connection in steps.
Definition: connection.h:126
void check_connection_(Node &dummy_target, Node &source, Node &target, rport receptor_type)
This function calls check_connection() on the sender to check if the receiver accepts the event type ...
Definition: connection.h:183
Node * get_node()
Definition: stdp_dopa_connection.cpp:92
const rport invalid_port_
Value for invalid connection port number.
Definition: nest.h:160
const Name weight("weight")
Connection parameters.
Definition: nest_names.h:344
Encapsulates information which is sent between Nodes.
Definition: event.h:73
double_t c_
Definition: stdp_dopa_connection.h:241
void process_dopa_spikes_(const vector< spikecounter > &dopa_spikes, double_t t0, double_t t1, const STDPDopaCommonProperties &cp)
Definition: stdp_dopa_connection.h:326
const vector< spikecounter > & deliver_spikes()
Definition: volume_transmitter.h:199
void set_weight(weight t)
Set weight of the event.
Definition: event.h:751
long_t rport
Connection port number to distinguish incoming connections, also called receiver port.
Definition: nest.h:147
double expm1(double x)
Supply expm1() function independent of system.
Definition: numerics.h:42
double_t A_minus_
Definition: stdp_dopa_connection.h:119
double_t Kplus_
Definition: stdp_dopa_connection.h:240
STDPDopaCommonProperties CommonPropertiesType
Definition: stdp_dopa_connection.h:147
void get_status(DictionaryDatum &d) const
Get all properties of this connection and put them into a dictionary.
Definition: stdp_dopa_connection.h:279
long_t get_vt_gid() const
Definition: stdp_dopa_connection.h:129
Node * get_target(thread t) const
Definition: connection.h:155
Class containing the common properties for all synapses of type dopamine connection.
Definition: stdp_dopa_connection.h:93
STDPDopaCommonProperties()
Default constructor.
Definition: stdp_dopa_connection.cpp:37
void update_weight_(double_t c0, double_t n0, double_t minus_dt, const STDPDopaCommonProperties &cp)
Definition: stdp_dopa_connection.h:313
STDPDopaConnection()
Default Constructor.
Definition: stdp_dopa_connection.h:257
double_t get_delay() const
Return the delay of the connection in ms.
Definition: connection.h:121
const Name w("w")
Specific to Brette & Gerstner 2005 (aeif_cond-*)
Definition: nest_names.h:343
double_t tau_n_
Definition: stdp_dopa_connection.h:122
void set_delay(delay)
Set the transmission delay of the event.
Definition: event.h:781
void update_dopamine_(const vector< spikecounter > &dopa_spikes, const STDPDopaCommonProperties &cp)
Definition: stdp_dopa_connection.h:304
double_t tau_plus_
Definition: stdp_dopa_connection.h:120
double_t Wmax_
Definition: stdp_dopa_connection.h:125
virtual void get_history(double_t t1, double_t t2, std::deque< histentry >::iterator *start, std::deque< histentry >::iterator *finish)
return the spike history for (t1,t2].
Definition: node.cpp:284
Time const & get_stamp() const
Return time stamp of the event.
Definition: event.h:757
const Name target("target")
Connection parameters.
Definition: nest_names.h:282
const Name start("start")
Device parameters.
Definition: nest_names.h:263
Base class for dummy nodes used in connection testing.
Definition: connection.h:64
volume transmitter class.
Definition: volume_transmitter.h:106
void get_status(DictionaryDatum &d) const
Get all properties and put them into a dictionary.
Definition: stdp_dopa_connection.cpp:50
volume_transmitter * vt_
Definition: stdp_dopa_connection.h:117
Class representing an STDPDopaConnection with homogeneous parameters, i.e.
Definition: stdp_dopa_connection.h:142
void send(Event &e, thread t, double_t, const STDPDopaCommonProperties &cp)
Send an event to the receiver of this connection.
Definition: stdp_dopa_connection.h:390
void trigger_update_weight(thread t, const vector< spikecounter > &dopa_spikes, double_t t_trig, const STDPDopaCommonProperties &cp)
Definition: stdp_dopa_connection.h:438
Exception to be thrown if a status parameter is incomplete or inconsistent.
Definition: exceptions.h:420
virtual void register_stdp_connection(double_t)
Register a STDP connection.
Definition: node.cpp:178
long_t port
Connection port number to distinguis outgoing connections.
Definition: nest.h:155
double double_t
Double precision floating point numbers.
Definition: nest.h:93
void set_status(const DictionaryDatum &d, ConnectorModel &cm)
Set properties of this connection from the values given in dictionary.
Definition: stdp_dopa_connection.h:292
void set_weight(double_t w)
Definition: stdp_dopa_connection.h:225
rport get_rport() const
Definition: connection.h:156
virtual port handles_test_event(SpikeEvent &, rport receptor_type)
Check if the node can handle a particular event and receptor type.
Definition: node.cpp:203
double_t get_ms() const
Definition: nest_time.h:389
index dopa_spikes_idx_
Definition: stdp_dopa_connection.h:246
Class containing the common properties for all connections of a certain type.
Definition: common_synapse_properties.h:44
double_t b_
Definition: stdp_dopa_connection.h:123
void facilitate_(double_t kplus, const STDPDopaCommonProperties &cp)
Definition: stdp_dopa_connection.h:370
Part of definition of volume_transmitter to record and manage spike times and multiplicity of neurons...
Base class for representing connections.
Definition: connection.h:85
double_t Wmin_
Definition: stdp_dopa_connection.h:124
double_t A_plus_
Definition: stdp_dopa_connection.h:118
Event for spike information.
Definition: event.h:320
Base class for all NEST network objects.
Definition: node.h:96
void depress_(double_t kminus, const STDPDopaCommonProperties &cp)
Definition: stdp_dopa_connection.h:377
double_t tau_c_
Definition: stdp_dopa_connection.h:121
Definition: connector_model.h:38
int_t thread
Thread index type.
Definition: nest.h:133
double_t t_last_update_
Definition: stdp_dopa_connection.h:249
long long_t
Integer number with at least 32 bit.
Definition: nest.h:96
const double e
Definition: numerics.cpp:62
port handles_test_event(SpikeEvent &, rport)
Check if the node can handle a particular event and receptor type.
Definition: stdp_dopa_connection.h:195
double_t n_
Definition: stdp_dopa_connection.h:242
const Name t_spike("t_spike")
Time of last spike.
Definition: nest_names.h:281
Definition: stdp_dopa_connection.h:189