00001
00026 #include "dneuron.h"
00027 #include <math.h>
00028 #include <mak/profile.h>
00029
00030 using namespace mak;
00031
00032
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
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
00069
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
00089
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 }
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 ,
00124 ntime_t ithr_hv_period ,
00125 real imin_threshold ,
00126 real imax_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
00145
00146
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 )
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
00236 }
00237 else
00238 {
00239 if( getDeb() )
00240 cout << setw(9) << setiosflags(ios::fixed) << setprecision(debug_precision) << current_time << " " << name << " Possible" << endl;
00241
00242 }
00243
00244
00245
00246
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
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
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
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
00344
00345
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
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
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 )
00494 {
00495 prof<1> profobj("scheduleFire");
00496
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
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
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
00574
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
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
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
00676
00677
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 {
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
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
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;
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
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
00842 if( next_bound >= 10000000 )
00843 {
00844 next_bound = 10000000;
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);
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
00907 }
00908
00909
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 }