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// Exector(rGen)
30 FD_DX("Executor(" << this << ")::Executor(rGen)");
31 Assign(rGen);
32}
33
34// Exector(filename)
35Executor::Executor(const std::string& rFileName) : TimedGenerator() {
36 FD_DX("Executor(" << this << ")::Executor("<< rFileName <<")");
37 Read(rFileName);
38}
39
40// Generator()
42 return *this;
43}
44
45// Generator(rGen)
47 FD_DX("Executor::Generator(" << &rGen << ")");
48 Assign(*this);
49}
50
51
52// Compile()
54 FD_DX("Executor(" << this << ")::Compile()");
55 // throw exception on non deterministic generator
56 if(!IsDeterministic() || InitState()==0) {
57 std::stringstream errstr;
58 errstr << "nondeterministic generator in simulation" << std::endl;
59 throw Exception("Executor::Compile", errstr.str(), 501);
60 }
61 // compile guards
63 for(tit=TransRelBegin(); tit!= TransRelEnd(); tit++) {
64 FD_DX("Executor(" << this << ")::Compile(): trans " << TStr(*tit));
65 TimeConstraint guard=Guard(*tit);
66 std::map<Idx,TimeInterval> guardtime;
67 ClockSet aclocks=guard.ActiveClocks();
68 ClockSet::Iterator cit;
69 for(cit=aclocks.Begin(); cit!= aclocks.End(); cit++)
70 guardtime[*cit]=guard.Interval(*cit);
71 mTransClockIntervalMap[*tit]=guardtime;
72 }
73 // compile invariants
74 StateSet::Iterator sit;
75 for(sit=StatesBegin(); sit!= StatesEnd(); sit++) {
76 FD_DX("Executor(" << this << ")::Compile(): state " << SStr(*sit));
77 TimeConstraint invariant=Invariant(*sit);
78 std::map<Idx,TimeInterval> invtime;
79 ClockSet aclocks=invariant.ActiveClocks();
80 ClockSet::Iterator cit;
81 for(cit=aclocks.Begin(); cit!= aclocks.End(); cit++)
82 invtime[*cit]=invariant.Interval(*cit);
83 mStateClockIntervalMap[*sit]=invtime;
84 }
85 // get ready
86 Reset();
87 FD_DX("Executor(" << this << ")::Compile(): done");
88}
89
90// Clear()
91void Executor::Clear(void) {
92 FD_DX("Executor(" << this << ")::Clear(): invalid executor");
98 mEValid=false;
99}
100
101// Reset()
102void Executor::Reset(void) {
105 ClockSet::Iterator cit;
106 for(cit=GlobalAttribute().mClocks.Begin(); cit!=GlobalAttribute().mClocks.End(); cit++)
108 mCurrentTime=0;
109 mCurrentStep=0;
110 mEValid=false;
111}
112
113
114// DoRead(rTr)
115void Executor::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
116 FD_DX("Executor(" << this << ")::DoRead(rTr)");
117 TimedGenerator::DoRead(rTr,rLabel,pContext);
118 Compile();
119}
120
121// DoWrite(rTr)
122void Executor::DoWrite(TokenWriter& rTw,const std::string& rLabel, const Type* pContext) const {
123 FD_DX("Executor(" << this << ")::DoWrite(rTw)");
124 TimedGenerator::DoWrite(rTw,rLabel,pContext);
125}
126
127// DoAssign
128void Executor::DoAssign(const Executor& rSrc) {
129 // call base
131 // fox my data
132 Compile();
133}
134
135
136
137// ComputeEnabled() fake const
138void Executor::ComputeEnabled(void) const {
139 Executor* fakeconst = const_cast<Executor*>(this);
140 fakeconst->ComputeEnabledNonConst();
141}
142
143// ComputeEnabledNoneConst()
145 FD_DX("Executor(" << this << ")::ComputeEnabled()");
146 // time is up: clear all
147 if(mCurrentTime>=Time::Max()) {
148 mAEvents.Clear();
149 mATrans.Clear();
152 mEEvents.Clear();
154 mEGuardInterval.clear();
155 mEValid=true;
156 FD_DX("Executor(" << this << ")::ComputeEnabled(): time is up");
157 return;
158 }
159 // set active events/transitions
162 // hypothesis: all time can pass [0,inf)
165 // hypothesis: no events can occur
166 mEEvents.Clear();
168 mEGuardInterval.clear();
169 // inspect invariant to restrict enabled time
170 std::map<Idx,TimeInterval> clockintervalmap=mStateClockIntervalMap[mCurrentTimedState.State];
171 std::map<Idx,TimeInterval>::const_iterator cit;
172 for(cit=clockintervalmap.begin(); cit!=clockintervalmap.end(); cit++) {
173 Idx clock = cit-> first;
174 Time::Type clockvalue = mCurrentTimedState.ClockValue[clock];
175 TimeInterval interval = cit->second;
176 // if a clock violates an invariant constraint return deadlock
177 if(! interval.In( clockvalue ) ) {
178 FD_DX("Executor(" << this << ")::ComputeEnabled(): clock " << CStr(cit->first)
179 << " at " << clockvalue << " violates invariant condition " << interval.Str() );
181 mEValid=true;
182 return;
183 }
184 // left shift interval by clock value to obtain an interval relative to current time
185 interval.PositiveLeftShift(clockvalue);
186 // intersect with enabled time
187 mETime.Intersect(interval);
188 }
189 FD_DX("Executor(" << this << ")::ComputeEnabled(): invariant is satisfied for "
190 << mETime.Str() );
191 // no events for all time that can pass to begin with ...
192 mEEvents.Clear();
193 mEEvents.Name("EnabledEvents");
195 mDEvents.Name("DisabledEvents");
197 // iterate over all transitions and check guards
199 for(tit=mATrans.Begin(); tit!= mATrans.End(); tit++) {
200 // hypothesis: transition is enabled for all time
201 bool enabled=true;
202 TimeInterval enabledtime;
203 enabledtime.SetPositive();
204 // check all clocks
205 std::map<Idx,TimeInterval> clockintervalmap=mTransClockIntervalMap[*tit];
206 std::map<Idx,TimeInterval>::const_iterator cit;
207 for(cit=clockintervalmap.begin(); cit!=clockintervalmap.end(); cit++) {
208 Idx clock = cit->first;
209 Time::Type clockvalue = mCurrentTimedState.ClockValue[clock];
210 TimeInterval interval = cit->second;
211 // reject transition if a clock violates a guard constraint
212 if(! interval.In(clockvalue) ) enabled=false;
213 // left shift interval by clock value to obtain an interval relative to current time
214 interval.PositiveLeftShift(clockvalue);
215 // intersect with enabled interval
216 enabledtime.Intersect(interval);
217 }
218 // record guard interval
219 mEGuardInterval[tit->Ev]=enabledtime;
220 // intersect with invariant
221 enabledtime.Intersect(mETime);
222 // intersect with time hypothesis
223 if(enabled) {
224 // easy: intersect enabledtime with mEInterval
225 FD_DX("Executor(" << this << ")::ComputeEnabled(): event " << EStr(tit->Ev)
226 << " is enabled for " << enabledtime.Str());
227 mEEvents.Insert(tit->Ev);
228 mDEvents.Erase(tit->Ev);
229 mEInterval.Intersect(enabledtime);
230 } else {
231 // first compute disabledtime, then intersect
232 TimeInterval disabledtime;
233 disabledtime.SetPositive();
234 if(!enabledtime.Empty()) {
235 disabledtime.UB(enabledtime.LB());
236 disabledtime.UBincl(!enabledtime.LBincl());
237 }
238 FD_DX("Executor(" << this << ")::ComputeEnabled(): event " << EStr(tit->Ev)
239 << " is disabled for " << disabledtime.Str() << " and enabled for " << enabledtime.Str());
240 mEInterval.Intersect(disabledtime);
241 }
242 } // loop transitions
243 FD_DX("Executor(" << this << ")::ComputeEnabled(): e/d status constant on "
244 << mEInterval.Str() );
245 mEValid=true;
246}
247
248// EnabledTime(void)
250 if(!mEValid) ComputeEnabled();
251 return mETime;
252}
253
254// EnabledEvents(void)
256 if(!mEValid) ComputeEnabled();
257 return mEEvents;
258}
259
260// DisabledEvents(void)
262 if(!mEValid) ComputeEnabled();
263 return mDEvents;
264}
265
266// EnabledInterval(void)
268 if(!mEValid) ComputeEnabled();
269 return mEInterval;
270}
271
272// ActiveEventSet(void)
274 if(!mEValid) ComputeEnabled();
275 return mAEvents;
276}
277
278// ActiveTransSet(void)
280 if(!mEValid) ComputeEnabled();
281 return mATrans;
282}
283
284// EnabledEventInterval(event)
286 if(!mEValid) ComputeEnabled();
287 TimeInterval res;
288 std::map<Idx,TimeInterval>::const_iterator eit;
289 eit=mEGuardInterval.find(event);
290 if(eit!= mEGuardInterval.end()) {
291 res = eit->second;
292 res.Intersect(mETime);
293 return res;
294 }
295 if(Alphabet().Exists(event)) {
296 res.SetEmpty();
297 return res;
298 }
299 res.SetPositive();
300 return res;
301}
302
303// EnabledGuardInterval(event)
305 if(!mEValid) ComputeEnabled();
306 std::map<Idx,TimeInterval>::const_iterator eit;
307 eit=mEGuardInterval.find(event);
308 if(eit!= mEGuardInterval.end()) return eit->second;
309 TimeInterval res;
310 res.SetEmpty();
311 if(Alphabet().Exists(event)) return res;
312 res.SetPositive();
313 return res;
314}
315
316// ExecuteTime(time)
318 if(mCurrentTime>=Time::Max()) return false;
319 if(!mEValid) ComputeEnabled();
320 if(!mETime.In(time) && !((time==Time::Max()) && mETime.UBinf()) ) {
321 FD_DX("Executor(" << this << ")::ExecuteTime: execution of " << time
322 << " conflicts with enabled status " );
323 return false;
324 }
325 FD_DX("Executor(" << this << ")::ExecuteTime(" << time << ")");
326 // progress current time
327 mCurrentTime += time;
328 // progres clocks
329 ClockSet::Iterator cit;
330 for(cit=ClocksBegin(); cit!=ClocksEnd(); cit++)
332 // fix infinity
333 if(time==Time::Max()) {
335 for(cit=ClocksBegin(); cit!=ClocksEnd(); cit++)
337 mEValid=false;
338 }
339 // progress enabled interval or invalidate enabled status
340 if(mEInterval.In(time) && mEValid) {
343 std::map<Idx,TimeInterval>::iterator iit;
344 for(iit=mEGuardInterval.begin();iit != mEGuardInterval.end(); iit++) {
345 iit->second.PositiveLeftShift(time);
346 }
347 } else {
348 mEValid=false;
349 }
350 return true;
351}
352
353// ExecuteEvent(event)
355 if(mCurrentTime>=Time::Max()) return false;
356 if(!mEValid) ComputeEnabled();
357 if(!mEEvents.Exists(event)) {
358 FD_DX("Executor(" << this << ")::ExecuteEvent: execution of event " << EStr(event)
359 << " conflicts with enabled status " );
360 return false;
361 }
362 FD_DX("Executor(" << this << ")::ExecuteEvent(" << EStr(event) << ")");
363 // pick transition
365 // TODO: invalid iterator error
366 // execute resets
367 ClockSet resets=Resets(*tit);
368 ClockSet::Iterator cit;
369 for(cit = resets.Begin(); cit!=resets.End(); cit++)
371 // progress state
373 // progress current time
374 mCurrentStep += 1;
375 // invalidate
376 mEValid=false;
377 return true;
378}
379
380
381// CurrentTimedState(tstate)
383 // test consitency
384 if(!ExistsState(tstate.State)) return false;
385 if(tstate.ClockValue.size()!=ClocksSize()) return false;
386 std::map<Idx,Time::Type>::const_iterator cvit;
387 for(cvit=tstate.ClockValue.begin(); cvit!=tstate.ClockValue.end(); cvit++)
388 if(!ExistsClock(cvit->first)) return false;
389 // set state
390 mCurrentTimedState=tstate;
391 mEValid=false;
392 return true;
393}
394
395// CurrentTimedState()
399
400// CurrentState(idx)
402 if(!ExistsState(index)) return false;
404 mEValid=false;
405 return true;
406}
407
408// CurrentState()
411}
412
413// CurrentClockValue(idx,time)
415 if(!ExistsClock(index)) return false;
416 mCurrentTimedState.ClockValue[index]=time;
417 mEValid=false;
418 return true;
419}
420
421// CurrentClockValue(idx)
423 std::map<Idx,Time::Type>::const_iterator cvit;
424 cvit=mCurrentTimedState.ClockValue.find(index);
425 if(cvit==mCurrentTimedState.ClockValue.end()) {}; // todo: error
426 return cvit->second;
427}
428
429// CurrentTime(time)
431 mCurrentTime=time;
432 mEValid=false;
433}
434
435// CurrentTime()
437 return mCurrentTime;
438}
439
440// CurrentStep(time)
441void Executor::CurrentStep(int step) {
442 mCurrentStep=step;
443 mEValid=false;
444}
445
446// CurrentStep()
447int Executor::CurrentStep(void) const {
448 return mCurrentStep;
449}
450
451// IsDeadlocked()
452bool Executor::IsDeadlocked(void) const {
453 if(!mEValid) ComputeEnabled();
454 if(!mEEvents.Empty()) return false;
455 if(!(mETime.UB()<=0)) return false;
456 return true;
457}
458
459// TSStr(tstate)
460std::string Executor::TSStr(const TimedState& tstate) const {
461 std::stringstream res;
462 res << "(state " << SStr(tstate.State);
463 if(Generator().ExistsMarkedState(tstate.State)) res << " [marked]";
464 res << ") (clocks";
465 ClockSet::Iterator cit;
466 for(cit=ClocksBegin();cit!=ClocksEnd();cit++){
467 res << " " << CStr(*cit) << "=";
468 std::map<Idx,Time::Type>::const_iterator cvit=tstate.ClockValue.find(*cit);
469 if(cvit!=tstate.ClockValue.end())
470 res << cvit->second;
471 else
472 res << "undef";
473 }
474 res << ")";
475 return res.str();
476}
477
478// CurrentTimedStateStr()
479std::string Executor::CurrentTimedStateStr(void) const {
481}
482
483// TEStr(tevent)
484std::string Executor::TEStr(const TimedEvent& tevent) const {
485 std::stringstream res;
486 res << "(" << EStr(tevent.mEvent) << " at " << tevent.mTime << ")";
487 return res.str();
488}
489
490// EStr(event)
491std::string Executor::EStr(Idx event) const {
492 return TimedGenerator::EStr(event);
493}
494
495// CStr(clock)
496std::string Executor::CStr(Idx clock) const {
497 return TimedGenerator::CStr(clock);
498}
499
500// SStr(clock)
501std::string Executor::SStr(Idx state) const {
502 return TimedGenerator::SStr(state);
503}
504
505
506} // namespace faudes
507
508
#define FAUDES_TYPE_IMPLEMENTATION(ftype, ctype, cbase)
Definition cfl_types.h:958
const TimeInterval & EnabledTime() const
std::string EStr(Idx idx) const
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
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
void DoAssign(const Executor &rSrc)
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
virtual void Clear(void)
const GlobalAttr & GlobalAttribute(void) const
void DoAssign(const TaGenerator &rGen)
virtual TcGenerator & Assign(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)
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.33k --- 2025.09.16 --- c++ api documentaion by doxygen