NEST main@caf0ae8
 
Loading...
Searching...
No Matches
eprop_archiving_node_impl.h
Go to the documentation of this file.
1/*
2 * eprop_archiving_node_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 EPROP_ARCHIVING_NODE_IMPL_H
24#define EPROP_ARCHIVING_NODE_IMPL_H
25
27
28// Includes from nestkernel:
29#include "kernel_manager.h"
30
31namespace nest
32{
33
34template < typename HistEntryT >
36 : Node()
39 , eprop_indegree_( 0 )
40 , eprop_isi_trace_cutoff_( std::numeric_limits< double >::infinity() )
41{
42}
43
44template < typename HistEntryT >
46 : Node( n )
49 , eprop_indegree_( n.eprop_indegree_ )
50 , eprop_isi_trace_cutoff_( n.eprop_isi_trace_cutoff_ )
51{
52}
53
54template < typename HistEntryT >
55void
57{
58 ++eprop_indegree_;
59}
60
61template < typename HistEntryT >
62void
64{
65 const long t_first_entry = model_dependent_history_shift_();
66
67 const auto it_hist = get_update_history( t_first_entry );
69 if ( it_hist == update_history_.end() or it_hist->t_ != t_first_entry )
70 {
71 update_history_.emplace_back( t_first_entry, 1 );
72 }
73 else
74 {
75 ++it_hist->access_counter_;
76 }
77}
78
79template < typename HistEntryT >
80void
82 const long t_current_update,
83 const bool is_flush_event,
84 const bool previous_was_flush_event )
85{
86 if ( eprop_indegree_ == 0 )
87 {
88 return;
89 }
90
91 const long shift = model_dependent_history_shift_();
92 const long t_curr_update_shifted = t_current_update + shift;
93 const long t_prev_update_shifted = t_previous_update + shift;
94
95 if ( not is_flush_event )
96 {
97 auto it_hist_curr = get_update_history( t_curr_update_shifted );
98
99 if ( it_hist_curr != update_history_.end() and it_hist_curr->t_ == t_curr_update_shifted )
101 ++it_hist_curr->access_counter_;
102 }
103 else
104 {
105 update_history_.emplace_back( t_curr_update_shifted, 1 );
106 }
107 }
109 if ( not previous_was_flush_event )
110 {
111 auto it_hist_prev = get_update_history( t_prev_update_shifted );
112
113 if ( it_hist_prev != update_history_.end() and it_hist_prev->t_ == t_prev_update_shifted )
114 {
115 // If an entry exists for the previous update time, decrement its access counter
116 --it_hist_prev->access_counter_;
117 if ( it_hist_prev->access_counter_ == 0 )
118 {
119 update_history_.erase( it_hist_prev );
120 }
121 }
122 }
123}
124
125template < typename HistEntryT >
126void
128 const typename std::vector< HistEntryT >::iterator eprop_hist_it,
129 const long time_step ) const
130{
131 if ( eprop_hist_it == eprop_history_.end() )
132 {
133 throw KernelException(
134 String::compose( "Expected in neuron with ID %1 e-prop history entry at t=%2, got end of e-prop history.",
135 get_node_id(),
136 time_step ) );
137 }
138
139 if ( eprop_hist_it->t_ != time_step )
140 {
141 throw KernelException( String::compose( "Expected in neuron with ID %1 e-prop history entry at t=%2, got t=%3.",
142 get_node_id(),
143 time_step,
144 eprop_hist_it->t_ ) );
145 }
146}
147
148template < typename HistEntryT >
149std::vector< HistEntryEpropUpdate >::iterator
151{
152 return std::lower_bound( update_history_.begin(), update_history_.end(), time_step );
153}
154
155template < typename HistEntryT >
156typename std::vector< HistEntryT >::iterator
158{
159 return std::lower_bound( eprop_history_.begin(), eprop_history_.end(), time_step );
160}
161
162template < typename HistEntryT >
163void
165{
166 if ( eprop_history_.empty() // nothing to remove
167 or update_history_.empty() // no time markers to check
168 )
169 {
170 return;
171 }
172
173 const long update_interval = kernel().simulation_manager.get_eprop_update_interval().get_steps();
174
175 auto it_update_hist = update_history_.begin();
176
177 for ( long t = update_history_.begin()->t_;
178 t <= ( update_history_.end() - 1 )->t_ and it_update_hist != update_history_.end();
179 t += update_interval )
180 {
181 if ( it_update_hist->t_ == t )
182 {
183 ++it_update_hist;
184 }
185 else
186 {
187 // erase no longer needed entries for update intervals with no spikes sent to the target neuron
188 eprop_history_.erase( get_eprop_history( t ), get_eprop_history( t + update_interval ) );
189 }
190 }
191 // erase no longer needed entries before the earliest current update
192 eprop_history_.erase( eprop_history_.begin(), get_eprop_history( update_history_.begin()->t_ ) );
193}
194
195template < typename HistEntryT >
196void
197EpropArchivingNode< HistEntryT >::erase_used_eprop_history( const long t_spike, const long t_spike_previous )
198{
199 auto it_hist = get_update_history( t_spike );
200
201 if ( it_hist != update_history_.end() and it_hist->t_ == t_spike )
202 {
203 ++it_hist->access_counter_;
204 }
205 else
206 {
207 update_history_.emplace( it_hist, t_spike, 1 );
208 }
209
210 if ( t_spike_previous > 0 )
211 {
212 auto it_hist_prev = get_update_history( t_spike_previous );
213
214 if ( it_hist_prev != update_history_.end() and it_hist_prev->t_ == t_spike_previous )
215 {
216 if ( it_hist_prev->access_counter_ > 0 )
217 {
218 --it_hist_prev->access_counter_;
219 }
220 if ( it_hist_prev->access_counter_ == 0 )
221 {
222 update_history_.erase( it_hist_prev );
223 }
224 }
225
226 // Erase eprop history between the previous spike and the cutoff, unless other synapses require it.
227 // For each spike in the search window, shrink the erase interval to keep history within cutoff steps afterward.
228
229 const long cutoff = get_eprop_isi_trace_cutoff();
230
231 const long erase_candidate_begin = t_spike_previous - 1;
232 const long erase_candidate_end = erase_candidate_begin + cutoff;
233
234 long erase_begin = erase_candidate_begin;
235 long erase_end = erase_candidate_end;
236
237 const long search_begin = std::max( 0L, erase_candidate_begin - cutoff );
238 const long search_end = erase_candidate_end;
239
240 auto it_search_begin = get_update_history( search_begin );
241 auto it_search_end = std::lower_bound( it_search_begin, update_history_.end(), search_end + 1 );
242
243 for ( auto it = it_search_begin; it != it_search_end and erase_begin < erase_end; ++it )
244 {
245 const long required_begin = it->t_ - 1;
246 const long required_end = required_begin + cutoff;
247
248 if ( required_begin >= erase_candidate_begin and required_begin <= erase_candidate_end )
249 {
250 erase_end = std::min( erase_end, required_begin );
251 }
252 if ( required_end >= erase_candidate_begin and required_end <= erase_candidate_end )
253 {
254 erase_begin = std::max( erase_begin, required_end );
255 }
256 }
257
258 const auto it_erase_begin = get_eprop_history( erase_begin );
259 const auto it_erase_end = get_eprop_history( erase_end );
260 if ( it_erase_begin < it_erase_end )
261 {
262 eprop_history_.erase( it_erase_begin, it_erase_end );
263 }
264 }
265
266 if ( update_history_.empty() or eprop_history_.empty() )
267 {
268 return;
269 }
270
271 const long time_keep = update_history_.front().t_ - 1;
272 auto it_keep = get_eprop_history( time_keep );
273
274 if ( it_keep != eprop_history_.end() and it_keep->t_ == time_keep and it_keep != eprop_history_.begin() )
275 {
276 eprop_history_.erase( eprop_history_.begin(), it_keep );
277 }
278}
279
280template < typename HistEntryT >
281inline double
283{
284 return Time::get_resolution().get_ms() * eprop_history_.size();
285}
286
287} // namespace nest
288
289#endif // EPROP_ARCHIVING_NODE_IMPL_H
Base class implementing archiving for node models supporting e-prop plasticity.
Definition eprop_archiving_node.h:53
std::vector< HistEntryT >::iterator get_eprop_history(const long time_step)
Retrieves the eprop history entry for a specified time step.
Definition eprop_archiving_node_impl.h:157
EpropArchivingNode()
Constructs a new EpropArchivingNode object.
Definition eprop_archiving_node_impl.h:35
void write_update_to_history(const long t_previous_update, const long t_current_update, const bool is_flush_event, const bool previous_was_flush_event) override
Registers the current update in the update history and deregisters the previous update.
Definition eprop_archiving_node_impl.h:81
double get_eprop_history_duration() const
Retrieves eprop history size.
Definition eprop_archiving_node_impl.h:282
void register_eprop_connection() override
Registers an eprop connection.
Definition eprop_archiving_node_impl.h:56
std::vector< HistEntryEpropUpdate >::iterator get_update_history(const long time_step)
Retrieves the update history entry for a specific time step.
Definition eprop_archiving_node_impl.h:150
void erase_used_eprop_history() override
Erases the used eprop history for bsshslm_2020 models.
Definition eprop_archiving_node_impl.h:164
void initialize_update_history() override
Initializes the update history.
Definition eprop_archiving_node_impl.h:63
void require_eprop_history_entry(const typename std::vector< HistEntryT >::iterator eprop_hist_it, const long time_step) const
Requires that an e-prop history iterator points to the expected time step.
Definition eprop_archiving_node_impl.h:127
Class implementing a flush event mechanism for neuron models.
Definition flush_event_mechanism.h:43
Class implementing an ignore-and-fire mechanism for neuron models.
Definition ignore_and_spike_mechanism.h:40
Base class for all Kernel exceptions.
Definition exceptions.h:65
Base class for all NEST network objects.
Definition node.h:99
Time get_eprop_update_interval() const
Definition simulation_manager.h:343
static Time get_resolution()
Definition nest_time.h:325
long get_steps() const
Definition nest_time.h:504
double get_ms() const
Definition nest_time.h:490
SimulationManager simulation_manager
Definition kernel_manager.h:237
Namespace for the NEST simulation kernel.
Definition beta_normalization_factor.h:33
KernelManager & kernel()
Definition kernel_manager.h:311