omg_buechifnct.cpp
Go to the documentation of this file.
1 /** @file omg_buechifnct.cpp
2 
3 Operations regarding omega languages accepted by Buechi automata
4 
5 */
6 
7 /* FAU Discrete Event Systems Library (libfaudes)
8 
9 Copyright (C) 2010, 2025 Thomas Moor
10 
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 2.1 of the License, or (at your option) any later version.
15 
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
20 
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
24 
25 
26 
27 #include "omg_buechifnct.h"
28 
29 
30 namespace faudes {
31 
32 // BuechiTrim
33 // (return True if resulting contains at least one initial state and at least one mark)
34 bool BuechiTrim(vGenerator& rGen) {
35 
36  // note: this really is inefficient; at least we should
37  // record the inverse transition relation for the coaccessile
38  // iteration
39 
40  // first we make the generator accessible
41  rGen.Accessible();
42  // iterate coaccessible and complete until convergence in oserved
43  while(1) {
44  Idx osize=rGen.States().Size();
45  rGen.Coaccessible();
46  rGen.Complete();
47  if(rGen.States().Size()==osize) break;
48  }
49  // done
50  return !rGen.InitStates().Empty() && !rGen.MarkedStates().Empty();
51 }
52 
53 // rti wrapper
54 bool BuechiTrim(const vGenerator& rGen, vGenerator& rRes) {
55  rRes=rGen;
56  return BuechiTrim(rRes);
57 }
58 
59 // IsBuechiTrim()
60 bool IsBuechiTrim(const vGenerator& rGen) {
61  bool res=true;
62  if(!rGen.IsAccessible()) res=false;
63  else if(!rGen.IsCoaccessible()) res=false;
64  else if(!rGen.IsComplete()) res=false;
65  FD_DF("IsBuechiTrim(): result " << res);
66  return res;
67 }
68 
69 // BuechiClosure(rGen)
70 void BuechiClosure(Generator& rGen) {
71  FD_DF("BuechiClosure("<< rGen.Name() << ")");
72  // fix name
73  std::string name=CollapsString("BuechiClosure("+ rGen.Name() + ")");
74  // remove all states that do net represent prefixes of marked strings
75  BuechiTrim(rGen);
76  // mark all remaining states
77  rGen.InjectMarkedStates(rGen.States());
78  // set name
79  rGen.Name(name);
80 }
81 
82 
83 // IsBuechiClosed
84 bool IsBuechiClosed(const Generator& rGen) {
85  FD_DF("IsBuechiClosed("<< rGen.Name() << ")");
86  // figure irrelevant states: not coaccessible / accessible
87  StateSet irrelevant = rGen.States();
88  irrelevant.EraseSet(rGen.AccessibleSet()* rGen.CoaccessibleSet());
89  // figure irrelevant states: terminal
90  irrelevant.InsertSet(rGen.TerminalStates());
91  // iterative search on indirect terminal states ...
92  bool done;
93  do {
94  // ... over all states
95  StateSet::Iterator sit = rGen.States().Begin();
96  StateSet::Iterator sit_end = rGen.States().End();
97  done=true;
98  for(; sit!=sit_end; ++sit) {
99  if(irrelevant.Exists(*sit)) continue;
100  TransSet::Iterator tit = rGen.TransRelBegin(*sit);
101  TransSet::Iterator tit_end = rGen.TransRelEnd(*sit);
102  for (; tit != tit_end; ++tit) {
103  if(!irrelevant.Exists(tit->X2)) break;
104  }
105  if(tit==tit_end) {
106  irrelevant.Insert(*sit);
107  done=false;
108  }
109  }
110  } while(!done);
111 
112  // marked states are irrelevant here
113  irrelevant.InsertSet(rGen.MarkedStates());
114  // report
115 #ifdef FAUDES_DEBUG_FUNCTION
116  FD_DF("IsBuechiClosed(..): irrelevant states "<< irrelevant.ToString());
117 #endif
118  // locate unmarked SCCs
119  // find all relevant SCCs
121  std::list<StateSet> umsccs;
122  StateSet umroots;
123  ComputeScc(rGen,umfilter,umsccs,umroots);
124  // report
125 #ifdef FAUDES_DEBUG_FUNCTION
126  std::list<StateSet>::iterator ssit=umsccs.begin();
127  for(;ssit!=umsccs.end(); ++ssit) {
128  FD_DF("IsBuechiClosed(): GPlant-marked scc without GCand-mark: " << ssit->ToString());
129  }
130 #endif
131  // done
132  return umsccs.empty();
133 }
134 
135 
136 // helper class for omega compositions
137 class OPState {
138 public:
139  // minimal interface
140  OPState() {};
141  OPState(const Idx& rq1, const Idx& rq2, const bool& rf) :
142  q1(rq1), q2(rq2), m1required(rf), mresolved(false) {};
143  std::string Str(void) { return ToStringInteger(q1)+"|"+
145  // order
146  bool operator < (const OPState& other) const {
147  if (q1 < other.q1) return(true);
148  if (q1 > other.q1) return(false);
149  if (q2 < other.q2) return(true);
150  if (q2 > other.q2) return(false);
151  if (!m1required && other.m1required) return(true);
152  if (m1required && !other.m1required) return(false);
153  if (!mresolved && other.mresolved) return(true);
154  return(false);
155  }
156  // member variables
160  bool mresolved;
161 };
162 
163 
164 
165 // BuechiProduct(rGen1, rGen2, res)
167  const Generator& rGen1, const Generator& rGen2,
168  Generator& rResGen)
169 {
170  FD_DF("BuechiProduct(" << &rGen1 << "," << &rGen2 << ")");
171 
172  // prepare result
173  Generator* pResGen = &rResGen;
174  if(&rResGen== &rGen1 || &rResGen== &rGen2) {
175  pResGen= rResGen.New();
176  }
177  pResGen->Clear();
178  pResGen->Name(CollapsString(rGen1.Name()+".x."+rGen2.Name()));
179 
180  // create res alphabet
181  pResGen->InsEvents(rGen1.Alphabet());
182  pResGen->InsEvents(rGen2.Alphabet());
183 
184  // reverse composition map
185  std::map< OPState, Idx> reverseCompositionMap;
186  // todo stack
187  std::stack< OPState > todo;
188  // current pair, new pair
189  OPState currentstates, newstates;
190  // state
191  Idx tmpstate;
192  StateSet::Iterator lit1, lit2;
193  TransSet::Iterator tit1, tit1_end, tit2, tit2_end;
194  std::map< OPState, Idx>::iterator rcit;
195  // push all combinations of initial states on todo stack
196  FD_DF("BuechiProduct: adding all combinations of initial states to todo:");
197  for (lit1 = rGen1.InitStatesBegin(); lit1 != rGen1.InitStatesEnd(); ++lit1) {
198  for (lit2 = rGen2.InitStatesBegin(); lit2 != rGen2.InitStatesEnd(); ++lit2) {
199  currentstates = OPState(*lit1, *lit2, true);
200  todo.push(currentstates);
201  reverseCompositionMap[currentstates] = pResGen->InsInitState();
202  FD_DF("BuechiProduct: " << currentstates.Str() << " -> " << reverseCompositionMap[currentstates]);
203  }
204  }
205 
206  // start algorithm
207  FD_DF("BuechiProduct: processing reachable states:");
208  while (! todo.empty()) {
209  // allow for user interrupt
210  LoopCallback();
211  // get next reachable state from todo stack
212  currentstates = todo.top();
213  todo.pop();
214  FD_DF("BuechiProduct: processing (" << currentstates.Str() << " -> " << reverseCompositionMap[currentstates]);
215  // iterate over all rGen1 transitions
216  tit1 = rGen1.TransRelBegin(currentstates.q1);
217  tit1_end = rGen1.TransRelEnd(currentstates.q1);
218  for(; tit1 != tit1_end; ++tit1) {
219  // find transition in rGen2
220  tit2 = rGen2.TransRelBegin(currentstates.q2, tit1->Ev);
221  tit2_end = rGen2.TransRelEnd(currentstates.q2, tit1->Ev);
222  for (; tit2 != tit2_end; ++tit2) {
223  newstates = OPState(tit1->X2, tit2->X2,currentstates.m1required);
224  // figure whether marking was resolved
225  if(currentstates.m1required) {
226  if(rGen1.ExistsMarkedState(currentstates.q1))
227  newstates.m1required=false;
228  } else {
229  if(rGen2.ExistsMarkedState(currentstates.q2))
230  newstates.m1required=true;
231  }
232  // add to todo list if composition state is new
233  rcit = reverseCompositionMap.find(newstates);
234  if(rcit == reverseCompositionMap.end()) {
235  todo.push(newstates);
236  tmpstate = pResGen->InsState();
237  if(!newstates.m1required)
238  if(rGen2.ExistsMarkedState(newstates.q2))
239  pResGen->SetMarkedState(tmpstate);
240  reverseCompositionMap[newstates] = tmpstate;
241  FD_DF("BuechiProduct: todo push: (" << newstates.Str() << ") -> " << reverseCompositionMap[newstates]);
242  }
243  else {
244  tmpstate = rcit->second;
245  }
246  pResGen->SetTransition(reverseCompositionMap[currentstates],
247  tit1->Ev, tmpstate);
248  FD_DF("BuechiProduct: add transition to new generator: " <<
249  pResGen->TStr(Transition(reverseCompositionMap[currentstates], tit1->Ev, tmpstate)));
250  }
251  }
252  }
253 
254  FD_DF("BuechiProduct: marked states: " << pResGen->MarkedStatesToString());
255 
256 
257  // fix statenames ...
258  if(rGen1.StateNamesEnabled() && rGen2.StateNamesEnabled() && rResGen.StateNamesEnabled())
259  for(rcit=reverseCompositionMap.begin(); rcit!=reverseCompositionMap.end(); rcit++) {
260  Idx x1=rcit->first.q1;
261  Idx x2=rcit->first.q2;
262  bool m1requ=rcit->first.m1required;
263  Idx x12=rcit->second;
264  if(!pResGen->ExistsState(x12)) continue;
265  std::string name1= rGen1.StateName(x1);
266  if(name1=="") name1=ToStringInteger(x1);
267  std::string name2= rGen2.StateName(x2);
268  if(name2=="") name1=ToStringInteger(x2);
269  std::string name12 = name1 + "|" + name2;
270  if(m1requ) name12 += "|r1m";
271  else name12 +="|r2m";
272  name12=pResGen->UniqueStateName(name12);
273  pResGen->StateName(x12,name12);
274  }
275 
276  // .. or clear them (?)
277  if(!(rGen1.StateNamesEnabled() && rGen2.StateNamesEnabled() && rResGen.StateNamesEnabled()))
278  pResGen->StateNamesEnabled(false);
279 
280  // copy result
281  if(pResGen != &rResGen) {
282  pResGen->Move(rResGen);
283  delete pResGen;
284  }
285 }
286 
287 // BuechiProduct for Generators, transparent for event attributes.
289  const Generator& rGen1,
290  const Generator& rGen2,
291  Generator& rResGen)
292 {
293  // inputs have to agree on attributes of shared events:
294  bool careattr=rGen1.Alphabet().EqualAttributes(rGen2.Alphabet());
295  // prepare result
296  Generator* pResGen = &rResGen;
297  if(&rResGen== &rGen1 || &rResGen== &rGen2) {
298  pResGen= rResGen.New();
299  }
300  // make product composition of inputs
301  BuechiProduct(rGen1,rGen2,*pResGen);
302  // copy all attributes of input alphabets
303  if(careattr) {
304  pResGen->EventAttributes(rGen1.Alphabet());
305  pResGen->EventAttributes(rGen2.Alphabet());
306  }
307  // copy result
308  if(pResGen != &rResGen) {
309  pResGen->Move(rResGen);
310  delete pResGen;
311  }
312 }
313 
314 
315 // BuechiParallel(rGen1, rGen2, res)
317  const Generator& rGen1, const Generator& rGen2,
318  Generator& rResGen)
319 {
320  FD_DF("BuechiParallel(" << &rGen1 << "," << &rGen2 << ")");
321  // prepare result
322  Generator* pResGen = &rResGen;
323  if(&rResGen== &rGen1 || &rResGen== &rGen2) {
324  pResGen= rResGen.New();
325  }
326  pResGen->Clear();
327  pResGen->Name(CollapsString(rGen1.Name()+"|||"+rGen2.Name()));
328  // create res alphabet
329  pResGen->InsEvents(rGen1.Alphabet());
330  pResGen->InsEvents(rGen2.Alphabet());
331  // shared events
332  EventSet sharedalphabet = rGen1.Alphabet() * rGen2.Alphabet();
333  FD_DF("BuechiParallel: g1 events: " << rGen1.Alphabet().ToString());
334  FD_DF("BuechiParallel: g2 events: " << rGen2.Alphabet().ToString());
335  FD_DF("BuechiParallel: shared events: " << sharedalphabet.ToString());
336 
337  // reverse composition map
338  std::map< OPState, Idx> reverseCompositionMap;
339  // todo stack
340  std::stack< OPState > todo;
341  // current pair, new pair
342  OPState currentstates, newstates;
343  // state
344  Idx tmpstate;
345  StateSet::Iterator lit1, lit2;
346  TransSet::Iterator tit1, tit1_end, tit2, tit2_end;
347  std::map< OPState, Idx>::iterator rcit;
348  // push all combinations of initial states on todo stack
349  FD_DF("BuechiParallel: adding all combinations of initial states to todo:");
350  for (lit1 = rGen1.InitStatesBegin(); lit1 != rGen1.InitStatesEnd(); ++lit1) {
351  for (lit2 = rGen2.InitStatesBegin(); lit2 != rGen2.InitStatesEnd(); ++lit2) {
352  currentstates = OPState(*lit1, *lit2, true);
353  tmpstate=pResGen->InsInitState();
354  if(rGen2.ExistsMarkedState(*lit2)) {
355  currentstates.mresolved=true;
356  pResGen->SetMarkedState(tmpstate);
357  }
358  todo.push(currentstates);
359  reverseCompositionMap[currentstates] = tmpstate;
360  FD_DF("BuechiParallel: " << currentstates.Str() << " -> " << tmpstate);
361  }
362  }
363 
364  // start algorithm
365  FD_DF("BuechiParallel: processing reachable states:");
366  while (! todo.empty()) {
367  // allow for user interrupt
368  LoopCallback();
369  // get next reachable state from todo stack
370  currentstates = todo.top();
371  todo.pop();
372  FD_DF("BuechiParallel: processing (" << currentstates.Str() << " -> "
373  << reverseCompositionMap[currentstates]);
374  // iterate over all rGen1 transitions
375  // (includes execution of shared events)
376  tit1 = rGen1.TransRelBegin(currentstates.q1);
377  tit1_end = rGen1.TransRelEnd(currentstates.q1);
378  for(; tit1 != tit1_end; ++tit1) {
379  // if event not shared
380  if(! sharedalphabet.Exists(tit1->Ev)) {
381  FD_DF("BuechiParallel: exists only in rGen1");
382  newstates = OPState(tit1->X2, currentstates.q2, currentstates.m1required);
383  // figure whether marking is resolved
384  // (tmoor 201208: only m1required can be resolved, since only G1 proceeds)
385  if(currentstates.m1required) {
386  if(rGen1.ExistsMarkedState(newstates.q1)) {
387  newstates.m1required=false;
388  //newstates.mresolved=true; // optional
389  }
390  }
391  // add to todo list if composition state is new
392  rcit = reverseCompositionMap.find(newstates);
393  if (rcit == reverseCompositionMap.end()) {
394  todo.push(newstates);
395  tmpstate = pResGen->InsState();
396  if(newstates.mresolved) pResGen->SetMarkedState(tmpstate);
397  reverseCompositionMap[newstates] = tmpstate;
398  FD_DF("BuechiParallel: todo push: " << newstates.Str() << "|"
399  << reverseCompositionMap[newstates]);
400  }
401  else {
402  tmpstate = rcit->second;
403  }
404  // insert transition to result
405  pResGen->SetTransition(reverseCompositionMap[currentstates], tit1->Ev,
406  tmpstate);
407  FD_DF("BuechiParallel: add transition to new generator: " <<
408  pResGen->TStr(Transition(reverseCompositionMap[currentstates], tit1->Ev, tmpstate)));
409  }
410  // if shared event
411  else {
412  FD_DF("BuechiParallel: common event");
413  // find shared transitions
414  tit2 = rGen2.TransRelBegin(currentstates.q2, tit1->Ev);
415  tit2_end = rGen2.TransRelEnd(currentstates.q2, tit1->Ev);
416  for (; tit2 != tit2_end; ++tit2) {
417  newstates = OPState(tit1->X2,tit2->X2,currentstates.m1required);
418  // figure whether marking was resolved
419  // (tmoor 201208: both markings can be resolved, since both G1 and G2 proceed)
420  if(currentstates.m1required) {
421  if(rGen1.ExistsMarkedState(newstates.q1)) {
422  newstates.m1required=false;
423  //newstates.mresolved=true; // optional
424  }
425  } else {
426  if(rGen2.ExistsMarkedState(newstates.q2)) {
427  newstates.m1required=true;
428  newstates.mresolved=true;
429  }
430  }
431  // add to todo list if composition state is new
432  rcit = reverseCompositionMap.find(newstates);
433  if (rcit == reverseCompositionMap.end()) {
434  todo.push(newstates);
435  tmpstate = pResGen->InsState();
436  if(newstates.mresolved) pResGen->SetMarkedState(tmpstate);
437  reverseCompositionMap[newstates] = tmpstate;
438  FD_DF("BuechiParallel: todo push: (" << newstates.Str() << ") -> "
439  << reverseCompositionMap[newstates]);
440  }
441  else {
442  tmpstate = rcit->second;
443  }
444  pResGen->SetTransition(reverseCompositionMap[currentstates],
445  tit1->Ev, tmpstate);
446  FD_DF("BuechiParallel: add transition to new generator: " <<
447  pResGen->TStr(Transition(reverseCompositionMap[currentstates], tit1->Ev, tmpstate)));
448  }
449  }
450  }
451  // iterate over all remaining rGen2 transitions
452  // (without execution of shared events)
453  tit2 = rGen2.TransRelBegin(currentstates.q2);
454  tit2_end = rGen2.TransRelEnd(currentstates.q2);
455  for (; tit2 != tit2_end; ++tit2) {
456  if (! sharedalphabet.Exists(tit2->Ev)) {
457  FD_DF("BuechiParallel: exists only in rGen2: " << sharedalphabet.Str(tit2->Ev));
458  newstates = OPState(currentstates.q1, tit2->X2, currentstates.m1required);
459  // figure whether marking was resolved
460  // (tmoor 201208: only m2required=!m1required can be resolved, since only G2 proceeds)
461  if(!currentstates.m1required) {
462  if(rGen2.ExistsMarkedState(newstates.q2)) {
463  newstates.m1required=true;
464  newstates.mresolved=true;
465  }
466  }
467  FD_DF("BuechiParallel: set trans: " << currentstates.Str() << " " << newstates.Str());
468  // add to todo list if composition state is new
469  rcit = reverseCompositionMap.find(newstates);
470  if (rcit == reverseCompositionMap.end()) {
471  todo.push(newstates);
472  tmpstate = pResGen->InsState();
473  if(newstates.mresolved) pResGen->SetMarkedState(tmpstate);
474  reverseCompositionMap[newstates] = tmpstate;
475  FD_DF("BuechiParallel: todo push: " << newstates.Str() << " -> "
476  << reverseCompositionMap[newstates]);
477  }
478  else {
479  tmpstate = rcit->second;
480  }
481  pResGen->SetTransition(reverseCompositionMap[currentstates],
482  tit2->Ev, tmpstate);
483  FD_DF("BuechiParallel: add transition to new generator: " <<
484  pResGen->TStr(Transition(reverseCompositionMap[currentstates], tit2->Ev, tmpstate)));
485  }
486  }
487  }
488 
489  FD_DF("BuechiParallel: marked states: " << pResGen->MarkedStatesToString());
490 
491  // fix statenames ...
492  if(rGen1.StateNamesEnabled() && rGen2.StateNamesEnabled() && rResGen.StateNamesEnabled())
493  for(rcit=reverseCompositionMap.begin(); rcit!=reverseCompositionMap.end(); rcit++) {
494  Idx x1=rcit->first.q1;
495  Idx x2=rcit->first.q2;
496  bool m1requ=rcit->first.m1required;
497  bool mres=rcit->first.mresolved;
498  Idx x12=rcit->second;
499  if(!pResGen->ExistsState(x12)) continue;
500  std::string name1= rGen1.StateName(x1);
501  if(name1=="") name1=ToStringInteger(x1);
502  std::string name2= rGen2.StateName(x2);
503  if(name2=="") name1=ToStringInteger(x2);
504  std::string name12 = name1 + "|" + name2 ;
505  if(m1requ) name12 += "|r1m";
506  else name12 +="|r2m";
507  if(mres) name12 += "*";
508  name12=pResGen->UniqueStateName(name12);
509  pResGen->StateName(x12,name12);
510  }
511 
512  // .. or clear them (?)
513  if(!(rGen1.StateNamesEnabled() && rGen2.StateNamesEnabled() && rResGen.StateNamesEnabled()))
514  pResGen->StateNamesEnabled(false);
515 
516  // copy result
517  if(pResGen != &rResGen) {
518  pResGen->Move(rResGen);
519  delete pResGen;
520  }
521 }
522 
523 
524 // BuechiParallel for Generators, transparent for event attributes.
526  const Generator& rGen1,
527  const Generator& rGen2,
528  Generator& rResGen)
529 {
530  // inputs have to agree on attributes of shared events:
531  bool careattr=rGen1.Alphabet().EqualAttributes(rGen2.Alphabet());
532  // prepare result
533  Generator* pResGen = &rResGen;
534  if(&rResGen== &rGen1 || &rResGen== &rGen2) {
535  pResGen= rResGen.New();
536  }
537  // make product composition of inputs
538  BuechiParallel(rGen1,rGen2,*pResGen);
539  // copy all attributes of input alphabets
540  if(careattr) {
541  pResGen->EventAttributes(rGen1.Alphabet());
542  pResGen->EventAttributes(rGen2.Alphabet());
543  }
544  // copy result
545  if(pResGen != &rResGen) {
546  pResGen->Move(rResGen);
547  delete pResGen;
548  }
549 }
550 
551 
552 // IsOmegaRelativelyMarked(rGenPlant,rGenCand)
553 bool IsBuechiRelativelyMarked(const Generator& rGenPlant, const Generator& rGenCand) {
554 
555 
556  FD_DF("IsBuechiRelativelyMarked(\"" << rGenPlant.Name() << "\", \"" << rGenCand.Name() << "\")");
557 
558  // alphabets must match
559  if ( rGenPlant.Alphabet() != rGenCand.Alphabet()) {
560  std::stringstream errstr;
561  errstr << "Alphabets of generators do not match.";
562  throw Exception("BuechiRelativelyMarked", errstr.str(), 100);
563  }
564 
565 #ifdef FAUDES_CHECKED
566  // generators are meant to be nonblocking
567  if ( !IsBuechiTrim(rGenCand) || !IsBuechiTrim(rGenPlant)) {
568  std::stringstream errstr;
569  errstr << "Arguments are expected to be nonblocking.";
570  throw Exception("IsBuechiRelativelyMarked", errstr.str(), 201);
571  }
572 #endif
573 
574 #ifdef FAUDES_CHECKED
575  // generators are meant to be deterministic
576  if ( !IsDeterministic(rGenCand) || !IsDeterministic(rGenPlant)) {
577  std::stringstream errstr;
578  errstr << "Arguments are expected to be deterministic.";
579  throw Exception("IsBuechiRelativelyMarked", errstr.str(), 202);
580  }
581 #endif
582 
583 
584  // perform composition
585  std::map< std::pair<Idx,Idx> , Idx> revmap;
586  Generator product;
587  product.StateNamesEnabled(false);
588  StateSet markCand;
589  StateSet markPlant;
590  Product(rGenPlant,rGenCand,revmap,markPlant,markCand,product);
591 
592  // find all relevant SCCs
594  markCand,markPlant);
595  std::list<StateSet> umsccs;
596  StateSet umroots;
597  ComputeScc(product,umfilter,umsccs,umroots);
598 
599  // report
600  std::list<StateSet>::iterator ssit=umsccs.begin();
601  for(;ssit!=umsccs.end(); ++ssit) {
602  FD_DF("IsBuechiRelativelyMarked(): GPlant-marked scc without GCand-mark: " << ssit->ToString());
603  }
604 
605  // result is true if no problematic SCCs exist
606  return umsccs.size()==0;
607 
608 }
609 
610 
611 
612 
613 // IsOmegaRelativelyClosed(rGenPlant,rGenCand)
614 bool IsBuechiRelativelyClosed(const Generator& rGenPlant, const Generator& rGenCand) {
615 
616 
617  FD_DF("IsBuechiRelativelyClosed(\"" << rGenPlant.Name() << "\", \"" << rGenCand.Name() << "\")");
618 
619  // alphabets must match
620  if ( rGenPlant.Alphabet() != rGenCand.Alphabet()) {
621  std::stringstream errstr;
622  errstr << "Alphabets of generators do not match.";
623  throw Exception("BuechiRelativelyClosed", errstr.str(), 100);
624  }
625 
626 #ifdef FAUDES_CHECKED
627  // generators are meant to be nonblocking
628  if( !IsBuechiTrim(rGenCand) ) {
629  std::stringstream errstr;
630  errstr << "Argument \"" << rGenCand.Name() << "\" is not omegatrim.";
631  throw Exception("IsBuechiRelativelyClosed", errstr.str(), 201);
632  }
633  if( !IsBuechiTrim(rGenPlant) ) {
634  std::stringstream errstr;
635  errstr << "Argument \"" << rGenPlant.Name() << "\" is not omega-trim.";
636  throw Exception("IsBuechiRelativelyClosed", errstr.str(), 201);
637  }
638 #endif
639 
640 
641  // the trivial case: if B1 is empty it is relatively closed
642  // (we must treat this case because empty generators are not regarded deterministic)
643  if(rGenCand.Empty()) {
644  FD_DF("IsBuechiRelativelyClosed(..): empty candidate: pass");
645  return true;
646  }
647 
648  // the trivial case: if B2 is empty but B1 is not empty, the test failed
649  // (we must treat this case because empty generators are not regarded deterministic)
650  if(rGenPlant.Empty()) {
651  FD_DF("IsBuechiRelativelyClosed(..): non-empty candidate. empty plant: fail");
652  return false;
653  }
654 
655 #ifdef FAUDES_CHECKED
656  // generators are meant to be deterministic
657  if ( !IsDeterministic(rGenCand) || !IsDeterministic(rGenPlant)) {
658  std::stringstream errstr;
659  errstr << "Arguments are expected to be deterministic.";
660  throw Exception("IsBuechiRelativelyClosed", errstr.str(), 202);
661  }
662 #endif
663 
664  // doit
665  return IsBuechiRelativelyClosedUnchecked(rGenPlant,rGenCand);
666 }
667 
668 
669 // IsOmegaRelativelyClosed(rGenPlant,rGenCand)
670 bool IsBuechiRelativelyClosedUnchecked(const Generator& rGenPlant, const Generator& rGenCand) {
671 
672  // perform composition (variant of cfl_parallel.cpp)
673  std::map< std::pair<Idx,Idx> , Idx> revmap;
674  Generator product;
675  product.StateNamesEnabled(false);
676  StateSet mark1;
677  StateSet mark2;
678 
679  // shared alphabet
680  product.InjectAlphabet(rGenCand.Alphabet());
681 
682  // todo stack
683  std::stack< std::pair<Idx,Idx> > todo;
684  // current pair, new pair
685  std::pair<Idx,Idx> currentstates, newstates;
686  // state
687  Idx tmpstate;
688  // iterators
689  StateSet::Iterator lit1, lit2;
690  TransSet::Iterator tit1, tit1_end, tit2, tit2_end;
691  std::map< std::pair<Idx,Idx>, Idx>::iterator rcit;
692  // sense violation of L(GenCand) <= L(GenPlant)
693  bool inclusion12=true;
694 
695  // push all combinations of initial states on todo stack
696  FD_DF("IsBuechiRelativelyClosed(): Product composition A");
697  for (lit1 = rGenCand.InitStatesBegin();
698  lit1 != rGenCand.InitStatesEnd(); ++lit1) {
699  for (lit2 = rGenPlant.InitStatesBegin();
700  lit2 != rGenPlant.InitStatesEnd(); ++lit2) {
701  currentstates = std::make_pair(*lit1, *lit2);
702  todo.push(currentstates);
703  tmpstate = product.InsInitState();
704  revmap[currentstates] = tmpstate;
705  FD_DF("IsBuechiRelativelyClosed(): Product composition A: (" << *lit1 << "|" << *lit2 << ") -> "
706  << revmap[currentstates]);
707  }
708  }
709 
710  // start algorithm
711  while (! todo.empty() && inclusion12) {
712  // allow for user interrupt
713  LoopCallback();
714  // get next reachable state from todo stack
715  currentstates = todo.top();
716  todo.pop();
717  FD_DF("IsBuechiRelativelyClosed(): Product composition B: (" << currentstates.first << "|"
718  << currentstates.second << ") -> " << revmap[currentstates]);
719  // iterate over all rGenCand transitions
720  tit1 = rGenCand.TransRelBegin(currentstates.first);
721  tit1_end = rGenCand.TransRelEnd(currentstates.first);
722  tit2 = rGenPlant.TransRelBegin(currentstates.second);
723  tit2_end = rGenPlant.TransRelEnd(currentstates.second);
724  Idx curev1=0;
725  bool resolved12=true;
726  while((tit1 != tit1_end) && (tit2 != tit2_end)) {
727  // sense new event
728  if(tit1->Ev != curev1) {
729  if(!resolved12) inclusion12=false;
730  curev1=tit1->Ev;
731  resolved12=false;
732  }
733  // shared event
734  if (tit1->Ev == tit2->Ev) {
735  resolved12=true;
736  newstates = std::make_pair(tit1->X2, tit2->X2);
737  // add to todo list if composition state is new
738  rcit = revmap.find(newstates);
739  if (rcit == revmap.end()) {
740  todo.push(newstates);
741  tmpstate = product.InsState();
742  revmap[newstates] = tmpstate;
743  FD_DF("IsBuechiRelativelyClosed(): Product composition C: (" << newstates.first << "|"
744  << newstates.second << ") -> " << revmap[newstates]);
745  }
746  else {
747  tmpstate = rcit->second;
748  }
749  product.SetTransition(revmap[currentstates], tit1->Ev, tmpstate);
750  ++tit1;
751  ++tit2;
752  }
753  // try resync tit1
754  else if (tit1->Ev < tit2->Ev) {
755  ++tit1;
756  }
757  // try resync tit2
758  else if (tit1->Ev > tit2->Ev) {
759  ++tit2;
760  }
761  }
762  // last event was not resolved in the product
763  if(!resolved12) inclusion12=false;
764  }
765  // report
766 #ifdef FAUDES_DEBUG_FUNCTION
767  FD_DF("IsBuechiRelativelyClosed(): Product: done");
768  if(!inclusion12) {
769  FD_DF("IsBuechiRelativelyClosed(): Product: inclusion L(GenCand) <= L(GenPlant) not satisfied");
770  }
771 #endif
772 
773  // bail out
774  if(!inclusion12) return false;
775 
776  // retrieve marking from reverse composition map
777  std::map< std::pair<Idx,Idx>, Idx>::iterator rit;
778  for(rit=revmap.begin(); rit!=revmap.end(); ++rit){
779  if(rGenCand.ExistsMarkedState(rit->first.first)) mark1.Insert(rit->second);
780  if(rGenPlant.ExistsMarkedState(rit->first.second)) mark2.Insert(rit->second);
781  }
782 
783  // find all relevant SCCs 1
785  mark1,mark2);
786  std::list<StateSet> umsccs12;
787  StateSet umroots12;
788  ComputeScc(product,umfilter12,umsccs12,umroots12);
789 
790  // report
791  std::list<StateSet>::iterator ssit=umsccs12.begin();
792  for(;ssit!=umsccs12.end(); ++ssit) {
793  FD_DF("IsBuechiRelativelyClosed(): G2-marked scc without G1-mark: " << ssit->ToString());
794  }
795 
796  // result is false if we found problematic SCCs to exist
797  if(umsccs12.size()!=0) return false;
798 
799  // find all relevant SCCs 2
801  mark2,mark1);
802  std::list<StateSet> umsccs21;
803  StateSet umroots21;
804  ComputeScc(product,umfilter21,umsccs21,umroots21);
805 
806  // report
807  ssit=umsccs21.begin();
808  for(;ssit!=umsccs21.end(); ++ssit) {
809  FD_DF("IsBuechiRelativelyClosed(): G1-marked scc without G2-mark: " << ssit->ToString());
810  }
811 
812  // result is false if we found problematic SCCs to exist
813  if(umsccs21.size()!=0) return false;
814 
815  // done, all tests passed
816  FD_DF("IsBuechiRelativelyClosed(): pass");
817  return true;
818 }
819 
820 
821 // LanguageInclusion
822 bool BuechiLanguageInclusion(const Generator& rGen1, const Generator& rGen2) {
823 
824  FD_DF("BuechiLanguageInclusion(\"" << rGen1.Name() << "\", \"" << rGen2.Name() << "\")");
825 
826  // alphabets must match
827  if ( rGen1.Alphabet() != rGen2.Alphabet()) {
828  std::stringstream errstr;
829  errstr << "Alphabets of generators do not match.";
830  throw Exception("BuechiLanguageInclusion", errstr.str(), 100);
831  }
832 
833 #ifdef FAUDES_CHECKED
834  // generators are meant to be nonblocking
835  if( !IsBuechiTrim(rGen1) ) {
836  std::stringstream errstr;
837  errstr << "Argument \"" << rGen1.Name() << "\" is not omegatrim.";
838  throw Exception("BuechiLanguageInclusion", errstr.str(), 201);
839  }
840  if( !IsBuechiTrim(rGen2) ) {
841  std::stringstream errstr;
842  errstr << "Argument \"" << rGen2.Name() << "\" is not omega-trim.";
843  throw Exception("BuechiLanguageInclusion", errstr.str(), 201);
844  }
845 #endif
846 
847  // the trivial case: if B1 is empty it is relatively closed
848  // (we must treat this case because empty generators are not regarded deterministic)
849  if(rGen1.Empty()) {
850  FD_DF("BuechiLanguageInclusion(..): empty candidate: pass");
851  return true;
852  }
853 
854  // the trivial case: if B2 is empty but B1 is not empty, the test failed
855  // (we must treat this case because empty generators are not regarded deterministic)
856  if(rGen2.Empty()) {
857  FD_DF("BuechiLanguageInclusion(..): non-empty candidate. empty plant: fail");
858  return false;
859  }
860 
861 #ifdef FAUDES_CHECKED
862  // generators are meant to be deterministic
863  if ( !IsDeterministic(rGen1) || !IsDeterministic(rGen2)) {
864  std::stringstream errstr;
865  errstr << "Arguments are expected to be deterministic.";
866  throw Exception("BuechiLanguageInclusion", errstr.str(), 202);
867  }
868 #endif
869 
870  // perform composition (variant of cfl_parallel.cpp)
871  std::map< std::pair<Idx,Idx> , Idx> revmap;
872  Generator product;
873  product.StateNamesEnabled(false);
874  StateSet mark1;
875  StateSet mark2;
876 
877  // shared alphabet
878  product.InjectAlphabet(rGen1.Alphabet());
879 
880  // todo stack
881  std::stack< std::pair<Idx,Idx> > todo;
882  // current pair, new pair
883  std::pair<Idx,Idx> currentstates, newstates;
884  // state
885  Idx tmpstate;
886  // iterators
887  StateSet::Iterator lit1, lit2;
888  TransSet::Iterator tit1, tit1_end, tit2, tit2_end;
889  std::map< std::pair<Idx,Idx>, Idx>::iterator rcit;
890  // sense violation of L(Gen1) <= L(Gen2)
891  bool inclusion12=true;
892 
893  // push all combinations of initial states on todo stack
894  FD_DF("BuechiLanguageInclusion(): Product composition A");
895  for (lit1 = rGen1.InitStatesBegin();
896  lit1 != rGen1.InitStatesEnd(); ++lit1) {
897  for (lit2 = rGen2.InitStatesBegin();
898  lit2 != rGen2.InitStatesEnd(); ++lit2) {
899  currentstates = std::make_pair(*lit1, *lit2);
900  todo.push(currentstates);
901  tmpstate = product.InsInitState();
902  revmap[currentstates] = tmpstate;
903  FD_DF("BuechiLanguageInclusion(): Product composition A: (" << *lit1 << "|" << *lit2 << ") -> "
904  << revmap[currentstates]);
905  }
906  }
907 
908  // start algorithm
909  while (! todo.empty() && inclusion12) {
910  // allow for user interrupt
911  LoopCallback();
912  // get next reachable state from todo stack
913  currentstates = todo.top();
914  todo.pop();
915  FD_DF("BuechiLanguageInclusion(): Product composition B: (" << currentstates.first << "|"
916  << currentstates.second << ") -> " << revmap[currentstates]);
917  // iterate over all rGenCand transitions
918  tit1 = rGen1.TransRelBegin(currentstates.first);
919  tit1_end = rGen1.TransRelEnd(currentstates.first);
920  tit2 = rGen2.TransRelBegin(currentstates.second);
921  tit2_end = rGen2.TransRelEnd(currentstates.second);
922  Idx curev1=0;
923  bool resolved12=true;
924  while((tit1 != tit1_end) && (tit2 != tit2_end)) {
925  // sense new event
926  if(tit1->Ev != curev1) {
927  if(!resolved12) inclusion12=false;
928  curev1=tit1->Ev;
929  resolved12=false;
930  }
931  // shared event
932  if (tit1->Ev == tit2->Ev) {
933  resolved12=true;
934  newstates = std::make_pair(tit1->X2, tit2->X2);
935  // add to todo list if composition state is new
936  rcit = revmap.find(newstates);
937  if (rcit == revmap.end()) {
938  todo.push(newstates);
939  tmpstate = product.InsState();
940  revmap[newstates] = tmpstate;
941  FD_DF("BuechiLanguageInclusion(): Product composition C: (" << newstates.first << "|"
942  << newstates.second << ") -> " << revmap[newstates]);
943  }
944  else {
945  tmpstate = rcit->second;
946  }
947  product.SetTransition(revmap[currentstates], tit1->Ev, tmpstate);
948  ++tit1;
949  ++tit2;
950  }
951  // try resync tit1
952  else if (tit1->Ev < tit2->Ev) {
953  ++tit1;
954  }
955  // try resync tit2
956  else if (tit1->Ev > tit2->Ev) {
957  ++tit2;
958  }
959  }
960  // last event was not resolved in the product
961  if(!resolved12) inclusion12=false;
962  }
963  // report
964 #ifdef FAUDES_DEBUG_FUNCTION
965  FD_DF("BuechiLanguageInclusion(): Product: done");
966  if(!inclusion12) {
967  FD_DF("BuechiLanguageInclusion(): Product: inclusion L(Gen1) <= L(Gen2) not satisfied");
968  }
969 #endif
970 
971  // bail out
972  if(!inclusion12) return false;
973 
974  // retrieve marking from reverse composition map
975  std::map< std::pair<Idx,Idx>, Idx>::iterator rit;
976  for(rit=revmap.begin(); rit!=revmap.end(); ++rit){
977  if(rGen1.ExistsMarkedState(rit->first.first)) mark1.Insert(rit->second);
978  if(rGen2.ExistsMarkedState(rit->first.second)) mark2.Insert(rit->second);
979  }
980 
981  // find all relevant SCCs
983  mark2,mark1);
984  std::list<StateSet> umsccs21;
985  StateSet umroots21;
986  ComputeScc(product,umfilter21,umsccs21,umroots21);
987 
988  // report
989  std::list<StateSet>::iterator ssit=umsccs21.begin();
990  for(;ssit!=umsccs21.end(); ++ssit) {
991  FD_DF("BuechiLanguageInclusion(): G1-marked scc without G2-mark: " << ssit->ToString());
992  }
993 
994  // result is false if we found problematic SCCs to exist
995  if(umsccs21.size()!=0) return false;
996 
997  // done, all tests passed
998  FD_DF("BuechiLanguageInclusion(): pass");
999  return true;
1000 }
1001 
1002 
1003 // LanguageEquality
1004 bool BuechiLanguageEquality(const Generator& rGen1, const Generator& rGen2) {
1005 
1006  FD_DF("BuechiLanguageEquality(\"" << rGen1.Name() << "\", \"" << rGen2.Name() << "\")");
1007 
1008  // alphabets must match
1009  if ( rGen1.Alphabet() != rGen2.Alphabet()) {
1010  std::stringstream errstr;
1011  errstr << "Alphabets of generators do not match.";
1012  throw Exception("BuechiLanguageEquality", errstr.str(), 100);
1013  }
1014 
1015 #ifdef FAUDES_CHECKED
1016  // generators are meant to be nonblocking
1017  if( !IsBuechiTrim(rGen1) ) {
1018  std::stringstream errstr;
1019  errstr << "Argument \"" << rGen1.Name() << "\" is not omegatrim.";
1020  throw Exception("BuechiLanguageEquality", errstr.str(), 201);
1021  }
1022  if( !IsBuechiTrim(rGen2) ) {
1023  std::stringstream errstr;
1024  errstr << "Argument \"" << rGen2.Name() << "\" is not omega-trim.";
1025  throw Exception("BuechiLanguageEquality", errstr.str(), 201);
1026  }
1027 #endif
1028 
1029 
1030  // the trivial case: both are empty, or one is empty and one not
1031  // (we must treat this case because empty generators are not regarded deterministic)
1032  bool empty1=rGen1.Empty();
1033  bool empty2=rGen2.Empty();
1034  if( empty1 && empty2) {
1035  FD_DF("BuechiLanguageEquality(..): empty candidates: pass");
1036  return true;
1037  }
1038  if( empty1 != empty2) {
1039  FD_DF("BuechiLanguageEquality(..): empty/non-empty candidates: fail");
1040  return false;
1041  }
1042 
1043 #ifdef FAUDES_CHECKED
1044  // generators are meant to be deterministic
1045  if ( !IsDeterministic(rGen1) || !IsDeterministic(rGen2)) {
1046  std::stringstream errstr;
1047  errstr << "Arguments are expected to be deterministic.";
1048  throw Exception("BuechiLanguageEquality", errstr.str(), 202);
1049  }
1050 #endif
1051 
1052  // perform composition (variant of cfl_parallel.cpp)
1053  std::map< std::pair<Idx,Idx> , Idx> revmap;
1054  Generator product;
1055  product.StateNamesEnabled(false);
1056  StateSet mark1;
1057  StateSet mark2;
1058 
1059  // shared alphabet
1060  product.InjectAlphabet(rGen1.Alphabet());
1061 
1062  // todo stack
1063  std::stack< std::pair<Idx,Idx> > todo;
1064  // current pair, new pair
1065  std::pair<Idx,Idx> currentstates, newstates;
1066  // state
1067  Idx tmpstate;
1068  // iterators
1069  StateSet::Iterator lit1, lit2;
1070  TransSet::Iterator tit1, tit1_end, tit2, tit2_end;
1071  std::map< std::pair<Idx,Idx>, Idx>::iterator rcit;
1072  // sense violation of L(Gen1) = L(Gen2)
1073  bool equal12=true;
1074 
1075  // push all combinations of initial states on todo stack
1076  FD_DF("BuechiLanguageEquality(): Product composition A");
1077  for (lit1 = rGen1.InitStatesBegin();
1078  lit1 != rGen1.InitStatesEnd(); ++lit1) {
1079  for (lit2 = rGen2.InitStatesBegin();
1080  lit2 != rGen2.InitStatesEnd(); ++lit2) {
1081  currentstates = std::make_pair(*lit1, *lit2);
1082  todo.push(currentstates);
1083  tmpstate = product.InsInitState();
1084  revmap[currentstates] = tmpstate;
1085  FD_DF("BuechiLanguageEquality(): Product composition A: (" << *lit1 << "|" << *lit2 << ") -> "
1086  << revmap[currentstates]);
1087  }
1088  }
1089 
1090  // start algorithm
1091  while (! todo.empty() && equal12) {
1092  // allow for user interrupt
1093  LoopCallback();
1094  // get next reachable state from todo stack
1095  currentstates = todo.top();
1096  todo.pop();
1097  FD_DF("BuechiLanguageEquality(): Product composition B: (" << currentstates.first << "|"
1098  << currentstates.second << ") -> " << revmap[currentstates]);
1099  // iterate over all rGen1, rGen2 transitions
1100  tit1 = rGen1.TransRelBegin(currentstates.first);
1101  tit1_end = rGen1.TransRelEnd(currentstates.first);
1102  tit2 = rGen2.TransRelBegin(currentstates.second);
1103  tit2_end = rGen2.TransRelEnd(currentstates.second);
1104  while((tit1 != tit1_end) && (tit2 != tit2_end)) {
1105  // event mismatch
1106  if (tit1->Ev != tit2->Ev) {
1107  equal12=false;
1108  break;
1109  }
1110  // matching event
1111  newstates = std::make_pair(tit1->X2, tit2->X2);
1112  // add to todo list if composition state is new
1113  rcit = revmap.find(newstates);
1114  if (rcit == revmap.end()) {
1115  todo.push(newstates);
1116  tmpstate = product.InsState();
1117  revmap[newstates] = tmpstate;
1118  FD_DF("BuechiLanguageEquality(): Product composition C: (" << newstates.first << "|"
1119  << newstates.second << ") -> " << revmap[newstates]);
1120  } else {
1121  tmpstate = rcit->second;
1122  }
1123  product.SetTransition(revmap[currentstates], tit1->Ev, tmpstate);
1124  ++tit1;
1125  ++tit2;
1126  }
1127  }
1128  // report
1129 #ifdef FAUDES_DEBUG_FUNCTION
1130  FD_DF("BuechiLanguageEquality(): Product: done");
1131  if(!equal12) {
1132  FD_DF("BuechiLanguageEquality(): Product: inclusion L(Gen1) == L(Gen2) not satisfied");
1133  }
1134 #endif
1135 
1136  // bail out
1137  if(!equal12) return false;
1138 
1139  // retrieve marking from reverse composition map
1140  std::map< std::pair<Idx,Idx>, Idx>::iterator rit;
1141  for(rit=revmap.begin(); rit!=revmap.end(); ++rit){
1142  if(rGen1.ExistsMarkedState(rit->first.first)) mark1.Insert(rit->second);
1143  if(rGen2.ExistsMarkedState(rit->first.second)) mark2.Insert(rit->second);
1144  }
1145 
1146  // find all relevant SCCs 1
1148  mark2,mark1);
1149  std::list<StateSet> umsccs12;
1150  StateSet umroots12;
1151  ComputeScc(product,umfilter12,umsccs12,umroots12);
1152 
1153  // report
1154  std::list<StateSet>::iterator ssit=umsccs12.begin();
1155  for(;ssit!=umsccs12.end(); ++ssit) {
1156  FD_DF("BuechiLanguageEquality(): G1-marked scc without G2-mark: " << ssit->ToString());
1157  }
1158 
1159  // result is false if we found problematic SCCs to exist
1160  if(umsccs12.size()!=0) return false;
1161 
1162  // find all relevant SCCs 2
1164  mark1,mark2);
1165  std::list<StateSet> umsccs21;
1166  StateSet umroots21;
1167  ComputeScc(product,umfilter21,umsccs21,umroots21);
1168 
1169  // report
1170  ssit=umsccs21.begin();
1171  for(;ssit!=umsccs21.end(); ++ssit) {
1172  FD_DF("BuechiLanguageEquality(): G2-marked scc without G1-mark: " << ssit->ToString());
1173  }
1174 
1175  // result is false if we found problematic SCCs to exist
1176  if(umsccs21.size()!=0) return false;
1177 
1178  // done, all tests passed
1179  FD_DF("BuechiLanguageEquality(): pass");
1180  return true;
1181 }
1182 
1183 
1184 
1185 } // namespace faudes
1186 
#define FD_DF(message)
const std::string & Name(void) const
Definition: cfl_types.cpp:422
bool Exists(const Idx &rIndex) const
virtual std::string Str(const Idx &rIndex) const
bool operator<(const OPState &other) const
OPState(const Idx &rq1, const Idx &rq2, const bool &rf)
std::string Str(void)
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
Definition: cfl_transset.h:273
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
Definition: cfl_types.cpp:175
StateSet::Iterator InitStatesBegin(void) const
bool SetTransition(Idx x1, Idx ev, Idx x2)
const StateSet & MarkedStates(void) const
const EventSet & Alphabet(void) const
virtual void Move(vGenerator &rGen)
std::string MarkedStatesToString(void) const
const StateSet & InitStates(void) const
TransSet::Iterator TransRelBegin(void) const
bool IsAccessible(void) const
void InsEvents(const EventSet &events)
bool IsComplete(void) const
virtual vGenerator * New(void) const
void InjectMarkedStates(const StateSet &rNewMarkedStates)
StateSet AccessibleSet(void) const
bool ExistsState(Idx index) const
bool IsCoaccessible(void) const
std::string TStr(const Transition &rTrans) const
std::string StateName(Idx index) const
TransSet::Iterator TransRelEnd(void) const
StateSet TerminalStates(void) const
void SetMarkedState(Idx index)
bool Empty(void) const
virtual void EventAttributes(const EventSet &rEventSet)
bool StateNamesEnabled(void) const
StateSet::Iterator InitStatesEnd(void) const
StateSet CoaccessibleSet(void) const
virtual void Clear(void)
bool ExistsMarkedState(Idx index) const
std::string UniqueStateName(const std::string &rName) const
const StateSet & States(void) const
void InjectAlphabet(const EventSet &rNewalphabet)
bool Empty(void) const
Definition: cfl_baseset.h:1904
bool Exists(const T &rElem) const
Definition: cfl_baseset.h:2322
Iterator End(void) const
Definition: cfl_baseset.h:2098
virtual void InsertSet(const TBaseSet &rOtherSet)
Definition: cfl_baseset.h:2194
bool EqualAttributes(const TBaseSet &rOtherSet) const
Definition: cfl_baseset.h:2403
Iterator Begin(void) const
Definition: cfl_baseset.h:2093
virtual void EraseSet(const TBaseSet &rOtherSet)
Definition: cfl_baseset.h:2249
Idx Size(void) const
Definition: cfl_baseset.h:1899
bool ComputeScc(const Generator &rGen, const SccFilter &rFilter, std::list< StateSet > &rSccList, StateSet &rRoots)
void Product(const Generator &rGen1, const Generator &rGen2, Generator &rResGen)
bool IsDeterministic(const vGenerator &rGen)
void aBuechiProduct(const Generator &rGen1, const Generator &rGen2, Generator &rResGen)
void BuechiProduct(const Generator &rGen1, const Generator &rGen2, Generator &rResGen)
void BuechiParallel(const Generator &rGen1, const Generator &rGen2, Generator &rResGen)
void aBuechiParallel(const Generator &rGen1, const Generator &rGen2, Generator &rResGen)
bool BuechiTrim(vGenerator &rGen)
void BuechiClosure(Generator &rGen)
bool IsBuechiClosed(const Generator &rGen)
uint32_t Idx
void LoopCallback(bool pBreak(void))
Definition: cfl_utils.cpp:693
bool BuechiLanguageInclusion(const Generator &rGen1, const Generator &rGen2)
bool BuechiLanguageEquality(const Generator &rGen1, const Generator &rGen2)
bool IsBuechiTrim(const vGenerator &rGen)
bool IsBuechiRelativelyClosed(const Generator &rGenPlant, const Generator &rGenCand)
std::string ToStringInteger(Int number)
Definition: cfl_utils.cpp:43
bool IsBuechiRelativelyMarked(const Generator &rGenPlant, const Generator &rGenCand)
std::string CollapsString(const std::string &rString, unsigned int len)
Definition: cfl_utils.cpp:91
bool IsBuechiRelativelyClosedUnchecked(const Generator &rGenPlant, const Generator &rGenCand)

libFAUDES 2.33l --- 2025.09.16 --- c++ api documentaion by doxygen