sp_plpexecutor.cpp

Go to the documentation of this file.
00001 /** @file sp_plpexecutor.cpp Executor that proposes transitions to execute */
00002 
00003 /* 
00004    FAU Discrete Event System Simulator 
00005 
00006    Copyright (C) 2007  Christoph Doerr
00007    Copyright (C) 2008  Thomas Moor
00008    Exclusive copyright is granted to Thomas Moor
00009 
00010 */
00011 
00012 #include "sp_plpexecutor.h"
00013 #include <cmath>
00014 #include <ctime>
00015 
00016 namespace faudes {
00017 
00018 // std faudes type
00019 FAUDES_TYPE_IMPLEMENTATION(ProposingExecutor, ProposingExecutor, ParallelExecutor)
00020 
00021 // constructor
00022 ProposingExecutor::ProposingExecutor(void) : LoggingExecutor() { 
00023   mPValid=false;
00024 }
00025 
00026 // copy constructor
00027 ProposingExecutor::ProposingExecutor(const ProposingExecutor& rOther) : LoggingExecutor() 
00028 { 
00029   mPValid=false;
00030   Assign(rOther);
00031 }
00032 
00033 // clear static data
00034 void ProposingExecutor::Clear(void){
00035   LoggingExecutor::Clear();
00036   mSimEvents.Clear();
00037   mPValid=false;
00038 }
00039 
00040 // DoAssign(other)
00041 void ProposingExecutor::DoAssign(const ProposingExecutor& rOther) {
00042   FD_DX("ProposingExecutor(" << this << ")::DoAssign(other)");
00043   // my members
00044   mSimEvents.Assign(rOther.mSimEvents);
00045   // base
00046   LoggingExecutor::DoAssign(rOther);
00047 }
00048 
00049 // lookup event attribute
00050 const SimEventAttribute& ProposingExecutor::EventAttribute(Idx index) const {
00051   return mSimEvents.Attribute(index);
00052 }
00053      
00054 // set simulation event attribute
00055 void ProposingExecutor::EventAttribute(Idx index, const SimEventAttribute& rAttr) {
00056   mSimEvents.Attribute(index,rAttr);
00057 }
00058 
00059 // set execution properties from attributed event set
00060 void ProposingExecutor::Alphabet(const sEventSet& rAlphabet) {
00061   // set ...
00062   mSimEvents=rAlphabet;
00063   // ... and ensure to cover all relevant alphabet
00064   mSimEvents.InsertSet(LoggingExecutor::Alphabet()); 
00065 }
00066 
00067 // clear dynamic data (reset state) 
00068 void ProposingExecutor::ResetProposer(long int seed){
00069   FD_DS("ProposingExecutor::ResetProposer()");
00070   //Initialize random number generator with computer system time as seed
00071   if(seed == 0) seed = static_cast<long>(time(NULL));
00072   ran_init(seed);
00073   // schedule all events
00074   EventSet::Iterator eit;
00075   for(eit=Alphabet().Begin(); eit!=Alphabet().End(); ++eit){
00076     SimEventAttribute* pattr= mSimEvents.Attributep(*eit);
00077     pattr->mScheduledFor=tpTime::UnDef;
00078     pattr->mDelayFor=tpTime::UnDef;
00079     pattr->mExpiresAt=0;
00080     if(pattr->IsPriority()) continue;
00081     if(!pattr->IsStochastic()) continue;
00082     Schedule(*eit,pattr);
00083   }
00084   // invalidate proposal
00085   mPValid=false;
00086   FD_DS("ProposingExecutor::ResetProposer(): done");
00087 
00088 
00089 }
00090 
00091 // clear dynamic data (reset state) 
00092 void ProposingExecutor::Reset(long int seed){
00093   FD_DS("ProposingExecutor::Reset()");
00094   LoggingExecutor::Reset();
00095   mSimEvents.InsertSet(LoggingExecutor::Alphabet()); 
00096   ResetProposer(seed);
00097   FD_DS("ProposingExecutor::Reset(): done");
00098 }
00099 
00100 
00101 //EventStatesToString
00102 std::string ProposingExecutor::EventStatesToString() const {
00103   std::stringstream retstr;
00104   EventSet::Iterator eit;
00105   for(eit=mSimEvents.Begin(); eit!=mSimEvents.End(); ++eit){
00106     const SimEventAttribute& attr= mSimEvents.Attribute(*eit);
00107     retstr<< "% simulation state: "<< ExpandString(mSimEvents.Str(*eit),FD_NAMELEN) << ": ";
00108     retstr<< "enabled: " << ExpandString(EnabledEventTime(*eit).Str(),FD_NAMELEN) << ": ";
00109     retstr<< attr.Str();
00110     if( eit!= --mSimEvents.End()) {
00111       retstr << std::endl;
00112     }
00113   }
00114   return retstr.str();
00115 }
00116 
00117 
00118 
00119 //ExecuteTime: todo: may hang + performance issue 
00120 bool ProposingExecutor::ExecuteTime(tpTime::Type duration){
00121   FD_DS("ProposingExecutor::ExecuteTime(): LoggingExecutor to execute time "<< duration);
00122   if(!LoggingExecutor::ExecuteTime(duration)) return false;
00123   // update stochastic event state
00124   EventSet::Iterator eit;
00125   for(eit=mSimEvents.Begin(); eit!=mSimEvents.End(); ++eit) {
00126     SimEventAttribute* pattr= mSimEvents.Attributep(*eit);
00127     // stochastic only
00128     if(!pattr->IsStochastic()) continue;
00129     // shift relative time: schedule/expiring time
00130     if(pattr->mScheduledFor!=tpTime::UnDef) 
00131     if(pattr->mScheduledFor!=tpTime::Max) 
00132       pattr->mScheduledFor -= duration;
00133     if(pattr->mExpiresAt!=tpTime::UnDef) 
00134     if(pattr->mExpiresAt!=tpTime::Max) 
00135       pattr->mExpiresAt -= duration;
00136     // shift reference interval for type trigger
00137     if(pattr->Stochastic().mType==SimStochasticEventAttribute::Trigger) {
00138       pattr->mReferenceInterval.PositiveLeftShift(duration);
00139     }
00140     // shift reference interval for type delay
00141     if(pattr->Stochastic().mType==SimStochasticEventAttribute::Delay) {
00142       if(!pattr->mReferenceInterval.Empty()) {
00143         tpTime::Type delay = duration - pattr->mReferenceInterval.LB();
00144         if(delay>0) pattr->mDelayFor-=delay;
00145         pattr->mReferenceInterval.PositiveLeftShift(duration);
00146       }
00147     }
00148     // re-schedule (required for type extern and delay)
00149     if(pattr->mExpiresAt<=0) Schedule(*eit,pattr);
00150   }
00151   FD_DS("ProposingExecutor::ExecuteTime(): LoggingExecutor to execute time: done ");
00152   // case a: no valid proposal anyway
00153   if(!mPValid) return true;
00154   // case b: proposal remains valid
00155   if(mProposal.Time==tpTime::Max) return true;
00156   // case c: proposal becomes invalid
00157   if(mProposal.Time < duration) { mPValid=false; return true;}
00158   // case d: adjust proposal
00159   mProposal.Time-=duration;
00160   mPValid= (mProposal.Time>0) || (mProposal.Event!=0);
00161   return true;
00162 }
00163 
00164 //ExecuteEvent
00165 bool ProposingExecutor::ExecuteEvent(Idx event){
00166   FD_DS("ProposingExecutor::ExecuteEvent(): ProposingExecutor to execute event "<< mSimEvents.Str(event));
00167 
00168   // (try to) execute
00169   if(!LoggingExecutor::ExecuteEvent(event)) return false;
00170   FD_DS("ProposingExecutor::ExecuteEvent(): executed "<< EventName(event));  
00171 
00172   // record enabled events
00173   const EventSet newActiveEvents=ActiveEventSet(CurrentParallelState());    
00174   FD_DS("ProposingExecutor::ExecuteEvent(): new active events "<< newActiveEvents.ToString());   
00175 
00176 
00177   // invalidate/re-schedule event states
00178   EventSet::Iterator eit;
00179   for(eit=mSimEvents.Begin(); eit!=mSimEvents.End(); ++eit) {
00180     SimEventAttribute* pattr= mSimEvents.Attributep(*eit);
00181     // stochastic only
00182     if(!pattr->IsStochastic()) continue;
00183     // invalidate schedule: type trigger 
00184     if(pattr->Stochastic().mType==SimStochasticEventAttribute::Trigger) {
00185       TimeInterval gtime=EnabledGuardTime(*eit);
00186       gtime.Canonical();
00187       if(gtime!=pattr->mReferenceInterval) {
00188         FD_DS("ProposingExecutor::ExecuteEvent(): invalidating trigger type event "<< EStr(*eit));
00189         pattr->mExpiresAt = 0;
00190       }
00191     }
00192     // update state: type delay (only if not expired)
00193     if(pattr->Stochastic().mType==SimStochasticEventAttribute::Delay) 
00194     if(pattr->mExpiresAt > 0) {
00195       TimeInterval etime=EnabledEventTime(*eit);
00196       etime.Canonical();
00197       pattr->mReferenceInterval=etime;
00198       pattr->mScheduledFor=tpTime::UnDef;
00199       pattr->mExpiresAt=tpTime::Max;
00200       tpTime::Type schedule= etime.LB()+ pattr->mDelayFor;
00201       if(etime.In(schedule)) {
00202         pattr->mScheduledFor=schedule;
00203         pattr->mExpiresAt=pattr->mScheduledFor+1;
00204         FD_DS("ProposingExecutor::ExecuteEvent(): delay event " << EStr(*eit) << ": etime " 
00205              << etime.Str() << " scheduled " << schedule);
00206       }
00207     }
00208     // invalidate schedule: event executed
00209     if(*eit==event) {
00210       FD_DS("ProposingExecutor::ExecuteEvent(): invalidating state for executed event "<< EStr(*eit));
00211       pattr->mExpiresAt = 0;
00212     }
00213     /*
00214     // invalidate schedule: type all reset
00215     if(pattr->Stochastic().mType==SimStochasticEventAttribute::State) {
00216       pattr->mExpiresAt = 0;
00217       pattr->mScheduledFor = 0;
00218       pattr->mDelayFor = tpTime::UnDef;
00219       FD_DS("ProposingExecutor::ExecuteEvent(): invalidating state for state-type " << EStr(*eit));
00220     }
00221     */
00222     /*
00223     // invalidate schedule: type intern
00224     if(pattr->Stochastic().mType==SimStochasticEventAttribute::Intern) {
00225       if(!EventValidity(*eit, event, oldActiveStateVec,newActiveStateVec)){
00226         pattr->mExpiresAt = 0;
00227         pattr->mScheduledFor = 0;
00228         pattr->mDelayFor = tpTime::UnDef;
00229         FD_DS("ProposingExecutor::ExecuteEvent(): invalidating state for intern-type " << EStr(*eit));
00230       }
00231     }
00232     */
00233     // re-schedule
00234     if(newActiveEvents.Exists(*eit))
00235     if(pattr->mExpiresAt<=0) Schedule(*eit,pattr);
00236   } // loop all events
00237 
00238   // invalidate proposal
00239   mPValid=false;
00240   // done
00241   FD_DS("ProposingExecutor::ExecuteEvent(): done");
00242   return true;  
00243 }
00244 
00245 
00246 //ExecuteTransition (rel time!) (event 0 for time only)
00247 bool ProposingExecutor::ExecuteTransition(const TimedEvent& executeEvent){
00248 
00249   if(!ExecuteTime(executeEvent.Time)) return false;
00250   if(executeEvent.Event==0) return true;
00251   if(!ExecuteEvent(executeEvent.Event)) return false;  
00252 
00253   return true;
00254 }
00255 
00256 
00257 
00258 //ProposeNextTransition (event 0 for time only)
00259 // todo: combine loops for performance
00260 const TimedEvent& ProposingExecutor::ProposeNextTransition(void){
00261 
00262   FD_DS("ProposingExecutor::ProposeNextTransition()");
00263 
00264   // return valid proposal
00265   if(mPValid) return mProposal;
00266 
00267   // compute valid proposal now
00268   mPValid=true;
00269 
00270   // vars
00271   EventSet::Iterator eit;
00272   TimeInterval enabledInterval=EnabledInterval();
00273   TimeInterval enabledTime=EnabledTime();
00274   const EventSet enabledEvents = EnabledEvents();
00275 
00276   // report
00277   FD_DS("\n" << EventStatesToString());
00278   FD_DS("ProposingExecutor::ProposeNextTransition(): current time: " << 
00279     CurrentTime()); 
00280   FD_DS("ProposingExecutor::ProposeNextTransition(): timed state: " <<
00281     CurrentParallelTimedStateStr());
00282   FD_DS("ProposingExecutor::ProposeNextTransition(): active events: " <<
00283       ActiveEventSet(CurrentParallelState()).ToString());
00284   FD_DS("ProposingExecutor::ProposeNextTransition(): enabled interval: " <<
00285     enabledInterval.Str());
00286   FD_DS("ProposingExecutor::ProposeNextTransition(): enabled time: " <<
00287     enabledTime.Str());
00288   FD_DS("ProposingExecutor::ProposeNextTransition(): enabled events: " << std::endl <<
00289     EnabledEvents().ToString());
00290 
00291   // find candidate to execute
00292   Idx candidate=0;
00293   std::vector<faudes::Idx> candidates;
00294   tpTime::Type passtime=0;
00295 
00296   //check if a priority event occurs in analyzed interval 
00297   long int prio = -1;
00298   for(eit=enabledEvents.Begin(); eit!=enabledEvents.End(); ++eit) {
00299     SimEventAttribute* pattr= mSimEvents.Attributep(*eit);
00300     if(!pattr->IsPriority()) continue;
00301     // priority wins
00302     if(pattr->Priority().mPriority >prio) {
00303       prio= pattr->Priority().mPriority;
00304       candidate=*eit;
00305       candidates.clear();
00306       candidates.push_back(candidate);
00307     }
00308     // indicate non determinism
00309     if((pattr->Priority().mPriority ==prio) && (prio>=0)) 
00310       candidates.push_back(*eit);
00311   }
00312 
00313   // choose arbitrarily
00314   if(candidates.size()>1) {
00315     candidate=candidates[ran_uniform_int(0,candidates.size())];
00316   }
00317 
00318   // propose priority candidate now
00319   if(candidate>0) {
00320     FD_DS("ProposingExecutor::ProposeNextTransition(): propose by priority: " << mSimEvents.Str(candidate));
00321     mProposal.Event=candidate;
00322     mProposal.Time=0;
00323     return mProposal;
00324   }
00325 
00326   //check if stochastic  events are enabled
00327   tpTime::Type occurence = -1;
00328   for(eit=enabledEvents.Begin(); eit!=enabledEvents.End(); ++eit){
00329     SimEventAttribute* pattr= mSimEvents.Attributep(*eit);
00330     if(!pattr->IsStochastic()) continue;
00331     if(pattr->mScheduledFor == tpTime::UnDef) continue; // dont need this anyway
00332     if(enabledInterval.In(pattr->mScheduledFor)) { 
00333       // occurence wins
00334       if(pattr->mScheduledFor < occurence || occurence < 0) {
00335         occurence= pattr->mScheduledFor;
00336         candidate=*eit;
00337         candidates.clear();
00338         candidates.push_back(candidate);
00339       }
00340       // indicate non determinism
00341       if(pattr->mScheduledFor == occurence) 
00342         candidates.push_back(*eit);
00343     }
00344   }
00345 
00346   // choose arbitrarily
00347   if(candidates.size()>1) {
00348     candidate=candidates[ran_uniform_int(0,candidates.size())];
00349   }
00350 
00351   // propose stochastic candidate now
00352   if(candidate>0) {
00353     FD_DS("ProposingExecutor::ProposeNextTransition(): propose by stochastic: " << mSimEvents.Str(candidate) << " for " << tpTime::Str(occurence));
00354     mProposal.Event=candidate;
00355     mProposal.Time=occurence;
00356     return mProposal;
00357   }
00358 
00359   // check if we can pass time
00360   if(!enabledTime.Empty()) {
00361     // pass enabled interval
00362     passtime=enabledInterval.UB();
00363     if(enabledInterval.Empty()) passtime=0;
00364     // be sure to be beyond enabled interval but within enabled time
00365     if(enabledInterval.UBincl()) passtime+=tpTime::Step;
00366     // be sure to be within enabled time
00367     if(!enabledTime.In(passtime)) passtime-=tpTime::Step;
00368     // fix infty
00369     if(enabledTime.UBinf() && enabledInterval.UBinf()) passtime=tpTime::Max;
00370     // if we can go for ever,  step with minstep 
00371     // if(passtime==tpTime::Max) passtime=tpTime::Step; 
00372     // only execute relevant steps -- otherwise max execute priority event
00373     if(passtime!=0) {    
00374       FD_DS("ProposingExecutor::ProposeNextTransition(): propose to pass time: "<< tpTime::Str(passtime));
00375       mProposal.Event=0;
00376       mProposal.Time=passtime;
00377       return mProposal;
00378     }
00379   }
00380 
00381   //check if prevent priority event occurs in analyzed interval 
00382   prio =0;
00383   for(eit=enabledEvents.Begin(); eit!=enabledEvents.End(); ++eit){
00384     SimEventAttribute* pattr= mSimEvents.Attributep(*eit);
00385     if(!pattr->IsPriority()) continue;
00386     // priority wins
00387     if(pattr->Priority().mPriority >prio || prio==0) {
00388       prio= pattr->Priority().mPriority;
00389       candidate=*eit;
00390       candidates.clear();
00391       candidates.push_back(candidate);
00392     }
00393     // alphabetical  
00394     if((pattr->Priority().mPriority ==prio) && (prio <0)) 
00395       candidates.push_back(*eit);
00396   }
00397 
00398   // choose arbitrarily
00399   if(candidates.size()>1) {
00400     candidate=candidates[ran_uniform_int(0,candidates.size())];
00401   }
00402 
00403   // propose prevent priority candidate now
00404   if(candidate>0) {
00405     FD_DS("ProposingExecutor::ProposeNextTransition(): propose by priority: " << mSimEvents.Str(candidate));
00406     mProposal.Event=candidate;
00407     mProposal.Time=passtime;
00408     return mProposal;
00409   }
00410 
00411   //Deadlock request
00412   if(IsDeadlocked()){
00413     FD_DS("ProposingExecutor::ProposeNextTransition(): Deadlocked");
00414     mProposal.Event=0; 
00415     mProposal.Time=tpTime::UnDef;
00416     return mProposal;
00417   }                           
00418 
00419   // nothing to propose but time 
00420   FD_DS("ProposingExecutor::ProposeNextTransition(): Lifelock");
00421   mProposal.Event=0; 
00422   mProposal.Time=tpTime::Step;
00423   return mProposal;
00424 }
00425 
00426 
00427 //ExecuteNextTransition
00428 TimedEvent ProposingExecutor::ExecuteNextTransition(void){
00429   FD_DS("ProposingExecutor::ExecuteNextTransition() *********************************************************** ");
00430 
00431   tpTime::Type currentTime=0;
00432   TimedEvent execTimedEvent;
00433 
00434   //********************************************
00435   //Execution loop
00436   //********************************************
00437   while(true){
00438 
00439     // get proposal
00440     execTimedEvent = ProposeNextTransition();
00441 
00442     // deadlocked? (todo: mintime/min float number etc)
00443     if((execTimedEvent.Event==0) && (execTimedEvent.Time==0)) break;
00444     if(IsDeadlocked()) break;
00445 
00446     // execute (time and/or event)
00447     ExecuteTransition(execTimedEvent);
00448  
00449     // done if there was an event
00450     if(execTimedEvent.Event!=0) break;
00451 
00452     // record time
00453     currentTime+=execTimedEvent.Time;
00454 
00455   }
00456 
00457   // success  
00458   if(execTimedEvent.Event!=0) {
00459      execTimedEvent.Time=currentTime;
00460      return execTimedEvent;
00461   }
00462 
00463   // failure
00464   execTimedEvent.Time=tpTime::UnDef;
00465   execTimedEvent.Event=0;
00466   return execTimedEvent;
00467 }
00468 
00469 
00470 
00471 //Schedule() by attribute
00472 tpTime::Type ProposingExecutor::Schedule(Idx event, SimEventAttribute* pattr) {
00473   FD_DS("ProposingExecutor::Schedule(" << EStr(event) << ")");
00474   // insist in stochastic attribute
00475   if(!pattr->IsStochastic()) {
00476     FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): no stoxchastic attribute found");
00477     pattr->mScheduledFor=tpTime::UnDef;
00478     return tpTime::UnDef;
00479   }
00480   // only reschedule when expired
00481   if(pattr->mExpiresAt>0) {
00482     FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): event not expired");
00483     return pattr->mScheduledFor;
00484   }
00485   // invalidate event state;
00486   tpTime::Type recentschedule=pattr->mScheduledFor;
00487   pattr->mScheduledFor=tpTime::UnDef;
00488   pattr->mExpiresAt=tpTime::UnDef;
00489   pattr->mDelayFor=tpTime::UnDef;
00490   pattr->mReferenceInterval.SetEmpty();
00491   // target interval for sample, defaults to positive axis
00492   TimeInterval atarget;
00493   atarget.SetPositive();
00494   // trigger type events have restricted target
00495   if(pattr->Stochastic().mType == SimStochasticEventAttribute::Trigger) {
00496     atarget.Intersect(EnabledGuardTime(event));
00497     atarget.Canonical();
00498   }
00499   // cannot have empty target
00500   if(atarget.Empty()) {
00501      FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): empty target");
00502      return tpTime::UnDef;
00503   }   
00504   // report timed automaton target
00505   FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): for timed automaton target " << atarget.Str());
00506   // get pdf parameters to figure restricted support 
00507   std::vector<double> pdfparavec=pattr->Stochastic().mParameter;
00508   TimeInterval starget;
00509   starget.LB(static_cast<tpTime::Type>(pdfparavec[0]));
00510   starget.UB(static_cast<tpTime::Type>(pdfparavec[1]));
00511   starget.LBincl(true);
00512   starget.UBincl(false);  
00513   atarget.Intersect(starget);
00514   FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): for restricted target " << atarget.Str());
00515   if(atarget.Empty()) {
00516     FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): empty target");
00517     return tpTime::UnDef;
00518   }
00519   // do the sample
00520   double occtime=-1; 
00521   switch(pattr->Stochastic().mPdf){
00522   // exponential
00523   case SimStochasticEventAttribute::Exponential:
00524     occtime=ran_exponential(pdfparavec[2],atarget.LB(),atarget.UB());
00525     break;
00526   // gauss
00527   case SimStochasticEventAttribute::Gauss:
00528     occtime=ran_gauss(pdfparavec[2],pdfparavec[3],atarget.LB(),atarget.UB());
00529     break;
00530   //Uniform
00531   case SimStochasticEventAttribute::Uniform: 
00532     occtime=ran_uniform(atarget.LB(),atarget.UB());
00533     break;
00534   //Undefined 
00535   case SimStochasticEventAttribute::Vector:
00536     FD_DS("ProposingExecutor::Schedule(" << EStr(event) << ") internal error: no valid stochastic defs");
00537     return tpTime::UnDef;
00538     break;
00539   }
00540   // report failure
00541   if(occtime < 0)  {
00542     FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): sampling failed: A");
00543     return tpTime::UnDef;
00544   }
00545   // discretize tpTime::Type 
00546   long int round= static_cast<unsigned long>(occtime/tpTime::Step + 0.5);     
00547   tpTime::Type schedule = static_cast<tpTime::Type>(round*tpTime::Step);
00548   FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): random sample " << schedule 
00549     << "(" << occtime << ")");
00550   // interpret sample
00551   switch(pattr->Stochastic().mType){
00552   // interpret sample: trigger type
00553   case SimStochasticEventAttribute::Trigger:
00554     // paranoid ... fix rounding issues
00555     if(!atarget.In(schedule)) schedule+=tpTime::Step;
00556     if(!atarget.In(schedule)) schedule-=2*tpTime::Step;
00557     if(!atarget.In(schedule)) schedule= tpTime::UnDef;
00558     // paranoid ... report failure
00559     if(!atarget.In(schedule))  {
00560       FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): sampling failed: B");
00561       return tpTime::UnDef;
00562     }
00563     // set schedule
00564     pattr->mScheduledFor=schedule;
00565     pattr->mExpiresAt=atarget.UB();
00566     pattr->mDelayFor=tpTime::UnDef;
00567     pattr->mReferenceInterval=atarget;
00568     break;   
00569   // interpret sample: extern type // issue: re-sampling can hang
00570   case SimStochasticEventAttribute::Extern:
00571     pattr->mScheduledFor=schedule;
00572     if(recentschedule!=tpTime::UnDef) 
00573       pattr->mScheduledFor+=recentschedule;
00574     pattr->mExpiresAt=pattr->mScheduledFor+1;
00575     pattr->mDelayFor=tpTime::UnDef;
00576     pattr->mReferenceInterval.SetEmpty();
00577     if(pattr->mScheduledFor<0) {   
00578       FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): re-sampling");
00579       return Schedule(event,pattr);
00580     }
00581     break;
00582   // interpret sample: delay type
00583   case SimStochasticEventAttribute::Delay:
00584     TimeInterval etime=EnabledEventTime(event);
00585     etime.Canonical();
00586     FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): delay type: etime " 
00587           << etime.Str() << " delay for " << schedule);
00588     pattr->mDelayFor=schedule;
00589     pattr->mReferenceInterval=etime;
00590     pattr->mScheduledFor=tpTime::UnDef;
00591     pattr->mExpiresAt=tpTime::Max;
00592     schedule+=etime.LB();
00593     if(etime.In(schedule)) {
00594       pattr->mScheduledFor=schedule;
00595       pattr->mExpiresAt=pattr->mScheduledFor+1;
00596     }
00597     return pattr->mScheduledFor;
00598   }
00599   // done
00600   return pattr->mScheduledFor;
00601 }
00602    
00603 
00604 
00605 //DoWrite(rTr,rLabel)
00606 void ProposingExecutor::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
00607   (void) pContext;
00608   std::string label=rLabel;
00609   if(label=="") label = "Executor";
00610   rTw.WriteBegin(label);
00611   ParallelExecutor::DoWriteGenerators(rTw);
00612   Conditions().Write(rTw,"Conditions",this);
00613   mSimEvents.Write(rTw,"SimEvents");
00614   rTw.WriteEnd(label);
00615 }
00616 
00617 //DoRead(rTr,rLabel)
00618 void ProposingExecutor::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
00619   (void) pContext;
00620   FD_DC("ProposingExecutor::DoRead(rTr, " << rLabel<<")");
00621   std::string label=rLabel;
00622   if(label=="") label = "Executor";
00623   rTr.ReadBegin(label);
00624 
00625   while(!rTr.Eos(label)) {
00626     FD_DC("ProposingExecutor::DoRead(rTr, " << rLabel<<"): loop");
00627     // peek token
00628     Token token;
00629     rTr.Peek(token);
00630     // case 1: generators
00631     if(token.Type()==Token::Begin)
00632     if(token.StringValue()=="Generators") {
00633       ParallelExecutor::DoReadGenerators(rTr);
00634       continue;
00635     }
00636     // case 2: conditions
00637     if(token.Type()==Token::Begin)
00638     if(token.StringValue()=="Conditions") {
00639       SimConditionSet conditions;
00640       conditions.Read(rTr,"Conditions",this);
00641       Conditions(conditions);
00642       continue;
00643     }
00644     // case 3: event attributes
00645     if(token.Type()==Token::Begin)
00646     if(token.StringValue()=="SimEvents") {
00647       mSimEvents.Read(rTr,"SimEvents");
00648       continue;
00649     }
00650     // case 3: event attributes (compatibility mode)
00651     if(token.Type()==Token::Begin)
00652     if(token.StringValue()=="SimEventAttributes") {
00653       mSimEvents.Read(rTr,"SimEventAttributes");
00654       continue;
00655     }
00656     // else report error
00657     std::stringstream errstr;
00658     errstr << "Invalid token, generators, conditions or simeventattribute section expected, " << rTr.FileLine();
00659     throw Exception("ProposingExecutor::DoRead", errstr.str(), 502);
00660   }
00661   rTr.ReadEnd(label);
00662   FD_DC("ProposingExecutor::DoRead(rTr, " << rLabel<<"): done");
00663   Reset();
00664 }
00665 
00666 
00667 // revert executors state to past step from buffer
00668 bool ProposingExecutor::RevertToStep(Idx step) {
00669   FD_DX("ProposingExecutor(" << this << ")::RevertToStep("<< step << ")");
00670   // call base
00671   bool res=LoggingExecutor::RevertToStep(step);
00672   // bail out
00673   if(!res) return false;
00674   // reset my dynamic data
00675   ResetProposer();
00676   // done
00677   return true;
00678 }
00679 
00680 } // end namespace
00681 
00682 
00683 
00684 
00685 
00686 /*
00687       Scratch: how to record relevant clocks in Schedule()
00688       This might be interesting to sense resets that invalidate delay type events
00689 
00690       // record relevant clocks
00691       pattr->mRelevantClocks.Clear();
00692       for(Iterator git=Begin(); git!=End(); git++){ 
00693         pattr->mRelevantClocks.InsertSet(git->Generator().Invariant(git->CurrentState()).ActiveClocks());
00694         TransSet::Iterator tit = git->Generator().TransRelBegin(git->CurrentState(),*eit);
00695         pattr->mRelevantClocks.InsertSet(git->Generator().Guard(*tit).ActiveClocks());
00696       }
00697       FD_DS("ProposingExecutor::ExecuteEvent(): relevant clocks " << pattr->mRelevantClocks.ToString());
00698 
00699 */
00700 
00701 
00702 
00703 
00704 /*
00705       Scratch: how to figure whether relevant clocks, guards, or invariants changed
00706       This was required for the old internal type events. Depreciated.
00707 
00708 
00709 //EventValidity(Idx, Idx, T_state_vec, T_state_vec) 
00710 bool ProposingExecutor::EventValidity(Idx ev, Idx executedEvent, 
00711       const ParallelState& oldStateVec, const ParallelState& newStateVec) {
00712   unsigned int i=0;
00713   Iterator xit;
00714   TransSet::Iterator tit;
00715   TimeConstraint::Iterator oldcit,newcit;
00716   ClockSet::Iterator clit;
00717   ClockSet* pclocks = &mSimEvents.Attributep(ev)->mRelevantClocks;
00718 
00719   //Check if event was indeed active and is is still active
00720   if(!Active(ev, oldStateVec)){ 
00721     FD_DS("ProposingExecutor::EventValidity(): Event "<<Alphabet().SymbolicName(ev)
00722          << " has not been active in last parallel state");
00723     return false;
00724   }
00725   if(!Active(ev, newStateVec)){ 
00726     FD_DS("ProposingExecutor::EventValidity(): Event "<<Alphabet().SymbolicName(ev)
00727              <<" is not active in current parallel state");
00728     return false;
00729   }
00730 
00731 
00732   //Check if relevant clocks are affected
00733   FD_DS("ProposingExecutor::EventValidity(): test clocks for " << Alphabet().Str(ev));
00734 
00735   for(xit=Begin(); xit!=End(); ++xit, i++){
00736     // If this excutor did not execute anything, nothing changed at all
00737     if(!xit->Generator().ExistsEvent(executedEvent)) continue;  
00738     // If this excutor does not share the event, no guards/invs/resets affects its enabled status
00739     if(!xit->Generator().ExistsEvent(ev)) continue; 
00740     //Check if a reset of a relevant clock was executed
00741     tit=xit->Generator().TransRelBegin(oldStateVec[i],executedEvent); 
00742     FD_DS("ProposingExecutor::EventValidity(): test resets of " << Generator().TStr(*tit));
00743     const ClockSet resetClocks=xit->Generator().Resets(*tit);
00744     if(!(resetClocks * (*pclocks)).Empty()) {
00745       FD_DS("ProposingExecutor::EventValidity(): relevant clock reset in " << xit->Name());
00746       return false;
00747     }
00748     // If the state didnt change, neither did guards/invariants
00749     if(oldStateVec[i]==newStateVec[i]) continue;  
00750     //Check if guards have changed wrt relevant clocks
00751     tit=xit->Generator().TransRelBegin(oldStateVec[i],ev);
00752     FD_DS("ProposingExecutor::EventValidity(): compare old guard of " << Generator().TStr(*tit));
00753     TimeConstraint oldGuard=xit->Generator().Guard(*tit);
00754     tit=xit->Generator().TransRelBegin(newStateVec[i],ev);
00755     FD_DS("ProposingExecutor::EventValidity(): ... with guard of " << Generator().TStr(*tit));
00756     TimeConstraint newGuard=xit->Generator().Guard(*tit);
00757     for(ClockSet::Iterator cit=pclocks->Begin(); cit!=pclocks->End(); cit++) {
00758       if(oldGuard.Interval(*cit)!=newGuard.Interval(*cit)) { 
00759         FD_DS("ProposingExecutor::EventValidity(): invalidate for change in guard wrt clock " << 
00760           pclocks->SymbolicName(*cit));
00761         FD_DS("ProposingExecutor::EventValidity(): old guard " << oldGuard.ToString());
00762         FD_DS("ProposingExecutor::EventValidity(): new guard " << newGuard.ToString());
00763         return false;
00764       }
00765     }
00766     //Check if invariants have changed
00767     TimeConstraint oldInv=xit->Generator().Invariant(oldStateVec[i]);
00768     TimeConstraint newInv=xit->Generator().Invariant(newStateVec[i]);
00769     for(ClockSet::Iterator cit=pclocks->Begin(); cit!=pclocks->End(); cit++) {
00770       if( oldInv.Interval(*cit)!=newInv.Interval(*cit)) { 
00771         FD_DS("ProposingExecutor::EventValidity(): invalidate for change in invariant wrt clock " << 
00772           pclocks->SymbolicName(*cit));
00773         FD_DS("ProposingExecutor::EventValidity(): old inv " << oldInv.ToString());
00774         FD_DS("ProposingExecutor::EventValidity(): new inv " << newInv.ToString());
00775         return false;
00776       }
00777     }
00778   } // loop all generators
00779   FD_DS("ProposingExecutor::EventValidity(): Event " << Alphabet().SymbolicName(ev)<< " is still valid"); 
00780   return true;
00781 }
00782 
00783 */
00784 
00785 
00786 
00787 
00788 
00789 
00790 

libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen