00001 #ifndef GENERICPOISSONNEURON_H_
00002 #define GENERICPOISSONNEURON_H_
00003
00004 #include "EvSimObject.h"
00005 #include "ProjectedEventSender.h"
00006 #include "DirectEventSender.h"
00007 #include "SpikeResponse.h"
00008 #include "Synapse.h"
00009 #include "EvSimObjectTypeUtils.h"
00010 #include "RandomDistribution.h"
00011 #include "Neuron.h"
00012
00013 #include <string>
00014 using std::string;
00015
00016
00017 class PoissonNeuronBase : public Neuron, public SingleOutputProjectedEventSender {
00018 public:
00019 PoissonNeuronBase();
00020 virtual ~PoissonNeuronBase();
00021
00022 virtual void updateState(SimContext &sim_context, Time time, update_id_t upd_id) {};
00023
00024 virtual unsigned numProjOutputPorts() const
00025 {
00026 return 1;
00027 };
00028
00029 virtual unsigned numOutputPorts() const
00030 {
00031 return 1;
00032 };
00033
00034
00035 virtual PortType getOutputPortType(port_id_t) const
00036 {
00037 return eventPortProjected;
00038 };
00039
00040
00041 virtual unsigned registerInputSynapse(EvSimObject *input_synapse) { return 0; };
00042
00043 virtual void announceEvEmitted(SimContext &sim_ctxt, Time time, global_out_port_id_t port_id);
00044
00045 protected:
00046 double Vm;
00047 Time lastSpike;
00048 bool in_refractory;
00049 };
00050
00051
00052 template <class Base >
00053 class GenericPoissNeuronRecalcVm : public Base {
00054 public:
00055
00056 virtual ~GenericPoissNeuronRecalcVm() {};
00057
00058 virtual unsigned registerInputSynapse(EvSimObject *input_synapse)
00059 {
00060 post_syn_potentials.push_back(static_cast<float *>(dynamic_cast<EvSimObject *>(input_synapse)->getVariablePtr("psr")));
00061 return post_syn_potentials.size() - 1;
00062 }
00063
00064 protected:
00065 struct Accum {
00066 Accum() : s(0) {}
00067
00068 inline void operator()(float *p) {s+=*p;}
00069
00070 double s;
00071 };
00072
00073 inline void updateVm(Time time)
00074 {
00075 Accum accumulate;
00076 std::for_each(post_syn_potentials.begin(), post_syn_potentials.end(), accumulate);
00077 Base::Vm = accumulate.s;
00078 }
00079
00080 vector<float *> post_syn_potentials;
00081 };
00082
00083
00084 template <class Base >
00085 class GenericPoissNeuronFast : public Base {
00086 public:
00087 virtual ~GenericPoissNeuronFast() {};
00088
00089 virtual void updatePSR(double psr, double psr_diff, Time time)
00090 {
00091 Base::Vm += psr_diff;
00092 }
00093
00094 virtual bool requiresActiveSynapse() {
00095 return true;
00096 }
00097
00098 inline void updateVm(Time time) {};
00099 };
00100
00101
00102 template <class Base >
00103 class GenericExpPoissonNeuron : public Base {
00104 public:
00105
00106 virtual ~GenericExpPoissonNeuron() {};
00107
00108 float C;
00109
00110 float A;
00111
00112 float bias;
00113
00114 virtual void reset(SimContext &sim_ctxt)
00115 {
00116 Base::reset(sim_ctxt);
00117 Base::Vm = 0;
00118 };
00119
00120 protected:
00121
00122 inline double firingRate()
00123 {
00124 return A*exp(C*(Base::Vm+bias));
00125 }
00126
00127 void recalcNextSpikeTime(SimContext &sim_info, Time time)
00128 {
00129 Time next_spike_time;
00130 double rate = firingRate();
00131 if (rate == 0) {
00132 next_spike_time = MAX_TIME;
00133 }
00134 else {
00135 ExponentialDistribution exp_dist(rate);
00136 next_spike_time = exp_dist( *global_sim_random_eng );
00137 }
00138 Base::changeProjectedEventTime(sim_info, (port_id_t)0, time + next_spike_time);
00139 };
00140 };
00141
00142
00143 template <class Base>
00144 class GenericGenPoissonNeuron : public Base {
00145 public:
00146
00147 virtual ~GenericGenPoissonNeuron();
00148
00149 float C;
00150
00151 virtual void reset(SimContext &sim_ctxt)
00152 {
00153 Base::Vm = 0;
00154 };
00155
00156 protected:
00157
00158 inline double firingRate()
00159 {
00160 return log(C*Base::Vm);
00161 };
00162
00163 void recalcNextSpikeTime(SimContext &sim_info, Time time)
00164 {
00165 Time next_spike_time;
00166 double rate = firingRate();
00167 if (rate == 0) {
00168 next_spike_time = MAX_TIME;
00169 }
00170 else {
00171 ExponentialDistribution exp_dist(rate);
00172 next_spike_time = exp_dist( *global_sim_random_eng );
00173 }
00174 Base::changeProjectedEventTime(sim_info, (port_id_t)0, time + next_spike_time);
00175 };
00176 };
00177
00178
00179 template <class Base>
00180 class GenericPoissonNeuronComplete : public Base
00181 {
00182 public:
00183
00184 virtual ~GenericPoissonNeuronComplete() {};
00185
00186 virtual void reset(SimContext &sim_ctxt)
00187 {
00188 Base::reset(sim_ctxt);
00189 Base::lastSpike = -Trefract-1;
00190 Base::in_refractory = false;
00191 Base::updateVm(0);
00192 Base::recalcNextSpikeTime(sim_ctxt, 0);
00193 };
00194
00195 virtual void updateState(SimContext &sim_ctxt, Time time, update_id_t upd_id)
00196 {
00197 Base::updateVm(time);
00198 if (!Base::in_refractory) {
00199 Base::recalcNextSpikeTime(sim_ctxt, time);
00200 }
00201 }
00202
00203 virtual void postAddedInNetwork(EvSimNetwork &net, EvSimObject::ID self){
00204 net.connect(self, 0, self, 0, Trefract);
00205 }
00206
00207 virtual void eventHit(SimContext & sim_ctxt, Time time, port_id_t port) {
00208 Base::in_refractory = false;
00209 Base::recalcNextSpikeTime(sim_ctxt, time);
00210 }
00211
00212 float Trefract;
00213 };
00214
00215 #endif