NEST main@caf0ae8
 
Loading...
Searching...
No Matches
binary_neuron.h
Go to the documentation of this file.
1/*
2 * binary_neuron.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 BINARY_NEURON_H
24#define BINARY_NEURON_H
25
26// C++ includes:
27#include <cmath>
28#include <limits>
29
30// Includes from libnestutil:
31#include "dict_util.h"
32#include "numerics.h"
33
34// Includes from nestkernel:
35#include "archiving_node.h"
36#include "connection.h"
37#include "event.h"
39#include "exceptions.h"
40#include "kernel_manager.h"
41#include "nest_timeconverter.h"
42#include "nest_types.h"
43#include "random_generators.h"
44#include "recordables_map.h"
45#include "ring_buffer.h"
47
48
49namespace nest
50{
74template < class TGainfunction >
76{
77
78public:
81
87 using Node::handle;
91
92 size_t send_test_event( Node&, size_t, synindex, bool ) override;
93
94 void handle( SpikeEvent& ) override;
95 void handle( CurrentEvent& ) override;
96 void handle( DataLoggingRequest& ) override;
97
98 size_t handles_test_event( SpikeEvent&, size_t ) override;
99 size_t handles_test_event( CurrentEvent&, size_t ) override;
100 size_t handles_test_event( DataLoggingRequest&, size_t ) override;
101
102 SignalType sends_signal() const override;
103 SignalType receives_signal() const override;
104
105 void get_status( Dictionary& ) const override;
106 void set_status( const Dictionary& ) override;
107
108 void calibrate_time( const TimeConverter& tc ) override;
109
110
111private:
112 void init_buffers_() override;
113 void pre_run_hook() override;
114
115 // gain function functor
116 // must have an double operator(double) defined
117 TGainfunction gain_;
118
119 void update( Time const&, const long, const long ) override;
120
121 // The next two classes need to be friends to access the State_ class/member
122 friend class RecordablesMap< binary_neuron< TGainfunction > >;
123 friend class UniversalDataLogger< binary_neuron< TGainfunction > >;
124
125 // ----------------------------------------------------------------
126
131 {
133 double tau_m_;
134
135 Parameters_();
136
137 void get( Dictionary& ) const;
138 void set( const Dictionary&, Node* node );
139 };
140
141 // ----------------------------------------------------------------
142
146 struct State_
147 {
148 bool y_;
149 double h_;
153
154 State_();
155
156 void get( Dictionary&, const Parameters_& ) const;
157 void set( const Dictionary&, const Parameters_&, Node* );
158 };
159
160 // ----------------------------------------------------------------
161
165 struct Buffers_
166 {
168 Buffers_( const Buffers_&, binary_neuron& );
169
173
174
176 UniversalDataLogger< binary_neuron > logger_;
177 };
178
179 // ----------------------------------------------------------------
180
189
190 // Access functions for UniversalDataLogger -------------------------------
191
193 double
195 {
196 return S_.y_;
197 }
198
200 double
202 {
203 return S_.h_;
204 }
205
206 // ----------------------------------------------------------------
207
222};
223
224
225template < class TGainfunction >
226inline size_t
227binary_neuron< TGainfunction >::send_test_event( Node& target, size_t receptor_type, synindex, bool )
228{
229 SpikeEvent e;
230 e.set_sender( *this );
231
232 return target.handles_test_event( e, receptor_type );
233}
234
235template < class TGainfunction >
236inline size_t
238{
239 if ( receptor_type != 0 )
240 {
241 throw UnknownReceptorType( receptor_type, get_name() );
242 }
243 return 0;
244}
245
246template < class TGainfunction >
247inline size_t
249{
250 if ( receptor_type != 0 )
251 {
252 throw UnknownReceptorType( receptor_type, get_name() );
253 }
254 return 0;
255}
256
257template < class TGainfunction >
258inline size_t
260{
261 if ( receptor_type != 0 )
262 {
263 throw UnknownReceptorType( receptor_type, get_name() );
264 }
265 return B_.logger_.connect_logging_device( dlr, recordablesMap_ );
266}
267
268
269template < class TGainfunction >
270inline SignalType
275
276template < class TGainfunction >
277inline SignalType
282
283
284template < class TGainfunction >
285inline void
287{
288 P_.get( d );
289 S_.get( d, P_ );
291 d[ names::recordables ] = recordablesMap_.get_list();
292
293 gain_.get( d );
294}
295
296template < class TGainfunction >
297inline void
299{
300 Parameters_ ptmp = P_; // temporary copy in case of errors
301 ptmp.set( d, this ); // throws if BadProperty
302 State_ stmp = S_; // temporary copy in case of errors
303 stmp.set( d, ptmp, this ); // throws if BadProperty
304
305 // We now know that (ptmp, stmp) are consistent. We do not
306 // write them back to (P_, S_) before we are also sure that
307 // the properties to be set in the parent class are internally
308 // consistent.
310
311 // if we get here, temporaries contain consistent set of properties
312 P_ = ptmp;
313 S_ = stmp;
314
315 gain_.set( d, this );
316}
317
318template < typename TGainfunction >
320
321/* ----------------------------------------------------------------
322 * Default constructors defining default parameters and state
323 * ---------------------------------------------------------------- */
324
325template < class TGainfunction >
327 : tau_m_( 10.0 ) // ms
328{
329 recordablesMap_.create();
330}
331
332template < class TGainfunction >
334 : y_( false )
335 , h_( 0.0 )
336 , last_in_node_id_( 0 )
337 , t_next_( Time::neg_inf() ) // mark as not initialized
338 , t_last_in_spike_( Time::neg_inf() ) // mark as not intialized
339{
340}
341
342/* ----------------------------------------------------------------
343 * Parameter and state extractions and manipulation functions
344 * ---------------------------------------------------------------- */
345
346template < class TGainfunction >
347void
352
353template < class TGainfunction >
354void
356{
357 update_value_param( d, names::tau_m, tau_m_, node );
358 if ( tau_m_ <= 0 )
359 {
360 throw BadProperty( "All time constants must be strictly positive." );
361 }
362}
363
364template < class TGainfunction >
365void
367{
368 d[ names::h ] = h_; // summed input
369 d[ names::S ] = y_; // binary_neuron output state
370}
371
372template < class TGainfunction >
373void
377
378template < class TGainfunction >
383
384template < class TGainfunction >
389
390
391/* ----------------------------------------------------------------
392 * Default and copy constructor for node
393 * ---------------------------------------------------------------- */
394
395template < class TGainfunction >
397 : ArchivingNode()
398 , P_()
399 , S_()
400 , B_( *this )
401{
402}
403
404template < class TGainfunction >
406 : ArchivingNode( n )
407 , gain_( n.gain_ )
408 , P_( n.P_ )
409 , S_( n.S_ )
410 , B_( *this )
411{
412}
413
414/* ----------------------------------------------------------------
415 * Node initialization functions
416 * ---------------------------------------------------------------- */
417
418template < class TGainfunction >
419void
421{
422 B_.spikes_.clear(); // includes resize
423 B_.currents_.clear(); // includes resize
424 B_.logger_.reset();
426}
427
428template < class TGainfunction >
429void
431{
432 // ensures initialization in case mm connected after Simulate
433 B_.logger_.init();
434 V_.rng_ = get_vp_specific_rng( get_thread() );
435
436 // draw next time of update for the neuron from exponential distribution
437 // only if not yet initialized
438 if ( S_.t_next_.is_neg_inf() )
439 {
440 S_.t_next_ = Time::ms( V_.exp_dist_( V_.rng_ ) * P_.tau_m_ );
441 }
442}
443
444
445/* ----------------------------------------------------------------
446 * Update and spike handling functions
447 */
448
449template < class TGainfunction >
450void
451binary_neuron< TGainfunction >::update( Time const& origin, const long from, const long to )
452{
453 for ( long lag = from; lag < to; ++lag )
454 {
455 // update the input current
456 // the buffer for incoming spikes for every time step contains the
457 // difference
458 // of the total input h with respect to the previous step, so sum them up
459 S_.h_ += B_.spikes_.get_value( lag );
460
461 double c = B_.currents_.get_value( lag );
462
463 // check, if the update needs to be done
464 if ( Time::step( origin.get_steps() + lag ) > S_.t_next_ )
465 {
466 // change the state of the neuron with probability given by
467 // gain function
468 // if the state has changed, the neuron produces an event sent to all its
469 // targets
470
471 bool new_y = gain_( V_.rng_, S_.h_ + c );
472
473 if ( new_y != S_.y_ )
474 {
475 SpikeEvent se;
476 // use multiplicity 2 to signal transition to 1 state
477 // use multiplicity 1 to signal transition to 0 state
478 se.set_multiplicity( new_y ? 2 : 1 );
479 kernel().event_delivery_manager.send( *this, se, lag );
480
481 // As multiplicity is used only to signal internal information
482 // to other binary neurons, we only set spiketime once, independent
483 // of multiplicity.
484 set_spiketime( Time::step( origin.get_steps() + lag + 1 ) );
485 S_.y_ = new_y;
486 }
487
488 // draw next update interval from exponential distribution
489 S_.t_next_ += Time::ms( V_.exp_dist_( V_.rng_ ) * P_.tau_m_ );
490
491 } // of if (update now)
492
493 // log state data
494 B_.logger_.record_data( origin.get_steps() + lag );
495
496 } // of for (lag ...
497}
498
499template < class TGainfunction >
500void
502{
503 assert( e.get_delay_steps() > 0 );
504
505 // The following logic implements the encoding:
506 // A single spike signals a transition to 0 state, two spikes in same time
507 // step signal the transition to 1 state.
508 //
509 // Remember the node ID of the sender of the last spike being received
510 // this assumes that several spikes being sent by the same neuron in the same
511 // time step are received consecutively or are conveyed by setting the
512 // multiplicity accordingly.
513 //
514 // Since in collocate_buffers spike events with multiplicity > 1
515 // will be converted into sequences of spikes with unit multiplicity,
516 // we will count the arrival of the first spike of a doublet (not yet knowing
517 // it's a doublet) with a weight -1. The second part of a doublet is then
518 // counted with weight 2. Since both parts of a doublet are delivered before
519 // update is called, the final value in the ring buffer is guaranteed to be
520 // correct.
521
522
523 const long m = e.get_multiplicity();
524 const long node_id = e.retrieve_sender_node_id_from_source_table();
525 const Time& t_spike = e.get_stamp();
526
527 if ( m == 1 )
528 { // multiplicity == 1, either a single 1->0 event or the first or second of a
529 // pair of 0->1 events
530 if ( node_id == S_.last_in_node_id_ and t_spike == S_.t_last_in_spike_ )
531 {
532 // received twice the same node ID, so transition 0->1
533 // take double weight to compensate for subtracting first event
534 B_.spikes_.add_value(
535 e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), 2.0 * e.get_weight() );
536 }
537 else
538 {
539 // count this event negatively, assuming it comes as single event
540 // transition 1->0
541 B_.spikes_.add_value(
542 e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), -e.get_weight() );
543 }
544 }
545 else if ( m == 2 )
546 {
547 // count this event positively, transition 0->1
548 B_.spikes_.add_value( e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), e.get_weight() );
549 }
550
551 S_.last_in_node_id_ = node_id;
552 S_.t_last_in_spike_ = t_spike;
553}
554
555template < class TGainfunction >
556void
558{
559 assert( e.get_delay_steps() > 0 );
560
561 const double c = e.get_current();
562 const double w = e.get_weight();
563
564 // we use the spike buffer to receive the binary events
565 // but also to handle the incoming current events added
566 // both contributions are directly added to the variable h
567 B_.currents_.add_value( e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), w * c );
568}
569
570
571template < class TGainfunction >
572void
574{
575 B_.logger_.handle( e );
576}
577
578template < class TGainfunction >
579void
581{
582 S_.t_next_ = tc.from_old_tics( S_.t_next_.get_tics() );
583 S_.t_last_in_spike_ = tc.from_old_tics( S_.t_last_in_spike_.get_tics() );
584}
585
586
587} // namespace
588
589#endif /* #ifndef BINARY_NEURON_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
void get_status(Dictionary &d) const override
Export properties of the node by setting entries in the status dictionary.
Definition archiving_node.cpp:220
void set_status(const Dictionary &d) override
Change properties of the node according to the entries in the dictionary.
Definition archiving_node.cpp:236
Exception to be thrown if a status parameter is incomplete or inconsistent.
Definition exceptions.h:680
Base class for RNG engine wrappers.
Definition random_generators.h:67
Event for electrical currents.
Definition event.h:569
Request data to be logged/logged data to be sent.
Definition event.h:636
void send(Node &source, EventT &e, const long lag=0)
Standard routine for sending events.
Definition event_delivery_manager_impl.h:60
Base class for all NEST network objects.
Definition node.h:99
virtual SignalType receives_signal() const
Definition node.h:974
virtual SignalType sends_signal() const
Definition node.h:963
Map names of recordables to data access functions.
Definition recordables_map.h:61
Buffer Layout.
Definition ring_buffer.h:83
Event for spike information.
Definition event.h:418
void set_multiplicity(size_t)
Definition event.h:443
Class to convert times from one representation to another.
Definition nest_timeconverter.h:42
Time from_old_tics(tic_t t_old) const
Converts a given number of tics with respect to old representation into a time object in current repr...
Definition nest_timeconverter.cpp:49
Definition nest_time.h:135
Exception to be thrown if the specified receptor type does not exist in the node.
Definition exceptions.h:417
Binary stochastic neuron with linear or sigmoidal gain function.
Definition binary_neuron.h:76
void calibrate_time(const TimeConverter &tc) override
Re-calculate time-based properties of the node.
Definition binary_neuron.h:580
TGainfunction gain_
Definition binary_neuron.h:117
SignalType sends_signal() const override
Definition binary_neuron.h:271
void get_status(Dictionary &) const override
Export properties of the node by setting entries in the status dictionary.
Definition binary_neuron.h:286
binary_neuron()
Definition binary_neuron.h:396
void init_buffers_() override
Configure persistent internal data structures.
Definition binary_neuron.h:420
void set_status(const Dictionary &) override
Change properties of the node according to the entries in the dictionary.
Definition binary_neuron.h:298
Variables_ V_
Definition binary_neuron.h:216
size_t send_test_event(Node &, size_t, synindex, bool) override
Send an event to the receiving_node passed as an argument.
Definition binary_neuron.h:227
double get_output_state__() const
Read out the binary_neuron state of the neuron.
Definition binary_neuron.h:194
Buffers_ B_
Definition binary_neuron.h:217
void pre_run_hook() override
Re-calculate dependent parameters of the node.
Definition binary_neuron.h:430
SignalType receives_signal() const override
Definition binary_neuron.h:278
static RecordablesMap< binary_neuron< TGainfunction > > recordablesMap_
Mapping of recordables names to access functions.
Definition binary_neuron.h:221
State_ S_
Definition binary_neuron.h:215
double get_input__() const
Read out the summed input of the neuron (= membrane potential)
Definition binary_neuron.h:201
void update(Time const &, const long, const long) override
Advance the state of the node in time through the given interval.
Definition binary_neuron.h:451
size_t handles_test_event(SpikeEvent &, size_t) override
Check if the node can handle a particular event and receptor type.
Definition binary_neuron.h:237
Parameters_ P_
Instances of private data structures for the different types of data pertaining to the model.
Definition binary_neuron.h:214
void handle(SpikeEvent &) override
Handle incoming spike events.
Definition binary_neuron.h:501
EventDeliveryManager event_delivery_manager
Definition kernel_manager.h:241
virtual size_t handles_test_event(SpikeEvent &, size_t receptor_type)
Check if the node can handle a particular event and receptor type.
Definition node.cpp:271
virtual void handle(SpikeEvent &e)
Handle incoming spike events.
Definition node.cpp:265
const std::string tau_m("tau_m")
const std::string S("S")
const std::string recordables("recordables")
const std::string h("h")
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
SignalType
enum type of signal conveyed by spike events of a node.
Definition nest_types.h:165
@ BINARY
Definition nest_types.h:168
size_t synindex
For enumerations of synapse types.
Definition nest_types.h:115
Definition nest_time.h:255
Definition nest_time.h:246
Buffers of the model.
Definition binary_neuron.h:166
UniversalDataLogger< binary_neuron > logger_
Logger for all analog data.
Definition binary_neuron.h:176
Buffers_(binary_neuron &)
Definition binary_neuron.h:379
RingBuffer spikes_
buffers and sums up incoming spikes/currents
Definition binary_neuron.h:171
RingBuffer currents_
Definition binary_neuron.h:172
Independent parameters of the model.
Definition binary_neuron.h:131
void get(Dictionary &) const
Store current values in dictionary.
Definition binary_neuron.h:348
void set(const Dictionary &, Node *node)
Set values from dictionary.
Definition binary_neuron.h:355
Parameters_()
Sets default parameter values.
Definition binary_neuron.h:326
double tau_m_
mean inter-update interval in ms (acts like a membrane time constant).
Definition binary_neuron.h:133
State variables of the model.
Definition binary_neuron.h:147
double last_in_node_id_
node ID of the last spike being received
Definition binary_neuron.h:150
void set(const Dictionary &, const Parameters_ &, Node *)
Definition binary_neuron.h:374
bool y_
output of neuron in [0,1]
Definition binary_neuron.h:148
void get(Dictionary &, const Parameters_ &) const
Definition binary_neuron.h:366
Time t_next_
time point of next update
Definition binary_neuron.h:151
Time t_last_in_spike_
time point of last input spike seen
Definition binary_neuron.h:152
State_()
Default initialization.
Definition binary_neuron.h:333
double h_
total input current to neuron
Definition binary_neuron.h:149
Internal variables of the model.
Definition binary_neuron.h:185
exponential_distribution exp_dist_
random deviate generator
Definition binary_neuron.h:187
RngPtr rng_
random number generator of my own thread
Definition binary_neuron.h:186