libFAUDES

Sections

Index

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

libFAUDES 2.16b --- 2010-9-8 --- c++ source docu by doxygen 1.6.3