diligent_connector_model.h
1 /*
2  * This file is part of SPORE.
3  *
4  * Copyright (C) 2016, the SPORE team (see AUTHORS).
5  *
6  * SPORE is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * SPORE is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with SPORE. If not, see <http://www.gnu.org/licenses/>.
18  *
19  * For more information see: https://github.com/IGITUGraz/spore-nest-module
20  *
21  * File: diligent_connector_model.h
22  * Author: Kappel
23  *
24  * This file is based on connector_model_impl.h which is part of NEST
25  * (Copyright (C) 2004 The NEST Initiative).
26  * See: http://nest-initiative.org/
27  */
28 
29 #ifndef DILIGENT_CONNECTOR_MODEL_H
30 #define DILIGENT_CONNECTOR_MODEL_H
31 
32 #include "connector_model_impl.h"
33 
34 #include "spore.h"
35 #include "connection_updater.h"
36 
37 
38 namespace spore
39 {
40 
80 template < typename ConnectionT >
81 class DiligentConnectorModel : public nest::GenericConnectorModel<ConnectionT>
82 {
83 public:
87  DiligentConnectorModel(const std::string name, bool is_primary = true,
88  bool has_delay = true, bool requires_symmetric = false)
89  : nest::GenericConnectorModel<ConnectionT>(name, is_primary, has_delay, requires_symmetric)
90  {
91  }
92 
96  DiligentConnectorModel(const DiligentConnectorModel& other, const std::string name)
97  : nest::GenericConnectorModel<ConnectionT>(other, name)
98  {
99  }
100 
101  virtual nest::ConnectorBase* add_connection(nest::Node& src, nest::Node& tgt, nest::ConnectorBase* conn,
102  nest::synindex syn_id, double weight,
103  double delay);
104 
105  virtual nest::ConnectorBase* add_connection(nest::Node& src, nest::Node& tgt, nest::ConnectorBase* conn,
106  nest::synindex syn_id, DictionaryDatum& d,
107  double weight, double delay);
108 
109  virtual nest::ConnectorBase* delete_connection(nest::Node& tgt, size_t target_thread,
110  nest::ConnectorBase* conn, nest::synindex syn_id);
111 
112  virtual nest::ConnectorModel* clone(std::string name) const;
113 
114 protected:
115 
116  nest::ConnectorBase* cleanup_delete_connection(nest::Node& tgt, const size_t target_thread,
117  nest::ConnectorBase* const conn, const nest::synindex syn_id);
118 
119  void register_connector(nest::ConnectorBase* new_conn, nest::ConnectorBase* old_conn, nest::index sender_gid,
120  size_t target_thread, nest::synindex syn_id);
121 
122  nest::ConnectorBase* get_hom_connector(nest::ConnectorBase* conn, nest::synindex syn_id);
123 
124 }; // DiligentConnectorModel
125 
143 template < typename ConnectionT >
144 nest::ConnectorBase*
146  nest::Node& tgt,
147  nest::ConnectorBase* conn,
148  nest::synindex syn_id,
149  double delay,
150  double weight)
151 {
152  nest::ConnectorBase* old_hom_conn = get_hom_connector(nest::validate_pointer(conn), syn_id);
153  nest::ConnectorBase* new_conn = nest::GenericConnectorModel< ConnectionT >::add_connection(src, tgt, conn,
154  syn_id, delay, weight);
155  nest::ConnectorBase* new_hom_conn = get_hom_connector(nest::validate_pointer(new_conn), syn_id);
156  register_connector(new_hom_conn, old_hom_conn, src.get_gid(), tgt.get_thread(), syn_id);
157  return new_conn;
158 }
159 
178 template < typename ConnectionT >
179 nest::ConnectorBase*
181  nest::Node& tgt,
182  nest::ConnectorBase* conn,
183  nest::synindex syn_id,
184  DictionaryDatum& p,
185  double delay,
186  double weight)
187 {
188  nest::ConnectorBase* old_hom_conn = get_hom_connector(nest::validate_pointer(conn), syn_id);
189  nest::ConnectorBase* new_conn = nest::GenericConnectorModel< ConnectionT >::add_connection(src, tgt, conn, syn_id,
190  p, delay, weight);
191  nest::ConnectorBase* new_hom_conn = get_hom_connector(nest::validate_pointer(new_conn), syn_id);
192  register_connector(new_hom_conn, old_hom_conn, src.get_gid(), tgt.get_thread(), syn_id);
193  return new_conn;
194 }
195 
206 template < typename ConnectionT >
207 nest::ConnectorBase*
209  size_t target_thread,
210  nest::ConnectorBase* conn,
211  nest::synindex syn_id)
212 {
213  nest::ConnectorBase* old_hom_conn = get_hom_connector(nest::validate_pointer(conn), syn_id);
214  nest::ConnectorBase* new_conn = cleanup_delete_connection(tgt, target_thread, conn, syn_id);
215  nest::ConnectorBase* new_hom_conn = get_hom_connector(nest::validate_pointer(new_conn), syn_id);
216  register_connector(new_hom_conn, old_hom_conn, nest::invalid_index, tgt.get_thread(), syn_id);
217  return new_conn;
218 }
219 
223 template < typename ConnectionT >
224 nest::ConnectorModel*
226 {
227  return new DiligentConnectorModel< ConnectionT >(*this, name); // calls copy construtor
228 }
229 
233 template < typename ConnectionT >
235  nest::ConnectorBase* old_conn,
236  nest::index sender_gid,
237  size_t target_thread,
238  nest::synindex syn_id)
239 {
240  ConnectionUpdateManager::instance()->register_connector(new_conn, old_conn, sender_gid,
241  target_thread, syn_id);
242 }
243 
262 template < typename ConnectionT >
264  const size_t target_thread,
265  nest::ConnectorBase* const conn,
266  const nest::synindex syn_id)
267 {
268  using nest::HetConnector;
269  using nest::vector_like;
270  using nest::pack_pointer;
271  using nest::kernel;
272 
273  assert(conn != 0); // we should not delete not existing synapses
274  bool found = false;
275  vector_like< ConnectionT >* vc;
276 
277  const bool b_has_primary = has_primary(conn);
278  const bool b_has_secondary = has_secondary(conn);
279 
280  nest::ConnectorBase* conn_vp = validate_pointer(conn);
281 
282  // from here on we can use conn as a valid pointer
283 
284  if (conn_vp->homogeneous_model())
285  {
286  assert(conn_vp->get_syn_id() == syn_id);
287  vc = static_cast<vector_like< ConnectionT >*> (conn_vp);
288  // delete the first Connection corresponding to the target
289  for (size_t i = 0; i < vc->size(); i++)
290  {
291  ConnectionT* connection = &vc->at(i);
292 
293  // only remove synapse if marked for deletion.
294  if ((connection->get_target(target_thread)->get_gid() == tgt.get_gid()) && connection->is_degenerated())
295  {
296  if (vc->get_num_connections() > 1)
297  conn_vp = &vc->erase(i);
298  else
299  {
300  delete vc;
301  conn_vp = 0;
302  }
304  if (conn_vp != 0)
305  {
306  conn_vp = pack_pointer(conn_vp, is_primary, !is_primary);
307  }
308  found = true;
309  break;
310  }
311  }
312  }
313  else
314  {
315  // heterogeneous case
316  // go through all entries and search for correct syn_id
317  // if not found create new entry for this syn_id
318  HetConnector* hc = static_cast< HetConnector* > (conn_vp);
319 
320  for (size_t i = 0; i < hc->size() && !found; i++)
321  {
322  // need to cast to vector_like to access syn_id there is already an entry
323  // for this type
324  if ((*hc)[ i ]->get_syn_id() == syn_id)
325  {
326  // here we know that the type is vector_like<connectionT>, because
327  // syn_id agrees so we can safely static cast
328  vector_like< ConnectionT >* vc =
329  static_cast< vector_like< ConnectionT >* > ((*hc)[ i ]);
330  // Find and delete the first Connection corresponding to the target
331  for (size_t j = 0; j < vc->size(); j++)
332  {
333  ConnectionT* connection = &vc->at(j);
334 
335  if ((connection->get_target(target_thread)->get_gid() == tgt.get_gid()) &&
336  connection->is_degenerated()) // only remove synapse if marked for deletion.
337  {
338  // Get rid of the ConnectionBase for this type of synapse if there
339  // is only this element left
340  if (vc->size() == 1)
341  {
342  (*hc).erase((*hc).begin() + i);
343  // Test if the homogeneous vector of connections went back to only
344  // 1 type of synapse... then go back to the simple vector_like
345  // case.
346  if (hc->size() == 1)
347  {
348  conn_vp = (*hc)[ 0 ];
349  const bool is_primary =
350  kernel().model_manager.get_synapse_prototype(conn_vp->get_syn_id()).is_primary();
351  conn_vp = pack_pointer(conn_vp, is_primary, not is_primary);
352  }
353  else
354  {
355  conn_vp = pack_pointer(hc, b_has_primary, b_has_secondary);
356  }
357  } // Otherwise, just remove the desired connection
358  else
359  {
360  (*hc)[ i ] = &vc->erase(j);
361  conn_vp = pack_pointer(hc, b_has_primary, b_has_secondary);
362  }
363  found = true;
364  break;
365  }
366  }
367  }
368  }
369  }
370 
371  if (found)
372  {
373  return conn_vp;
374  }
375  else
376  {
377  return nest::GenericConnectorModel< ConnectionT >::delete_connection(tgt, target_thread, conn, syn_id);
378  }
379 }
380 
393 template < typename ConnectionT >
394 nest::ConnectorBase* DiligentConnectorModel< ConnectionT >::get_hom_connector(nest::ConnectorBase* conn,
395  nest::synindex syn_id)
396 {
397  if (!conn)
398  {
399  return 0;
400  }
401  else if (conn->homogeneous_model())
402  {
403  if (conn->get_syn_id() == syn_id)
404  return conn;
405  }
406  else
407  {
408  // connector is heterogeneous - go through all entries and search for correct syn_id
409  nest::HetConnector* hc = static_cast<nest::HetConnector*> (conn);
410  for (size_t i = 0; i < hc->size(); i++)
411  {
412  // need to cast to vector_like to access syn_id
413  if ((*hc)[ i ]->get_syn_id() == syn_id) // find entry for this type
414  {
415  return (*hc)[ i ];
416  }
417  }
418  }
419 
420  return 0;
421 }
422 
436 template <class ConnectionT>
437 void register_diligent_connection_model(const std::string& name, bool requires_symmetric = false)
438 {
439  nest::kernel().model_manager.register_connection_model< ConnectionT, DiligentConnectorModel >
440  (name, requires_symmetric);
441 }
442 
443 }
444 
445 #endif
DiligentConnectorModel(const std::string name, bool is_primary=true, bool has_delay=true, bool requires_symmetric=false)
Definition: diligent_connector_model.h:87
void register_connector(nest::ConnectorBase *new_conn, nest::ConnectorBase *old_conn, nest::index sender_gid, size_t target_thread, nest::synindex syn_id)
Definition: diligent_connector_model.h:234
virtual nest::ConnectorModel * clone(std::string name) const
Definition: diligent_connector_model.h:225
DiligentConnectorModel(const DiligentConnectorModel &other, const std::string name)
Definition: diligent_connector_model.h:96
Definition: poisson_dbl_exp_neuron.cpp:43
Connector model for diligent connections.
Definition: diligent_connector_model.h:81
void register_diligent_connection_model(const std::string &name, bool requires_symmetric=false)
Definition: diligent_connector_model.h:437
void register_connector(nest::ConnectorBase *new_conn, nest::ConnectorBase *old_conn, nest::index sender_gid, nest::thread th, nest::synindex syn_id)
Definition: connection_updater.cpp:160
virtual nest::ConnectorBase * delete_connection(nest::Node &tgt, size_t target_thread, nest::ConnectorBase *conn, nest::synindex syn_id)
Definition: diligent_connector_model.h:208
virtual nest::ConnectorBase * add_connection(nest::Node &src, nest::Node &tgt, nest::ConnectorBase *conn, nest::synindex syn_id, double weight, double delay)
Definition: diligent_connector_model.h:145
static ConnectionUpdateManager * instance()
Definition: connection_updater.cpp:312
nest::ConnectorBase * get_hom_connector(nest::ConnectorBase *conn, nest::synindex syn_id)
Definition: diligent_connector_model.h:394
nest::ConnectorBase * cleanup_delete_connection(nest::Node &tgt, const size_t target_thread, nest::ConnectorBase *const conn, const nest::synindex syn_id)
Cleanup and delete the given connection.
Definition: diligent_connector_model.h:263
Global namespace holding all classes of the SPORE NEST module.
Definition: circular_buffer.h:31