23#ifndef EPROP_ARCHIVING_NODE_IMPL_H
24#define EPROP_ARCHIVING_NODE_IMPL_H
34template <
typename HistEntryT >
39 , eprop_indegree_( 0 )
40 , eprop_isi_trace_cutoff_( std::numeric_limits< double >::infinity() )
44template <
typename HistEntryT >
49 , eprop_indegree_( n.eprop_indegree_ )
50 , eprop_isi_trace_cutoff_( n.eprop_isi_trace_cutoff_ )
54template <
typename HistEntryT >
61template <
typename HistEntryT >
65 const long t_first_entry = model_dependent_history_shift_();
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 )
71 update_history_.emplace_back( t_first_entry, 1 );
75 ++it_hist->access_counter_;
79template <
typename HistEntryT >
82 const long t_current_update,
83 const bool is_flush_event,
84 const bool previous_was_flush_event )
86 if ( eprop_indegree_ == 0 )
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;
95 if ( not is_flush_event )
97 auto it_hist_curr = get_update_history( t_curr_update_shifted );
99 if ( it_hist_curr != update_history_.end() and it_hist_curr->t_ == t_curr_update_shifted )
101 ++it_hist_curr->access_counter_;
105 update_history_.emplace_back( t_curr_update_shifted, 1 );
109 if ( not previous_was_flush_event )
111 auto it_hist_prev = get_update_history( t_prev_update_shifted );
113 if ( it_hist_prev != update_history_.end() and it_hist_prev->t_ == t_prev_update_shifted )
116 --it_hist_prev->access_counter_;
117 if ( it_hist_prev->access_counter_ == 0 )
119 update_history_.erase( it_hist_prev );
125template <
typename HistEntryT >
128 const typename std::vector< HistEntryT >::iterator eprop_hist_it,
129 const long time_step )
const
131 if ( eprop_hist_it == eprop_history_.end() )
134 String::compose(
"Expected in neuron with ID %1 e-prop history entry at t=%2, got end of e-prop history.",
139 if ( eprop_hist_it->t_ != time_step )
141 throw KernelException( String::compose(
"Expected in neuron with ID %1 e-prop history entry at t=%2, got t=%3.",
144 eprop_hist_it->t_ ) );
148template <
typename HistEntryT >
149std::vector< HistEntryEpropUpdate >::iterator
152 return std::lower_bound( update_history_.begin(), update_history_.end(), time_step );
155template <
typename HistEntryT >
156typename std::vector< HistEntryT >::iterator
159 return std::lower_bound( eprop_history_.begin(), eprop_history_.end(), time_step );
162template <
typename HistEntryT >
166 if ( eprop_history_.empty()
167 or update_history_.empty()
175 auto it_update_hist = update_history_.begin();
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 )
181 if ( it_update_hist->t_ == t )
188 eprop_history_.erase( get_eprop_history( t ), get_eprop_history( t + update_interval ) );
192 eprop_history_.erase( eprop_history_.begin(), get_eprop_history( update_history_.begin()->t_ ) );
195template <
typename HistEntryT >
199 auto it_hist = get_update_history( t_spike );
201 if ( it_hist != update_history_.end() and it_hist->t_ == t_spike )
203 ++it_hist->access_counter_;
207 update_history_.emplace( it_hist, t_spike, 1 );
210 if ( t_spike_previous > 0 )
212 auto it_hist_prev = get_update_history( t_spike_previous );
214 if ( it_hist_prev != update_history_.end() and it_hist_prev->t_ == t_spike_previous )
216 if ( it_hist_prev->access_counter_ > 0 )
218 --it_hist_prev->access_counter_;
220 if ( it_hist_prev->access_counter_ == 0 )
222 update_history_.erase( it_hist_prev );
229 const long cutoff = get_eprop_isi_trace_cutoff();
231 const long erase_candidate_begin = t_spike_previous - 1;
232 const long erase_candidate_end = erase_candidate_begin + cutoff;
234 long erase_begin = erase_candidate_begin;
235 long erase_end = erase_candidate_end;
237 const long search_begin = std::max( 0L, erase_candidate_begin - cutoff );
238 const long search_end = erase_candidate_end;
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 );
243 for (
auto it = it_search_begin; it != it_search_end and erase_begin < erase_end; ++it )
245 const long required_begin = it->t_ - 1;
246 const long required_end = required_begin + cutoff;
248 if ( required_begin >= erase_candidate_begin and required_begin <= erase_candidate_end )
250 erase_end = std::min( erase_end, required_begin );
252 if ( required_end >= erase_candidate_begin and required_end <= erase_candidate_end )
254 erase_begin = std::max( erase_begin, required_end );
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 )
262 eprop_history_.erase( it_erase_begin, it_erase_end );
266 if ( update_history_.empty() or eprop_history_.empty() )
271 const long time_keep = update_history_.front().t_ - 1;
272 auto it_keep = get_eprop_history( time_keep );
274 if ( it_keep != eprop_history_.end() and it_keep->t_ == time_keep and it_keep != eprop_history_.begin() )
276 eprop_history_.erase( eprop_history_.begin(), it_keep );
280template <
typename HistEntryT >
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