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;
212 
213  protected:
214 
215  /** need to reimplement to care about Additional members */
216  void DoAssign(const TrGenerator& rSrc);
217 
218 
219 
220 }; // end class TpGenerator
221 
222 
223 /**
224  * Convenience typedef for std prioritised generator
225  */
227 
228 
229 
230 /*
231 ***************************************************************************
232 ***************************************************************************
233 ***************************************************************************
234 
235 Implementation pGenerator
236 
237 ***************************************************************************
238 ***************************************************************************
239 ***************************************************************************
240 */
241 
242 /* convenience access to relevant scopes */
243 #define THIS TrGenerator<GlobalAttr, StateAttr, EventAttr, TransAttr>
244 #define BASE TcGenerator<GlobalAttr, StateAttr, EventAttr, TransAttr>
245 #define TEMP template <class GlobalAttr, class StateAttr, class EventAttr, class TransAttr>
246 
247 
248 // TrGenerator(void)
249 TEMP THIS::TrGenerator(void) : BASE() {
250  FD_DG("TrGenerator(" << this << ")::TrGenerator()");
251 }
252 
253 // TrGenerator(rOtherGen)
254 TEMP THIS::TrGenerator(const TrGenerator& rOtherGen) : BASE(rOtherGen) {
255  FD_DG("TrGenerator(" << this << ")::TrGenerator(rOtherGen)");
256 }
257 
258 // TrGenerator(rOtherGen)
259 TEMP THIS::TrGenerator(const vGenerator& rOtherGen) : BASE(rOtherGen) {
260  FD_DG("TrGenerator(" << this << ")::TrGenerator(rOtherGen)");
261 }
262 
263 // TrGenerator(rFilename)
264 TEMP THIS::TrGenerator(const std::string& rFileName) : BASE(rFileName) {
265  FD_DG("TrGenerator(" << this << ")::TrGenerator(rFilename) : done");
266 }
267 
268 // full assign of matching type (not virtual)
269 TEMP void THIS::DoAssign(const TrGenerator& rSrc) {
270  FD_DG("TrGenerator(" << this << ")::operator = " << &rOtherGen);
271  // recursive call base, incl virtual clear
272  BASE::DoAssign(rSrc);
273 }
274 
275 // operator=
276 TEMP THIS& THIS::operator= (const TrGenerator& rSrc) {
277  FD_DG("TrGenerator(" << this << ")::operator = " << &rSrc);
278  DoAssign(rSrc);
279  return *this;
280 }
281 
282 // copy from other faudes type
283 TEMP THIS& THIS::Assign(const Type& rSrc) {
284  // bail out on match
285  if(&rSrc==static_cast<const Type*>(this))
286  return *this;
287  // dot if we can
288  const THIS* pgen=dynamic_cast<const THIS*>(&rSrc);
289  if(pgen!=nullptr) {
290  DoAssign(*pgen);
291  return *this;
292  }
293  // pass on to base
294  FD_DG("TrGenerator(" << this << ")::Assign([type] " << &rSrc << "): call base");
295  BASE::Assign(rSrc);
296  return *this;
297 }
298 
299 // New
300 TEMP THIS* THIS::New(void) const {
301  // allocate
302  THIS* res = new THIS;
303  // fix base data
304  res->EventSymbolTablep(BASE::mpEventSymbolTable);
305  res->mStateNamesEnabled=BASE::mStateNamesEnabled;
306  res->mReindexOnWrite=BASE::mReindexOnWrite;
307  return res;
308 }
309 
310 // Copy
311 TEMP THIS* THIS::Copy(void) const {
312  // allocate
313  THIS* res = new THIS(*this);
314  // done
315  return res;
316 }
317 
318 // NewPGen
319 TEMP THIS THIS::NewRGen(void) const {
320  // call base (fixes by assignment constructor)
321  THIS res= BASE::NewCGen();
322  return res;
323 }
324 
325 // Member access, set
326 TEMP void THIS::RabinAcceptance(const faudes::RabinAcceptance& rRabAcc) {
327  BASE::GlobalAttribute(rRabAcc);
328 }
329 
330 // Member access, get by ref
331 TEMP RabinAcceptance& THIS::RabinAcceptance(void) {
332  return *BASE::GlobalAttributep();
333 }
334 
335 // Member access, get by const ref
336 TEMP const RabinAcceptance& THIS::RabinAcceptance(void) const {
337  return BASE::GlobalAttribute();
338 }
339 
340 // Member access, set
341 TEMP void THIS::RabinAcceptance(const StateSet& rMarking) {
343  RabinPair rpair;
344  rpair.ISet()=THIS::States();
345  rpair.RSet()=rMarking;
346  RabinAcceptance().Insert(rpair);
347 }
348 
349 // pretty print
350 TEMP void THIS::RabinAcceptanceWrite(void) const {
351  this->RabinAcceptance().Write(this);
352 }
353 
354 // reimplememt
355 TEMP void THIS::RestrictStates(const StateSet& rStates) {
356  BASE::RestrictStates(rStates);
357  this->RabinAcceptance().RestrictStates(rStates);
358 }
359 
360 
361 // DotWrite(rFileName), second version, using HTML style lables inspired by ltldstar
362 TEMP void THIS::DotWrite(const std::string& rFileName) const {
363  FD_DG("RabinAutomaton(" << this << ")::DotWrite(" << rFileName << ")");
364  // prepare
365  if(BASE::ReindexOnWrite()) BASE::SetMinStateIndexMap();
366  TransSetX1X2Ev trx1x2ev(BASE::TransRel());
367  StateSet::Iterator lit;
369  // list of colors (pairs light vs. solid for I-Set and R-Set)
370  std::vector<std::string> ColorPalette;
371  ColorPalette.push_back("lightblue"); // X11 light blue
372  ColorPalette.push_back("darkblue"); // X11 dark blue
373  ColorPalette.push_back("#ffcc80"); // my light orange
374  ColorPalette.push_back("#ff9900"); // my dark orange
375  ColorPalette.push_back("#b0ffb0"); // my light green
376  ColorPalette.push_back("#307030"); // my dark green
377  ColorPalette.push_back("#ff9090"); // my light red
378  ColorPalette.push_back("#a00202"); // my dark red
379  ColorPalette.push_back("black"); // have black for std marking
380  if(2*THIS::RabinAcceptance().Size()>ColorPalette.size()-1) {
381  FD_DG("RabinAutomaton(" << this << ")::DotWrite(...): to many Rabin pairs");
382  BASE::DotWrite(rFileName);
383  return;
384  }
385  // do dot write
386  try {
387  std::ofstream stream;
388  stream.exceptions(std::ios::badbit|std::ios::failbit);
389 
390  // header
391  stream.open(rFileName.c_str());
392  stream << "// dot output generated by libFAUDES RabinAutomaton" << std::endl;
393  stream << "digraph \"" << BASE::Name() << "\" {" << std::endl;
394  stream << " rankdir=LR" << std::endl;
395  //stream << " bgcolor=\"transparent\"" << std::endl;
396  stream << " node [shape=rectangle, style=rounded];" << std::endl;
397  stream << std::endl;
398 
399  // initial state(s)
400  stream << " // initial states" << std::endl;
401  int i=0;
402  for (lit = BASE::InitStatesBegin(); lit != BASE::InitStatesEnd(); ++lit) {
403  std::string xname= BASE::StateName(*lit);
404  if(xname=="") xname=ToStringInteger(static_cast<long int>(BASE::MinStateIndex(*lit)));
405  stream << " dot_dummyinit_" << i << " [shape=none, label=\"\" ];" << std::endl;
406  stream << " dot_dummyinit_" << i << " -> \"" << xname << "\";" << std::endl;
407  i++;
408  }
409  stream << std::endl;
410 
411  // figure marked states
412  StateSet marked;
413  RabinAcceptance::CIterator rit;
414  for(rit=THIS::RabinAcceptance().Begin();rit!=THIS::RabinAcceptance().End();++rit) {
415  marked = marked + rit->ISet();
416  marked = marked + rit->RSet();
417  }
418  marked.InsertSet(this->MarkedStates());
419 
420  // uncolored states - output
421  stream << " // plain states" << std::endl;
422  for (lit = BASE::pStates->Begin(); lit != BASE::pStates->End(); ++lit) {
423  if(marked.Exists(*lit)) continue;
424  std::string xname=BASE::StateName(*lit);
425  if(xname=="") xname=ToStringInteger(BASE::MinStateIndex(*lit));
426  stream << " \"" << xname << "\";" << std::endl;
427  }
428  stream << std::endl;
429 
430  // colored states
431  stream << " // colored states" << std::endl;
432  for (lit = marked.Begin(); lit != marked.End(); ++lit) {
433  std::string xname=BASE::StateName(*lit);
434  if(xname=="") xname=ToStringInteger(static_cast<long int>(BASE::MinStateIndex(*lit)));
435  stream << " \"" << xname << "\"";
436  // figure the colors by testing each rabin pair
437  RabinAcceptance::CIterator rit;
438  std::vector<int> colvec;
439  int col=0;
440  for(rit=THIS::RabinAcceptance().Begin();rit!=THIS::RabinAcceptance().End();++rit) {
441  if(rit->ISet().Exists(*lit)) colvec.push_back(col);
442  if(rit->RSet().Exists(*lit)) colvec.push_back(col+1);
443  col+=2;
444  }
445  // add traditional marking (black is at the end of our palette)
446  if(this->ExistsMarkedState(*lit))
447  colvec.push_back(ColorPalette.size()-1);
448  // begin HTML label
449  stream << " [label=<<TABLE BORDER=\"0\"><TR>";
450  // add state name to table
451  stream << "<TD>" << xname << "</TD>";
452  // add hspace to table
453  stream << "<TD WIDTH=\"5\"></TD>";
454  // assembling td elements per color
455  size_t i;
456  for(i=0;i<colvec.size();++i) {
457  stream << "<TD BGCOLOR=\"" << ColorPalette.at(colvec.at(i)) << "\" BORDER=\"0\" WIDTH=\"10\"></TD>";
458  }
459  // finalize table
460  stream << "</TR></TABLE>>";
461  stream << "];" << std::endl;
462  }
463 
464  // transrel
465  stream << " // transition relation" << std::endl;
466  std::string elabel;
467  for(tit = trx1x2ev.Begin(); tit != trx1x2ev.End();) {
468  // accumulate label
469  if(!elabel.empty()) elabel = elabel + ", ";
470  if(elabel.length()>9) elabel = elabel + "\n";
471  elabel=elabel + BASE::EventName(tit->Ev);
472  Idx x1=tit->X1;
473  Idx x2=tit->X2;
474  bool flush=false;
475  // next transition
476  ++tit;
477  if(tit==trx1x2ev.End())
478  flush =true;
479  else
480  flush=((tit->X1 != x1) || (tit->X2 != x2));
481  // write out
482  if(flush) {
483  std::string x1name= BASE::StateName(x1);
484  if(x1name=="") x1name=ToStringInteger(BASE::MinStateIndex(x1));
485  std::string x2name= BASE::StateName(x2);
486  if(x2name=="") x2name=ToStringInteger(BASE::MinStateIndex(x2));
487  stream << " \"" << x1name << "\" -> \"" << x2name
488  << "\" [label=\"" << elabel << "\"];" << std::endl;
489  elabel="";
490  }
491  }
492 
493  // finalize
494  stream << "}" << std::endl;
495  stream.close();
496  }
497  catch (std::ios::failure&) {
498  throw Exception("TaGenerator::DotWrite",
499  "Exception opening/writing dotfile \""+rFileName+"\"", 3);
500  }
501  BASE::ClearMinStateIndexMap();
502 }
503 
504 
505 #undef TEMP
506 #undef BASE
507 #undef THIS
508 
509 
510 
511 } // namespace faudes
512 #endif // _H
#define FD_DG(message)
#define FAUDES_TAPI
Definition: cfl_platform.h:88
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)
Iterator Begin(void) const
Iterator End(void) const
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:2322
Iterator End(void) const
Definition: cfl_baseset.h:2098
virtual void InsertSet(const TBaseSet &rOtherSet)
Definition: cfl_baseset.h:2194
Iterator Begin(void) const
Definition: cfl_baseset.h:2093
uint32_t Idx
TrGenerator< RabinAcceptance, AttributeVoid, AttributeCFlags, AttributeVoid > RabinAutomaton
Definition: omg_rabinaut.h:226
std::string ToStringInteger(Int number)
Definition: cfl_utils.cpp:43
#define TEMP
Definition: omg_rabinaut.h:245
#define BASE
Definition: omg_rabinaut.h:244
#define THIS
Definition: omg_rabinaut.h:243

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