NEST main@caf0ae8
 
Loading...
Searching...
No Matches
rate_neuron_ipn_impl.h
Go to the documentation of this file.
1/*
2 * rate_neuron_ipn_impl.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 RATE_NEURON_IPN_IMPL_H
24#define RATE_NEURON_IPN_IMPL_H
25
26#include "rate_neuron_ipn.h"
27
28// C++ includes:
29#include <cmath> // in case we need isnan() // fabs
30#include <cstdio>
31#include <iomanip>
32#include <iostream>
33#include <limits>
34#include <string>
35
36// Includes from libnestutil:
37#include "dict_util.h"
38#include "numerics.h"
39
40// Includes from nestkernel:
41#include "exceptions.h"
42#include "kernel_manager.h"
44
45
46namespace nest
47{
48
49/* ----------------------------------------------------------------
50 * Recordables map
51 * ---------------------------------------------------------------- */
52
53template < class TNonlinearities >
54RecordablesMap< rate_neuron_ipn< TNonlinearities > > rate_neuron_ipn< TNonlinearities >::recordablesMap_;
55
56/* ----------------------------------------------------------------
57 * Default constructors defining default parameters and state
58 * ---------------------------------------------------------------- */
59
60template < class TNonlinearities >
62 : tau_( 10.0 ) // ms
63 , lambda_( 1.0 ) // ms
64 , sigma_( 1.0 )
65 , mu_( 0.0 )
66 , rectify_rate_( 0.0 )
67 , linear_summation_( true )
68 , rectify_output_( false )
69 , mult_coupling_( false )
70{
71 recordablesMap_.create();
72}
73
74template < class TNonlinearities >
76 : rate_( 0.0 )
77 , noise_( 0.0 )
78{
79}
80
81/* ----------------------------------------------------------------
82 * Parameter and state extractions and manipulation functions
83 * ---------------------------------------------------------------- */
84
85template < class TNonlinearities >
86void
88{
89 d[ names::tau ] = tau_;
90 d[ names::lambda ] = lambda_;
91 d[ names::sigma ] = sigma_;
92 d[ names::mu ] = mu_;
93 d[ names::rectify_rate ] = rectify_rate_;
94 d[ names::linear_summation ] = linear_summation_;
95 d[ names::rectify_output ] = rectify_output_;
96 d[ names::mult_coupling ] = mult_coupling_;
97
98 // Also allow old names (to not break old scripts)
99 d[ names::std ] = sigma_;
100 d[ names::mean ] = mu_;
101}
102
103template < class TNonlinearities >
104void
106{
107 update_value_param( d, names::tau, tau_, node );
108 update_value_param( d, names::lambda, lambda_, node );
109 update_value_param( d, names::mu, mu_, node );
110 update_value_param( d, names::rectify_rate, rectify_rate_, node );
111 update_value_param( d, names::sigma, sigma_, node );
112 update_value_param( d, names::linear_summation, linear_summation_, node );
113 update_value_param( d, names::rectify_output, rectify_output_, node );
114 update_value_param( d, names::mult_coupling, mult_coupling_, node );
115
116 // Check for old names
117 if ( update_value_param( d, names::mean, mu_, node ) )
118 {
120 "rate_neuron_ipn< TNonlinearities >::Parameters_::set",
121 "The parameter mean has been renamed to mu. Please use the new "
122 "name from now on." );
123 }
124
125 if ( update_value_param( d, names::std, sigma_, node ) )
126 {
128 "rate_neuron_ipn< TNonlinearities >::Parameters_::set",
129 "The parameter std has been renamed to sigma. Please use the new "
130 "name from now on." );
131 }
132
133 // Check for invalid parameters
134 if ( tau_ <= 0 )
135 {
136 throw BadProperty( "Time constant must be > 0." );
137 }
138 if ( lambda_ < 0 )
139 {
140 throw BadProperty( "Passive decay rate must be >= 0." );
141 }
142 if ( sigma_ < 0 )
143 {
144 throw BadProperty( "Noise parameter must not be negative." );
145 }
146 if ( rectify_rate_ < 0 )
147 {
148 throw BadProperty( "Rectifying rate must not be negative." );
149 }
150}
151
152template < class TNonlinearities >
153void
155{
156 d[ names::rate ] = rate_; // Rate
157 d[ names::noise ] = noise_; // Noise
158}
159
160template < class TNonlinearities >
161void
163{
164 update_value_param( d, names::rate, rate_, node ); // Rate
165}
166
167template < class TNonlinearities >
172
173template < class TNonlinearities >
178
179/* ----------------------------------------------------------------
180 * Default and copy constructor for node
181 * ---------------------------------------------------------------- */
182
183template < class TNonlinearities >
185 : ArchivingNode()
186 , P_()
187 , S_()
188 , B_( *this )
189{
190 recordablesMap_.create();
191 Node::set_node_uses_wfr( kernel().simulation_manager.use_wfr() );
192}
193
194template < class TNonlinearities >
196 : ArchivingNode( n )
197 , nonlinearities_( n.nonlinearities_ )
198 , P_( n.P_ )
199 , S_( n.S_ )
200 , B_( n.B_, *this )
201{
202 Node::set_node_uses_wfr( kernel().simulation_manager.use_wfr() );
203}
204
205/* ----------------------------------------------------------------
206 * Node initialization functions
207 * ---------------------------------------------------------------- */
208
209template < class TNonlinearities >
210void
212{
213 B_.delayed_rates_ex_.clear(); // includes resize
214 B_.delayed_rates_in_.clear(); // includes resize
215
216 // resize buffers
217 const size_t buffer_size = kernel().connection_manager.get_min_delay();
218 B_.instant_rates_ex_.resize( buffer_size, 0.0 );
219 B_.instant_rates_in_.resize( buffer_size, 0.0 );
220 B_.last_y_values.resize( buffer_size, 0.0 );
221 B_.random_numbers.resize( buffer_size, numerics::nan );
222
223 // initialize random numbers
224 for ( unsigned int i = 0; i < buffer_size; i++ )
225 {
226 B_.random_numbers[ i ] = V_.normal_dist_( get_vp_specific_rng( get_thread() ) );
227 }
228
229 B_.logger_.reset(); // includes resize
231}
232
233template < class TNonlinearities >
234void
236{
237 B_.logger_.init(); // ensures initialization in case mm connected after Simulate
238
239 const double h = Time::get_resolution().get_ms();
240
241 if ( P_.lambda_ > 0 )
242 {
243 // use stochastic exponential Euler method
244 V_.P1_ = std::exp( -P_.lambda_ * h / P_.tau_ );
245 V_.P2_ = -1.0 / P_.lambda_ * numerics::expm1( -P_.lambda_ * h / P_.tau_ );
246 V_.input_noise_factor_ = std::sqrt( -0.5 / P_.lambda_ * numerics::expm1( -2. * P_.lambda_ * h / P_.tau_ ) );
247 }
248 else
249 {
250 // use Euler-Maruyama method
251 V_.P1_ = 1;
252 V_.P2_ = h / P_.tau_;
253 V_.input_noise_factor_ = std::sqrt( h / P_.tau_ );
254 }
255}
256
257/* ----------------------------------------------------------------
258 * Update and event handling functions
259 */
260
261template < class TNonlinearities >
262bool
264 const long from,
265 const long to,
266 const bool called_from_wfr_update )
267{
268 const size_t buffer_size = kernel().connection_manager.get_min_delay();
269 const double wfr_tol = kernel().simulation_manager.get_wfr_tol();
270 bool wfr_tol_exceeded = false;
271
272 // allocate memory to store rates to be sent by rate events
273 std::vector< double > new_rates( buffer_size, 0.0 );
274
275 for ( long lag = from; lag < to; ++lag )
276 {
277 // store rate
278 new_rates[ lag ] = S_.rate_;
279 // get noise
280 S_.noise_ = P_.sigma_ * B_.random_numbers[ lag ];
281 // propagate rate to new time step (exponential integration)
282 S_.rate_ = V_.P1_ * new_rates[ lag ] + V_.P2_ * P_.mu_ + V_.input_noise_factor_ * S_.noise_;
283
284 double delayed_rates_in = 0;
285 double delayed_rates_ex = 0;
286 if ( called_from_wfr_update )
287 {
288 // use get_value_wfr_update to keep values in buffer
289 delayed_rates_in = B_.delayed_rates_in_.get_value_wfr_update( lag );
290 delayed_rates_ex = B_.delayed_rates_ex_.get_value_wfr_update( lag );
291 }
292 else
293 {
294 // use get_value to clear values in buffer after reading
295 delayed_rates_in = B_.delayed_rates_in_.get_value( lag );
296 delayed_rates_ex = B_.delayed_rates_ex_.get_value( lag );
297 }
298 double instant_rates_in = B_.instant_rates_in_[ lag ];
299 double instant_rates_ex = B_.instant_rates_ex_[ lag ];
300 double H_ex = 1.; // valid value for non-multiplicative coupling
301 double H_in = 1.; // valid value for non-multiplicative coupling
302 if ( P_.mult_coupling_ )
303 {
304 H_ex = nonlinearities_.mult_coupling_ex( new_rates[ lag ] );
305 H_in = nonlinearities_.mult_coupling_in( new_rates[ lag ] );
306 }
307
308 if ( P_.linear_summation_ )
309 {
310 // In this case we explicitly need to distinguish the cases of
311 // multiplicative coupling and non-multiplicative coupling in
312 // order to compute input( ex + in ) instead of input(ex) + input(in) in
313 // the non-multiplicative case.
314 if ( P_.mult_coupling_ )
315 {
316 S_.rate_ += V_.P2_ * H_ex * nonlinearities_.input( delayed_rates_ex + instant_rates_ex );
317 S_.rate_ += V_.P2_ * H_in * nonlinearities_.input( delayed_rates_in + instant_rates_in );
318 }
319 else
320 {
321 S_.rate_ +=
322 V_.P2_ * nonlinearities_.input( delayed_rates_ex + instant_rates_ex + delayed_rates_in + instant_rates_in );
323 }
324 }
325 else
326 {
327 // In this case multiplicative and non-multiplicative coupling
328 // can be handled with the same code.
329 S_.rate_ += V_.P2_ * H_ex * ( delayed_rates_ex + instant_rates_ex );
330 S_.rate_ += V_.P2_ * H_in * ( delayed_rates_in + instant_rates_in );
331 }
332
333 if ( P_.rectify_output_ and S_.rate_ < P_.rectify_rate_ )
334 {
335 S_.rate_ = P_.rectify_rate_;
336 }
337
338 if ( called_from_wfr_update )
339 {
340 // check if deviation from last iteration exceeds wfr_tol
341 wfr_tol_exceeded = wfr_tol_exceeded or fabs( S_.rate_ - B_.last_y_values[ lag ] ) > wfr_tol;
342 // update last_y_values for next wfr iteration
343 B_.last_y_values[ lag ] = S_.rate_;
344 }
345 else
346 {
347 // rate logging
348 B_.logger_.record_data( origin.get_steps() + lag );
349 }
350 }
351
352 if ( not called_from_wfr_update )
353 {
354 // Send delay-rate-neuron-event. This only happens in the final iteration
355 // to avoid accumulation in the buffers of the receiving neurons.
357 drve.set_coeffarray( new_rates );
359
360 // clear last_y_values
361 std::vector< double >( buffer_size, 0.0 ).swap( B_.last_y_values );
362
363 // modifiy new_rates for rate-neuron-event as proxy for next min_delay
364 for ( long temp = from; temp < to; ++temp )
365 {
366 new_rates[ temp ] = S_.rate_;
367 }
368
369 // create new random numbers
370 B_.random_numbers.resize( buffer_size, numerics::nan );
371 for ( unsigned int i = 0; i < buffer_size; i++ )
372 {
373 B_.random_numbers[ i ] = V_.normal_dist_( get_vp_specific_rng( get_thread() ) );
374 }
375 }
376
377 // Send rate-neuron-event
379 rve.set_coeffarray( new_rates );
381
382 // Reset variables
383 std::vector< double >( buffer_size, 0.0 ).swap( B_.instant_rates_ex_ );
384 std::vector< double >( buffer_size, 0.0 ).swap( B_.instant_rates_in_ );
385
386 return wfr_tol_exceeded;
387}
388
389
390template < class TNonlinearities >
391void
393{
394 const double weight = e.get_weight();
395
396 size_t i = 0;
397 std::vector< unsigned int >::iterator it = e.begin();
398 // The call to get_coeffvalue( it ) in this loop also advances the iterator it
399 while ( it != e.end() )
400 {
401 if ( P_.linear_summation_ )
402 {
403 if ( weight >= 0.0 )
404 {
405 B_.instant_rates_ex_[ i ] += weight * e.get_coeffvalue( it );
406 }
407 else
408 {
409 B_.instant_rates_in_[ i ] += weight * e.get_coeffvalue( it );
410 }
411 }
412 else
413 {
414 if ( weight >= 0.0 )
415 {
416 B_.instant_rates_ex_[ i ] += weight * nonlinearities_.input( e.get_coeffvalue( it ) );
417 }
418 else
419 {
420 B_.instant_rates_in_[ i ] += weight * nonlinearities_.input( e.get_coeffvalue( it ) );
421 }
422 }
423 i++;
424 }
425}
426
427template < class TNonlinearities >
428void
430{
431 const double weight = e.get_weight();
432 const long delay = e.get_delay_steps() - kernel().connection_manager.get_min_delay();
433
434 size_t i = 0;
435 std::vector< unsigned int >::iterator it = e.begin();
436 // The call to get_coeffvalue( it ) in this loop also advances the iterator it
437 while ( it != e.end() )
438 {
439 if ( P_.linear_summation_ )
440 {
441 if ( weight >= 0.0 )
442 {
443 B_.delayed_rates_ex_.add_value( delay + i, weight * e.get_coeffvalue( it ) );
444 }
445 else
446 {
447 B_.delayed_rates_in_.add_value( delay + i, weight * e.get_coeffvalue( it ) );
448 }
449 }
450 else
451 {
452 if ( weight >= 0.0 )
453 {
454 B_.delayed_rates_ex_.add_value( delay + i, weight * nonlinearities_.input( e.get_coeffvalue( it ) ) );
455 }
456 else
457 {
458 B_.delayed_rates_in_.add_value( delay + i, weight * nonlinearities_.input( e.get_coeffvalue( it ) ) );
459 }
460 }
461 ++i;
462 }
463}
464
465template < class TNonlinearities >
466void
468{
469 B_.logger_.handle( e );
470}
471
472} // namespace
473
474#endif /* #ifndef RATE_NEURON_IPN_IMPL_H */
Dictionary class for interface to Python and C++ API.
Definition dictionary.h:213
A node which archives spike history for the purposes of spike-timing dependent plasticity (STDP)
Definition archiving_node.h:49
void clear_history()
Clear spike history.
Definition archiving_node.cpp:269
Exception to be thrown if a status parameter is incomplete or inconsistent.
Definition exceptions.h:680
long get_min_delay() const
Return minimal connection delay, which is precomputed by update_delay_extrema_().
Definition connection_manager.h:728
Request data to be logged/logged data to be sent.
Definition event.h:636
void set_coeffarray(std::vector< DataType > &ca)
Definition secondary_event.h:224
Event for rate model connections with delay.
Definition secondary_event.h:331
void send_secondary(Node &source, SecondaryEvent &e)
Send a secondary event remote.
Definition event_delivery_manager_impl.h:138
Event for rate model connections without delay.
Definition secondary_event.h:315
Base class for all NEST network objects.
Definition node.h:99
void set_node_uses_wfr(const bool)
Sets node_uses_wfr_ member variable (to be able to set it to "true" for any class derived from Node)
Definition node.h:1158
double get_wfr_tol() const
Get the convergence tolerance of the waveform relaxation method.
Definition simulation_manager.h:331
Definition nest_time.h:135
static Time get_resolution()
Definition nest_time.h:325
double get_ms() const
Definition nest_time.h:490
Definition rate_neuron_ipn.h:109
void init_buffers_() override
Configure persistent internal data structures.
Definition rate_neuron_ipn_impl.h:211
bool update_(Time const &, const long, const long, const bool)
This is the actual update function.
Definition rate_neuron_ipn_impl.h:263
rate_neuron_ipn()
Definition rate_neuron_ipn_impl.h:184
State_ S_
Definition rate_neuron_ipn.h:291
Parameters_ P_
Definition rate_neuron_ipn.h:290
Buffers_ B_
Definition rate_neuron_ipn.h:293
static RecordablesMap< rate_neuron_ipn< TNonlinearities > > recordablesMap_
Mapping of recordables names to access functions.
Definition rate_neuron_ipn.h:296
void pre_run_hook() override
Re-calculate dependent parameters of the node.
Definition rate_neuron_ipn_impl.h:235
void handle(InstantaneousRateConnectionEvent &) override
Handler for rate neuron events.
Definition rate_neuron_ipn_impl.h:392
ConnectionManager connection_manager
Definition kernel_manager.h:239
EventDeliveryManager event_delivery_manager
Definition kernel_manager.h:241
SimulationManager simulation_manager
Definition kernel_manager.h:237
#define LOG(s, fctn, msg)
Definition logging.h:29
const std::string std("std")
const std::string tau("tau")
const std::string mult_coupling("mult_coupling")
const std::string linear_summation("linear_summation")
const std::string lambda("lambda")
const std::string rate("rate")
const std::string mean("mean")
const std::string rectify_output("rectify_output")
const std::string noise("noise")
const std::string rectify_rate("rectify_rate")
const std::string sigma("sigma")
const std::string mu("mu")
Namespace for the NEST simulation kernel.
Definition beta_normalization_factor.h:33
RngPtr get_vp_specific_rng(size_t tid)
Definition kernel_manager.h:298
KernelManager & kernel()
Definition kernel_manager.h:311
bool update_value_param(Dictionary const &d, const std::string &key, T &value, nest::Node *node)
Obtain value from parameter dictionary including evaluation of random or spatial parameters.
Definition dict_util.h:42
const double nan
Definition numerics.cpp:36
double expm1(double x)
Definition numerics.h:44
Buffers of the model.
Definition rate_neuron_ipn.h:237
Buffers_(rate_neuron_ipn &)
Definition rate_neuron_ipn_impl.h:168
void get(Dictionary &) const
Store current values in dictionary.
Definition rate_neuron_ipn_impl.h:87
Parameters_()
Sets default parameter values.
Definition rate_neuron_ipn_impl.h:61
void set(const Dictionary &, Node *node)
Definition rate_neuron_ipn_impl.h:105
State_()
Default initialization.
Definition rate_neuron_ipn_impl.h:75
void set(const Dictionary &, Node *node)
Set values from dictionary.
Definition rate_neuron_ipn_impl.h:162
void get(Dictionary &) const
Definition rate_neuron_ipn_impl.h:154