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