sp_executor.cpp

Go to the documentation of this file.
00001 /** @file sp_executor.cpp Execute transitions in a timed generator  */
00002 
00003 /* 
00004    FAU Discrete Event Systems Library (libfaudes)
00005 
00006    Copyright (C) 2007  Ruediger Berndt
00007    Copyright (C) 2007  Thomas Moor
00008    Exclusive copyright is granted to Klaus Schmidt
00009   
00010 */
00011 
00012 
00013 #include "sp_executor.h"
00014 
00015 namespace faudes {
00016 
00017 // std faudes type
00018 FAUDES_TYPE_IMPLEMENTATION(Executor,Executor,TimedGenerator)
00019 
00020 
00021 // Executor(void)
00022 Executor::Executor(void) : TimedGenerator() {
00023   FD_DX("Executor(" << this << ")::Executor()");
00024   InsInitState("init");
00025   Compile();
00026 }
00027 
00028 // Exector(rGen)
00029 Executor::Executor(const TimedGenerator& rGen) : TimedGenerator() {
00030   FD_DX("Executor(" << this << ")::Executor(rGen)");
00031   Assign(rGen);
00032 }  
00033 
00034 // Exector(filename)
00035 Executor::Executor(const std::string& rFileName) : TimedGenerator() {
00036   FD_DX("Executor(" << this << ")::Executor("<< rFileName <<")");
00037   Read(rFileName);
00038 }  
00039 
00040 // Generator()
00041 const TimedGenerator& Executor::Generator(void) const{
00042   return *this;
00043 }
00044 
00045 // Generator(rGen)
00046 void Executor::Generator(const TimedGenerator& rGen) {
00047   FD_DX("Executor::Generator(" << &rGen << ")");
00048   Assign(*this);
00049 }  
00050 
00051 
00052 // Compile()
00053 void Executor::Compile(void) {
00054   FD_DX("Executor(" << this << ")::Compile()");
00055   // throw exception on non deterministic generator
00056   if(!IsDeterministic() || InitState()==0) {
00057     std::stringstream errstr;
00058     errstr << "nondeterministic generator in simulation" << std::endl;
00059     throw Exception("Executor::Compile", errstr.str(), 501);
00060   }
00061   // compile guards
00062   TransSet::Iterator tit;
00063   for(tit=TransRelBegin(); tit!= TransRelEnd(); tit++) {
00064     FD_DX("Executor(" << this << ")::Compile(): trans " << TStr(*tit));
00065     TimeConstraint guard=Guard(*tit);
00066     std::map<Idx,TimeInterval> guardtime;
00067     ClockSet aclocks=guard.ActiveClocks();
00068     ClockSet::Iterator cit;
00069     for(cit=aclocks.Begin(); cit!= aclocks.End(); cit++) 
00070       guardtime[*cit]=guard.Interval(*cit);
00071     mTransClockIntervalMap[*tit]=guardtime;
00072   }
00073   // compile invariants
00074   StateSet::Iterator sit;
00075   for(sit=StatesBegin(); sit!= StatesEnd(); sit++) {
00076     FD_DX("Executor(" << this << ")::Compile(): state " << SStr(*sit));
00077     TimeConstraint invariant=Invariant(*sit);
00078     std::map<Idx,TimeInterval> invtime;
00079     ClockSet aclocks=invariant.ActiveClocks();
00080     ClockSet::Iterator cit;
00081     for(cit=aclocks.Begin(); cit!= aclocks.End(); cit++) 
00082       invtime[*cit]=invariant.Interval(*cit);
00083     mStateClockIntervalMap[*sit]=invtime;
00084   }
00085   // get ready
00086   Reset();
00087   FD_DX("Executor(" << this << ")::Compile(): done");
00088 }
00089 
00090 // Clear()
00091 void Executor::Clear(void) {
00092   FD_DX("Executor(" << this << ")::Clear(): invalid executor");
00093   TimedGenerator::Clear();
00094   mCurrentTimedState.State=0;
00095   mCurrentTimedState.ClockValue.clear();
00096   mCurrentTime=0;
00097   mCurrentStep=0;
00098   mEValid=false;
00099 }
00100 
00101 // Reset()
00102 void Executor::Reset(void) {
00103   mCurrentTimedState.State=*InitStatesBegin();
00104   mCurrentTimedState.ClockValue.clear();
00105   ClockSet::Iterator cit;
00106   for(cit=GlobalAttribute().mClocks.Begin(); cit!=GlobalAttribute().mClocks.End(); cit++)
00107     mCurrentTimedState.ClockValue[*cit]=0;
00108   mCurrentTime=0;
00109   mCurrentStep=0;
00110   mEValid=false;
00111 }
00112 
00113 
00114 // DoRead(rTr)
00115 void Executor::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
00116   FD_DX("Executor(" << this << ")::DoRead(rTr)");
00117   TimedGenerator::DoRead(rTr,rLabel,pContext);
00118   Compile();
00119 }  
00120 
00121 // DoWrite(rTr)
00122 void Executor::DoWrite(TokenWriter& rTw,const std::string& rLabel, const Type* pContext) const {
00123   FD_DX("Executor(" << this << ")::DoWrite(rTw)");
00124   TimedGenerator::DoWrite(rTw,rLabel,pContext);
00125 }
00126 
00127 // DoAssign
00128 void Executor::DoAssign(const Executor& rSrc) {
00129   // call base
00130   TimedGenerator::DoAssign(rSrc);
00131   // fox my data
00132   Compile();
00133 }
00134 
00135 
00136 
00137 // ComputeEnabled() fake const
00138 void Executor::ComputeEnabled(void) const {
00139   Executor* fakeconst = const_cast<Executor*>(this);
00140   fakeconst->ComputeEnabledNonConst();
00141 }
00142 
00143 // ComputeEnabledNoneConst()
00144 void Executor::ComputeEnabledNonConst(void) {
00145   FD_DX("Executor(" << this << ")::ComputeEnabled()");
00146   // time is up: clear all
00147   if(mCurrentTime>=tpTime::Max) {
00148     mAEvents.Clear();
00149     mATrans.Clear();
00150     mETime.SetEmpty();
00151     mEInterval.SetEmpty();
00152     mEEvents.Clear();
00153     mDEvents=Alphabet();
00154     mEGuardInterval.clear();
00155     mEValid=true;
00156     FD_DX("Executor(" << this << ")::ComputeEnabled(): time is up");
00157     return;
00158   }
00159   // set active events/transitions
00160   mAEvents= TimedGenerator::ActiveEventSet(mCurrentTimedState.State);
00161   mATrans=  TimedGenerator::ActiveTransSet(mCurrentTimedState.State);
00162   // hypothesis: all time can pass [0,inf)
00163   mETime.SetPositive();
00164   mEInterval.SetPositive();
00165   // hypothesis: no events can occur
00166   mEEvents.Clear();
00167   mDEvents=Alphabet();
00168   mEGuardInterval.clear();
00169   // inspect invariant to restrict enabled time
00170   std::map<Idx,TimeInterval> clockintervalmap=mStateClockIntervalMap[mCurrentTimedState.State];
00171   std::map<Idx,TimeInterval>::const_iterator cit;
00172   for(cit=clockintervalmap.begin(); cit!=clockintervalmap.end(); cit++) {
00173     Idx clock =  cit-> first;
00174     tpTime::Type clockvalue = mCurrentTimedState.ClockValue[clock];
00175     TimeInterval interval = cit->second;
00176     // if a clock violates an invariant constraint return deadlock
00177     if(! interval.In( clockvalue ) ) {
00178       FD_DX("Executor(" << this << ")::ComputeEnabled(): clock " << CStr(cit->first) 
00179         << " at " <<  clockvalue << " violates invariant condition " << interval.Str() );
00180       mETime.SetEmpty();
00181       mEValid=true; 
00182       return;
00183     }
00184     // left shift interval by clock value to obtain an interval relative to current time
00185     interval.PositiveLeftShift(clockvalue);
00186     // intersect with enabled time
00187     mETime.Intersect(interval);
00188   }
00189   FD_DX("Executor(" << this << ")::ComputeEnabled(): invariant is satisfied for " 
00190      << mETime.Str() );
00191   // no events for all time that can pass to begin with ...
00192   mEEvents.Clear();
00193   mEEvents.Name("EnabledEvents");
00194   mDEvents=Alphabet();
00195   mDEvents.Name("DisabledEvents");
00196   mEInterval=mETime;
00197   // iterate over all transitions and check guards
00198   TransSet::Iterator tit;
00199   for(tit=mATrans.Begin(); tit!= mATrans.End(); tit++) {
00200     // hypothesis: transition is enabled for all time
00201     bool enabled=true;
00202     TimeInterval enabledtime;
00203     enabledtime.SetPositive(); 
00204     // check all clocks
00205     std::map<Idx,TimeInterval> clockintervalmap=mTransClockIntervalMap[*tit];
00206     std::map<Idx,TimeInterval>::const_iterator cit;
00207     for(cit=clockintervalmap.begin(); cit!=clockintervalmap.end(); cit++) {
00208       Idx clock =  cit->first;
00209       tpTime::Type clockvalue = mCurrentTimedState.ClockValue[clock];
00210       TimeInterval interval = cit->second;
00211       // reject transition if a clock violates a guard constraint
00212       if(!  interval.In(clockvalue) ) enabled=false;
00213       // left shift interval by clock value to obtain an interval relative to current time
00214       interval.PositiveLeftShift(clockvalue);
00215       // intersect with enabled interval
00216       enabledtime.Intersect(interval);
00217     }
00218     // record guard interval
00219     mEGuardInterval[tit->Ev]=enabledtime;
00220     // intersect with invariant
00221     enabledtime.Intersect(mETime);
00222     // intersect with time hypothesis
00223     if(enabled) {
00224       // easy: intersect enabledtime with mEInterval  
00225       FD_DX("Executor(" << this << ")::ComputeEnabled(): event " << EStr(tit->Ev) 
00226          << " is enabled for " << enabledtime.Str());
00227       mEEvents.Insert(tit->Ev);
00228       mDEvents.Erase(tit->Ev);
00229       mEInterval.Intersect(enabledtime);
00230     } else {
00231       // first compute disabledtime, then intersect
00232       TimeInterval disabledtime;
00233       disabledtime.SetPositive();
00234       if(!enabledtime.Empty()) {
00235         disabledtime.UB(enabledtime.LB());
00236         disabledtime.UBincl(!enabledtime.LBincl());
00237       }
00238       FD_DX("Executor(" << this << ")::ComputeEnabled(): event " << EStr(tit->Ev) 
00239       << " is disabled for " << disabledtime.Str() << " and enabled for " << enabledtime.Str());
00240       mEInterval.Intersect(disabledtime);
00241     }
00242   }  // loop transitions
00243   FD_DX("Executor(" << this << ")::ComputeEnabled(): e/d status constant on "
00244     << mEInterval.Str() );    
00245   mEValid=true; 
00246 }
00247 
00248 // EnabledTime(void)  
00249 const TimeInterval& Executor::EnabledTime(void) const {
00250   if(!mEValid) ComputeEnabled();
00251   return mETime;
00252 }
00253 
00254 // EnabledEvents(void)  
00255 const EventSet& Executor::EnabledEvents(void) const {
00256   if(!mEValid) ComputeEnabled();
00257   return mEEvents;
00258 }
00259 
00260 // DisabledEvents(void)  
00261 const EventSet& Executor::DisabledEvents(void) const {
00262   if(!mEValid) ComputeEnabled();
00263   return mDEvents;
00264 }
00265 
00266 // EnabledInterval(void)  
00267 const TimeInterval& Executor::EnabledInterval(void) const {
00268   if(!mEValid) ComputeEnabled();
00269   return mEInterval;
00270 }
00271 
00272 // ActiveEventSet(void)  
00273 const EventSet& Executor::ActiveEventSet(void) const {
00274   if(!mEValid) ComputeEnabled();
00275   return mAEvents;
00276 }
00277 
00278 // ActiveTransSet(void)  
00279 const TransSet& Executor::ActiveTransSet(void) const {
00280   if(!mEValid) ComputeEnabled();
00281   return mATrans;
00282 }
00283 
00284 // EnabledEventInterval(event)   
00285 TimeInterval Executor::EnabledEventTime(Idx event) const {
00286   if(!mEValid) ComputeEnabled();
00287   TimeInterval res;  
00288   std::map<Idx,TimeInterval>::const_iterator eit;
00289   eit=mEGuardInterval.find(event);
00290   if(eit!= mEGuardInterval.end()) {
00291     res = eit->second;
00292     res.Intersect(mETime);
00293     return res;
00294   }
00295   if(Alphabet().Exists(event)) {
00296      res.SetEmpty();
00297      return res;
00298   }
00299   res.SetPositive();
00300   return res;
00301 }
00302 
00303 // EnabledGuardInterval(event)   
00304 TimeInterval Executor::EnabledGuardTime(Idx event) const {
00305   if(!mEValid) ComputeEnabled();
00306   std::map<Idx,TimeInterval>::const_iterator eit;
00307   eit=mEGuardInterval.find(event);
00308   if(eit!= mEGuardInterval.end()) return eit->second;
00309   TimeInterval res;  
00310   res.SetEmpty();
00311   if(Alphabet().Exists(event)) return res;
00312   res.SetPositive();
00313   return res;
00314 }
00315 
00316 // ExecuteTime(time) 
00317 bool Executor::ExecuteTime(tpTime::Type time) {
00318   if(mCurrentTime>=tpTime::Max) return false;
00319   if(!mEValid) ComputeEnabled();
00320   if(!mETime.In(time) && !((time==tpTime::Max) && mETime.UBinf()) ) {
00321     FD_DX("Executor(" << this << ")::ExecuteTime: execution of  " << time 
00322        << " conflicts with enabled status " );
00323     return false; 
00324   }
00325   FD_DX("Executor(" << this << ")::ExecuteTime(" << time << ")");
00326   // progress current time
00327   mCurrentTime += time;
00328   // progres clocks
00329   ClockSet::Iterator cit;
00330   for(cit=ClocksBegin(); cit!=ClocksEnd(); cit++) 
00331     mCurrentTimedState.ClockValue[*cit]= mCurrentTimedState.ClockValue[*cit]+time;  
00332   // fix infinity
00333   if(time==tpTime::Max) {
00334     mCurrentTime=tpTime::Max;
00335     for(cit=ClocksBegin(); cit!=ClocksEnd(); cit++) 
00336       mCurrentTimedState.ClockValue[*cit]= tpTime::Max;
00337     mEValid=false;
00338   }  
00339   // progress enabled interval or invalidate enabled status 
00340   if(mEInterval.In(time) && mEValid) {
00341     mEInterval.PositiveLeftShift(time);
00342     mETime.PositiveLeftShift(time);
00343     std::map<Idx,TimeInterval>::iterator iit;
00344     for(iit=mEGuardInterval.begin();iit != mEGuardInterval.end(); iit++) {
00345       iit->second.PositiveLeftShift(time);
00346     }
00347   } else {
00348     mEValid=false;
00349   }
00350   return true;
00351 }
00352 
00353 // ExecuteEvent(event) 
00354 bool Executor::ExecuteEvent(Idx event) {
00355   if(mCurrentTime>=tpTime::Max) return false;
00356   if(!mEValid) ComputeEnabled();
00357   if(!mEEvents.Exists(event)) {
00358     FD_DX("Executor(" << this << ")::ExecuteEvent: execution of event " << EStr(event) 
00359        << " conflicts with enabled status " );
00360     return false; 
00361   }
00362   FD_DX("Executor(" << this << ")::ExecuteEvent(" << EStr(event) << ")");
00363   // pick transition
00364   TransSet::Iterator tit=TransRelBegin(mCurrentTimedState.State,event);
00365   // TODO: invalid iterator error     
00366   // execute resets
00367   ClockSet resets=Resets(*tit);
00368   ClockSet::Iterator cit;
00369   for(cit = resets.Begin(); cit!=resets.End(); cit++) 
00370     mCurrentTimedState.ClockValue[*cit]=0;
00371   // progress state
00372   mCurrentTimedState.State=tit->X2;
00373   // progress current time
00374   mCurrentStep += 1;
00375   // invalidate
00376   mEValid=false;
00377   return true;
00378 }  
00379 
00380 
00381 // CurrentTimedState(tstate)
00382 bool Executor::CurrentTimedState(const TimedState& tstate) {
00383   // test consitency
00384   if(!ExistsState(tstate.State)) return false;
00385   if(tstate.ClockValue.size()!=ClocksSize()) return false;
00386   std::map<Idx,tpTime::Type>::const_iterator cvit;
00387   for(cvit=tstate.ClockValue.begin(); cvit!=tstate.ClockValue.end(); cvit++)
00388     if(!ExistsClock(cvit->first)) return false;
00389   // set state
00390   mCurrentTimedState=tstate;
00391   mEValid=false;
00392   return true; 
00393 }
00394   
00395 // CurrentTimedState()
00396 const Executor::TimedState& Executor::CurrentTimedState(void) const {
00397   return mCurrentTimedState;
00398 }
00399   
00400 // CurrentState(idx)
00401 bool Executor::CurrentState(Idx index) {
00402   if(!ExistsState(index)) return false;
00403   mCurrentTimedState.State=index;
00404   mEValid=false;
00405   return true;
00406 }
00407   
00408 // CurrentState()
00409 Idx Executor::CurrentState(void) const {
00410   return mCurrentTimedState.State;
00411 }
00412   
00413 // CurrentClockValue(idx,time)
00414 bool Executor::CurrentClockValue(Idx index, tpTime::Type time) {
00415   if(!ExistsClock(index)) return false;
00416   mCurrentTimedState.ClockValue[index]=time;
00417   mEValid=false;
00418   return true;
00419 }
00420   
00421 // CurrentClockValue(idx)
00422 tpTime::Type Executor::CurrentClockValue(Idx index) const {
00423   std::map<Idx,tpTime::Type>::const_iterator cvit;
00424   cvit=mCurrentTimedState.ClockValue.find(index);
00425   if(cvit==mCurrentTimedState.ClockValue.end()) {}; // todo: error
00426   return cvit->second;
00427 }
00428   
00429 // CurrentTime(time)
00430 void Executor::CurrentTime(tpTime::Type time) {
00431   mCurrentTime=time;
00432   mEValid=false;
00433 }
00434   
00435 // CurrentTime()
00436 tpTime::Type Executor::CurrentTime(void) const {
00437   return mCurrentTime;
00438 }
00439   
00440 // CurrentStep(time)
00441 void Executor::CurrentStep(int step) {
00442   mCurrentStep=step;
00443   mEValid=false;
00444 }
00445   
00446 // CurrentStep()
00447 int Executor::CurrentStep(void) const {
00448   return mCurrentStep;
00449 }
00450   
00451 // IsDeadlocked() 
00452 bool Executor::IsDeadlocked(void) const {
00453   if(!mEValid) ComputeEnabled();
00454   if(!mEEvents.Empty()) return false;
00455   if(!(mETime.UB()<=0)) return false;
00456   return true;
00457 }
00458 
00459 // TSStr(tstate)
00460 std::string Executor::TSStr(const TimedState& tstate) const {
00461   std::stringstream res;
00462   res << "(state " << SStr(tstate.State); 
00463   if(Generator().ExistsMarkedState(tstate.State))  res << " [marked]";
00464   res << ")  (clocks";
00465   ClockSet::Iterator cit;
00466   for(cit=ClocksBegin();cit!=ClocksEnd();cit++){
00467     res << " " << CStr(*cit) << "=";
00468     std::map<Idx,tpTime::Type>::const_iterator cvit=tstate.ClockValue.find(*cit);
00469     if(cvit!=tstate.ClockValue.end()) 
00470       res << cvit->second;
00471     else
00472       res << "undef";
00473   }
00474   res << ")";
00475   return res.str();
00476 }
00477 
00478 // CurrentTimedStateStr()
00479 std::string Executor::CurrentTimedStateStr(void) const {
00480   return TSStr(mCurrentTimedState);
00481 }
00482 
00483 // TEStr(tevent)
00484 std::string Executor::TEStr(const TimedEvent& tevent) const {
00485   std::stringstream res;
00486   res << "(" << EStr(tevent.Event) << " at " << tevent.Time << ")";
00487   return res.str();
00488 }
00489 
00490 // EStr(event)
00491 std::string Executor::EStr(Idx event) const {
00492   return TimedGenerator::EStr(event);
00493 }
00494 
00495 // CStr(clock)
00496 std::string Executor::CStr(Idx clock) const {
00497   return TimedGenerator::CStr(clock);
00498 }
00499 
00500 // SStr(clock)
00501 std::string Executor::SStr(Idx state) const {
00502   return TimedGenerator::SStr(state);
00503 }
00504 
00505 
00506 } // namespace faudes
00507 
00508 

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