/*
* generic_connector_model.h
*
* This file is part of NEST.
*
* Copyright (C) 2004 The NEST Initiative
*
* NEST is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* NEST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NEST. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* first version
* date: march 2006
* author: Moritz Helias
*
* modified for new Connetion system
* Jochen Martin Eppler, Moritz Helias
* date march 2007
*/
#ifndef GENERICCONNECTORMODEL_H
#define GENERICCONNECTORMODEL_H
#include<vector>
#include<cstdlib>
#include "network.h"
#include "connector_model.h"
#include "common_synapse_properties.h"
namespace nest
{
/**
* Template base class for ConnectorModels.
* An actual ConnectorModel for a specific connector of type ConnectorT is obtained by deriving from the
* specialization to ConnectionT, CommonPropertiesT and ConnectorT and overriding the
* pure virtual function double_t get_default_delay_().
* ConnectionT is the class representing a single sonnection (=synapse).
* CommonProperties conntains properties that are shared among all Connections of type ConnectionT.
* ConnectorT is the connector class that contains the connections.
*/
template< typename ConnectionT, typename CommonPropertiesT, typename ConnectorT >
class GenericConnectorModelBase : public ConnectorModel
{
public:
/** Standard constructor. */
GenericConnectorModelBase(Network& net, std::string name);
/** Copy constructor. */
GenericConnectorModelBase(const GenericConnectorModelBase& f, std::string name);
///////////////////////////////////////////////////////
// Implementation of interface to ConnectionManager. //
// virtual functions defined in ConnectorModel //
///////////////////////////////////////////////////////
/** see ConnectorModel::get_connector() */
ConnectorT* get_connector();
/** see ConnectorModel::reset() */
void reset();
/** see ConnectorModel::calibrate(const TimeConverter &) */
void calibrate(const TimeConverter &);
/** see ConnectorModel::get_status() */
void get_status(DictionaryDatum& d) const;
/** see ConnectorModel::set_status() */
void set_status(const DictionaryDatum& d);
/** needed for heterosynaptic connections */
Node* get_registering_node();
///////////////////////////////////////////////////////
// Public member functions for the interface to //
// Connection and or Connector. //
// These functions do not need to be virtual //
///////////////////////////////////////////////////////
/**
* Tell the connector model that the default delay has been used to create a synapse.
* This is needed by the delay checking.
*/
inline
void used_default_delay();
/**
* Return the receptor type for this connection.
*/
inline
port get_receptor_type() const;
/**
* Return the default connection which serves as as prototype to create a new
* connection from it. This is done via ConnectionT's copy constructor,
* which therefore has to be defined propertly
*/
inline
const ConnectionT & get_default_connection() const;
/**
* Returns the comom properties for all synapses.
* These contain parameters which are the same for all synapses.
* We cannot return a const reference here, since some connections
* want to store information in the CommonProperties object.
*/
inline
CommonPropertiesT & get_common_properties();
protected:
///////////////////////////////
// private member functions //
///////////////////////////////
/**
* This function has to be overridden by the derived class in order to return the default delay. The default delay may either reside
* in the default connection or in the common properties object. This allows us to write generic code for connections with
* homogeneous delays and heterogeneous delays.
*/
virtual double_t get_default_delay_() = 0;
ConnectionT defaults_; //!< Connection object to store default parameters for one synapse
CommonPropertiesT common_props_; //!< Common proerties to all synapses
port receptor_type_; //!< The default receptor used for new connections.
};
template< typename ConnectionT, typename CommonPropertiesT, typename ConnectorT >
GenericConnectorModelBase< ConnectionT, CommonPropertiesT, ConnectorT >::GenericConnectorModelBase(Network& net, std::string name)
: ConnectorModel(net, name),
defaults_(),
common_props_(),
receptor_type_(0)
{
}
template< typename ConnectionT, typename CommonPropertiesT, typename ConnectorT >
GenericConnectorModelBase< ConnectionT, CommonPropertiesT, ConnectorT >::GenericConnectorModelBase(const GenericConnectorModelBase& f, std::string name)
: ConnectorModel(f, name),
defaults_(f.defaults_),
common_props_(f.common_props_),
receptor_type_(f.receptor_type_)
{
}
///////////////////////////////////////////////////////
// Imlementation of ConnectorModel virtual functions //
///////////////////////////////////////////////////////
template< typename ConnectionT, typename CommonPropertiesT, typename ConnectorT >
void GenericConnectorModelBase< ConnectionT, CommonPropertiesT, ConnectorT >::reset()
{
min_delay_ = Time::pos_inf();
max_delay_ = Time::neg_inf();
// create a new default Connection with default parameters
defaults_ = ConnectionT();
// create new commom properties with default values
common_props_ = CommonPropertiesT();
}
template< typename ConnectionT, typename CommonPropertiesT, typename ConnectorT >
void GenericConnectorModelBase< ConnectionT, CommonPropertiesT, ConnectorT >::get_status(DictionaryDatum& d) const
{
// first get properties common to all synapses
// these are stored only once (not within each Connection)
common_props_.get_status(d);
(*d)["property_object"]= (size_t) &common_props_;
// then get default properties for individual synapses
defaults_.get_status(d);
(*d)["min_delay"] = get_min_delay().get_ms();
(*d)["max_delay"] = get_max_delay().get_ms();
(*d)[names::receptor_type] = receptor_type_;
(*d)["num_connections"] = get_num_connections();
(*d)["num_connectors"] = get_num_connectors();
(*d)["synapsemodel"] = LiteralDatum(get_name());
}
template< typename ConnectionT, typename CommonPropertiesT, typename ConnectorT >
void GenericConnectorModelBase< ConnectionT, CommonPropertiesT, ConnectorT >::set_status(const DictionaryDatum& d)
{
double_t min_delay, max_delay, new_delay;
bool min_delay_updated = updateValue<double_t>(d, "min_delay", min_delay);
bool max_delay_updated = updateValue<double_t>(d, "max_delay", max_delay);
// the delay might also be updated, so check new_min_delay and new_max_delay against new_delay, if given
if ( ! updateValue<double_t>(d, "delay", new_delay) )
new_delay = get_default_delay_(); // call overridden virtual function
// depending on its implementation, it returns the default delay from
// the default connection or from common properties object
if (min_delay_updated xor max_delay_updated)
net_.message(SLIInterpreter::M_ERROR,
"SetDefaults", "Both min_delay and max_delay have to be specified");
if (min_delay_updated && max_delay_updated)
{
if (num_connections_ > 0)
net_.message(SLIInterpreter::M_ERROR,
"SetDefaults",
"Connections already exist. Please call ResetKernel first");
else if ( min_delay > new_delay )
net_.message(SLIInterpreter::M_ERROR,
"SetDefaults",
"min_delay is not compatible with default delay");
else if ( max_delay < new_delay )
net_.message(SLIInterpreter::M_ERROR,
"SetDefaults",
"max_delay is not compatible with default delay");
else if ( min_delay < Time::get_resolution().get_ms() )
net_.message(SLIInterpreter::M_ERROR,
"SetDefaults",
"min_delay must be greater than or equal to resolution");
else if ( max_delay < Time::get_resolution().get_ms() )
net_.message(SLIInterpreter::M_ERROR,
"SetDefaults",
"max_delay must be greater than or equal to resolution");
else
{
min_delay_ = Time(Time::ms(min_delay));
max_delay_ = Time(Time::ms(max_delay));
user_set_delay_extrema_ = true;
}
}
// common_props_.set_status(d, *this) AND defaults_.set_status(d, *this);
// has to be done after adapting min_delay / max_delay, since Connection::set_status
// and CommonProperties::set_status might want to check the delay
// store min_delay_, max_delay_
// calling set_status will check the delay.
// and so may modify min_delay, max_delay, if the specified delay exceeds one of these bounds
// we have to save min/max_delay because we dont know, if the default will ever be used
Time min_delay_tmp = min_delay_;
Time max_delay_tmp = max_delay_;
common_props_.set_status(d, *this);
defaults_.set_status(d, *this);
// restore min_delay_, max_delay_
min_delay_ = min_delay_tmp;
max_delay_ = max_delay_tmp;
// we've possibly just got a new default delay. So enforce checking netxt time it is used
default_delay_needs_check_ = true;
#ifdef HAVE_MUSIC
// We allow music_channel as alias for receptor_type during connection setup
updateValue<long_t>(d, names::music_channel, receptor_type_);
#endif
updateValue<long_t>(d, names::receptor_type, receptor_type_);
}
template< typename ConnectionT, typename CommonPropertiesT, typename ConnectorT >
ConnectorT * GenericConnectorModelBase< ConnectionT, CommonPropertiesT, ConnectorT >::get_connector()
{
num_connectors_++;
return new ConnectorT(*this);
}
template< typename ConnectionT, typename CommonPropertiesT, typename ConnectorT >
void GenericConnectorModelBase< ConnectionT, CommonPropertiesT, ConnectorT >::calibrate(const TimeConverter &tc)
{
// calibrate the dalay of the default properties here
defaults_.calibrate(tc);
// Calibrate will be called after a change in resolution, when there are no network elements present.
// calibrate any time objects that might reside in CommonProperties
common_props_.calibrate(tc);
min_delay_ = tc.from_old_steps(min_delay_.get_steps());
max_delay_ = tc.from_old_steps(max_delay_.get_steps());
}
template< typename ConnectionT, typename CommonPropertiesT, typename ConnectorT >
Node* GenericConnectorModelBase< ConnectionT, CommonPropertiesT, ConnectorT >::get_registering_node()
{
return common_props_.get_node(); //should't work w/o return should it?
}
template< typename ConnectionT, typename CommonPropertiesT, typename ConnectorT >
inline
const ConnectionT & GenericConnectorModelBase< ConnectionT, CommonPropertiesT, ConnectorT >::get_default_connection() const
{
return defaults_;
}
template< typename ConnectionT, typename CommonPropertiesT, typename ConnectorT >
inline
CommonPropertiesT & GenericConnectorModelBase< ConnectionT, CommonPropertiesT, ConnectorT >::get_common_properties()
{
return common_props_;
}
template< typename ConnectionT, typename CommonPropertiesT, typename ConnectorT >
inline
port GenericConnectorModelBase< ConnectionT, CommonPropertiesT, ConnectorT >::get_receptor_type() const
{
return receptor_type_;
}
template< typename ConnectionT, typename CommonPropertiesT, typename ConnectorT >
inline
void GenericConnectorModelBase< ConnectionT, CommonPropertiesT, ConnectorT >::used_default_delay()
{
// if not used before, check now. Solves bug #138, MH 08-01-08
// replaces whole delay checking for the default delay, see bug #217, MH 08-04-24
// get_default_delay_ must be overridded by derived class to return the correct default delay
// (either from commonprops or default connection)
if (default_delay_needs_check_)
{
if ( !check_delay( get_default_delay_() ) )
throw BadDelay(get_default_delay_());
default_delay_needs_check_ = false;
}
}
/**
* Template class for ConnectorModels with heterogeneous delays.
* An actual ConnectorModel for a specific connector of type ConnectorT is obtained by
* specialization to ConnectionT, CommonPropertiesT and ConnectorT.
* ConnectionT is the class representing a single sonnection (=synapse).
* CommonProperties conntains properties that are shared among all Connections of type ConnectionT.
* ConnectorT is the connector class that contains the connections.
*/
template< typename ConnectionT, typename CommonPropertiesT, typename ConnectorT >
class GenericConnectorModel
: public GenericConnectorModelBase< ConnectionT, CommonPropertiesT, ConnectorT >
{
public:
/** Standard constructor. */
GenericConnectorModel(Network& net, std::string name)
: GenericConnectorModelBase< ConnectionT,
CommonPropertiesT,
ConnectorT
> (net, name)
{ }
/** Copy constructor. */
GenericConnectorModel(const GenericConnectorModel& f, std::string name)
: GenericConnectorModelBase< ConnectionT,
CommonPropertiesT,
ConnectorT
> (f, name)
{ }
ConnectorModel* clone(std::string) const;
private:
/**
* Returns the default delay from the prototype connection.
*/
double_t get_default_delay_();
};
template< typename ConnectionT, typename CommonPropertiesT, typename ConnectorT >
ConnectorModel* GenericConnectorModel< ConnectionT, CommonPropertiesT, ConnectorT >::clone(std::string name) const
{
return new GenericConnectorModel(*this, name); // calls copy construtor
}
template< typename ConnectionT, typename CommonPropertiesT, typename ConnectorT >
double_t GenericConnectorModel< ConnectionT, CommonPropertiesT, ConnectorT >::get_default_delay_()
{
return GenericConnectorModelBase< ConnectionT, CommonPropertiesT, ConnectorT >::defaults_.get_delay();
}
/**
* Template class for ConnectorModels with homogeneous delays.
* An actual ConnectorModel for a specific connector of type ConnectorT is obtained by
* specialization to ConnectionT, CommonPropertiesT and ConnectorT.
* ConnectionT is the class representing a single sonnection (=synapse).
* CommonProperties conntains properties that are shared among all Connections of type ConnectionT.
* ConnectorT is the connector class that contains the connections.
*/
template< typename ConnectionT, typename CommonPropertiesT, typename ConnectorT >
class GenericConnectorModelHomD
: public GenericConnectorModelBase< ConnectionT, CommonPropertiesT, ConnectorT >
{
public:
/** Standard constructor. */
GenericConnectorModelHomD(Network& net, std::string name)
: GenericConnectorModelBase< ConnectionT,
CommonPropertiesT,
ConnectorT
> (net, name)
{ }
/** Copy constructor. */
GenericConnectorModelHomD(const GenericConnectorModelHomD& f, std::string name)
: GenericConnectorModelBase< ConnectionT,
CommonPropertiesT,
ConnectorT
> (f, name)
{ }
ConnectorModel* clone(std::string) const;
private:
/**
* Return the default delay from the common property object.
*/
double_t get_default_delay_();
};
template< typename ConnectionT, typename CommonPropertiesT, typename ConnectorT >
ConnectorModel* GenericConnectorModelHomD< ConnectionT, CommonPropertiesT, ConnectorT >::clone(std::string name) const
{
return new GenericConnectorModelHomD(*this, name); // calls copy construtor
}
template< typename ConnectionT, typename CommonPropertiesT, typename ConnectorT >
double_t GenericConnectorModelHomD< ConnectionT, CommonPropertiesT, ConnectorT >::get_default_delay_()
{
return GenericConnectorModelBase< ConnectionT, CommonPropertiesT, ConnectorT >::common_props_.get_delay();
}
/////////////////////////////////////////////////////////////////////////////////
// Convenient versions of template functions for registering new synapse types //
// by modules //
/////////////////////////////////////////////////////////////////////////////////
// synapses wit heterogeneous delays
/**
* registering new synapse with heterogeneous delay
*/
template <class ConnectionT, class ConnectorT >
index register_prototype_connection_connector(Network& net, const std::string &name)
{
ConnectorModel* prototype = new GenericConnectorModel < ConnectionT,
CommonSynapseProperties,
ConnectorT
> (net, name);
return net.register_synapse_prototype(prototype);
}
template <class ConnectionT, class ConnectorT, class CommonPropertiesT>
index register_prototype_connection_connector_commonproperties(Network& net, const std::string &name)
{
ConnectorModel* prototype = new GenericConnectorModel < ConnectionT,
CommonPropertiesT,
ConnectorT
> (net, name);
return net.register_synapse_prototype(prototype);
}
// synapses with homogeneous delays
/**
* registering new synapse with homogeneous delay
*/
template< typename ConnectionT, typename ConnectorT, typename CommonPropertiesT >
index register_prototype_connection_connector_commonproperties_hom_d(Network& net, const std::string &name)
{
ConnectorModel* prototype = new GenericConnectorModelHomD < ConnectionT,
CommonPropertiesT,
ConnectorT
> (net, name);
return net.register_synapse_prototype(prototype);
}
} // namespace nest
#endif /* #ifndef GENERICCONNECTORMODEL_H */