omg_rabinaut.h
Go to the documentation of this file.
1 /** @file omg_rabinaut.h Class RabinAutomaton */
2 
3 
4 /* FAU Discrete Event Systems Library (libfaudes)
5 
6  Copyright (C) 2025 Thomas Moor
7  Exclusive copyright is granted to Klaus Schmidt
8 
9  This library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU Lesser General Public
11  License as published by the Free Software Foundation; either
12  version 2.1 of the License, or (at your option) any later version.
13 
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public
20  License along with this library; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22 
23 #ifndef FAUDES_OMG_RABINAUT_H
24 #define FAUDES_OMG_RABINAUT_H
25 
26 #include "corefaudes.h"
27 #include "omg_rabinacc.h"
28 
29 namespace faudes {
30 
31 
32 /**
33  * Generator with Rabin acceptance conditiom.
34  *
35  * @section SecRabinAut Overview
36  *
37  * The TrGenerator is a variant of the TcGenerator to add an interface for a Rabin acceptance condition.
38  * For convenience, the configuration with the minimum attributes is been typedef-ed as RabinAutomaton.
39  *
40  * Technically, the construct is based on the global attribute class faudes::RabinAcceptance
41  * derived from faudes::AttributeVoid. Hence TrGenerator expects an event attribute template parameter
42  * with the minimum interface defined in RabinAcceptance.
43  *
44  * The current implementation provides the absolute minimum member access, i.e., methods to get and
45  * the acceptance condition. A future implementation may be more elaborate at this end.
46  *
47  *
48  * @ingroup GeneratorClasses
49  */
50 
51 template <class GlobalAttr, class StateAttr, class EventAttr, class TransAttr>
52  class FAUDES_TAPI TrGenerator : public TcGenerator<GlobalAttr, StateAttr, EventAttr, TransAttr> {
53  public:
54 
55 
56  /**
57  * Creates an emtpy RabinAutomaton object
58  */
59  TrGenerator(void);
60 
61  /**
62  * RabinAutomaton from a std Generator. Copy constructor
63  *
64  * @param rOtherGen
65  */
66  TrGenerator(const vGenerator& rOtherGen);
67 
68  /**
69  * RabinAutomaton from RabinAutomaton. Copy constructor
70  *
71  * @param rOtherGen
72  */
73  TrGenerator(const TrGenerator& rOtherGen);
74 
75  /**
76  * Construct from file
77  *
78  * @param rFileName
79  * Filename
80  *
81  * @exception Exception
82  * If opening/reading fails an Exception object is thrown (id 1, 50, 51)
83  */
84  TrGenerator(const std::string& rFileName);
85 
86  /**
87  * Construct on heap
88  *
89  * @return
90  * new Generator
91  */
92  TrGenerator* New(void) const;
93 
94  /**
95  * Construct on stack
96  *
97  * @return
98  * new Generator
99  */
100  TrGenerator NewRGen(void) const;
101 
102  /**
103  * Construct copy on heap
104  *
105  * @return
106  * new Generator
107  */
108  TrGenerator* Copy(void) const;
109 
110  /**
111  * Type test.
112  *
113  * Uses C++ dynamic cast to test whether the specified object
114  * casts to a RabinAutomaton.
115  *
116  * NOT IMPLEMENTED
117  *
118  * @param pOther
119  * poinetr to object to test
120  *
121  * @return
122  * TpGenerator reference if dynamic cast succeeds, else NULL
123  */
124  virtual const Type* Cast(const Type* pOther) const {
125  return dynamic_cast< const TrGenerator* > (pOther); };
126 
127 
128  /**
129  * Assignment operator (uses Assign)
130  *
131  * Note: you must reimplement this operator in derived
132  * classes in order to handle internal pointers correctly
133  *
134  * @param rOtherGen
135  * Other generator
136  */
137  TrGenerator& operator= (const TrGenerator& rOtherGen);
138 
139  /**
140  * Assignment method
141  *
142  * Note: you must reimplement this method in derived
143  * classes in order to handle internal pointers correctly
144  *
145  * @param rSource
146  * Other generator
147  */
148  virtual TrGenerator& Assign(const Type& rSource);
149 
150  /**
151  * Set Rabin acceptance Condition
152  *
153  * @param rRabAcc
154  * Acceptance conditiomn to set
155  *
156  */
157  void RabinAcceptance(const faudes::RabinAcceptance& rRabAcc);
158 
159  /**
160  * Get Rabin acceptance condition
161  *
162  *
163  */
164  const faudes::RabinAcceptance& RabinAcceptance(void) const;
165 
166  /**
167  * Get Rabin acceotance condition
168  *
169  */
171 
172  /**
173  * Set Rabin acceptance condition from marked states
174  *
175  * This methods interprets the specified states as Buechi acceptance
176  * condition and constructs an equivalient Rabin avvecptance condition.
177  */
178  void RabinAcceptance(const StateSet& rMarking);
179 
180  /**
181  * Pretty print Rabin acceotance condition
182  *
183  * not yet implemanted
184  *
185  */
186  void RabinAcceptanceWrite(void) const;
187 
188  /**
189  * Restrict states
190  *
191  * Cleans mpStates, mInitStates, mMarkedStates, mpTransrel, and mpStateSymboltable.
192  * We reimplement this method to also care about the acceptance condition.
193  *
194  * @param rStates
195  * StateSet containing valid states
196  */
197  virtual void RestrictStates(const StateSet& rStates);
198 
199 
200  /**
201  * Writes generator to dot input format.
202  *
203  * The dot file format is specified by the graphiz package; see http://www.graphviz.org. The package
204  * includes the dot command line tool to generate a graphical representation of the generators graph.
205  * See also Generator::GrphWrite(). *
206  * This functions sets the re-indexing to minimal indices.
207  *
208  * @param rFileName
209  * Name of file to save result
210  */
211  virtual void DotWrite(const std::string& rFileName) const; protected:
212 
213  /** need to reimplement to care about Additional members */
214  void DoAssign(const TrGenerator& rSrc);
215 
216 
217 
218 }; // end class TpGenerator
219 
220 
221 /**
222  * Convenience typedef for std prioritised generator
223  */
225 
226 
227 
228 /*
229 ***************************************************************************
230 ***************************************************************************
231 ***************************************************************************
232 
233 Implementation pGenerator
234 
235 ***************************************************************************
236 ***************************************************************************
237 ***************************************************************************
238 */
239 
240 /* convenience access to relevant scopes */
241 #define THIS TrGenerator<GlobalAttr, StateAttr, EventAttr, TransAttr>
242 #define BASE TcGenerator<GlobalAttr, StateAttr, EventAttr, TransAttr>
243 #define TEMP template <class GlobalAttr, class StateAttr, class EventAttr, class TransAttr>
244 
245 
246 // TrGenerator(void)
247 TEMP THIS::TrGenerator(void) : BASE() {
248  FD_DG("TrGenerator(" << this << ")::TrGenerator()");
249 }
250 
251 // TrGenerator(rOtherGen)
252 TEMP THIS::TrGenerator(const TrGenerator& rOtherGen) : BASE(rOtherGen) {
253  FD_DG("TrGenerator(" << this << ")::TrGenerator(rOtherGen)");
254 }
255 
256 // TrGenerator(rOtherGen)
257 TEMP THIS::TrGenerator(const vGenerator& rOtherGen) : BASE(rOtherGen) {
258  FD_DG("TrGenerator(" << this << ")::TrGenerator(rOtherGen)");
259 }
260 
261 // TrGenerator(rFilename)
262 TEMP THIS::TrGenerator(const std::string& rFileName) : BASE(rFileName) {
263  FD_DG("TrGenerator(" << this << ")::TrGenerator(rFilename) : done");
264 }
265 
266 // full assign of matching type (not virtual)
267 TEMP void THIS::DoAssign(const TrGenerator& rSrc) {
268  FD_DG("TrGenerator(" << this << ")::operator = " << &rOtherGen);
269  // recursive call base, incl virtual clear
270  BASE::DoAssign(rSrc);
271 }
272 
273 // operator=
274 TEMP THIS& THIS::operator= (const TrGenerator& rSrc) {
275  FD_DG("TrGenerator(" << this << ")::operator = " << &rSrc);
276  DoAssign(rSrc);
277  return *this;
278 }
279 
280 // copy from other faudes type
281 TEMP THIS& THIS::Assign(const Type& rSrc) {
282  // bail out on match
283  if(&rSrc==static_cast<const Type*>(this))
284  return *this;
285  // dot if we can
286  const THIS* pgen=dynamic_cast<const THIS*>(&rSrc);
287  if(pgen!=nullptr) {
288  DoAssign(*pgen);
289  return *this;
290  }
291  // pass on to base
292  FD_DG("TrGenerator(" << this << ")::Assign([type] " << &rSrc << "): call base");
293  BASE::Assign(rSrc);
294  return *this;
295 }
296 
297 // New
298 TEMP THIS* THIS::New(void) const {
299  // allocate
300  THIS* res = new THIS;
301  // fix base data
302  res->EventSymbolTablep(BASE::mpEventSymbolTable);
303  res->mStateNamesEnabled=BASE::mStateNamesEnabled;
304  res->mReindexOnWrite=BASE::mReindexOnWrite;
305  return res;
306 }
307 
308 // Copy
309 TEMP THIS* THIS::Copy(void) const {
310  // allocate
311  THIS* res = new THIS(*this);
312  // done
313  return res;
314 }
315 
316 // NewPGen
317 TEMP THIS THIS::NewRGen(void) const {
318  // call base (fixes by assignment constructor)
319  THIS res= BASE::NewCGen();
320  return res;
321 }
322 
323 // Member access, set
324 TEMP void THIS::RabinAcceptance(const faudes::RabinAcceptance& rRabAcc) {
325  BASE::GlobalAttribute(rRabAcc);
326 }
327 
328 // Member access, get by ref
329 TEMP RabinAcceptance& THIS::RabinAcceptance(void) {
330  return *BASE::GlobalAttributep();
331 }
332 
333 // Member access, get by const ref
334 TEMP const RabinAcceptance& THIS::RabinAcceptance(void) const {
335  return BASE::GlobalAttribute();
336 }
337 
338 // Member access, set
339 TEMP void THIS::RabinAcceptance(const StateSet& rMarking) {
341  RabinPair rpair;
342  rpair.ISet()=THIS::States();
343  rpair.RSet()=rMarking;
344  RabinAcceptance().Insert(rpair);
345 }
346 
347 // pretty print
348 TEMP void THIS::RabinAcceptanceWrite(void) const {
349  this->RabinAcceptance().Write(this);
350 }
351 
352 // reimplememt
353 TEMP void THIS::RestrictStates(const StateSet& rStates) {
354  BASE::RestrictStates(rStates);
355  this->RabinAcceptance().RestrictStates(rStates);
356 }
357 
358 // DotWrite(rFileName)
359 TEMP void THIS::DotWrite(const std::string& rFileName) const {
360  FD_DG("RabinAutomaton(" << this << ")::DotWrite(" << rFileName << ")");
361  if(THIS::RabinAcceptance().Size()>5) {
362  FD_DG("RabinAutomaton(" << this << ")::DotWrite(...): to many Rabin pairs");
363  BASE::DotWrite(rFileName);
364  return;
365  }
366  StateSet::Iterator it;
367  BASE::SetMinStateIndexMap();
368  typename TransSet::Iterator tit;
369  try {
370  std::ofstream stream;
371  stream.exceptions(std::ios::badbit|std::ios::failbit);
372  stream.open(rFileName.c_str());
373  stream << "// dot output generated by libFAUDES RabinAutomaton" << std::endl;
374  stream << "digraph \"" << BASE::Name() << "\" {" << std::endl;
375  stream << " rankdir=LR" << std::endl;
376  stream << " node [shape=circle];" << std::endl;
377  stream << std::endl;
378  stream << " // initial states" << std::endl;
379  int i=0;
380  for (it = BASE::InitStatesBegin(); it != BASE::InitStatesEnd(); ++it) {
381  std::string xname= BASE::StateName(*it);
382  if(xname=="") xname=ToStringInteger(static_cast<long int>(BASE::MinStateIndex(*it)));
383  stream << " dot_dummyinit_" << i << " [shape=none, label=\"\" ];" << std::endl;
384  stream << " dot_dummyinit_" << i << " -> \"" << xname << "\";" << std::endl;
385  i++;
386  }
387  stream << std::endl;
388 
389  // figure marked states
390  StateSet marked;
391  RabinAcceptance::CIterator rit;
392  for(rit=THIS::RabinAcceptance().Begin();rit!=THIS::RabinAcceptance().End();++rit) {
393  marked = marked + rit->ISet();
394  marked = marked + rit->RSet();
395  }
396 
397  // uncolored states - output
398  stream << " // plain states" << std::endl;
399  for (it = BASE::pStates->Begin(); it != BASE::pStates->End(); ++it) {
400  if(marked.Exists(*it)) continue;
401  std::string xname=BASE::StateName(*it);
402  if(xname=="") xname=ToStringInteger(BASE::MinStateIndex(*it));
403  stream << " \"" << xname << "\";" << std::endl;
404  }
405  stream << std::endl;
406 
407  // list of colors (pairs light vs. solid for I-Set and R-Set)
408  std::vector<std::string> ColorVector;
409  ColorVector.push_back("blue");
410  ColorVector.push_back("darkblue");
411  ColorVector.push_back("green");
412  ColorVector.push_back("orange");
413  ColorVector.push_back("green");
414  ColorVector.push_back("darkgreen");
415  ColorVector.push_back("red");
416  ColorVector.push_back("darkred");
417 
418  // coloered states
419  stream << " // colored states" << std::endl;
420  int clustNr = 0;
421  for (it = marked.Begin(); it != marked.End(); ++it) {
422  std::string xname=BASE::StateName(*it);
423  if(xname=="") xname=ToStringInteger(static_cast<long int>(BASE::MinStateIndex(*it)));
424  // figure the colors by testing each rabin pair
425  RabinAcceptance::CIterator rit;
426  std::vector<int> colvec;
427  int col=0;
428  for(rit=THIS::RabinAcceptance().Begin();rit!=THIS::RabinAcceptance().End();++rit) {
429  if(rit->ISet().Exists(*it)) colvec.push_back(col);
430  if(rit->RSet().Exists(*it)) colvec.push_back(col+1);
431  col+=2;
432  }
433  // draw multiple colors as clusters
434  if(colvec.size()>1) {
435  for(size_t i=0; i<colvec.size(); ++i) {
436  stream << " subgraph cluster_" << clustNr++ << " {color=" << ColorVector.at(colvec.at(i)) << ";" << std::endl;
437  }
438  stream << " \"" << xname << "\" " << std::endl << " ";
439  for (size_t i=0; i<colvec.size(); i++) {
440  stream << "}";
441  }
442  stream << std::endl;
443  }
444  // draw single color by attribute
445  if(colvec.size()==1) {
446  stream << " \"" << xname << "\" " << "[color=" << colvec.at(0) << "]" << std::endl;
447  }
448  }
449  stream << std::endl;
450 
451  // marked states
452  /*
453  stream << " // marked states" << std::endl;
454  for (it = BASE::MarkedStatesBegin(); it != BASE::MarkedStatesEnd(); ++it) {
455  std::string xname= BASE::StateName(*it);
456  if(xname=="") xname=ToStringInteger(static_cast<long int>(BASE::MinStateIndex(*it)));
457  stream << " \"" << xname << "\";" << std::endl;
458  i++;
459  }
460  */
461 
462  // transitions
463  stream << std::endl;
464  stream << " // transition relation" << std::endl;
465  for (tit = BASE::TransRelBegin(); tit != BASE::TransRelEnd(); ++tit) {
466  std::string x1name= BASE::StateName(tit->X1);
467  if(x1name=="") x1name=ToStringInteger(BASE::MinStateIndex(tit->X1));
468  std::string x2name= BASE::StateName(tit->X2);
469  if(x2name=="") x2name=ToStringInteger(BASE::MinStateIndex(tit->X2));
470  stream << " \"" << x1name << "\" -> \"" << x2name << "\" [label=\"" << BASE::EventName(tit->Ev) << "\"];" << std::endl;
471  }
472  stream << "}" << std::endl;
473  stream.close();
474  }
475  catch (std::ios::failure&) {
476  throw Exception("TaGenerator::DotWrite",
477  "Exception opening/writing dotfile \""+rFileName+"\"", 3);
478  }
479  BASE::ClearMinStateIndexMap();
480 }
481 
482 #undef TEMP
483 #undef BASE
484 #undef THIS
485 
486 
487 
488 } // namespace faudes
489 #endif // _H
#define FD_DG(message)
#define FAUDES_TAPI
Definition: cfl_platform.h:83
void RestrictStates(const StateSet &rDomain)
StateSet & RSet(void)
Definition: omg_rabinacc.h:68
StateSet & ISet(void)
Definition: omg_rabinacc.h:84
virtual void Insert(const T &rElem)
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
Definition: cfl_transset.h:273
virtual const Type * Cast(const Type *pOther) const
Definition: omg_rabinaut.h:124
void Write(const Type *pContext=0) const
Definition: cfl_types.cpp:145
virtual void Clear(void)
bool Exists(const T &rElem) const
Definition: cfl_baseset.h:2180
Iterator End(void) const
Definition: cfl_baseset.h:1956
Iterator Begin(void) const
Definition: cfl_baseset.h:1951
TrGenerator< RabinAcceptance, AttributeVoid, AttributeCFlags, AttributeVoid > RabinAutomaton
Definition: omg_rabinaut.h:224
std::string ToStringInteger(Int number)
Definition: cfl_utils.cpp:43
#define TEMP
Definition: omg_rabinaut.h:243
#define BASE
Definition: omg_rabinaut.h:242
#define THIS
Definition: omg_rabinaut.h:241

libFAUDES 2.33h --- 2025.06.18 --- c++ api documentaion by doxygen