Skip to content

Commit

Permalink
Add symmetric stdp synapse to NEST
Browse files Browse the repository at this point in the history
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
sanjayankur31 committed Feb 2, 2016
1 parent d570eb5 commit 1c78eb9
Show file tree
Hide file tree
Showing 3 changed files with 490 additions and 0 deletions.
11 changes: 11 additions & 0 deletions models/modelsmodule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
#include "stdp_triplet_connection.h"
#include "stdp_dopa_connection.h"
#include "stdp_pl_connection_hom.h"
#include "stdp_symmetric_connection.h"
#include "tsodyks2_connection.h"
#include "tsodyks_connection.h"
#include "tsodyks_connection_hom.h"
Expand Down Expand Up @@ -478,6 +479,16 @@ ModelsModule::init( SLIInterpreter* )
"stdp_dopamine_synapse" );
kernel().model_manager.register_connection_model< STDPDopaConnection< TargetIdentifierIndex > >(
"stdp_dopamine_synapse_hpc" );

/* BeginDocumentation
Name: stdp_symmetric_synapse_hpc - Variant of stdp_symmetric_synapse with low memory consumption.
SeeAlso: synapsedict, stdp_symmetric_synapse
*/
kernel()
.model_manager.register_connection_model< STDPSymmetricConnection< TargetIdentifierPtrRport > >(
"stdp_symmetric_synapse" );
kernel().model_manager.register_connection_model< STDPSymmetricConnection< TargetIdentifierIndex > >(
"stdp_symmetric_synapse_hpc" );
}

} // namespace nest
301 changes: 301 additions & 0 deletions models/stdp_symmetric_connection.h
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
Loading

0 comments on commit 1c78eb9

Please sign in to comment.