00001
00026 #ifndef __dneuron_h
00027 #define __dneuron_h
00028
00029 #include <vector>
00030 #include <map>
00031 #include <string>
00032 #include <algorithm>
00033 #include <math.h>
00034 #include <queue>
00035 #include <iostream>
00036 #include <iomanip>
00037
00038 #include "dsched.h"
00039 #include "func.h"
00040
00041 namespace punnets_common {
00042
00043 const int debug_precision = 5;
00044
00045 typedef unsigned long long u_int64_t;
00046
00049
00051 extern u_int64_t totalfire;
00052
00054 extern u_int64_t totalpulse;
00055
00057 extern u_int64_t totalpartition;
00058
00061 extern u_int64_t totalpartition_nonewton[4];
00062
00065
00066 extern u_int64_t totalpartition_newton[4];
00067
00071
00072 extern u_int64_t totalpeaksearch[3];
00073
00075 extern u_int64_t totalpeakenclosing;
00076
00078 extern u_int64_t totalrescheduled;
00079
00081 extern u_int64_t totalfiltered_maxgrad;
00082
00084 extern u_int64_t totalfiltered_incontinuity;
00085
00087 extern u_int64_t totalfiltered_nextpulse;
00088
00090
00091
00092
00093
00095 const real epsilon = 1e-10;
00096
00097 class tsynapse_base;
00098
00099
00106
00107 template <bool d>
00108 class debugflag;
00109
00113
00114 template <> class debugflag<false>
00115 {
00116 public:
00118 bool getDeb() const { return false; }
00120 void setDeb(bool) { std::cout << "No Debug" << std::endl; }
00121 };
00122
00124
00125 template <> class debugflag<true>
00126 {
00127 protected:
00129 bool debug;
00130 public:
00132 debugflag() { debug = false; }
00134 bool getDeb() const { return debug; }
00136 void setDeb(bool b) { debug = b; }
00137 };
00138
00141
00146
00147 class tneuron_base
00148 {
00149 protected:
00151 std::string name;
00153 mutable tqueue _queue;
00154
00155 public:
00157 tneuron_base(std::string iname = "")
00158 : name(iname) { }
00159 virtual ~tneuron_base() { }
00161 const std::string &getName() const { return name; }
00162
00166 virtual void pulseArrive(
00167 tscheduler &scheduler,
00168 ntime_t current_time,
00169 real pulse_level) = 0;
00170 virtual void pulseArrive(
00171 tscheduler &,
00172 ntime_t ,
00173 message_base * ) { }
00174 virtual void pulseArrive(
00175 tscheduler &,
00176 ntime_t ,
00177 func_base * ) { }
00178
00180 virtual void addSynapse(tsynapse_base *) { }
00181
00183 virtual real getCurrentSigLevel(ntime_t ) { return 0.0; };
00185 virtual real getCurrentThrLevel(ntime_t ) { return 0.0; };
00187 virtual real getCurrentExtInput(ntime_t ) { return 0.0; }
00188
00190 virtual ntime_t getLastFire() const { return 0; }
00192 virtual ntime_t getLastSimulate() const { return 0; }
00194 virtual int getLastSimulateType() const { return 0; }
00195
00197 virtual tqueue *queue() const { return &_queue; }
00198
00200 virtual const char *getClassName() const { return "tneuron_base"; };
00201 };
00202
00204
00205
00206
00209
00216
00217 class tsynapse_base : public taction
00218 {
00219 protected:
00221 ntime_t ndelay;
00222
00223 public:
00225 tsynapse_base(ntime_t idelay) : taction(), ndelay(idelay) { }
00227 ntime_t getDelay() const { return ndelay; }
00229 virtual real getWeight() const { return 0; }
00230
00232 virtual void setSrc(tneuron_base &) { }
00234 virtual tneuron_base &getSrc() const { throw "ERROR"; }
00236 virtual tneuron_base &getDest() const { throw "ERROR"; }
00237
00242 virtual void activate(tscheduler &scheduler, ntime_t current_time) = 0;
00243
00245 virtual const char *getClassName() const { return "tsynapse_base"; };
00246 };
00248
00250 }
00252
00254
00255
00258
00263
00264 template <bool debug>
00265 class tsynapse : public tsynapse_base, public debugflag<debug>
00266 {
00267 protected:
00268 tneuron_base *src;
00269 tneuron_base *dest;
00270 real weight;
00271
00272 public:
00274 tsynapse(tneuron_base &isrc, tneuron_base &idest, ntime_t idelay, real iweight)
00275 : tsynapse_base(idelay), src(&isrc), dest(&idest), weight(iweight) { }
00278 tsynapse(tneuron_base &idest, ntime_t idelay, real iweight)
00279 : tsynapse_base(idelay), src(NULL), dest(&idest), weight(iweight) { }
00280 virtual ~tsynapse() { }
00281
00283 virtual void setSrc(tneuron_base &isrc) { src = &isrc; }
00284
00286 virtual real getWeight() const { return weight; }
00288 virtual tneuron_base &getSrc() const { if( src == NULL ) throw "ERROR"; return *src; }
00290 virtual tneuron_base &getDest() const { return *dest; }
00291
00293 void addWeight(real delta_w) { weight += delta_w; }
00295 void addDelay(ntime_t delta_d) { ndelay += delta_d; }
00296
00298 virtual void activate(tscheduler &scheduler, ntime_t current_time)
00299 {
00300 if( getDeb() )
00301 std::cout << std::setw(9) << std::setiosflags(std::ios::fixed) << std::setprecision(debug_precision) << current_time << " " << dest->getName() <<
00302 " Pulse Arrived from " << src->getName() << " (delay=" << ndelay << ", w=" << weight << ")" << std::endl;
00303 dest->pulseArrive( scheduler, current_time, weight );
00304 }
00305
00307 virtual tqueue *queue() const { return dest->queue(); }
00308 };
00309
00310
00315
00316 template <bool debug>
00317 class tsynapse_message : public tsynapse_base, public debugflag<debug>
00318 {
00319 protected:
00320 tneuron_base *src;
00321 tneuron_base *dest;
00322 message_base *mess;
00323
00324 public:
00327 tsynapse_message(tneuron_base &isrc, tneuron_base &idest, real idelay, message_base *imess)
00328 : tsynapse_base(idelay), src(&isrc), dest(&idest), mess(imess) { }
00332 tsynapse_message(tneuron_base &idest, real idelay, message_base *imess)
00333 : tsynapse_base(idelay), src(NULL), dest(&idest), mess(imess) { }
00335 virtual ~tsynapse_message() { delete mess; }
00336
00338 virtual void setSrc(tneuron_base &isrc) { src = &isrc; }
00339
00341 virtual tneuron_base &getSrc() const { if( src == NULL ) throw "ERROR"; return *src; }
00343 virtual tneuron_base &getDest() const { return *dest; }
00344
00346 virtual void activate(tscheduler &scheduler, ntime_t current_time)
00347 {
00348 if( getDeb() )
00349 std::cout << std::setw(9) << std::setiosflags(std::ios::fixed) << std::setprecision(debug_precision) << current_time << " " << dest->getName() <<
00350 " Pulse Arrived from " << src->getName() << std::endl;
00351 dest->pulseArrive( scheduler, current_time, mess );
00352 }
00353 };
00354
00355
00361
00362 template <bool debug>
00363 class tsynapse_fatigue : public tsynapse_base, public debugflag<debug>
00364 {
00365 protected:
00366 tneuron_base *src;
00367 tneuron_base *dest;
00368 real weight;
00369 ntime_t last_fire;
00370 real last_weight;
00371
00373 static const ntime_t recover_hv_period = 2000;
00375 static const real fire_ratio = 0.002;
00376
00377 public:
00379 tsynapse_fatigue(tneuron_base &isrc, tneuron_base &idest, real idelay, real iweight)
00380 : tsynapse_base(idelay), src(&isrc), dest(&idest), weight(iweight / fire_ratio), last_fire( -Infinity ), last_weight(weight) { }
00383 tsynapse_fatigue(tneuron_base &idest, real idelay, real iweight)
00384 : tsynapse_base(idelay), src(NULL), dest(&idest), weight(iweight / fire_ratio), last_fire( -Infinity ), last_weight(weight) { }
00385 virtual ~tsynapse_fatigue() { }
00386
00388 virtual real getWeight() const { return weight; }
00390 virtual tneuron_base &getSrc() const { if( src == NULL ) throw "ERROR"; return *src; }
00392 virtual tneuron_base &getDest() const { return *dest; }
00393
00395 void addWeight(real delta_w) { weight += delta_w; }
00397 void addDelay(ntime_t delta_d) { ndelay += delta_d; }
00398
00401 virtual void activate(tscheduler &scheduler, ntime_t current_time)
00402 {
00403 real this_weight = weight + (last_weight - weight) * exp( (current_time - last_fire) * (-M_LN2 / recover_hv_period) );
00404 if( getDeb() )
00405 std::cout << std::setw(9) << std::setiosflags(std::ios::fixed) << std::setprecision(debug_precision) << current_time << " " << dest->getName() <<
00406 " Pulse Arrived from " << src->getName() << "(" << this_weight * fire_ratio << "/" << weight << ")" << std::endl;
00407 dest->pulseArrive( scheduler, current_time, this_weight * fire_ratio );
00408 last_fire = current_time;
00409 last_weight = this_weight * (1.0 - fire_ratio);
00410 }
00411
00412 virtual const char *getClassName() const { return "tsynapse_fatigue"; };
00413 };
00414
00416
00417
00418
00421
00429
00430 template <bool debug>
00431 class tneuron : public tneuron_base, public taction, public debugflag<debug>
00432 {
00433 protected:
00434
00435 real sig_level;
00436 ntime_t last_simulate;
00437 ntime_t last_fire;
00438 std::vector<tsynapse_base *> synapses;
00439
00440 void fire(tscheduler &scheduler, ntime_t current_time);
00441
00442 static const ntime_t def_sig_hv_period = 2.0;
00443 static const ntime_t def_thr_hv_period = 0.5;
00444 static const real def_min_threshold = 1.0;
00445 static const real def_max_threshold = 11.0;
00446
00448 ntime_t sig_hv_period;
00450 ntime_t thr_hv_period;
00452 real min_threshold;
00454 real max_threshold;
00456 static const real sig_converge_level = 0.0;
00457
00459 real coeff_sigdecay;
00461 real coeff_thrdecay;
00462
00464 void simulateElapse( ntime_t current_time )
00465 {
00466 sig_level = sig_converge_level +
00467 ( ( sig_level - sig_converge_level )
00468 * exp( (current_time - last_simulate) * coeff_sigdecay ) );
00469 last_simulate = current_time;
00470 }
00472 virtual void scheduleFire( tscheduler &scheduler, ntime_t current_time, bool resched = true );
00473
00474 public:
00477 tneuron(std::string iname = "",
00478 ntime_t isig_hv_period = def_sig_hv_period,
00479 ntime_t ithr_hv_period = def_thr_hv_period,
00480 real imin_threshold = def_min_threshold,
00481 real imax_threshold = def_max_threshold );
00482 virtual ~tneuron();
00483
00485 virtual real getCurrentSigLevel(ntime_t current_time)
00486 { simulateElapse( current_time ); return sig_level; }
00487
00489 virtual real getCurrentThrLevel(ntime_t current_time)
00490 {
00491 return min_threshold +
00492 ( (max_threshold - min_threshold)
00493 * exp( (current_time - last_fire) * coeff_thrdecay ) );
00494 }
00495
00497 virtual void pulseArrive(
00498 tscheduler &scheduler,
00499 ntime_t current_time,
00500 real pulse_level)
00501 { totalpulse++; simulateElapse( current_time ); sig_level += pulse_level; scheduleFire( scheduler, current_time ); }
00502
00504 virtual void addSynapse(tsynapse_base *s)
00505 { synapses.push_back(s); s->setSrc(*this); }
00507 virtual void eraseSynapse(tsynapse_base *s)
00508 { remove( synapses.begin(), synapses.end(), s); }
00509
00511 virtual ntime_t getLastFire() const { return last_fire; }
00513 virtual ntime_t getLastSimulate() const { return last_simulate; }
00514
00516 virtual void activate(tscheduler &scheduler, ntime_t current_time)
00517 {
00518 if( getDeb() )
00519 std::cout << std::setw(9) << std::setiosflags(std::ios::fixed) << std::setprecision(debug_precision) << current_time << " " << getName() <<
00520 " Pulse arrived (loopback)" << std::endl;
00521 simulateElapse(current_time); scheduleFire(scheduler, current_time, false); };
00522
00524 virtual const char *getClassName() const { return "tneuron"; };
00525
00527 virtual tqueue *queue() const { return &_queue; }
00528
00530 const std::vector<tsynapse_base *> &getSynapses() { return synapses; }
00531 };
00532
00533
00534
00537
00538 template <bool debug>
00539 class tneuron_ext_const : public tneuron<debug>
00540 {
00541 protected:
00542 static const real def_ext_input = 0.0;
00543 real ext_input;
00544 real sig_converge_level;
00545
00548 void simulateElapse( ntime_t current_time )
00549 {
00550 sig_level = sig_converge_level +
00551 ( ( sig_level - sig_converge_level )
00552 * exp( (current_time - last_simulate) * coeff_sigdecay ) );
00553 last_simulate = current_time;
00554 }
00556 virtual void scheduleFire( tscheduler &scheduler, ntime_t current_time, bool resched = true );
00557
00558 public:
00562 tneuron_ext_const(std::string iname = "",
00563 ntime_t isig_hv_period = def_sig_hv_period,
00564 ntime_t ithr_hv_period = def_thr_hv_period,
00565 real imin_threshold = def_min_threshold,
00566 real imax_threshold = def_max_threshold,
00567 real iext_input = def_ext_input )
00568 : tneuron<debug>( iname, isig_hv_period, ithr_hv_period, imin_threshold, imax_threshold ),
00569 ext_input(iext_input), sig_converge_level(iext_input / coeff_sigdecay) { }
00570 virtual ~tneuron_ext_const() { }
00571
00573 virtual real getCurrentSigLevel(ntime_t current_time)
00574 { simulateElapse( current_time ); return sig_level; }
00575
00577 real getExtInput() { return ext_input; }
00579 virtual real getCurrentExtInput(ntime_t ) { return ext_input; }
00581 void setExtInput(tscheduler &scheduler, ntime_t current_time, real val)
00582 { simulateElapse( current_time ); ext_input = val; sig_converge_level = ext_input / coeff_sigdecay; scheduleFire( scheduler, current_time ); }
00584 real getConvergeLevel() { return sig_converge_level; }
00587 void setConvergeLevel(tscheduler &scheduler, ntime_t current_time, real val)
00588 { simulateElapse( current_time ); sig_converge_level = val; ext_input = sig_converge_level * coeff_sigdecay; scheduleFire( scheduler, current_time ); }
00589
00591 virtual const char *getClassName() const { return "tneuron_ext_const"; };
00592 };
00593
00594
00595
00596
00602
00603 template <bool debug>
00604 class tneuron_ext : public tneuron_base, public taction, public debugflag<debug>
00605 {
00606 protected:
00608 std::vector<tsynapse_base *> synapses;
00610 std::vector<func_base *> exts;
00612 func_delta_int *pulses;
00614 ntime_t last_simulate;
00616 ntime_t last_fire;
00618 ntime_t loopback;
00619
00621 real lambda;
00622
00624 int last_simulate_type;
00625
00626
00628 void fire(tscheduler &scheduler, ntime_t current_time);
00629
00631 real calcSignal( ntime_t current_time );
00632
00634 virtual void scheduleFire( tscheduler &scheduler, ntime_t current_time, bool resched = true );
00635
00637 bool sendMessage(ntime_t t, message_base *mess);
00639 bool broadcastMessage(ntime_t t, message_base *mess);
00640
00641 public:
00643 tneuron_ext(std::string iname = "", real sig_hv_period = 1.0);
00644 virtual ~tneuron_ext();
00645
00647 virtual real getCurrentSigLevel(ntime_t current_time)
00648 { return calcSignal(current_time); }
00649
00651 virtual real getCurrentThrLevel(ntime_t )
00652 { return 0.0; }
00653
00655 virtual void pulseArrive(
00656 tscheduler &scheduler,
00657 ntime_t current_time,
00658 real pulse_level);
00659
00661 virtual void pulseArrive(
00662 tscheduler &scheduler,
00663 ntime_t current_time,
00664 message_base *mess);
00665
00667 virtual void pulseArrive(
00668 tscheduler &scheduler,
00669 ntime_t current_time,
00670 func_base *func);
00671
00673 virtual void addSynapse(tsynapse_base *s)
00674 { synapses.push_back(s); s->setSrc(*this); }
00676 virtual void eraseSynapse(tsynapse_base *s)
00677 { remove( synapses.begin(), synapses.end(), s); }
00679 virtual void addExt(func_base *s)
00680 { s->setLambda(lambda);
00681 s->setZeroPoint(last_fire);
00682 exts.push_back(s); }
00683
00685 virtual ntime_t getLastFire() const { return last_fire; }
00687 virtual ntime_t getLastSimulate() const { return last_simulate; }
00689 virtual int getLastSimulateType() const { return last_simulate_type; }
00690
00692 virtual void activate(tscheduler &scheduler, ntime_t current_time)
00693 {
00694 if( getDeb() )
00695 std::cout << std::setw(9) << std::setiosflags(std::ios::fixed) << std::setprecision(debug_precision) << current_time << " " << getName() <<
00696 " Pulse arrived (loopback)" << std::endl;
00697 if( current_time == loopback )
00698 scheduleFire(scheduler, current_time, false);
00699 else
00700 {
00701 if( getDeb() )
00702 std::cout << std::setw(9) << std::setiosflags(std::ios::fixed) << std::setprecision(debug_precision) << current_time << " " << getName() <<
00703 " Pulse loopback ignored loopback=" << loopback << ", diff=" << std::setprecision(10) << loopback - current_time << std::endl;
00704 }
00705 };
00706
00708 virtual const char *getClassName() const { return "tneuron_ext"; };
00709
00711 const std::vector<tsynapse_base *> &getSynapses() { return synapses; }
00712
00714 virtual tqueue *queue() const { return tneuron_base::queue(); }
00715
00718 void setLoopBack(tscheduler &scheduler, ntime_t schedule_time)
00719 {
00720 loopback = schedule_time;
00721 if( schedule_time < mak::Infinity )
00722 scheduler.scheduleEvent( schedule_time, *this );
00723 }
00724
00725 };
00726
00728
00731
00733 template <bool debug>
00734 class tsynapse_addfunc : public tsynapse_base, public debugflag<debug>
00735 {
00736 protected:
00737 tneuron_base *src;
00738 tneuron_ext<debug> *dest;
00739 func_base *func;
00740 message_base *mess;
00741 real lev;
00742
00743 public:
00746 tsynapse_addfunc(tneuron_base &isrc, tneuron_ext<debug> &idest, real idelay, func_base *ifunc, message_base *imess = NULL, real ilev = 0.0)
00747 : tsynapse_base(idelay), src(&isrc), dest(&idest), func(ifunc), mess(imess), lev(ilev) { }
00750 tsynapse_addfunc(tneuron_ext<debug> &idest, real idelay, func_base *ifunc, message_base *imess = NULL, real ilev = 0.0)
00751 : tsynapse_base(idelay), src(NULL), dest(&idest), func(ifunc), mess(imess), lev(ilev) { }
00752 virtual ~tsynapse_addfunc() { }
00753
00754 virtual void setSrc(tneuron_base &isrc) { src = &isrc; }
00755
00756
00757 virtual tneuron_base &getSrc() const { if( src == NULL ) throw "ERROR"; return *src; }
00758 virtual tneuron_ext<debug> &getDest() const { return *dest; }
00759
00761 virtual void activate(tscheduler &scheduler, ntime_t current_time)
00762 {
00763 if( getDeb() )
00764 std::cout << std::setw(9) << std::setiosflags(std::ios::fixed) << std::setprecision(debug_precision) << current_time << " " << dest->getName() << " Pulse Arrived (func) from " << src->getName() << std::endl;
00765 func_base *f = func->clone();
00766 if( mess )
00767 f->processMessage( current_time, *mess );
00768 dest->addExt(f);
00769 dest->pulseArrive( scheduler, current_time, lev );
00770 }
00771
00772 virtual tqueue *queue() const { return dest->queue(); }
00773 };
00774
00778 template <bool debug>
00779 class tsynapse_messfunc : public tsynapse_base, public debugflag<debug>
00780 {
00781 protected:
00782 tneuron_base *src;
00783 tneuron_ext<debug> *dest;
00784 func_base *func;
00785 message_base *mess;
00786 real lev;
00787
00788 public:
00792 tsynapse_messfunc(tneuron_base &isrc, tneuron_ext<debug> &idest, real idelay, func_base *ifunc, message_base *imess, real ilev=0.0)
00793 : tsynapse_base(idelay), src(&isrc), dest(&idest), func(ifunc), mess(imess), lev(ilev) { dest->addExt(func); }
00797 tsynapse_messfunc(tneuron_ext<debug> &idest, real idelay, func_base *ifunc, message_base *imess, real ilev=0.0)
00798 : tsynapse_base(idelay), src(NULL), dest(&idest), func(ifunc), mess(imess), lev(ilev) { dest->addExt(func); }
00799 virtual ~tsynapse_messfunc() { }
00800
00801 virtual void setSrc(tneuron_base &isrc) { src = &isrc; }
00802
00803
00804 virtual tneuron_base &getSrc() const { if( src == NULL ) throw "ERROR"; return *src; }
00805 virtual tneuron_ext<debug> &getDest() const { return *dest; }
00806
00809 virtual void activate(tscheduler &scheduler, ntime_t current_time)
00810 {
00811 if( getDeb() )
00812 std::cout << std::setw(9) << std::setiosflags(std::ios::fixed) << std::setprecision(debug_precision) << current_time << " " << dest->getName() << " Pulse Arrived (func) from " << src->getName() << std::endl;
00813 func->processMessage( current_time, *mess );
00814
00815 dest->pulseArrive( scheduler, current_time, lev );
00816 }
00817 virtual tqueue *queue() const { return dest->queue(); }
00818 };
00819
00821
00822 }
00823
00824 namespace punnets_common {
00826 taction &makePulse( tneuron_base &idest, real ilevel );
00828 taction &makePulse( tneuron_base &idest, message_base *message );
00830 template <bool b>
00831 taction &setExtInput( punnets_private::tneuron_ext_const<b> &idest, real ilevel );
00832 }
00833
00834
00835 namespace punnets {
00837 typedef class punnets_private::tsynapse<true> tsynapse;
00839 typedef class punnets_private::tsynapse_message<true> tsynapse_message;
00841 typedef class punnets_private::tsynapse_fatigue<true> tsynapse_fatigue;
00843 typedef class punnets_private::tsynapse_addfunc<true> tsynapse_addfunc;
00845 typedef class punnets_private::tsynapse_messfunc<true> tsynapse_messfunc;
00846
00848 typedef class punnets_private::tneuron<true> tneuron;
00850 typedef class punnets_private::tneuron_ext_const<true> tneuron_ext_const;
00852 typedef class punnets_private::tneuron_ext<true> tneuron_ext;
00853
00854 }
00855
00856
00857 namespace punnets_nodebug {
00859 typedef class punnets_private::tsynapse<false> tsynapse;
00861 typedef class punnets_private::tsynapse_message<false> tsynapse_message;
00863 typedef class punnets_private::tsynapse_fatigue<false> tsynapse_fatigue;
00865 typedef class punnets_private::tsynapse_addfunc<false> tsynapse_addfunc;
00867 typedef class punnets_private::tsynapse_messfunc<false> tsynapse_messfunc;
00868
00870 typedef class punnets_private::tneuron<false> tneuron;
00872 typedef class punnets_private::tneuron_ext_const<false> tneuron_ext_const;
00874 typedef class punnets_private::tneuron_ext<false> tneuron_ext;
00875
00876 }
00877
00878 #endif