63 FD_DF(
"SupConClosedUnchecked(" << &rSupCandGen <<
"," << &rPlantGen <<
")");
70 std::stack<Idx> todog, todoh;
85 while (! todog.empty()) {
89 FD_WPC(1,2,
"Controllability(): iterating states");
91 Idx currentg = todog.top();
92 Idx currenth = todoh.top();
95 FD_DF(
"SupCon: todo pop: (" << rPlantGen.
SStr(currentg) <<
"|"
96 << rSupCandGen.
SStr(currenth) <<
")");
99 if(processed.
Exists(currenth))
continue;
101 #ifdef FAUDES_DEBUG_FUNCTION
104 FD_DF(
"SupCon: transitions from current states:");
106 FD_DF(
"SupCon: g: " << rPlantGen.
SStr(_titg->X1) <<
"-"
107 << rPlantGen.
EStr(_titg->Ev) <<
"-" << rPlantGen.
SStr(_titg->X2));
109 FD_DF(
"SupCon: h: " << rSupCandGen.
SStr(_tith->X1) <<
"-"
110 << rSupCandGen.
EStr(_tith->Ev) <<
"-" << rSupCandGen.
SStr(_tith->X2));
118 while ((tith != tith_end) && (titg != titg_end)) {
119 FD_DF(
"SupCon: processing g-transition: " << rPlantGen.
SStr(titg->X1)
120 <<
"-" << rPlantGen.
EStr(titg->Ev) <<
"-" << rPlantGen.
SStr(titg->X2));
121 FD_DF(
"SupCon: processing h-transition: " << rSupCandGen.
SStr(tith->X1)
122 <<
"-" << rSupCandGen.
EStr(tith->Ev) <<
"-" << rSupCandGen.
SStr(tith->X2));
124 if (titg->Ev == tith->Ev) {
125 FD_DF(
"SupCon: processing common event " << rPlantGen.
EStr(titg->Ev));
127 if(!processed.
Exists(tith->X2)) {
128 todog.push(titg->X2);
129 todoh.push(tith->X2);
130 FD_DF(
"SupCon: todo push: (" << rPlantGen.
SStr(titg->X2) <<
"|"
131 << rSupCandGen.
SStr(tith->X2) <<
")");
134 if (!critical.
Exists(tith->X2)) {
136 FD_DF(
"SupCon: incrementing g and h transrel");
141 else if (!rCAlph.
Exists(titg->Ev)) {
142 FD_DF(
"SupCon: successor state " << rSupCandGen.
SStr(tith->X2) <<
143 " critical and event " << rPlantGen.
EStr(titg->Ev) <<
" uncontrollable:");
144 FD_DF(
"SupCon: TraverseUncontrollableBackwards(" << rSupCandGen.
SStr(currenth) <<
")");
146 #ifdef FAUDES_CHECKED
148 FD_DF(
"IsControllable: incrementing g an h transrel (FAUDES_CHECKED)");
161 FD_DF(
"SupCon: incrementing g and h transrel");
167 else if (titg->Ev < tith->Ev) {
168 FD_DF(
"SupCon: asynchronous execution of event "
169 << rPlantGen.
EStr(titg->Ev) <<
" in g while " << rSupCandGen.
EStr(tith->Ev)
173 if (!rCAlph.
Exists(titg->Ev)) {
174 FD_DF(
"SupCon: asynchronous event " << rPlantGen.
EStr(titg->Ev)
175 <<
" in g is uncontrollable");
176 FD_DF(
"SupCon: TraverseUncontrollableBackwards(" << rSupCandGen.
SStr(currenth) <<
")");
182 FD_DF(
"SupCon: incrementing g transrel");
191 FD_DF(
"SupCon: incrementing h transrel");
196 while (titg != titg_end) {
197 FD_DF(
"SupCon: asynchronous execution of event "
198 << rPlantGen.
EStr(titg->Ev) <<
" in g at end of h");
199 FD_DF(
"SupCon: actual g-transition: " << rPlantGen.
SStr(titg->X1)
200 <<
"-" << rPlantGen.
EStr(titg->Ev) <<
"-" << rPlantGen.
SStr(titg->X2));
201 FD_DF(
"SupCon: actual h-transition: end");
203 if (!rCAlph.
Exists(titg->Ev)) {
204 FD_DF(
"SupCon: asynchronous execution of uncontrollable event "
205 << rPlantGen.
EStr(titg->Ev) <<
" in g");
206 FD_DF(
"SupCon: TraverseUncontrollableBackwards(" << rPlantGen.
SStr(currenth) <<
")");
211 FD_DF(
"SupCon: incrementing g transrel");
222 processed.
Insert(currenth);
227 critical = rSupCandGen.
States() - ( processed - critical );
249 FD_DF(
"IsControllableUnchecked(" << &rSupCandGen <<
"," << &rPlantGen <<
")");
252 std::stack< std::pair<Idx,Idx> > todo;
254 std::set< std::pair<Idx,Idx> > processed;
257 rCriticalStates.
Clear();
258 rCriticalStates.
Name(
"CriticalStates");
270 while (! todo.empty()) {
274 FD_WPC(1,2,
"Controllability(): iterating states");
276 std::pair<Idx,Idx> current = todo.top(); todo.pop();
277 processed.insert(current);
278 Idx currentg = current.first;
279 Idx currenth = current.second;
280 FD_DF(
"IsControllable: todo pop: (" << rPlantGen.
SStr(currentg) <<
"|"
281 << rSupCandGen.
SStr(currenth) <<
")");
283 #ifdef FAUDES_DEBUG_FUNCTION
286 FD_DF(
"IsControllable: transitions from current states:");
288 FD_DF(
"IsControllable: g: " << rPlantGen.
SStr(_titg->X1) <<
"-"
289 << rPlantGen.
EStr(_titg->Ev) <<
"-" << rPlantGen.
SStr(_titg->X2));
291 FD_DF(
"IsControllable: h: " << rSupCandGen.
SStr(_tith->X1) <<
"-"
292 << rSupCandGen.
EStr(_tith->Ev) <<
"-" << rSupCandGen.
SStr(_tith->X2));
300 while ((tith != tith_end) && (titg != titg_end)) {
301 FD_DF(
"IsControllable: processing g-transition: " << rPlantGen.
SStr(titg->X1)
302 <<
"-" << rPlantGen.
EStr(titg->Ev) <<
"-" << rPlantGen.
SStr(titg->X2));
303 FD_DF(
"IsControllable: processing h-transition: " << rSupCandGen.
SStr(tith->X1)
304 <<
"-" << rSupCandGen.
EStr(tith->Ev) <<
"-" << rSupCandGen.
SStr(tith->X2));
306 if (titg->Ev == tith->Ev) {
307 FD_DF(
"IsControllable: processing common event " << rPlantGen.
EStr(titg->Ev));
309 std::pair<Idx,Idx> next = std::make_pair(titg->X2,tith->X2);
311 if(processed.find(next)==processed.end()) {
312 FD_DF(
"IsControllable: todo push: (" << rPlantGen.
SStr(titg->X2) <<
"|"
313 << rSupCandGen.
SStr(tith->X2) <<
")");
321 else if (titg->Ev < tith->Ev) {
322 FD_DF(
"IsControllable: asynchronous execution of event "
323 << rPlantGen.
EStr(titg->Ev) <<
" in g while " << rSupCandGen.
EStr(tith->Ev)
327 if (!rCAlph.
Exists(titg->Ev)) {
328 FD_DF(
"IsControllable: asynchronous event " << rPlantGen.
EStr(titg->Ev)
329 <<
" in g is uncontrollable");
330 FD_DF(
"IsControllable: TraverseUncontrollableBackwards(" << rSupCandGen.
SStr(currenth) <<
")");
331 rCriticalStates.
Insert(currenth);
336 FD_DF(
"IsControllable: incrementing g transrel");
345 FD_DF(
"IsControllable: incrementing h transrel");
350 while (titg != titg_end) {
351 FD_DF(
"IsControllable: asynchronous execution of event "
352 << rPlantGen.
EStr(titg->Ev) <<
" in g at end of h");
353 FD_DF(
"IsControllable: actual g-transition: " << rPlantGen.
SStr(titg->X1)
354 <<
"-" << rPlantGen.
EStr(titg->Ev) <<
"-" << rPlantGen.
SStr(titg->X2));
355 FD_DF(
"IsControllable: actual h-transition: end");
357 if (!rCAlph.
Exists(titg->Ev)) {
358 FD_DF(
"IsControllable: asynchronous execution of uncontrollable event "
359 << rPlantGen.
EStr(titg->Ev) <<
" in g");
360 FD_DF(
"IsControllable: TraverseUncontrollableBackwards(" << rPlantGen.
SStr(currenth) <<
")");
361 rCriticalStates.
Insert(currenth);
365 FD_DF(
"IsControllable: incrementing g transrel");
380 return rCriticalStates.
Empty();
390 std::map< std::pair<Idx,Idx>,
Idx>& rCompositionMap,
393 FD_DF(
"SupConProduct(" << &rPlantGen <<
"," << &rSpecGen <<
")");
398 std::stack< std::pair<Idx,Idx> > todo;
402 std::pair<Idx,Idx> currentp, nextp;
405 std::map< std::pair<Idx,Idx>,
Idx>::iterator rcmapit;
406 StateSet::Iterator lit1, lit2;
411 rCompositionMap.clear();
415 FD_DF(
"SupConProduct: plant got no initial states. "
416 <<
"parallel composition contains empty language.");
420 FD_DF(
"SupConProduct: spec got no initial states. "
421 <<
"parallel composition contains empty language.");
429 FD_DF(
"SupConProduct: insert initial state: ("
430 << rPlantGen.
SStr(currentp.first)
431 <<
"|" << rSpecGen.
SStr(currentp.second) <<
") as idx "
432 << rCompositionMap[currentp]);
436 FD_DF(
"SupConProduct: initial state is marked");
442 FD_DF(
"SupConProduct: *** processing reachable states ***");
443 while (! todo.empty()) {
447 FD_WPC(rCompositionMap.size(),rCompositionMap.size()+todo.size(),
"SupConProduct(): processing");
449 currentp = todo.top();
451 currentt = rCompositionMap[currentp];
452 FD_DF(
"SupConProduct: todo pop: ("
453 << rPlantGen.
SStr(currentp.first)
454 <<
"|" << rSpecGen.
SStr(currentp.second) <<
") as idx "
457 if(critical.
Exists(currentt))
continue;
464 #ifdef FAUDES_DEBUG_FUNCTION
466 FD_DF(
"SupConParallel: transitions from current state:");
467 for (;titg != titg_end; ++titg)
468 FD_DF(
"SupConParallel: g: " << rPlantGen.
TStr(*titg));
469 for (;tith != tith_end; ++tith) {
470 FD_DF(
"SupConParallel: h: " << rSpecGen.
TStr(*tith));
477 while((tith != tith_end) && (titg != titg_end)) {
478 FD_DF(
"SupConProduct: current g-transition: " << rPlantGen.
TStr(*titg) );
479 FD_DF(
"SupConProduct: current h-transition: " << rSpecGen.
TStr(*tith));
482 if(titg->Ev == tith->Ev) {
483 FD_DF(
"SupConProduct: executing common event " << rPlantGen.
EStr(titg->Ev));
484 nextp = std::make_pair(titg->X2, tith->X2);
485 rcmapit = rCompositionMap.find(nextp);
487 if(rcmapit == rCompositionMap.end()) {
492 rCompositionMap[nextp] = nextt;
493 FD_DF(
"SupConProduct: insert state: (" <<
494 rPlantGen.
SStr(nextp.first) <<
"|"
495 << rSpecGen.
SStr(nextp.second) <<
") as idx "
501 FD_DF(
"SupConProduct: marked nes state")
506 nextt = rcmapit->second;
509 if(!critical.
Exists(nextt)) {
510 FD_DF(
"SupConProduct: set transition " <<
513 FD_DF(
"SupConProduct: incrementing g and h transrel");
518 else if (!rCAlph.
Exists(titg->Ev)) {
519 FD_DF(
"SupConProduct: successor in critical with uncntr. shared event " << rSpecGen.
EStr(titg->Ev))
520 FD_DF(
"SupConProduct: critical insert, exit loop");
521 critical.
Insert(currentt);
528 FD_DF(
"SupConProduct: incrementing g and h transrel");
535 else if (titg->Ev < tith->Ev) {
536 FD_DF(
"SupConProduct: event only enabled in g: " << rPlantGen.
EStr(titg->Ev));
538 if(!rCAlph.
Exists(titg->Ev)) {
539 FD_DF(
"SupConProduct: asynchronous event is uncontrollable, critical insert, exit loop");
540 critical.
Insert(currentt);
546 FD_DF(
"SupConProduct: incrementing g transrel");
552 FD_DF(
"SupConProduct: incrementing h transrel");
558 while (titg != titg_end) {
559 FD_DF(
"SupConProduct: event only enabled in g: " << rPlantGen.
EStr(titg->Ev));
561 if (!rCAlph.
Exists(titg->Ev)) {
562 FD_DF(
"SupConProduct: asynchronous event is uncontrollable, critical insert, exit loop");
563 critical.
Insert(currentt);
567 FD_DF(
"SupConProduct: incrementing g transrel");
579 FD_DF(
"SupConProduct: deleting critical states...");
590 std::map< std::pair<Idx,Idx>,
Idx>& rCompositionMap,
593 FD_DF(
"SupConNB(" << &rPlantGen <<
"," << &rSpecGen <<
")");
597 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
598 pResGen= rResGen.
New();
605 FD_DF(
"SupConNB: controllable events: " << rCAlph.
ToString());
608 SupConProduct(rPlantGen, rCAlph, rSpecGen, rCompositionMap, *pResGen);
612 if(pResGen->
Empty())
break;
613 Idx state_num = pResGen->
Size();
616 if(pResGen->
Size() == state_num)
break;
626 if(pResGen != &rResGen) {
627 pResGen->
Move(rResGen);
644 only_in_plant.
Name(
"Only_In_Plant");
645 only_in_spec.
Name(
"Only_In_Specification");
646 std::stringstream errstr;
647 errstr <<
"Alphabets of generators do not match.";
648 if(!only_in_plant.
Empty())
649 errstr <<
" " << only_in_plant.
ToString() <<
".";
650 if(!only_in_spec.
Empty())
651 errstr <<
" " << only_in_spec.
ToString() <<
".";
652 throw Exception(
"SupCon/SupConNB", errstr.str(), 100);
656 if(!(rCAlph<=rPlantGen.
Alphabet())) {
658 std::stringstream errstr;
659 errstr <<
"Not all controllable events are contained in Sigma: "
661 throw Exception(
"ControllProblemConsistencyCheck", errstr.str(), 100);
670 if ((plant_det ==
false) && (spec_det ==
true)) {
671 std::stringstream errstr;
672 errstr <<
"Plant generator must be deterministic, "
673 <<
"but is nondeterministic";
674 throw Exception(
"ControllableConsistencyCheck", errstr.str(), 201);
676 else if ((plant_det ==
true) && (spec_det ==
false)) {
677 std::stringstream errstr;
678 errstr <<
"Spec generator must be deterministic, "
679 <<
"but is nondeterministic";
680 throw Exception(
"ControllableConsistencyCheck", errstr.str(), 203);
682 else if ((plant_det ==
false) && (spec_det ==
false)) {
683 std::stringstream errstr;
684 errstr <<
"Plant and spec generator must be deterministic, "
685 <<
"but both are nondeterministic";
686 throw Exception(
"ControllableConsistencyCheck", errstr.str(), 204);
700 if(!(rOAlph<=rPlantGen.
Alphabet())) {
702 std::stringstream errstr;
703 errstr <<
"Not all observable events are contained in Sigma: "
705 throw Exception(
"ControllProblemConsistencyCheck", errstr.str(), 100);
723 FD_DF(
"IsControllable(" << &rSupCandGen <<
"," << &rPlantGen <<
")");
726 FD_DF(
"IsControllable: controllable events: " << rCAlph.
ToString());
746 FD_DF(
"IsControllable(" << &rSupCandGen <<
"," << &rPlantGen <<
")");
768 std::map< std::pair<Idx,Idx>,
Idx> rcmap;
785 std::map< std::pair<Idx,Idx>,
Idx> rcmap;
788 SupConClosed(rPlantGen, rCAlph, rSpecGen, rcmap, rResGen);
797 std::map< std::pair<Idx,Idx>,
Idx>& rCompositionMap,
800 FD_DF(
"SupConClosed(" << &rPlantGen <<
"," << &rSpecGen <<
")");
806 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
807 pResGen= rResGen.
New();
822 SupConProduct(rPlantGen, rCAlph, rSpecGen, rCompositionMap, *pResGen);
827 std::map< std::pair<Idx,Idx>,
Idx>::iterator rcmapit = rCompositionMap.begin();
828 while(rcmapit != rCompositionMap.end())
829 if(!rResGen.
ExistsState(rcmapit->second)) rCompositionMap.erase(rcmapit++);
839 if(pResGen != &rResGen) {
840 pResGen->
Move(rResGen);
852 FD_DF(
"TraverseUncontrollableBackwards: " << rCriticalStates.
Str(current));
855 std::stack<Idx> todo;
860 rCriticalStates.
Insert(current);
862 FD_DF(
"TraverseUncontrollableBackwards: current rCriticalStates set: "
865 while(! todo.empty()) {
867 current = todo.top(); todo.pop();
869 rtit_end = rtransrel.
EndByX2(current);
871 for(; rtit != rtit_end; ++rtit) {
873 if((!rCAlph.
Exists(rtit->Ev)) && (! rCriticalStates.
Exists(rtit->X1))) {
874 FD_DF(
"TraverseUncontrollableBackwards: todo push " << rCriticalStates.
Str(rtit->X1));
876 FD_DF(
"TraverseUncontrollableBackwards: critical insert: " << rCriticalStates.
Str(rtit->X1));
877 rCriticalStates.
Insert(rtit->X1);
902 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
903 pResGen= rResGen.
New();
913 if(pResGen != &rResGen) {
914 pResGen->
Move(rResGen);
929 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
930 pResGen= rResGen.
New();
940 if(pResGen != &rResGen) {
941 pResGen->
Move(rResGen);
#define FD_WPC(cntnow, contdone, message)
Application callback: optional write progress report to console or application, incl count
#define FD_DF(message)
Debug: optional report on user functions.
std::string Str(const Idx &rIndex) const
Return pretty printable index.
Idx Insert(void)
Insert new index to set.
Set of indices with symbolic names.
bool Exists(const Idx &rIndex) const
Test existence of index.
Iterator class for high-level api to TBaseSet.
Iterator BeginByX2(Idx x2) const
Iterator to first Transition specified by successor state x2.
bool Insert(const Transition &rTransition)
Add a Transition.
Iterator EndByX2(Idx x2) const
Iterator to first Transition after specified successor state x2.
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
Iterator on transition.
const TaEventSet< EventAttr > & Alphabet(void) const
Return const reference to alphabet.
Generator with controllability attributes.
EventSet ControllableEvents(void) const
Get EventSet with controllable events.
Triple (X1,Ev,X2) to represent current state, event and next state.
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
Write configuration data to a string.
Base class of all FAUDES generators.
StateSet::Iterator InitStatesBegin(void) const
Iterator to Begin() of mInitStates.
bool SetTransition(Idx x1, Idx ev, Idx x2)
Add a transition to generator by indices.
const EventSet & Alphabet(void) const
Return const reference to alphabet.
virtual void Move(vGenerator &rGen)
Destructive copy to other vGenerator.
bool InitStatesEmpty(void) const
Check if set of initial states are empty.
TransSet::Iterator TransRelBegin(void) const
Iterator to Begin() of transition relation.
bool Trim(void)
Make generator trim.
void ClearStates(void)
Clear all states and transitions, maintain alphabet.
virtual vGenerator * New(void) const
Construct on heap.
bool ExistsState(Idx index) const
Test existence of state in state set.
std::string TStr(const Transition &rTrans) const
Return pretty printable transition (eg for debugging)
void Name(const std::string &rName)
Set the generator's name.
void DelStates(const StateSet &rDelStates)
Delete a set of states Cleans mpStates, mInitStates, mMarkedStates, mpTransrel, and mpStateSymboltabl...
TransSet::Iterator TransRelEnd(void) const
Iterator to End() of transition relation.
bool IsDeterministic(void) const
Check if generator is deterministic.
std::string EStr(Idx index) const
Pretty printable event name for index (eg for debugging).
Idx InsState(void)
Add new anonymous state to generator.
void SetMarkedState(Idx index)
Set an existing state as marked state by index.
bool Empty(void) const
Check if generator is empty (no states)
Idx InsInitState(void)
Create new anonymous state and set as initial state.
virtual void EventAttributes(const EventSet &rEventSet)
Set attributes for existing events.
bool StateNamesEnabled(void) const
Whether libFAUEDS functions are requested to generate state names.
Idx Size(void) const
Get generator size (number of states)
std::string SStr(Idx index) const
Return pretty printable state name for index (eg for debugging)
virtual void Clear(void)
Clear generator data.
bool ExistsMarkedState(Idx index) const
Test existence of state in mMarkedStates.
const StateSet & States(void) const
Return reference to state set.
void InjectAlphabet(const EventSet &rNewalphabet)
Set mpAlphabet without consistency check.
bool Empty(void) const
Test whether if the TBaseSet is Empty.
bool Exists(const T &rElem) const
Test existence of element.
virtual void Clear(void)
Clear all set.
const std::string & Name(void) const
Return name of TBaseSet.
bool IsControllable(const Generator &rPlantGen, const EventSet &rCAlph, const Generator &rSupCandGen)
Test controllability.
void SupConNB(const Generator &rPlantGen, const EventSet &rCAlph, const Generator &rSpecGen, Generator &rResGen)
Nonblocking Supremal Controllable Sublanguage.
void SupConClosed(const Generator &rPlantGen, const EventSet &rCAlph, const Generator &rSpecGen, Generator &rResGen)
Supremal Controllable and Closed Sublanguage.
libFAUDES resides within the namespace faudes.
uint32_t Idx
Type definition for index type (allways 32bit)
void SetComposedStateNames(const Generator &rGen1, const Generator &rGen2, const std::map< std::pair< Idx, Idx >, Idx > &rCompositionMap, Generator &rGen12)
Helper: uses composition map to track state names in a paralell composition.
void SupConProduct(const Generator &rPlantGen, const EventSet &rCAlph, const Generator &rSpecGen, std::map< std::pair< Idx, Idx >, Idx > &rCompositionMap, Generator &rResGen)
Parallel composition optimized for the purpose of SupCon (internal function)
std::string CollapsString(const std::string &rString, unsigned int len)
Limit length of string, return head and tail of string.
void ControlProblemConsistencyCheck(const GeneratorVector &rPlantGenVec, const EventSet &rConAlph, const GeneratorVector &rSpecGenVec)
Compositional synthesis.
void SupConClosedUnchecked(const Generator &rPlantGen, const EventSet &rCAlph, Generator &rSupCandGen)
Supremal Controllable Sublangauge (internal function)
void SupConNBUnchecked(const Generator &rPlantGen, const EventSet &rCAlph, const Generator &rSpecGen, std::map< std::pair< Idx, Idx >, Idx > &rCompositionMap, Generator &rResGen)
Nonblocking Supremal Controllable Sublanguage (internal function)
void TraverseUncontrollableBackwards(const EventSet &rCAlph, TransSetX2EvX1 &rtransrel, StateSet &rCriticalStates, Idx current)
Helper function for IsControllable.
bool IsControllableUnchecked(const Generator &rPlantGen, const EventSet &rCAlph, const Generator &rSupCandGen, StateSet &rCriticalStates)
Controllability (internal function)
Supremal controllable sublanguage.