summaryrefslogtreecommitdiff
path: root/core/sim_causality.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/sim_causality.hpp')
-rw-r--r--core/sim_causality.hpp177
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
contact: Jan Huwald // Impressum