-
Notifications
You must be signed in to change notification settings - Fork 370
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reference: Vogels et al. (2011) Inhibitory Plasticity Balances Excitation and Inhibition in Sensory Pathways and Memory Networks. Science Vol. 334, Issue 6062, pp. 1569-1573 DOI: 10.1126/science.1211095 http://www.sciencemag.org/content/334/6062/1569.abstract Also adds a python test file to the manualtests folders.
- Loading branch information
1 parent
d570eb5
commit 1c78eb9
Showing
3 changed files
with
490 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,301 @@ | ||
/* | ||
* stdp_symmetric_connection.h | ||
* | ||
* 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/>. | ||
* | ||
*/ | ||
|
||
#ifndef STDP_SYMMETRIC_CONNECTION_H | ||
#define STDP_SYMMETRIC_CONNECTION_H | ||
|
||
/* BeginDocumentation | ||
Name: stdp_symmetric_synapse - Synapse type for symmetric spike-timing dependent | ||
plasticity. | ||
Description: | ||
stdp_symmetric_synapse is a connector to create synapses with symmetric spike time | ||
dependent plasticity (as defined in [1]). | ||
Parameters: | ||
tau double - Time constant of STDP window, potentiation in ms | ||
lambda double - Step size | ||
Wmax double - Maximum allowed weight | ||
eta double - learning rate | ||
kappa double - target firing rate | ||
Transmits: SpikeEvent | ||
References: | ||
[1] Vogels et al. (2011) Inhibitory Plasticity Balances Excitation and | ||
Inhibition in Sensory Pathways and Memory Networks. | ||
Science Vol. 334, Issue 6062, pp. 1569-1573 | ||
DOI: 10.1126/science.1211095 | ||
FirstVersion: January 2016 | ||
Author: Ankur Sinha | ||
SeeAlso: synapsedict | ||
*/ | ||
|
||
#include <cmath> | ||
|
||
#include "connection.h" | ||
|
||
//#include "network.h" | ||
//#include "dictdatum.h" | ||
//#include "connector_model.h" | ||
//#include "common_synapse_properties.h" | ||
//#include "event.h" | ||
|
||
|
||
namespace nest | ||
{ | ||
|
||
// connections are templates of target identifier type (used for pointer / target index addressing) | ||
// derived from generic connection template | ||
template < typename targetidentifierT > | ||
class STDPSymmetricConnection : public Connection< targetidentifierT > | ||
{ | ||
|
||
public: | ||
typedef CommonSynapseProperties CommonPropertiesType; | ||
typedef Connection< targetidentifierT > ConnectionBase; | ||
|
||
/** | ||
* Default Constructor. | ||
* Sets default values for all parameters. Needed by GenericConnectorModel. | ||
*/ | ||
STDPSymmetricConnection(); | ||
|
||
|
||
/** | ||
* Copy constructor. | ||
* Needs to be defined properly in order for GenericConnector to work. | ||
*/ | ||
STDPSymmetricConnection( const STDPSymmetricConnection& ); | ||
|
||
// Explicitly declare all methods inherited from the dependent base ConnectionBase. | ||
// This avoids explicit name prefixes in all places these functions are used. | ||
// Since ConnectionBase depends on the template parameter, they are not automatically | ||
// found in the base class. | ||
using ConnectionBase::get_delay_steps; | ||
using ConnectionBase::get_delay; | ||
using ConnectionBase::get_rport; | ||
using ConnectionBase::get_target; | ||
|
||
/** | ||
* Get all properties of this connection and put them into a dictionary. | ||
*/ | ||
void get_status( DictionaryDatum& d ) const; | ||
|
||
/** | ||
* Set properties of this connection from the values given in dictionary. | ||
*/ | ||
void set_status( const DictionaryDatum& d, ConnectorModel& cm ); | ||
|
||
/** | ||
* Send an event to the receiver of this connection. | ||
* \param e The event to send | ||
* \param t_lastspike Point in time of last spike sent. | ||
* \param cp common properties of all synapses (empty). | ||
*/ | ||
void send( Event& e, thread t, double_t t_lastspike, const CommonSynapseProperties& cp ); | ||
|
||
|
||
class ConnTestDummyNode : public ConnTestDummyNodeBase | ||
{ | ||
public: | ||
// Ensure proper overriding of overloaded virtual functions. | ||
// Return values from functions are ignored. | ||
using ConnTestDummyNodeBase::handles_test_event; | ||
port | ||
handles_test_event( SpikeEvent&, rport ) | ||
{ | ||
return invalid_port_; | ||
} | ||
}; | ||
|
||
void | ||
check_connection( Node& s, | ||
Node& t, | ||
rport receptor_type, | ||
double_t t_lastspike, | ||
const CommonPropertiesType& ) | ||
{ | ||
ConnTestDummyNode dummy_target; | ||
|
||
ConnectionBase::check_connection_( dummy_target, s, t, receptor_type ); | ||
|
||
t.register_stdp_connection( t_lastspike - get_delay() ); | ||
} | ||
|
||
void | ||
set_weight( double_t w ) | ||
{ | ||
weight_ = w; | ||
} | ||
|
||
private: | ||
double_t | ||
facilitate_( double_t w, double_t kplus ) | ||
{ | ||
double_t norm_w = | ||
( w / Wmax_ ) + ( lambda_ * eta_ * kplus ); | ||
return norm_w < 1.0 ? norm_w * Wmax_ : Wmax_; | ||
} | ||
|
||
double_t | ||
depress_( double_t w ) | ||
{ | ||
double_t norm_w = | ||
( w / Wmax_ ) - ( 2.* kappa_ * tau_ * lambda_ * eta_ ); | ||
return norm_w > 0.0 ? norm_w * Wmax_ : 0.0; | ||
} | ||
|
||
// data members of each connection | ||
double_t weight_; | ||
double_t tau_; | ||
double_t lambda_; | ||
double_t kappa_; | ||
double_t eta_; | ||
double_t Wmax_; | ||
double_t Kplus_; | ||
}; | ||
|
||
|
||
/** | ||
* Send an event to the receiver of this connection. | ||
* \param e The event to send | ||
* \param t The thread on which this connection is stored. | ||
* \param t_lastspike Time point of last spike emitted | ||
* \param cp Common properties object, containing the stdp parameters. | ||
*/ | ||
template < typename targetidentifierT > | ||
inline void | ||
STDPSymmetricConnection< targetidentifierT >::send( Event& e, | ||
thread t, | ||
double_t t_lastspike, | ||
const CommonSynapseProperties& ) | ||
{ | ||
// synapse STDP depressing/facilitation dynamics | ||
// if(t_lastspike >0) {std::cout << "last spike " << t_lastspike << std::endl ;} | ||
double_t t_spike = e.get_stamp().get_ms(); | ||
// t_lastspike_ = 0 initially | ||
|
||
// use accessor functions (inherited from Connection< >) to obtain delay and target | ||
Node* target = get_target( t ); | ||
double_t dendritic_delay = get_delay(); | ||
|
||
// get spike history in relevant range (t1, t2] from post-synaptic neuron | ||
std::deque< histentry >::iterator start; | ||
std::deque< histentry >::iterator finish; | ||
target->get_history( t_lastspike - dendritic_delay, t_spike - dendritic_delay, &start, &finish ); | ||
|
||
// presynaptic neuron j, post synaptic neuron i | ||
// Facilitation for each post synaptic spike | ||
// Wij = Wij + eta*xj | ||
double_t minus_dt; | ||
while ( start != finish ) | ||
{ | ||
minus_dt = t_lastspike - ( start->t_ + dendritic_delay ); | ||
++start; | ||
if (minus_dt == 0) | ||
continue; | ||
// Use value of kplus at the time of the post synaptic spike | ||
// therefore the exponential multiplier | ||
// for minus_dt = 0, the exponential becomes 1 and facilitation occurs | ||
// normally | ||
weight_ = facilitate_( weight_, Kplus_ * std::exp( minus_dt / tau_ ) ); | ||
} | ||
|
||
// For pre-synaptic spikes | ||
// Wij = Wij + eta(xi - alpha) | ||
// Facilitation and constant depression | ||
// Getting kvalue at required time already for deferred processing, so no | ||
// need to transform it to the current time, and so, no exponential required | ||
weight_ = facilitate_( weight_, target->get_K_value( t_spike - dendritic_delay) ); | ||
weight_ = depress_( weight_ ); | ||
|
||
e.set_receiver( *target ); | ||
e.set_weight( weight_ ); | ||
// use accessor functions (inherited from Connection< >) to obtain delay in steps and rport | ||
e.set_delay( get_delay_steps() ); | ||
e.set_rport( get_rport() ); | ||
e(); | ||
|
||
// exponential part for the decay, addition of one for each spike | ||
Kplus_ = Kplus_ * std::exp( ( t_lastspike - t_spike ) / tau_ ) + 1.0; | ||
} | ||
|
||
|
||
template < typename targetidentifierT > | ||
STDPSymmetricConnection< targetidentifierT >::STDPSymmetricConnection() | ||
: ConnectionBase() | ||
, weight_( 0.5 ) | ||
, tau_( 20.0 ) | ||
, lambda_( 0.01 ) | ||
, kappa_ ( 3. ) | ||
, eta_ ( 0.001 ) | ||
, Wmax_( 1.0 ) | ||
, Kplus_( 0.0 ) | ||
{ | ||
} | ||
|
||
template < typename targetidentifierT > | ||
STDPSymmetricConnection< targetidentifierT >::STDPSymmetricConnection( | ||
const STDPSymmetricConnection< targetidentifierT >& rhs ) | ||
: ConnectionBase( rhs ) | ||
, weight_( rhs.weight_ ) | ||
, tau_( rhs.tau_ ) | ||
, lambda_( rhs.lambda_ ) | ||
, kappa_ (rhs.kappa_ ) | ||
, eta_ (rhs.eta_ ) | ||
, Wmax_( rhs.Wmax_ ) | ||
, Kplus_( rhs.Kplus_ ) | ||
{ | ||
} | ||
|
||
template < typename targetidentifierT > | ||
void | ||
STDPSymmetricConnection< targetidentifierT >::get_status( DictionaryDatum& d ) const | ||
{ | ||
ConnectionBase::get_status( d ); | ||
def< double_t >( d, names::weight, weight_ ); | ||
def< double_t >( d, "tau", tau_ ); | ||
def< double_t >( d, "lambda", lambda_ ); | ||
def< double_t >( d, "kappa", kappa_ ); | ||
def< double_t >( d, "eta", eta_ ); | ||
def< double_t >( d, "Wmax", Wmax_ ); | ||
def< long_t >( d, names::size_of, sizeof( *this ) ); | ||
} | ||
|
||
template < typename targetidentifierT > | ||
void | ||
STDPSymmetricConnection< targetidentifierT >::set_status( const DictionaryDatum& d, ConnectorModel& cm ) | ||
{ | ||
ConnectionBase::set_status( d, cm ); | ||
updateValue< double_t >( d, names::weight, weight_ ); | ||
updateValue< double_t >( d, "tau", tau_ ); | ||
updateValue< double_t >( d, "lambda", lambda_ ); | ||
updateValue< double_t >( d, "kappa", kappa_ ); | ||
updateValue< double_t >( d, "eta", eta_ ); | ||
updateValue< double_t >( d, "Wmax", Wmax_ ); | ||
} | ||
|
||
} // of namespace nest | ||
|
||
#endif // of #ifndef STDP_SYMMETRIC_CONNECTION_H |
Oops, something went wrong.