sp_executor.cpp
Go to the documentation of this file.
1/** @file sp_executor.cpp Execute transitions in a timed generator */
2
3/*
4 FAU Discrete Event Systems Library (libfaudes)
5
6 Copyright (C) 2007 Ruediger Berndt
7 Copyright (C) 2007, 2010, 2024 Thomas Moor
8 Exclusive copyright is granted to Klaus Schmidt
9
10*/
11
12
13#include "sp_executor.h"
14
15namespace faudes {
16
17// std faudes type
19
20
21// Executor(void)
23 FD_DX("Executor(" << this << ")::Executor()");
24 InsInitState("init");
25 Compile();
26}
27
28// Executor(Executor)
30 FD_DX("Executor(" << this << ")::Executor(other)");
31 DoCopy(rOther);
32 Compile();
33}
34
35// Exector(rGen)
37 FD_DX("Executor(" << this << ")::Executor(rGen)");
38 Copy(rGen);
39}
40
41// Exector(filename)
42Executor::Executor(const std::string& rFileName) : TimedGenerator() {
43 FD_DX("Executor(" << this << ")::Executor("<< rFileName <<")");
44 Read(rFileName);
45}
46
47// Generator()
49 return *this;
50}
51
52// Generator(rGen)
54 FD_DX("Executor::Generator(" << &rGen << ")");
55 Copy(*this);
56}
57
58
59// Compile()
61 FD_DX("Executor(" << this << ")::Compile()");
62 // throw exception on non deterministic generator
63 if(!IsDeterministic() || InitState()==0) {
64 std::stringstream errstr;
65 errstr << "nondeterministic generator in simulation" << std::endl;
66 throw Exception("Executor::Compile", errstr.str(), 501);
67 }
68 // compile guards
70 for(tit=TransRelBegin(); tit!= TransRelEnd(); tit++) {
71 FD_DX("Executor(" << this << ")::Compile(): trans " << TStr(*tit));
72 TimeConstraint guard=Guard(*tit);
73 std::map<Idx,TimeInterval> guardtime;
74 ClockSet aclocks=guard.ActiveClocks();
75 ClockSet::Iterator cit;
76 for(cit=aclocks.Begin(); cit!= aclocks.End(); cit++)
77 guardtime[*cit]=guard.Interval(*cit);
78 mTransClockIntervalMap[*tit]=guardtime;
79 }
80 // compile invariants
81 StateSet::Iterator sit;
82 for(sit=StatesBegin(); sit!= StatesEnd(); sit++) {
83 FD_DX("Executor(" << this << ")::Compile(): state " << SStr(*sit));
84 TimeConstraint invariant=Invariant(*sit);
85 std::map<Idx,TimeInterval> invtime;
86 ClockSet aclocks=invariant.ActiveClocks();
87 ClockSet::Iterator cit;
88 for(cit=aclocks.Begin(); cit!= aclocks.End(); cit++)
89 invtime[*cit]=invariant.Interval(*cit);
90 mStateClockIntervalMap[*sit]=invtime;
91 }
92 // get ready
93 Reset();
94 FD_DX("Executor(" << this << ")::Compile(): done");
95}
96
97// Clear()
98void Executor::Clear(void) {
99 FD_DX("Executor(" << this << ")::Clear(): invalid executor");
103 mCurrentTime=0;
104 mCurrentStep=0;
105 mEValid=false;
106}
107
108// Reset()
109void Executor::Reset(void) {
112 ClockSet::Iterator cit;
113 for(cit=GlobalAttribute().mClocks.Begin(); cit!=GlobalAttribute().mClocks.End(); cit++)
115 mCurrentTime=0;
116 mCurrentStep=0;
117 mEValid=false;
118}
119
120
121// DoRead(rTr)
122void Executor::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
123 FD_DX("Executor(" << this << ")::DoRead(rTr)");
124 TimedGenerator::DoRead(rTr,rLabel,pContext);
125 Compile();
126}
127
128// DoWrite(rTr)
129void Executor::DoWrite(TokenWriter& rTw,const std::string& rLabel, const Type* pContext) const {
130 FD_DX("Executor(" << this << ")::DoWrite(rTw)");
131 TimedGenerator::DoWrite(rTw,rLabel,pContext);
132}
133
134// DoCopy
135void Executor::DoCopy(const Executor& rSrc) {
136 // call base
138 // fix my data
139 Compile();
140}
141
142// DoMove
144 // call base
146 // fox my data
147 Compile();
148}
149
150
151
152// ComputeEnabled() fake const
153void Executor::ComputeEnabled(void) const {
154 Executor* fakeconst = const_cast<Executor*>(this);
155 fakeconst->ComputeEnabledNonConst();
156}
157
158// ComputeEnabledNoneConst()
160 FD_DX("Executor(" << this << ")::ComputeEnabled()");
161 // time is up: clear all
162 if(mCurrentTime>=Time::Max()) {
163 mAEvents.Clear();
164 mATrans.Clear();
167 mEEvents.Clear();
169 mEGuardInterval.clear();
170 mEValid=true;
171 FD_DX("Executor(" << this << ")::ComputeEnabled(): time is up");
172 return;
173 }
174 // set active events/transitions
177 // hypothesis: all time can pass [0,inf)
180 // hypothesis: no events can occur
181 mEEvents.Clear();
183 mEGuardInterval.clear();
184 // inspect invariant to restrict enabled time
185 std::map<Idx,TimeInterval> clockintervalmap=mStateClockIntervalMap[mCurrentTimedState.State];
186 std::map<Idx,TimeInterval>::const_iterator cit;
187 for(cit=clockintervalmap.begin(); cit!=clockintervalmap.end(); cit++) {
188 Idx clock = cit-> first;
189 Time::Type clockvalue = mCurrentTimedState.ClockValue[clock];
190 TimeInterval interval = cit->second;
191 // if a clock violates an invariant constraint return deadlock
192 if(! interval.In( clockvalue ) ) {
193 FD_DX("Executor(" << this << ")::ComputeEnabled(): clock " << CStr(cit->first)
194 << " at " << clockvalue << " violates invariant condition " << interval.Str() );
196 mEValid=true;
197 return;
198 }
199 // left shift interval by clock value to obtain an interval relative to current time
200 interval.PositiveLeftShift(clockvalue);
201 // intersect with enabled time
202 mETime.Intersect(interval);
203 }
204 FD_DX("Executor(" << this << ")::ComputeEnabled(): invariant is satisfied for "
205 << mETime.Str() );
206 // no events for all time that can pass to begin with ...
207 mEEvents.Clear();
208 mEEvents.Name("EnabledEvents");
210 mDEvents.Name("DisabledEvents");
212 // iterate over all transitions and check guards
214 for(tit=mATrans.Begin(); tit!= mATrans.End(); tit++) {
215 // hypothesis: transition is enabled for all time
216 bool enabled=true;
217 TimeInterval enabledtime;
218 enabledtime.SetPositive();
219 // check all clocks
220 std::map<Idx,TimeInterval> clockintervalmap=mTransClockIntervalMap[*tit];
221 std::map<Idx,TimeInterval>::const_iterator cit;
222 for(cit=clockintervalmap.begin(); cit!=clockintervalmap.end(); cit++) {
223 Idx clock = cit->first;
224 Time::Type clockvalue = mCurrentTimedState.ClockValue[clock];
225 TimeInterval interval = cit->second;
226 // reject transition if a clock violates a guard constraint
227 if(! interval.In(clockvalue) ) enabled=false;
228 // left shift interval by clock value to obtain an interval relative to current time
229 interval.PositiveLeftShift(clockvalue);
230 // intersect with enabled interval
231 enabledtime.Intersect(interval);
232 }
233 // record guard interval
234 mEGuardInterval[tit->Ev]=enabledtime;
235 // intersect with invariant
236 enabledtime.Intersect(mETime);
237 // intersect with time hypothesis
238 if(enabled) {
239 // easy: intersect enabledtime with mEInterval
240 FD_DX("Executor(" << this << ")::ComputeEnabled(): event " << EStr(tit->Ev)
241 << " is enabled for " << enabledtime.Str());
242 mEEvents.Insert(tit->Ev);
243 mDEvents.Erase(tit->Ev);
244 mEInterval.Intersect(enabledtime);
245 } else {
246 // first compute disabledtime, then intersect
247 TimeInterval disabledtime;
248 disabledtime.SetPositive();
249 if(!enabledtime.Empty()) {
250 disabledtime.UB(enabledtime.LB());
251 disabledtime.UBincl(!enabledtime.LBincl());
252 }
253 FD_DX("Executor(" << this << ")::ComputeEnabled(): event " << EStr(tit->Ev)
254 << " is disabled for " << disabledtime.Str() << " and enabled for " << enabledtime.Str());
255 mEInterval.Intersect(disabledtime);
256 }
257 } // loop transitions
258 FD_DX("Executor(" << this << ")::ComputeEnabled(): e/d status constant on "
259 << mEInterval.Str() );
260 mEValid=true;
261}
262
263// EnabledTime(void)
265 if(!mEValid) ComputeEnabled();
266 return mETime;
267}
268
269// EnabledEvents(void)
271 if(!mEValid) ComputeEnabled();
272 return mEEvents;
273}
274
275// DisabledEvents(void)
277 if(!mEValid) ComputeEnabled();
278 return mDEvents;
279}
280
281// EnabledInterval(void)
283 if(!mEValid) ComputeEnabled();
284 return mEInterval;
285}
286
287// ActiveEventSet(void)
289 if(!mEValid) ComputeEnabled();
290 return mAEvents;
291}
292
293// ActiveTransSet(void)
295 if(!mEValid) ComputeEnabled();
296 return mATrans;
297}
298
299// EnabledEventInterval(event)
301 if(!mEValid) ComputeEnabled();
302 TimeInterval res;
303 std::map<Idx,TimeInterval>::const_iterator eit;
304 eit=mEGuardInterval.find(event);
305 if(eit!= mEGuardInterval.end()) {
306 res = eit->second;
307 res.Intersect(mETime);
308 return res;
309 }
310 if(Alphabet().Exists(event)) {
311 res.SetEmpty();
312 return res;
313 }
314 res.SetPositive();
315 return res;
316}
317
318// EnabledGuardInterval(event)
320 if(!mEValid) ComputeEnabled();
321 std::map<Idx,TimeInterval>::const_iterator eit;
322 eit=mEGuardInterval.find(event);
323 if(eit!= mEGuardInterval.end()) return eit->second;
324 TimeInterval res;
325 res.SetEmpty();
326 if(Alphabet().Exists(event)) return res;
327 res.SetPositive();
328 return res;
329}
330
331// ExecuteTime(time)
333 if(mCurrentTime>=Time::Max()) return false;
334 if(!mEValid) ComputeEnabled();
335 if(!mETime.In(time) && !((time==Time::Max()) && mETime.UBinf()) ) {
336 FD_DX("Executor(" << this << ")::ExecuteTime: execution of " << time
337 << " conflicts with enabled status " );
338 return false;
339 }
340 FD_DX("Executor(" << this << ")::ExecuteTime(" << time << ")");
341 // progress current time
342 mCurrentTime += time;
343 // progres clocks
344 ClockSet::Iterator cit;
345 for(cit=ClocksBegin(); cit!=ClocksEnd(); cit++)
347 // fix infinity
348 if(time==Time::Max()) {
350 for(cit=ClocksBegin(); cit!=ClocksEnd(); cit++)
352 mEValid=false;
353 }
354 // progress enabled interval or invalidate enabled status
355 if(mEInterval.In(time) && mEValid) {
358 std::map<Idx,TimeInterval>::iterator iit;
359 for(iit=mEGuardInterval.begin();iit != mEGuardInterval.end(); iit++) {
360 iit->second.PositiveLeftShift(time);
361 }
362 } else {
363 mEValid=false;
364 }
365 return true;
366}
367
368// ExecuteEvent(event)
370 if(mCurrentTime>=Time::Max()) return false;
371 if(!mEValid) ComputeEnabled();
372 if(!mEEvents.Exists(event)) {
373 FD_DX("Executor(" << this << ")::ExecuteEvent: execution of event " << EStr(event)
374 << " conflicts with enabled status " );
375 return false;
376 }
377 FD_DX("Executor(" << this << ")::ExecuteEvent(" << EStr(event) << ")");
378 // pick transition
380 // TODO: invalid iterator error
381 // execute resets
382 ClockSet resets=Resets(*tit);
383 ClockSet::Iterator cit;
384 for(cit = resets.Begin(); cit!=resets.End(); cit++)
386 // progress state
388 // progress current time
389 mCurrentStep += 1;
390 // invalidate
391 mEValid=false;
392 return true;
393}
394
395
396// CurrentTimedState(tstate)
398 // test consitency
399 if(!ExistsState(tstate.State)) return false;
400 if(tstate.ClockValue.size()!=ClocksSize()) return false;
401 std::map<Idx,Time::Type>::const_iterator cvit;
402 for(cvit=tstate.ClockValue.begin(); cvit!=tstate.ClockValue.end(); cvit++)
403 if(!ExistsClock(cvit->first)) return false;
404 // set state
405 mCurrentTimedState=tstate;
406 mEValid=false;
407 return true;
408}
409
410// CurrentTimedState()
414
415// CurrentState(idx)
417 if(!ExistsState(index)) return false;
419 mEValid=false;
420 return true;
421}
422
423// CurrentState()
426}
427
428// CurrentClockValue(idx,time)
430 if(!ExistsClock(index)) return false;
431 mCurrentTimedState.ClockValue[index]=time;
432 mEValid=false;
433 return true;
434}
435
436// CurrentClockValue(idx)
438 std::map<Idx,Time::Type>::const_iterator cvit;
439 cvit=mCurrentTimedState.ClockValue.find(index);
440 if(cvit==mCurrentTimedState.ClockValue.end()) {}; // todo: error
441 return cvit->second;
442}
443
444// CurrentTime(time)
446 mCurrentTime=time;
447 mEValid=false;
448}
449
450// CurrentTime()
452 return mCurrentTime;
453}
454
455// CurrentStep(time)
456void Executor::CurrentStep(int step) {
457 mCurrentStep=step;
458 mEValid=false;
459}
460
461// CurrentStep()
462int Executor::CurrentStep(void) const {
463 return mCurrentStep;
464}
465
466// IsDeadlocked()
467bool Executor::IsDeadlocked(void) const {
468 if(!mEValid) ComputeEnabled();
469 if(!mEEvents.Empty()) return false;
470 if(!(mETime.UB()<=0)) return false;
471 return true;
472}
473
474// TSStr(tstate)
475std::string Executor::TSStr(const TimedState& tstate) const {
476 std::stringstream res;
477 res << "(state " << SStr(tstate.State);
478 if(Generator().ExistsMarkedState(tstate.State)) res << " [marked]";
479 res << ") (clocks";
480 ClockSet::Iterator cit;
481 for(cit=ClocksBegin();cit!=ClocksEnd();cit++){
482 res << " " << CStr(*cit) << "=";
483 std::map<Idx,Time::Type>::const_iterator cvit=tstate.ClockValue.find(*cit);
484 if(cvit!=tstate.ClockValue.end())
485 res << cvit->second;
486 else
487 res << "undef";
488 }
489 res << ")";
490 return res.str();
491}
492
493// CurrentTimedStateStr()
494std::string Executor::CurrentTimedStateStr(void) const {
496}
497
498// TEStr(tevent)
499std::string Executor::TEStr(const TimedEvent& tevent) const {
500 std::stringstream res;
501 res << "(" << EStr(tevent.mEvent) << " at " << tevent.mTime << ")";
502 return res.str();
503}
504
505// EStr(event)
506std::string Executor::EStr(Idx event) const {
507 return TimedGenerator::EStr(event);
508}
509
510// CStr(clock)
511std::string Executor::CStr(Idx clock) const {
512 return TimedGenerator::CStr(clock);
513}
514
515// SStr(clock)
516std::string Executor::SStr(Idx state) const {
517 return TimedGenerator::SStr(state);
518}
519
520
521} // namespace faudes
522
523
#define FAUDES_TYPE_IMPLEMENTATION(ftype, ctype, cbase)
Definition cfl_types.h:1017
const TimeInterval & EnabledTime() const
std::string EStr(Idx idx) const
void DoCopy(const Executor &rSrc)
const TimedGenerator & Generator(void) const
bool ExecuteTime(Time::Type time)
const EventSet & EnabledEvents() const
void Compile(void)
std::map< Idx, TimeInterval > mEGuardInterval
Time::Type CurrentTime(void) const
Idx CurrentState(void) const
std::string SStr(Idx idx) const
const EventSet & ActiveEventSet(void) const
Time::Type mCurrentTime
virtual void DoWrite(TokenWriter &rTw, const std::string &rLabel="", const Type *pContext=0) const
std::map< Transition, std::map< Idx, TimeInterval > > mTransClockIntervalMap
bool ExecuteEvent(Idx event)
void ComputeEnabled(void) const
std::map< Idx, std::map< Idx, TimeInterval > > mStateClockIntervalMap
TimeInterval EnabledEventTime(Idx event) const
std::string TSStr(const TimedState &tstate) const
std::string CStr(Idx idx) const
const TransSet & ActiveTransSet(void) const
void DoMove(Executor &rSrc)
const TimeInterval & EnabledInterval() const
const EventSet & DisabledEvents() const
bool CurrentClockValue(Idx clock, Time::Type time)
TimeInterval mETime
virtual void DoRead(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
std::string TEStr(const TimedEvent &tevent) const
TimeInterval mEInterval
const TimedState & CurrentTimedState(void) const
bool IsDeadlocked() const
TimedState mCurrentTimedState
TimeInterval EnabledGuardTime(Idx event) const
int CurrentStep(void) const
std::string CurrentTimedStateStr(void) const
void ComputeEnabledNonConst(void)
const std::string & Name(void) const
bool Exists(const Idx &rIndex) const
bool Insert(const Idx &rIndex)
virtual bool Erase(const Idx &rIndex)
Iterator Begin(void) const
Iterator End(void) const
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
void DoCopy(const TaGenerator &rGen)
virtual void Clear(void)
const GlobalAttr & GlobalAttribute(void) const
virtual TcGenerator & Copy(const Type &rSource)
TimeInterval Interval(Idx clockindex) const
ClockSet ActiveClocks(void) const
void LB(Time::Type time)
void PositiveLeftShift(Time::Type time)
bool UBinf(void) const
bool In(Time::Type time) const
std::string Str(void) const
void UBincl(bool incl)
void LBincl(bool incl)
void UB(Time::Type time)
bool Empty(void) const
void Intersect(const TimeInterval &rOtherInterval)
static Type Max(void)
Idx ClocksSize(void) const
const TimeConstraint & Invariant(Idx idx) const
bool ExistsClock(Idx index) const
ClockSet::Iterator ClocksEnd(void) const
ClockSet::Iterator ClocksBegin(void) const
void Resets(const Transition &rTrans, const ClockSet &rResets)
void Guard(const Transition &rTrans, const TimeConstraint &rGuard)
std::string CStr(Idx index) const
void Read(const std::string &rFileName, const std::string &rLabel="", const Type *pContext=0)
StateSet::Iterator StatesBegin(void) const
StateSet::Iterator InitStatesBegin(void) const
EventSet ActiveEventSet(Idx x1) const
TransSet::Iterator TransRelBegin(void) const
virtual void DoWrite(TokenWriter &rTw, const std::string &rLabel="", const Type *pContext=0) const
TransSet ActiveTransSet(Idx x1) const
bool ExistsState(Idx index) const
virtual void DoRead(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
void DoMove(vGenerator &rSrc)
std::string TStr(const Transition &rTrans) const
StateSet::Iterator StatesEnd(void) const
TransSet::Iterator TransRelEnd(void) const
bool IsDeterministic(void) const
std::string EStr(Idx index) const
Idx InitState(void) const
std::string SStr(Idx index) const
bool ExistsMarkedState(Idx index) const
TaNameSet< AttributeCFlags > Alphabet
bool Empty(void) const
virtual void Clear(void)
Iterator End(void) const
Iterator Begin(void) const
uint32_t Idx
TtGenerator< AttributeTimedGlobal, AttributeTimedState, AttributeCFlags, AttributeTimedTrans > TimedGenerator
#define FD_DX(message)
Definition sp_executor.h:27
std::map< Idx, Time::Type > ClockValue

libFAUDES 2.34d --- 2026.03.11 --- c++ api documentaion by doxygen