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