sp_executor.cppGo 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 |