diff options
Diffstat (limited to 'core/sim_causality.hpp')
-rw-r--r-- | core/sim_causality.hpp | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/core/sim_causality.hpp b/core/sim_causality.hpp new file mode 100644 index 0000000..239a070 --- /dev/null +++ b/core/sim_causality.hpp @@ -0,0 +1,177 @@ +#ifndef GyWue2EL4TyiAsNv0XegfFL4jk +#define GyWue2EL4TyiAsNv0XegfFL4jk + +#include <map> + +#include "sim_replay.hpp" + +// discrete property Egal +struct Egal { + typedef uint8_t type; + typedef SpikeArrival quant; + typedef SpikeArrival::instance_ptr_t instance_ptr_t; + static const uint32_t size = 2; + static const char* const name; +}; +const char* const Egal::name = "Egal"; + +namespace SimCausalityImpl { + +using namespace boost::mpl; +using namespace boost; +namespace MC = ModelConsts; + +template<typename PropList> struct SimCausality; + +template<typename ReplayQuant, typename Quant> +struct MaybeTrackEvent { + template<typename Sim> + void operator() (Sim &sim) { + // we handle every event but only track those affecting neurons + auto &sg = static_cast<SimCausality<typename Sim::PropComp::properties_t>&>(sim); + if (is_same<Quant, SpikeArrival>::value) { + sg.handleSA(); + }else if (is_same<Quant, RandomSpike>::value) { + sg.handleRand(); + }else{ + sim.template handleEvent<Quant>(); + } + } + + typedef MaybeTrackEvent<ReplayQuant, Quant> impl; +}; + +template<typename PropList> +struct SimCausality : public SimReplay<PropList, Neuron, MaybeTrackEvent> { + typedef SimReplay<PropList, Neuron, MaybeTrackEvent> Super; + using Super::queues; + using Super::pc; + using Super::ct; + using Super::handleEvent; + + SimCausality(Time start) + : Super(IdList<uint16_t>((char*) "0-999"), start), + totalMarks{}, + trueMarks{}, + inactiveNeurons(1000), + hasFired{} + { + if (start == Time(0)) { + // special case: at t=0 all neurons are have zero membrane + // voltage and can be used for analysis before firing the first + // time + inactiveNeurons = 0; + for (int i=0; i<1000; i++) + hasFired[i] = true; + } + } + + bool run(const Time until, uint64_t maxEvents) __attribute__((noinline)) { + return Super::run(until, maxEvents); + } + + void handleRand() { + Ptr<Neuron> neuron(queues.get<RandomSpike>().minPayload().dst); + Ptr<SpikeArrival> fakeSA(Index<SpikeArrival>::nil()); + handleDiff(neuron, fakeSA, MC::RandomSpikeWeight, + &SimCausality<PropList>::template handleEvent<RandomSpike>); + } + + void handleSA() { + auto &event(queues.get<SpikeArrival>().minPayload()); + Ptr<SpikeArrival> sa (event.src.get<0>()); + Ptr<Synapse> syn (event.src.get<1>()); + Ptr<Neuron> neuron(event.dst); + PLA_Get<Weight> getWeight (ct, syn); + Weight::type weight(pc.call(getWeight)); + handleDiff(neuron, sa, weight, + &SimCausality<PropList>::template handleEvent<SpikeArrival>); + } + + void handleDiff(Ptr<Neuron> neuron, Ptr<SpikeArrival> sa, Voltage::type diff, + bool (SimCausality<PropList>::*handleEvent)()) { + PLA_Get<Voltage> getVoltage (ct, neuron); + PLA_Get<IPCoeff1> getIPCoeff1(ct, neuron); + Voltage::type preEventVoltage(pc.call(getVoltage)); + IPCoeff1::type ipCoeff1 (pc.call(getIPCoeff1)); + bool evokedSpike = (this->*handleEvent)(); + auto &openExc(this->openExc[neuron()]); + auto &openInh(this->openInh[neuron()]); + + if (!hasFired[neuron()]) { + if (evokedSpike) { + hasFired[neuron()] = true; + inactiveNeurons--; + if (!inactiveNeurons) + lastNeuronActivation = ct; + } + return; + } + + if (evokedSpike) { + // check exc. list against voltage diff + Time wntGap = ct + wntNorm(diff + preEventVoltage + - MC::FireThreshold - ipCoeff1); + for (auto i = openExc.lower_bound(wntGap); + i != openExc.end();) { + mark(i->second, 0); + openExc.erase(i++); + } + + // mark own spike + mark(sa, 0); + + // mark remainig inh/exc spikes as q>0, clear buffers + for (auto i : openExc) mark(i.second, 1); openExc.clear(); + for (auto i : openInh) mark(i.second, 1); openInh.clear(); + }else{ + if (diff < 0) { + // add to inh. list + Time wnt = ct + wntNorm(- diff); + openInh.insert(std::make_pair(wnt, sa)); + }else{ + // add to exc. list + Time wntSelf = ct + wntNorm(diff); + openExc.insert(std::make_pair(wntSelf, sa)); + + // check inh. list against voltage gap + PLA_Get<Voltage> pla_get(ct, neuron); + Voltage::type voltage = pc.call(pla_get); + Time wntGap = ct + wntNorm(MC::FireThreshold + ipCoeff1 - voltage); + for (auto i = openInh.lower_bound(wntGap); + i != openInh.end();) { + mark(i->second, 0); + openInh.erase(i++); + } + } + } + } + + void mark(Ptr<SpikeArrival> ptr, bool m) { + bool isSA = ptr() != Index<SpikeArrival>::nil(); + totalMarks[isSA]++; + trueMarks[isSA] += !m; + if (isSA) + egalPC.cast(PLA_Set<Egal>(ptr, 1+m)); // unset values are encoded as zero + } + + Time wntNorm(Voltage::type diff) { + return MC::Tau_Voltage * log(diff); + } + + PropertyComposition<boost::mpl::list< + boost::mpl::pair<Egal, boost::mpl::bool_<true>> + >> egalPC; + uint64_t totalMarks[2], + trueMarks[2]; + uint16_t inactiveNeurons; + Time lastNeuronActivation; + bool hasFired[maxNeurons]; + std::multimap<Time, Ptr<SpikeArrival>> openInh[maxNeurons], openExc[maxNeurons]; +}; + +} // NS + +using SimCausalityImpl::SimCausality; + +#endif // GyWue2EL4TyiAsNv0XegfFL4jk |