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