Main Page   Modules   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   Related Pages  

dneuron.cpp

Go to the documentation of this file.
00001 
00026 #include "dneuron.h"
00027 #include <math.h>
00028 #include <mak/profile.h>
00029 
00030 using namespace mak;
00031 
00032 //#define DEBUG
00033 
00035 namespace punnets_common {
00037 
00038 u_int64_t totalfire = 0;
00039 u_int64_t totalpulse = 0;
00040 u_int64_t totalpartition = 0;
00041 u_int64_t totalpartition_nonewton[4] = {0,0,0,0};
00042 u_int64_t totalpartition_newton[4] = {0,0,0,0};
00043 u_int64_t totalpeaksearch[3] = {0,0,0};
00044 u_int64_t totalpeakenclosing = 0;
00045 u_int64_t totalrescheduled = {0};
00046 u_int64_t totalfiltered_maxgrad = 0;
00047 u_int64_t totalfiltered_incontinuity = 0;
00048 u_int64_t totalfiltered_nextpulse = 0;
00049 
00050 const int iporder = 2;
00051 const ntime_t ip_delta_t = 1e-5;
00052 
00053 //const bool use_next_known_pulse = false;
00054 const bool use_next_known_pulse = true;
00055 
00056 using namespace std;
00057 
00058 class tpulse : public taction
00059 {
00060     tneuron_base &dest;
00061     real level;
00062 
00063 public:
00064     tpulse(tneuron_base &idest, real ilevel) : taction(), dest(idest), level(ilevel) { }
00065     
00066     virtual void activate(tscheduler &scheduler, ntime_t current_time) 
00067         { 
00068 //      if( getDeb() )
00069 //          cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << dest.getName() << " Pulse Arrived (external input)" << endl;
00070         dest.pulseArrive( scheduler, current_time, level ); delete this; }
00071 
00072     tqueue *queue() const { return dest.queue(); }
00073     virtual const char *getClassName() const { return "tpulse"; };
00074 };
00075 
00076 class tmessage : public taction
00077 {
00078     tneuron_base &dest;
00079     message_base *mess;
00080     real level;
00081 
00082 public:
00083     tmessage(tneuron_base &idest, message_base *imess) : taction(), dest(idest), mess(imess) { }
00084     virtual ~tmessage() { delete mess; }
00085     
00086     virtual void activate(tscheduler &scheduler, ntime_t current_time) 
00087         { 
00088 //      if( getDeb() )
00089 //          cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << dest.getName() << " Pulse Arrived (external message " << mess->getMessageId() << ")" << endl;
00090         dest.pulseArrive( scheduler, current_time, mess ); delete this; }
00091 
00092     tqueue *queue() const { return dest.queue(); }
00093     virtual const char *getClassName() const { return "tmessage"; };
00094 };
00095 
00096 
00097 taction &makePulse( tneuron_base &idest, real ilevel )
00098 {
00099     return *new tpulse( idest, ilevel );
00100 }
00101 
00102 taction &makePulse( tneuron_base &idest, message_base *mess )
00103 {
00104     return *new tmessage( idest, mess );
00105 }
00106 
00107 
00108 }  // namespace punnets
00109 
00110 namespace punnets_private {
00111 
00112 template <bool debug>
00113 tneuron<debug>::~tneuron()
00114 
00115 {
00116     for( vector<tsynapse_base *>::iterator i = synapses.begin(); i != synapses.end(); i++ )
00117         delete *i;
00118 }
00119 
00120 
00121 template <bool debug>
00122 tneuron<debug>::tneuron(string iname /*= ""*/, 
00123                  ntime_t isig_hv_period /*= def_sig_hv_period */,
00124                  ntime_t ithr_hv_period /*= def_thr_hv_period */,
00125                  real imin_threshold    /*= def_min_threshold */,
00126                  real imax_threshold    /*= def_max_threshold */ )
00127         : tneuron_base(iname), 
00128           sig_level(0.0), last_simulate(0.0), last_fire(0.0),
00129           sig_hv_period(isig_hv_period), thr_hv_period(ithr_hv_period),
00130           min_threshold(imin_threshold), max_threshold(imax_threshold),
00131           coeff_sigdecay(- M_LN2 / isig_hv_period), 
00132           coeff_thrdecay( - M_LN2 / ithr_hv_period )
00133 { }
00134 
00135 
00136 template <bool debug>
00137 void tneuron<debug>::fire(tscheduler &scheduler, ntime_t current_time)
00138 {
00139     prof<1> pf("tneuron::Fire");
00140     totalfire++;
00141 
00142     for( vector<tsynapse_base *>::iterator i = synapses.begin(); i != synapses.end(); i++ )
00143     {
00144 //#ifdef DEBUG
00145 //      cout << "schedule pulse at " << current_time + i->getDelay() << " to " << i->getDest().getName() << endl;
00146 //#endif
00147         scheduler.scheduleEvent(current_time + (*i)->getDelay(), **i);
00148     }
00149     sig_level = 0.0;
00150     last_fire = current_time;
00151 }
00152 
00153 template <bool debug>
00154 void tneuron<debug>::scheduleFire(tscheduler &scheduler, ntime_t current_time, bool /*resched*/)
00155 {
00156     prof<1> pf("tneuron::scheduleFire");
00157     real current_threshold = 0.0;
00158     if( sig_level >= min_threshold )
00159     {
00160         // 最大しきい値を超えていたら即座に発火
00161         if( sig_level >= max_threshold || (current_threshold = getCurrentThrLevel( current_time )) - sig_level < epsilon )
00162         {
00163             if( getDeb() )
00164                 cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name << " Fire, level " << sig_level << ", threshold " << current_threshold << endl;
00165             fire(scheduler, current_time);
00166             return;
00167         }
00168         else
00169         {
00170             if( getDeb() )
00171                 cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name << " Candid, level " << sig_level << ", threshold " << current_threshold << endl;
00172         }
00173     }
00174     else
00175         if( getDeb() )
00176             cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name << " Accumulate, " << sig_level << endl;
00177 }
00178 
00179 /************************************************************************/
00180 
00181 template <bool debug>
00182 void tneuron_ext_const<debug>::scheduleFire(tscheduler &scheduler, ntime_t current_time, bool resched)
00183 {
00184     real current_threshold = 0.0;
00185     if( sig_level >= min_threshold || sig_converge_level > min_threshold )
00186     {
00187         // 最大しきい値を超えていたら即座に発火
00188         if( sig_level >= max_threshold || (current_threshold = getCurrentThrLevel( current_time )) - sig_level < epsilon )
00189         {
00190             if( getDeb() )
00191                 cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name << " Fire, level " << sig_level << ", threshold " << current_threshold << endl;
00192             fire(scheduler, current_time);
00193             if( sig_converge_level < min_threshold )
00194                 return;
00195             current_threshold = max_threshold;
00196         }
00197         else
00198         {
00199             if( getDeb() )
00200                 cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name << " Candid, level " << sig_level << ", threshold " << current_threshold << endl;
00201             if( ! resched )
00202                 return;
00203         }
00204 
00205         // 今後、しきい値以下であれば、超える可能性があるか調べる
00206         real sig_decay_level = sig_level - sig_converge_level;
00207         real thr_decay_level = current_threshold - min_threshold;
00208         // 最小しきい値が信号収束値未満なら確実に越えるので、それ以外の場合だけ調べる
00209         if( min_threshold >= sig_converge_level )
00210         {
00211             // 信号の半減期のほうが長い場合以外は可能性がない
00212             if( coeff_sigdecay - coeff_thrdecay <= 0 )
00213             {
00214                 if( getDeb() )
00215                     cout << current_time << " Fail neuron " << name << endl;
00216                 return;
00217             }
00218                 
00219             // (しきい値関数 - 信号関数) が極大になる時刻
00220             ntime_t maximal_time = 
00221                 (coeff_sigdecay - coeff_thrdecay) *
00222                 log( ( coeff_thrdecay * thr_decay_level ) / 
00223                      ( coeff_sigdecay * sig_decay_level )   );
00224             // 極大になったときに越えているか?
00225             real siglvl_at_maximal = sig_decay_level * exp(coeff_sigdecay * maximal_time) + sig_converge_level;
00226             real thrlvl_at_maximal = thr_decay_level * exp(coeff_thrdecay * maximal_time) + min_threshold;
00227             if( siglvl_at_maximal < thrlvl_at_maximal )
00228             {
00229                 if( getDeb() )
00230                     cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name << " Fail, max_lvl " << siglvl_at_maximal << ", threshold " << thrlvl_at_maximal << endl;
00231                 return; // 越えていない、発火の可能性なし
00232             }
00233             if( getDeb() )
00234                 cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name << " Possible, max_lvl " << siglvl_at_maximal << ", threshold " << thrlvl_at_maximal << endl;
00235 //          cout << T << endl;
00236         }
00237         else
00238         {
00239             if( getDeb() )
00240                 cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name << " Possible" << endl;
00241 //          cout << T << endl;
00242         }
00243         // しばらく後で発火するのでその時刻 t を調べる
00244         // ニュートン法 T = exp(t)
00245 
00246         // 初期値は 1.0 だが、1回まわした後の値で計算
00247         real T = 1.0 - (sig_level - current_threshold) / (coeff_sigdecay * sig_decay_level - coeff_thrdecay * thr_decay_level);
00248 
00249         int count = 0;
00250 
00251         ntime_t fire_time = log(T);
00252         while(1) {
00253             real atb = sig_decay_level * exp(fire_time * coeff_sigdecay);
00254             real ctd = thr_decay_level * exp(fire_time * coeff_thrdecay);
00255             real T_ = (atb - ctd - min_threshold + sig_converge_level) / (coeff_sigdecay * atb - coeff_thrdecay * ctd);
00256             if( fabs(T_ ) < epsilon )
00257                 break;
00258             T *= 1.0 - T_;
00259 //              cout << T << "\t" << T_ << endl;
00260             fire_time = log(T);
00261             count++;
00262         }
00263 
00264         // 発火時刻にもう一度スケジューリング
00265         if( getDeb() )
00266         {
00267             real siglvl_at_fire = sig_decay_level * exp(coeff_sigdecay * fire_time) + sig_converge_level;
00268             real thrlvl_at_fire = thr_decay_level * exp(coeff_thrdecay * fire_time) + min_threshold;
00269             cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name << " Reschedule, time " << fire_time << ", fire_lvl " << siglvl_at_fire << ", threshold " << thrlvl_at_fire << ", newton " << count << endl;
00270         }
00271 //              cout << "newton " << count << endl;
00272         scheduler.scheduleEvent(current_time + fire_time, *this);
00273     }
00274     else
00275         if( getDeb() )
00276             cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name << " Accumulate, level " << sig_level << endl;
00277 }
00278 
00279 /************************************************************************/
00280 
00281 
00282 /************************************************************************
00283  ***** tneuron_ext ******************************************************
00284  ************************************************************************/
00285 
00286 template <bool debug>
00287 tneuron_ext<debug>::~tneuron_ext()
00288 {
00289     for( vector<tsynapse_base *>::iterator i = synapses.begin(); i != synapses.end(); i++ )
00290         delete *i;
00291     for( vector<func_base *>::iterator i = exts.begin(); i != exts.end(); i++ )
00292         delete *i;
00293 }
00294 
00295 template <bool debug>
00296 tneuron_ext<debug>::tneuron_ext(string iname /*= ""*/, real sig_hv_period)
00297         : tneuron_base(iname), 
00298           last_simulate(-10000000), last_fire(-10000000),
00299           lambda(M_LN2 / sig_hv_period) 
00300 {
00301     pulses = new func_delta_int(0, 0);
00302     addExt(pulses);
00303 }
00304 
00305 template <bool debug>
00306 bool tneuron_ext<debug>::sendMessage(ntime_t t, message_base *mess)
00307 {
00308     for( vector<func_base *>::iterator i = exts.begin(); i != exts.end(); i++ )
00309         if( (*i)->processMessage(t, *mess) )
00310             return true;
00311     return false;
00312 }
00313 
00314 template <bool debug>
00315 bool tneuron_ext<debug>::broadcastMessage(ntime_t t, message_base *mess)
00316 {
00317     bool ret = false;
00318     for( vector<func_base *>::iterator i = exts.begin(); i != exts.end(); i++ )
00319         ret = (*i)->processMessage(t, *mess) || ret;
00320     return ret;
00321 }
00322 
00323 template <bool debug>
00324 real tneuron_ext<debug>::calcSignal( ntime_t current_time )
00325 {
00326     real signal = 0.0;
00327     for( vector<func_base *>::iterator i = exts.begin(); i != exts.end(); i++ )
00328     {
00329         signal += (*i)->getValue(current_time);
00330     }
00331     return signal;
00332 }
00333 
00334 template <bool debug>
00335 void tneuron_ext<debug>::fire(tscheduler &scheduler, ntime_t current_time)
00336 {
00337     {
00338         prof<1> profobj("Fire");
00339         totalfire++;
00340 
00341         for( vector<tsynapse_base *>::iterator i = synapses.begin(); i != synapses.end(); i++ )
00342         {
00343     //#ifdef DEBUG
00344     //      cout << "schedule pulse at " << current_time + i->getDelay() << " to " << i->getDest().getName() << endl;
00345     //#endif
00346             scheduler.scheduleEvent(current_time + (*i)->getDelay(), **i);
00347         }
00348         last_fire = current_time;
00349         for( vector<func_base *>::iterator i = exts.begin(); i != exts.end(); i++ )
00350         {
00351             (*i)->setZeroPoint(current_time);
00352         }
00353     }
00354     scheduleFire(scheduler, current_time);
00355 }
00356 
00357 
00358 struct valdomain { real value, upslope, ceil, downslope, floor; };
00359 
00360 ostream& operator<<(ostream &o, const valdomain &v) 
00361 {
00362     return o << setprecision(8) << "val=" << v.value << ", u=" << v.upslope << ", c=" << v.ceil << ", d=" << v.downslope << ", f=" << v.floor;
00363 }
00364 
00365 const bool debug_domain = false;
00366 
00367 real domain_floor_time( vector<valdomain> &sig_domain, ntime_t next_incontinuity )
00368 {
00369     if( debug_domain )
00370         cout << "enter domain_floor" << endl;
00371     ntime_t search_from = 0;
00372     ntime_t old_search_from;
00373 
00374     do {
00375         if( debug_domain )
00376             cout << "domain_floor search_from=" << search_from << endl;
00377 
00378         real sig = 0.0, slo = 0.0;
00379         for( vector<valdomain>::iterator i = sig_domain.begin(); i != sig_domain.end(); i++ )
00380         {
00381             real nsig = i->value + i->downslope * search_from;
00382             if( debug_domain )
00383                 cout << "domain nsig=" << nsig << ", " << *i << endl;
00384             if( nsig < i->floor ) {
00385                 sig += i->floor;
00386             }
00387             else {
00388                 sig += nsig; 
00389                 slo += i->downslope;
00390             }
00391         }
00392         old_search_from = search_from;
00393         if( debug_domain )
00394             cout << "domain_floor sig=" << sig << ", slo=" << slo << endl;
00395         if( fabs(slo) < 1e-8 )
00396         {
00397             if( fabs(sig) > 1e-4 )
00398                 search_from = Infinity;
00399         }
00400         else
00401             search_from -= sig / slo;
00402     } while( old_search_from < search_from && search_from < next_incontinuity);
00403 
00404     if( debug_domain )
00405         cout << "leave domain_floor search_from=" << search_from << endl;
00406     return search_from;
00407 }
00408 
00409 real domain_ceil_time( vector<valdomain> &sig_domain, ntime_t next_incontinuity )
00410 {
00411     if( debug_domain )
00412         cout << "enter domain_ceil" << endl;
00413     ntime_t search_from = 0;
00414     ntime_t old_search_from;
00415 
00416     do {
00417         if( debug_domain )
00418             cout << "domain_ceil search_from=" << search_from << endl;
00419         real sig = 0.0, slo = 0.0;
00420         for( vector<valdomain>::iterator i = sig_domain.begin(); i != sig_domain.end(); i++ )
00421         {
00422             if( debug_domain )
00423                 cout << "domain " << *i << endl;
00424             real nsig = i->value + i->upslope * search_from;
00425             if( nsig >= i->ceil ) {
00426                 sig += i->ceil;
00427             }
00428             else {
00429                 sig += nsig; 
00430                 slo += i->upslope;
00431             }
00432         }
00433         old_search_from = search_from;
00434         if( debug_domain )
00435             cout << "domain_ceil sig=" << sig << ", slo=" << slo << endl;
00436         if( fabs(slo) < 1e-8 )
00437         {
00438             if( fabs(sig) > 1e-4 )
00439                 search_from = Infinity;
00440         }
00441         else
00442             search_from -= sig / slo;
00443     } while( old_search_from < search_from && search_from < next_incontinuity);
00444 
00445     if( debug_domain )
00446         cout << "leave domain_ceil search_from=" << search_from << endl;
00447     return search_from;
00448 }
00449 
00450 template <bool debug>
00451 void tneuron_ext<debug>::pulseArrive(tscheduler &scheduler, ntime_t current_time, real pulse_level)
00452 {
00453     real curval = pulses->getValue(current_time);
00454 
00455     pulses->setParam(curval + pulse_level, current_time);
00456 
00457     if( getDeb() )
00458     cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00459         << " Pulse arrived, signal level " << pulse_level << ", new pulse " << pulses->getValue(current_time) << endl; 
00460 
00461     scheduleFire(scheduler, current_time);
00462 }
00463 
00464 template <bool debug>
00465 void tneuron_ext<debug>::pulseArrive(tscheduler &scheduler, ntime_t current_time, message_base *base)
00466 {
00467 //  real curval = pulses->getValue(current_time);
00468 
00469     if( getDeb() )
00470     cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00471         << " Pulse arrived, message=" << base->getMessageId() << flush;
00472     bool ret = sendMessage(current_time, base);
00473     if( getDeb() )
00474         cout << " result=" << ret << endl;
00475 
00476     scheduleFire(scheduler, current_time);
00477 }
00478 
00479 template <bool debug>
00480 void tneuron_ext<debug>::pulseArrive(tscheduler &scheduler, ntime_t current_time, func_base *base)
00481 {
00482 //  real curval = pulses->getValue(current_time);
00483 
00484     if( getDeb() )
00485     cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00486         << " Pulse arrived, func=" << base->getDescription() << flush;
00487     addExt(base);
00488 
00489     scheduleFire(scheduler, current_time);
00490 }
00491 
00492 template <bool debug>
00493 void tneuron_ext<debug>::scheduleFire(tscheduler &scheduler, ntime_t current_time, bool /*resched*/)
00494 {
00495     prof<1> profobj("scheduleFire");
00496 //  if( getDeb() ) cout << "enter tneuron_ext::schedulefire" << endl;
00497     
00498     real signal = 0.0;
00499     real deriv1st = 0.0;
00500     real deriv2nd = 0.0;
00501     real next_incontinuity = Infinity;
00502     ntime_t next_known_pulse;
00503 
00504     int extssize = exts.size();
00505     vector<valdomain> sig_domain(extssize);
00506     vector<valdomain> d1st_domain(extssize);
00507     vector<valdomain> d2nd_domain(extssize);
00508 
00509     last_simulate = current_time;
00510     real maxgrad = 0.0;
00511 
00512     if( use_next_known_pulse ) { 
00513         prof<2> profobj("tneuron_ext::0 calcval");
00514         while( !queue()->empty() && &(queue()->top().getAction()) == this )
00515         {
00516             totalrescheduled++;
00517             queue()->pop();
00518         }
00519         if( queue()->empty() )
00520             next_known_pulse = Infinity;
00521         else
00522             next_known_pulse = queue()->top().getTime();
00523 
00524         vector<valdomain>::iterator sdi = sig_domain.begin();
00525         for( vector<func_base *>::iterator i = exts.begin(); i != exts.end(); i++ )
00526         {
00527             real v = (*i)->getValue(current_time);
00528             sdi++->value = v;
00529             signal += v;
00530 
00531 //          cout << "v=" << v << ", m=" << (*i)->getMaxGradient(current_time) << ", desc= "<< (*i)->getDescription() << endl;
00532 
00533             maxgrad += (*i)->getMaxGradient(current_time);
00534         }
00535     } 
00536     else {
00537         next_known_pulse = Infinity;
00538         vector<valdomain>::iterator sdi = sig_domain.begin();
00539         for( vector<func_base *>::iterator i = exts.begin(); i != exts.end(); i++ )
00540         {
00541             real v = (*i)->getValue(current_time);
00542             valdomain vd; vd.value = v;
00543             sdi++->value = v;
00544             signal += v;
00545     //cout << "v=" << v << ", desc= "<< (*i)->getDescription() << endl;
00546         }
00547     }
00548 
00549     if( signal >= - 1e-8 )
00550     {
00551         if( getDeb() )
00552             cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00553                 << " Fire, signal level " << signal << endl; 
00554         fire(scheduler, current_time);
00555     }
00556     else
00557     {
00558         if( use_next_known_pulse ) { 
00559             if( signal < - maxgrad * (next_known_pulse - current_time) )
00560             {
00561                 if( getDeb() )
00562                     cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00563                         << " Stay, signal level " << signal << ", filtered by max gradient " << maxgrad << ", next " << next_known_pulse << endl;
00564                 totalfiltered_maxgrad++;
00565                 return;
00566             }
00567         }
00568         {
00569         prof<2> profobj("tneuron_ext::1 sigdomain");
00570         vector<valdomain>::iterator sdi = sig_domain.begin();
00571         for( vector<func_base *>::iterator i = exts.begin(); i != exts.end(); i++ )
00572         {
00573     //      if( getDeb() )
00574     //          cout << "func_base " << (*i)->getDescription() << endl;
00575             while( (*i)->shouldDelete(current_time) )
00576             {
00577                 prof<2> profobj("delete");
00578                 delete *i;
00579                 exts.erase(i);
00580                 sig_domain.erase(sdi);
00581                 if( i == exts.end() )
00582                     goto EXIT_DOM_LOOP;
00583             }
00584 
00585     //      if( sdi == sig_domain.end() ) cout << "Why? " << sig_domain.size() << " / " << exts.size() << endl;
00586             (*i)->getValueDomain(current_time, sdi->upslope, sdi->ceil, sdi->downslope, sdi->floor);
00587             sdi++;
00588         }
00589         EXIT_DOM_LOOP: ;
00590         }
00591         real value_bound;
00592         {
00593         prof<2> profobj("tneuron_ext::2 filter");
00594         value_bound = domain_ceil_time(sig_domain, next_incontinuity - current_time);
00595 
00596         if( value_bound + current_time >= next_incontinuity && next_incontinuity < Infinity )
00597         {
00598             if( getDeb() )
00599                 cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00600                     << " Stay, signal level " << signal << ", Reschedule at next incontinuity " << next_incontinuity << endl; 
00601             setLoopBack(scheduler, next_incontinuity);
00602             totalfiltered_incontinuity++;
00603             return;
00604         }
00605         if( use_next_known_pulse && value_bound + current_time >= next_known_pulse && next_known_pulse < Infinity )
00606         {
00607             if( getDeb() )
00608                 cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00609                     << " Stay, signal level " << signal << ", wait for the next known pulse at " << next_known_pulse << endl; 
00610             totalfiltered_nextpulse++;
00611             return;
00612         }
00613         }
00614         real next_bound, bound_val;
00615         {
00616         prof<2> profobj("tneuron_ext::3 bounder");
00617         if( iporder >= 1 )
00618         {
00619             vector<valdomain>::iterator d1d = d1st_domain.begin();
00620             for( vector<func_base *>::iterator i = exts.begin(); i != exts.end(); i++ )
00621             {
00622                 real v = (*i)->get1stDeriv(current_time);
00623                 d1d->value = v;
00624                 deriv1st += v;
00625                 (*i)->get1stDerivDomain(current_time, d1d->upslope, d1d->ceil, d1d->downslope, d1d->floor);
00626                 d1d++;
00627             }
00628         }
00629 
00630         real d1st_bound = 0.0, d2nd_bound = 0.0;
00631 
00632         if( iporder>=1 && deriv1st >= 1e-5 )
00633             d1st_bound = domain_floor_time( d1st_domain, next_incontinuity - current_time);
00634         else if( iporder>=1 && deriv1st <= -1e-5 )
00635             d1st_bound = domain_ceil_time( d1st_domain, next_incontinuity - current_time);
00636 
00637         if( iporder >= 2 && value_bound < 1e-1 && d1st_bound < 1e-1 && (use_next_known_pulse ? deriv1st + current_time < next_known_pulse : true) )
00638         {
00639             vector<valdomain>::iterator d2d = d2nd_domain.begin();
00640             for( vector<func_base *>::iterator i = exts.begin(); i != exts.end(); i++ )
00641             {
00642                 real v = (*i)->get2ndDeriv(current_time);
00643                 d2d->value = v;
00644                 deriv2nd += v;
00645                 (*i)->get2ndDerivDomain(current_time, d2d->upslope, d2d->ceil, d2d->downslope, d2d->floor);
00646                 d2d++;
00647             }
00648 
00649             if( iporder>=2 && deriv2nd >= 1e-5 )
00650                 d2nd_bound = domain_floor_time( d2nd_domain, next_incontinuity - current_time);
00651             else if( iporder>=2 && deriv2nd <= -1e-5 )
00652                 d2nd_bound = domain_ceil_time( d2nd_domain, next_incontinuity - current_time);
00653         }
00654         
00655         totalpartition++;
00656         next_bound = 0.0;
00657         // real bound_val; // The value of the signal at the next bound
00658         bool need_newton = false;
00659         if( (iporder<1 || value_bound >= d1st_bound) && (iporder<2 || value_bound >= d2nd_bound) )
00660         {
00661             prof<3> profobj("tneuron_ext::3-0th_bound");
00662             if( getDeb() )
00663                 cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00664                     << " Stay, signal level " << signal << ", value_bound is the longest " << value_bound << ":" << d1st_bound << ":" << d2nd_bound << endl; 
00665             next_bound = value_bound;
00666             last_simulate_type = 0;
00667         }
00668         else if( iporder<2 || d1st_bound >= d2nd_bound )
00669         {   
00670             prof<3> profobj("tneuron_ext::3-1st_bound");
00671             next_bound = d1st_bound;
00672             last_simulate_type = 1;
00673             if( deriv1st > 0.0 && (bound_val=calcSignal( current_time + next_bound )) > 0.0 )
00674                 need_newton = true;
00675 //          cout << "signal = " << signal << endl;
00676 //          cout << "deriv1st = " << deriv1st << endl;
00677 //          cout << "bound_val = " << bound_val << endl;
00678             if( getDeb() )
00679                 cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00680                     << " Stay, signal level " << signal << ", d1st_bound is the longest " << value_bound << ":" << d1st_bound << ":" << d2nd_bound << " need_newton = " << (need_newton ? "true" : "false") << endl; 
00681         }
00682         else {
00683             prof<3> profobj("tneuron_ext::3-2nd-order");
00684             next_bound = d2nd_bound;
00685             last_simulate_type = 2;
00686             if( deriv1st < 0.0 && deriv2nd < 0.0 )
00687             {
00688                 if( getDeb() )
00689                     cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00690                         << " Stay, signal level " << signal << ", d2nd_bound is the longest " << value_bound << ":" << d1st_bound << ":" << d2nd_bound << ", need_newton = false (d1<0,d2<0)" << endl; 
00691                 need_newton = false;
00692             }
00693             else if( (bound_val = calcSignal( current_time + next_bound )) > 0.0 )
00694             {
00695                 if( getDeb() )
00696                     cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00697                         << " d2nd_bound is the longest " << value_bound << ":" << d1st_bound << ":" << d2nd_bound << ", need_newton = true (bound_val=" << bound_val << ")" << endl; 
00698                 need_newton = true;
00699             }
00700             else if( deriv2nd >= 0.0 )
00701             {
00702                 if( getDeb() )
00703                     cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00704                         << " d2nd_bound is the longest " << value_bound << ":" << d1st_bound << ":" << d2nd_bound << ", need_newton = false (no convex nor end)" << endl; 
00705                 need_newton = false;
00706             }
00707             else {
00708                 if( getDeb() )
00709                     cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00710                         << " d2nd_bound is the longest " << value_bound << ":" << d1st_bound << ":" << d2nd_bound << ", peak search" << endl; 
00711                 real left = 0.0, right = next_bound, mid = d1st_bound + (right-d1st_bound) * 0.38197;
00712                 real leftval = signal, rightval = bound_val, midval = calcSignal( current_time + mid );
00713                 if( midval < rightval || midval < leftval )
00714                 {                   // Cannot enclose the peak...
00715                     if( midval < rightval ) {
00716                         real right_deriv = 0.0;
00717                         for( vector<func_base *>::iterator i = exts.begin(); i != exts.end(); i++ )
00718                             right_deriv += (*i)->get1stDeriv(current_time + right);
00719                         if( right_deriv >= 0.0 )
00720                         {
00721                             if( getDeb() )
00722                                 cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00723                                     << " peak is not exist, right_deriv = " << right_deriv << endl;
00724                             totalpeaksearch[2]++;
00725                             goto PEAK_SEARCH_FINISH;
00726                         }
00727                     }
00728                     totalpeakenclosing++;
00729                     while( midval < rightval || midval < leftval )
00730                     {
00731                         if( getDeb() )
00732                             cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00733                                 << " peak enclosing " << setprecision(5) << left << ":" << mid << ":" << right << "=" << leftval << ":" << midval << ":" << rightval << endl;
00734                         if( midval < rightval ) {
00735                             left = mid; leftval = midval; mid = left + (right - left) * 0.38197;
00736                         } else {
00737                             right = mid; rightval = midval; mid = left + (right - left) * 0.61803;
00738                         }
00739                         midval = calcSignal( current_time + mid );
00740                     }
00741                 }
00742                 if( midval > 0.0 )
00743                 {
00744                     if( getDeb() )
00745                         cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00746                             << " peak found " << mid << "=" << midval << endl; 
00747                     next_bound = mid; bound_val = midval; need_newton = true;
00748                 }
00749                 else /* Look for the peak */
00750                 {
00751                     real oldp = 0, newp=-1;
00752                     while( fabs(oldp - newp) >= 1e-8 ) 
00753                     {
00754                         if( getDeb() )
00755                             cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00756                                 << " peak search " << setprecision(5) << left << ":" << mid << ":" << right << "=" << leftval << ":" << midval << ":" << rightval << endl;
00757 
00758                         real newpmove, newpval;
00759                         real mlmr = (mid - left) * (midval - rightval);
00760                         real mrml = (mid - right) * (midval - leftval);
00761 
00762                         // abort peak search, if no hope to go over zero
00763 
00764                         real left_best = midval - mlmr / (mid - right);
00765                         real right_best = midval - mrml / (mid - left);
00766                         if( left_best < 0 && right_best < 0 )
00767                         {
00768                             if( getDeb() )
00769                                 cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00770                                     << " peak search aborted, left_best=" << setprecision(10) << left_best << ", right_best=" << right_best << endl;
00771                             break;
00772                         }
00773 
00774                         real mlmr_mrml = -2.0 * (mlmr - mrml);
00775                         real mlmlmr_mrmrml = (mid - left) * mlmr - (mid - right) * mrml;
00776                         if( mlmr_mrml < 0.0 ) { mlmr_mrml = - mlmr_mrml; mlmlmr_mrmrml = - mlmlmr_mrmrml; }
00777                         
00778                         if( mlmlmr_mrmrml > mlmr_mrml*(left-mid) && mlmlmr_mrmrml < mlmr_mrml*(right-mid) )
00779                         {
00780                             newpmove = mlmlmr_mrmrml / mlmr_mrml; // use parabora interpolation
00781                             if( getDeb() )
00782                                 cout << "parabola " << setprecision(10) << newpmove << ", " << newp - (mid + newpmove) << endl;
00783                         }
00784                         else
00785                         {
00786                             cout << "mid - left = " << setprecision(10) << mid - left << endl;
00787                             cout << "mid - right = " << setprecision(10) << mid - right << endl;
00788                             cout << "parabola = " << setprecision(10) << mlmlmr_mrmrml / mlmr_mrml << endl;
00789                             if( mid - left > right - mid ) newpmove = (left-mid) * 0.38197;
00790                                                       else newpmove = (right-mid) * 0.38197;
00791                             cout << "golden   " << setprecision(10) << newpmove << ", " << newp - (mid + newpmove) << endl;
00792                         }
00793                         oldp = newp;
00794                         newp = mid + newpmove;
00795                         newpval = calcSignal(current_time + newp);
00796                         if( newpval > midval )
00797                         { 
00798                             if( newp < mid ) { right = mid; rightval = midval; }
00799                                         else { left = mid; leftval = midval; }
00800                             mid = newp; midval = newpval; 
00801                             if( newpval > 0.0 )
00802                             { next_bound = newp; bound_val = newpval; need_newton = true; break; }
00803                         }
00804                         else 
00805                             if( newp < mid ) { left = newp; leftval = newpval; }
00806                                         else { right = newp; rightval = newpval; }
00807                     }
00808                     /* if peak value is < 0.0, then need_newton is false */
00809                     totalpeaksearch[need_newton ? 1 : 0]++;
00810                 }
00811                 PEAK_SEARCH_FINISH:
00812                 if( getDeb() )
00813                     cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00814                         << " peak search finished, need_newton = " << (need_newton ? "true" : "false") << ", mid " << mid << "=" << midval << endl;
00815             }
00816         }
00817         if( need_newton == false )
00818         {
00819             if( next_bound < ip_delta_t )
00820             {
00821                 next_bound = ip_delta_t;
00822                 last_simulate_type = 3;
00823                 if( (bound_val=calcSignal( current_time + next_bound )) > 0.0 )
00824                     need_newton = true;
00825                 if( getDeb() )
00826                     cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00827                         << " next_bound is adjusted to delta_t, need_newton = " << (need_newton ? "true" : "false") << endl;
00828             }
00829             if( need_newton == false ) {
00830                 totalpartition_nonewton[last_simulate_type]++;
00831                 if( getDeb() )
00832                     cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00833                         << " Reschedule at the end of no-newton-area " << current_time + next_bound << endl; 
00834                 setLoopBack(scheduler, current_time + next_bound);
00835                 return; 
00836             }
00837         }
00838         }
00839         prof<2> profobj2("tneuron_ext::4 newton");
00840         totalpartition_newton[last_simulate_type]++;
00841         /* Do newton to find fire point */
00842         if( next_bound >= 10000000 )
00843         {
00844             next_bound = 10000000; // to avoid infinity operation
00845             if( bound_val >= 10000000 )
00846                 bound_val = calcSignal(current_time + next_bound);
00847         }
00848         real left = 0.0, right = next_bound;
00849         real newtonp = right * signal / (signal - bound_val); // set newtonp to the linear interpolation point
00850         if( getDeb() )
00851             cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00852                 << " Start newton in range of " << next_bound << ", signal=" << signal << ", bound_val=" << bound_val << endl; 
00853 
00854         real val = 0.0, deriv= 0.0;
00855         for( vector<func_base *>::iterator i = exts.begin(); i != exts.end(); i++ )
00856         {
00857             val += (*i)->getValue(current_time + newtonp);
00858             deriv += (*i)->get1stDeriv(current_time + newtonp);
00859         }
00860 
00861         real old_newtonp = newtonp - 1;
00862         while( fabs(old_newtonp - newtonp) > 1e-8 )
00863         {
00864             if( getDeb() )
00865                 cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00866                     << " Newton left=" << left << ", newtonp=" << newtonp << ", right=" << right << ", val=" << val << endl;
00867             old_newtonp = newtonp;
00868 
00869             real newtonp_move = Infinity;
00870             if( fabs(deriv) > 1e-8 ) 
00871                 newtonp_move = - val / deriv;
00872             if( newtonp + newtonp_move < left || newtonp + newtonp_move > right )
00873             {
00874                 if( getDeb() )
00875                     cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00876                         << " Newton_safe newtonp_move=" << newtonp + newtonp_move << endl;
00877                 if( val > 0.0 ) newtonp_move = (left - newtonp) * 0.5;
00878                            else newtonp_move = (right - newtonp) * 0.5;
00879             }
00880             if( newtonp_move < 0.0 )
00881                 { right = newtonp; newtonp += newtonp_move; }
00882             else{ left  = newtonp; newtonp += newtonp_move; }
00883 
00884             val = 0.0; deriv= 0.0;
00885             for( vector<func_base *>::iterator i = exts.begin(); i != exts.end(); i++ )
00886             {
00887                 val += (*i)->getValue(current_time + newtonp);
00888                 deriv += (*i)->get1stDeriv(current_time + newtonp);
00889             }
00890         }
00891         if( val > -1e-5 )
00892         {
00893             if( getDeb() )
00894                 cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00895                     << " Newton success, reschedule at next fire " << current_time + newtonp << endl; 
00896             setLoopBack(scheduler, current_time + newtonp);
00897         }
00898         else
00899         {
00900             if( getDeb() )
00901                 cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name 
00902                     << " Newton failed, Reschedule at next prediction bound " << current_time + next_bound << endl; 
00903             setLoopBack(scheduler, current_time + next_bound);
00904         }
00905     }
00906 //  if( getDeb() ) cout << "leave tneuron_ext::schedulefire" << endl;
00907 }
00908 
00909 // template instantiation.
00910 template class punnets_private::tsynapse<true>        ;
00911 template class punnets_private::tsynapse_message<true>;
00912 template class punnets_private::tsynapse_fatigue<true>;
00913 template class punnets_private::tsynapse_addfunc<true>   ;
00914 template class punnets_private::tsynapse_messfunc<true>   ;
00915 
00916 template class punnets_private::tneuron<true>          ;
00917 template class punnets_private::tneuron_ext_const<true>;
00918 template class punnets_private::tneuron_ext<true>      ;
00919 
00920 template class punnets_private::tsynapse<false>        ;
00921 template class punnets_private::tsynapse_message<false>;
00922 template class punnets_private::tsynapse_fatigue<false>;
00923 template class punnets_private::tsynapse_addfunc<false>   ;
00924 template class punnets_private::tsynapse_messfunc<false>   ;
00925 
00926 template class punnets_private::tneuron<false>          ;
00927 template class punnets_private::tneuron_ext_const<false>;
00928 template class punnets_private::tneuron_ext<false>      ;
00929 
00931 } // namespace punnets_private

Generated on Mon Jun 16 15:42:25 2003 for Punnets by doxygen1.2.18