1 /*
2  *  ht_synapse.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 HT_SYNAPSE_H
24 #define HT_SYNAPSE_H
25 
26 // Includes from nestkernel:
27 #include "connection.h"
28 
29 namespace nest
30 {
31 
32 /* BeginUserDocs: synapse, Hill-Tononi plasticity
33 
34 Short description
35 +++++++++++++++++
36 
37 Synapse with depression after Hill & Tononi (2005)
38 
39 Description
40 +++++++++++
41 
42 This synapse implements the depression model described in [1, p 1678].
43 
44 Synaptic dynamics are given by
45 
46 .. math::
47 
48     P'(t) = ( 1 - P ) / \tau_P  \\
49     P(T+) = (1 - \delta_P) P(T-)    \text{ for T : time of a spike } \\
50     P(t=0) = 1
51 
52 :math:`w(t) = w_{max} * P(t)`   is the resulting synaptic weight
53 
54 For implementation details see:
55 `HillTononi_model <../model_details/HillTononiModels.ipynb>`_
56 
57 .. warning::
58 
59    This synaptic plasticity rule does not take
60    :doc:`precise spike timing <simulations_with_precise_spike_times>` into
61    account. When calculating the weight update, the precise spike time part
62    of the timestamp is ignored.
63 
64 Parameters
65 ++++++++++
66 
67 The following parameters can be set in the status dictionary:
68 
69 ========  ======  =========================================================
70  tau_P    ms      Synaptic vesicle pool recovery time constant
71  delta_P  real    Fractional change in vesicle pool on incoming spikes
72                   (unitless)
73  P        real    Current size of the vesicle pool [unitless, 0 <= P <= 1]
74 ========  ======  =========================================================
75 
76 References
77 ++++++++++
78 
79 .. [1] Hill S, Tononi G (2005). Modeling sleep and wakefulness in the
80        thalamocortical system. Journal of Neurophysiology. 93:1671-1698.
81        DOI: https://doi.org/10.1152/jn.00915.2004
82 
83 Transmits
84 +++++++++
85 
86 SpikeEvent
87 
88 See also
89 ++++++++
90 
91 ht_neuron, tsodyks_synapse, stdp_synapse, static_synapse
92 
93 EndUserDocs */
94 
95 template < typename targetidentifierT >
96 class ht_synapse : public Connection< targetidentifierT >
97 {
98 public:
99   typedef CommonSynapseProperties CommonPropertiesType;
100   typedef Connection< targetidentifierT > ConnectionBase;
101 
102   /**
103    * Default Constructor.
104    * Sets default values for all parameters. Needed by GenericConnectorModel.
105    */
106   ht_synapse();
107 
108   /**
109    * Copy constructor.
110    * Needs to be defined properly in order for GenericConnector to work.
111    */
112   ht_synapse( const ht_synapse& ) = default;
113 
114   // Explicitly declare all methods inherited from the dependent base
115   // ConnectionBase. This avoids explicit name prefixes in all places these
116   // functions are used. Since ConnectionBase depends on the template parameter,
117   // they are not automatically found in the base class.
118   using ConnectionBase::get_delay_steps;
119   using ConnectionBase::get_delay;
120   using ConnectionBase::get_rport;
121   using ConnectionBase::get_target;
122 
123   /**
124    * Default Destructor.
125    */
~ht_synapse()126   virtual ~ht_synapse()
127   {
128   }
129 
130   /**
131    * Get all properties of this connection and put them into a dictionary.
132    */
133   virtual void get_status( DictionaryDatum& d ) const;
134 
135   /**
136    * Set properties of this connection from the values given in dictionary.
137    */
138   virtual void set_status( const DictionaryDatum& d, ConnectorModel& cm );
139 
140   /**
141    * Send an event to the receiver of this connection.
142    * \param e The event to send
143    * \param cp Common properties to all synapses (empty).
144    */
145   void send( Event& e, thread t, const CommonSynapseProperties& cp );
146 
147   class ConnTestDummyNode : public ConnTestDummyNodeBase
148   {
149   public:
150     // Ensure proper overriding of overloaded virtual functions.
151     // Return values from functions are ignored.
152     using ConnTestDummyNodeBase::handles_test_event;
153     port
handles_test_event(SpikeEvent &,rport)154     handles_test_event( SpikeEvent&, rport )
155     {
156       return invalid_port_;
157     }
158   };
159 
160   void
check_connection(Node & s,Node & t,rport receptor_type,const CommonPropertiesType &)161   check_connection( Node& s, Node& t, rport receptor_type, const CommonPropertiesType& )
162   {
163     ConnTestDummyNode dummy_target;
164     ConnectionBase::check_connection_( dummy_target, s, t, receptor_type );
165   }
166 
167   //! allows efficient initialization from ConnectorModel::add_connection()
168   void
set_weight(double w)169   set_weight( double w )
170   {
171     weight_ = w;
172   }
173 
174 private:
175   double weight_; //!< Synaptic weight
176 
177   double tau_P_;   //!< Time constant for recovery [ms]
178   double delta_P_; //!< Fractional decrease in pool size per spike
179 
180   double p_; //!< Current pool size
181 
182   double t_lastspike_; //!< Time point of last spike emitted
183 };
184 
185 
186 /**
187  * Send an event to the receiver of this connection.
188  * \param e The event to send
189  * \param p The port under which this connection is stored in the Connector.
190  */
191 template < typename targetidentifierT >
192 inline void
send(Event & e,thread t,const CommonSynapseProperties &)193 ht_synapse< targetidentifierT >::send( Event& e, thread t, const CommonSynapseProperties& )
194 {
195   // propagation t_lastspike -> t_spike, t_lastspike_ = 0 initially, p_ = 1
196   const double t_spike = e.get_stamp().get_ms();
197   const double h = t_spike - t_lastspike_;
198   p_ = 1 - ( 1 - p_ ) * std::exp( -h / tau_P_ );
199 
200   // send the spike to the target
201   e.set_receiver( *get_target( t ) );
202   e.set_weight( weight_ * p_ );
203   e.set_delay_steps( get_delay_steps() );
204   e.set_rport( get_rport() );
205   e();
206 
207   // reduce pool after spike is sent
208   p_ *= ( 1 - delta_P_ );
209 
210   t_lastspike_ = t_spike;
211 }
212 
213 template < typename targetidentifierT >
ht_synapse()214 ht_synapse< targetidentifierT >::ht_synapse()
215   : ConnectionBase()
216   , weight_( 1.0 )
217   , tau_P_( 500.0 )
218   , delta_P_( 0.125 )
219   , p_( 1.0 )
220   , t_lastspike_( 0.0 )
221 {
222 }
223 
224 template < typename targetidentifierT >
225 void
get_status(DictionaryDatum & d)226 ht_synapse< targetidentifierT >::get_status( DictionaryDatum& d ) const
227 {
228   ConnectionBase::get_status( d );
229   def< double >( d, names::weight, weight_ );
230   def< double >( d, names::tau_P, tau_P_ );
231   def< double >( d, names::delta_P, delta_P_ );
232   def< double >( d, names::P, p_ );
233   def< long >( d, names::size_of, sizeof( *this ) );
234 }
235 
236 template < typename targetidentifierT >
237 void
set_status(const DictionaryDatum & d,ConnectorModel & cm)238 ht_synapse< targetidentifierT >::set_status( const DictionaryDatum& d, ConnectorModel& cm )
239 {
240   ConnectionBase::set_status( d, cm );
241 
242   updateValue< double >( d, names::weight, weight_ );
243   updateValue< double >( d, names::tau_P, tau_P_ );
244   updateValue< double >( d, names::delta_P, delta_P_ );
245   updateValue< double >( d, names::P, p_ );
246 
247   if ( tau_P_ <= 0.0 )
248   {
249     throw BadProperty( "tau_P > 0 required." );
250   }
251 
252   if ( delta_P_ < 0.0 || delta_P_ > 1.0 )
253   {
254     throw BadProperty( "0 <= delta_P <= 1 required." );
255   }
256 
257   if ( p_ < 0.0 || p_ > 1.0 )
258   {
259     throw BadProperty( "0 <= P <= 1 required." );
260   }
261 }
262 
263 } // namespace
264 
265 #endif // HT_SYNAPSE_H
266