cfl_statemin.cpp
Go to the documentation of this file.
1 /** @file cfl_statemin.cpp state space minimization */
2 
3 /* FAU Discrete Event Systems Library (libfaudes)
4 
5 Copyright (C) 2006 Bernd Opitz
6 Copyright (C) 2015 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 
24 #include "cfl_statemin.h"
25 #include "cfl_exception.h"
26 #include "cfl_project.h"
27 
28 #include <stack>
29 
30 namespace faudes {
31 
32 /*
33 *********************************************************
34 Part 1: Stages of Hopcroft algorithm wrapped in a class
35 - construct with generator to minimize
36 - invoke Minimize() to run Hopcroft iteration
37 - invoke Partition() to construct quotient automaton
38 
39 [Code revision 201508, tmoor]
40 *********************************************************
41 */
42 
43 class Hopcroft {
44 
45 public:
46 
47  /**
48  * Internal representation of reverse transition relation with consecutive indexed states and events.
49  * Technically, re-indexing is equivalent to "pointers on original indicees" and
50  * buffers log-n searches for transitions
51  */
52  struct State {
53  Idx idx; // original state idx
54  std::vector< std::vector<Idx> > pre; // predecessors by event
55  };
56  std::vector<State> states; // vector of all states [starting with 1 -- use min-index for debugging]
57  std::vector<Idx> events; // vector of all events [starting with 1]
58 
59  /**
60  * plain stl set debugging output
61  */
62  std::string setstr(const std::set<Idx>& sset) {
63  std::set<Idx>::iterator ssit;
64  std::stringstream str;
65  str << "{";
66  for(ssit = sset.begin(); ssit != sset.end(); ++ssit)
67  str << " " << *ssit;
68  str << " }";
69  return str.str();
70  }
71 
72  /**
73  * Hopcroft algorithm data structure: vector of blocks
74  * [revision 201508 tmoor: use plain stl vectors and maintain sorting manually]
75  */
76  std::vector< std::vector<Idx> > blocks;
77 
78  /**
79  * Keep reference to argument (symbolic names etc)
80  */
81  const Generator* gen;
82 
83  /**
84  * Initialize from specified generator
85  */
86  Hopcroft(const Generator& rGen){
87 
88  //FAUDES_TIMER_START("");
89 
90  // ensure generator is deterministic
91 #ifdef FAUDES_CHECKED
92  if(!rGen.IsDeterministic())
93  throw Exception("StateMin", "input automaton non-deterministic", 101);
94 #endif
95 
96  //keep ref
97  gen=&rGen;
98 
99  // convert accessible part to internal data structure
100  StateSet acc = gen->AccessibleSet();
101  std::map<Idx,Idx> smap; // original->internal
102  std::map<Idx,Idx> emap; // original->internal
103  Idx max=0;
104  events.resize(gen->Alphabet().Size()+1);
105  EventSet::Iterator eit=gen->AlphabetBegin();
106  for(; eit != gen->AlphabetEnd(); ++eit) {
107  emap[*eit]=++max;
108  events[max]=*eit;
109  }
110  max=0;
111  states.resize(acc.Size()+1);
112  StateSet::Iterator sit=acc.Begin();
113  for(; sit != acc.End(); ++sit) {
114  smap[*sit]=++max;
115  states[max].idx=*sit;
116  states[max].pre.resize(events.size());
117  }
119  for(; tit != gen->TransRelEnd(); ++tit) {
120  if(!acc.Exists(tit->X1)) continue;
121  if(!acc.Exists(tit->X2)) continue;
122  states[smap[tit->X2]].pre[emap[tit->Ev]].push_back(smap[tit->X1]);
123  }
124 
125  FD_DF("Hopcroft::Initialize(): states #" << states.size()-1);
126 
127  //FAUDES_TIMER_LAP("reindexing: done");
128 
129  }
130 
131 
132  /**
133  * Destruct
134  */
135  ~Hopcroft(void){
136  // nothing to do
137  }
138 
139 
140  /**
141  * Hopcroft iteration (invoke this only once, needs empty blocks vector)
142  */
143  void Minimize(void) {
144 
145  // no accessible states: return no blocks
146  if(states.size()-1 == 0) {
147  FD_DF("Hopcroft::Minimize(): generator size 0");
148  return;
149  }
150 
151  // one accessible state: return that one block
152  if(states.size()-1 == 1) {
153  FD_DF("Hopcroft::Minimize(): generator size 1");
154  std::vector<Idx> b;
155  b.push_back(1);
156  blocks.push_back(b);
157  return;
158  }
159 
160  // loop variables
161  std::stack<Idx> active; // active blocks
162  std::vector<Idx>::iterator ssit;
163  std::vector<Idx>::iterator ssit_end;
164  std::vector<Idx> dp;
165  std::vector<Idx> dpp;
166  std::vector<Idx> c;
167 
168  // set up blocks B[0] and B[1] as Xm and X-Xm, resp.
169  // [revision tmoor 200909: prevent empty blocks]
170  std::vector<Idx> bm;
171  std::vector<Idx> bnm;
172  for(Idx q=1; q<states.size();++q) {
173  if(gen->ExistsMarkedState(states[q].idx)) bm.push_back(q);
174  else bnm.push_back(q);
175  }
176  if(bm.size()>0) {
177  blocks.push_back(std::vector<Idx>());
178  blocks.back().swap(bm);
179  active.push(blocks.size()-1);
180  FD_DF("Hopcroft::Minimize(): initial partition not-marked #" << blocks.back().size());
181  }
182  if(bnm.size()>0) {
183  blocks.push_back(std::vector<Idx>());
184  blocks.back().swap(bnm);
185  active.push(blocks.size()-1);
186  FD_DF("Hopcroft::Minimize(): initial partition not-marked #" << blocks.back().size());
187  }
188 
189  // while there is an active block B[i]
190  while(!active.empty()) {
191  FD_WPC(blocks.size()-active.size(), blocks.size(), "StateMin: blocks/active: " << blocks.size() << " / " << active.size());
192  FD_DF("Hopcroft::Minimize(): active blocks #" << active.size());
193 
194  // pick an arbitrary active block B[i] (need a copy for splitting B[i] by itself)
195  std::vector<Idx> b_current(blocks.at(active.top()));
196  FD_DF("StateMin: getting active block B[" << active.top() << "] = { #" << b_current.size() << "}");
197  active.pop();
198 
199  // compute C = f^-1(B[i]) per event with B[i] as b_current
200  Idx ev=1;
201  for(; ev!= events.size(); ++ev){
202  // iteration over states in current block
203  c.clear();
204  ssit = b_current.begin();
205  ssit_end = b_current.end();
206  for(; ssit != ssit_end; ++ssit) {
207  // find predecessor states by current ev + x2
208  std::vector<Idx>& preevx2=states[*ssit].pre[ev];
209  std::vector<Idx>::iterator rit = preevx2.begin();
210  std::vector<Idx>::iterator rit_end = preevx2.end();
211  for (; rit != rit_end; ++rit) c.push_back(*rit);
212  }
213  std::sort(c.begin(),c.end());
214  // if no predecessor states where found current block wont split anyway
215  if(c.empty()) continue;
216  // search for block to be split
217  FD_DF("StateMin: computed predecessor states C = {#" << c.size() << "} for event " << gen->EventName(events[ev]));
218  // foreach block D
219  for(Idx j=0; j < blocks.size(); ++j) {
220  // d_current <- B[j]
221  const std::vector<Idx>& d_current = blocks[j];
222  // singletons wont split anyway
223  if(d_current.size()==1) continue;
224  FD_DF("StateMin: examining block D=B[" << j << "] = {#" << d_current.size() << "}");
225  // compute D' = D intersection C
226  dp.clear();
227  std::set_intersection(d_current.begin(), d_current.end(), c.begin(), c.end(),
228  std::inserter(dp, dp.begin()));
229  // check whether D splits by B
230  if(dp.empty() || (dp.size()==d_current.size())) continue;
231  FD_DF("StateMin: -> split:");
232  // compute split block D'' = D - D'
233  dpp.clear();
234  std::set_difference(d_current.begin(), d_current.end(), dp.begin(), dp.end(),
235  std::inserter(dpp,dpp.begin()));
236  // make D'' the smaller part
237  if(dp.size() < dpp.size()) dp.swap(dpp);
238  // record split blocks D' and D'' (invalidates references)
239  // [performance: using swap (constant) as opposed to assignment (linear) did not make a difference]
240  blocks[j].swap(dp);
241  blocks.push_back(std::vector<Idx>());
242  blocks.back().swap(dpp);
243  FD_DF("StateMin: new block D' as B[" << j << "] = " << setstr(dp));
244  FD_DF("StateMin: new block D'' as B[" << blocks.size()-1 << "] = " << setstr(dpp));
245  // if D was active then mark both D', D'' active, else mark smaller part D'' as active
246  // [... and both cases effectively amount to mark D'' active]
247  active.push((Idx)blocks.size()- 1);
248  } // foreach block D
249  } // foreach event
250  } // while active blocks exist
251  //FAUDES_TIMER_LAP("minimzing: done");
252 
253  };
254 
255 
256  /***
257  * Extract result
258  * By convention: use consecutive state idx matching respective blocks starting with 1
259  */
260 
261  void Partition(Generator& rResGen) {
262 
263  FD_DF("Hopcroft:Partition: building minimized generator #" << blocks.size());
264 
265  // buffered result (lazy)
266  Generator* pResGen= &rResGen;
267  if(pResGen == gen) pResGen= gen->New();
268 
269  // prepare result
270  pResGen->Clear();
271  pResGen->Name(gen->Name()+" [minstate]");
272  pResGen->InjectAlphabet(gen->Alphabet());
273  bool stateNames= pResGen->StateNamesEnabled() && gen->StateNamesEnabled();
274 
275  // build minimized generator
276  std::map<Idx,Idx> minstatemap; // original states index -> new state index
277  // loop over all blocks B
278  for(Idx i = 0; i < blocks.size(); ++i) {
279  // create state in new generator for every block
280  Idx newstate = i+1;
281  pResGen->InsState(newstate);
282  FD_DF("StateMin: block " << setstr(blocks.at(i)) << " -> new state " << newstate);
283  std::ostringstream ostr;
284  std::vector<Idx>::iterator ssit = blocks[i].begin();
285  std::vector<Idx>::iterator ssit_end = blocks[i].end();
286  for(; ssit != ssit_end; ++ssit) {
287  Idx orgstate = states[*ssit].idx;
288  // set minstatemap entry for every state in gen
289  minstatemap[orgstate] = newstate;
290  if(stateNames) {
291  if (gen->StateName(orgstate) == "") ostr << ToStringInteger(orgstate) << ",";
292  else ostr << gen->StateName(orgstate) << ",";
293  }
294  // set istates
295  if(gen->ExistsInitState(orgstate)) {
296  pResGen->SetInitState(newstate);
297  FD_DF("StateMin: -> initial state");
298  }
299  // set mstates
300  if(gen->ExistsMarkedState(orgstate)) {
301  pResGen->SetMarkedState(newstate);
302  FD_DF("StateMmin: -> marked state");
303  }
304  }
305  if(stateNames) {
306  std::string statename = ostr.str();
307  if(statename!="") statename.erase(statename.length()-1);
308  statename = "{" + statename + "}";
309  pResGen->StateName(newstate, statename);
310  }
311  }
312  // create transition relation
314  for(; tit != gen->TransRelEnd(); ++tit) {
315  std::map<Idx,Idx>::iterator xit1=minstatemap.find(tit->X1);
316  std::map<Idx,Idx>::iterator xit2=minstatemap.find(tit->X2);
317  if(xit1==minstatemap.end()) continue;
318  if(xit2==minstatemap.end()) continue;
319  pResGen->SetTransition(xit1->second, tit->Ev, xit2->second);
320  }
321 
322  // resolve buffered result
323  if(pResGen != &rResGen) {
324  pResGen->Move(rResGen);
325  delete pResGen;
326  }
327 
328  //FAUDES_TIMER_LAP("quotient-generator: done");
329  };
330 
331 
332  /***
333  * Extract result
334  * support original 2006 interface --- depreciated
335  */
336 
337  void Partition(std::vector< StateSet >& rSubsets, std::vector<Idx>& rNewIndices){
338 
339  FD_DF("Hopcroft:Partition: returning blocks #" << blocks.size());
340 
341  // loop over all blocks B
342  StateSet block;
343  for(Idx i = 0; i < blocks.size(); ++i) {
344  Idx newstate = i+1;
345  rNewIndices.push_back(newstate);
346  FD_DF("StateMin: block " << setstr(*blocks[i]) << " -> new state " << newstate);
347  std::vector<Idx>::iterator ssit = blocks[i].begin();
348  std::vector<Idx>::iterator ssit_end = blocks[i].end();
349  block.Clear();
350  for(; ssit != ssit_end; ++ssit) {
351  Idx orgstate = states[*ssit].idx;
352  block.Insert(orgstate);
353  }
354  rSubsets.push_back(block);
355  }
356  //FAUDES_TIMER_LAP("partition: done");
357  };
358 
359 
360 
361 }; // end class Hopcroft
362 
363 
364 
365 /*
366 *********************************************************
367 Part 2: Original 2006 code basis for reference.
368 -- with 2009 minor revision
369 -- with 2015 minor revision for a const-interface
370 *********************************************************
371 */
372 
373 
374 // StateMin(rGen, rResGen, rSubSets, rNewIndices)
375 void StateMin_org(const Generator& rGen, Generator& rResGen,
376  std::vector<StateSet>& rSubsets, std::vector<Idx>& rNewIndices) {
377  FD_DF("StateMin: *** computing state space minimization of generator "
378  << &rGen << " ***");
379 
380  FD_DF("StateMin: restrict to accessible states");
381  StateSet acc=rGen.AccessibleSet();
382 
383  // figure special cases
384  if(acc.Size() == 0) {
385  FD_DF("StateMin: generator size 0. returning given generator");
386  rResGen = rGen;
387  rResGen.RestrictStates(acc);
388  return;
389  }
390  if(rGen.Size() == 1) {
391  FD_DF("StateMin: generator size 1. returning given generator");
392  rResGen = rGen;
393  rResGen.RestrictStates(acc);
394  rSubsets.push_back(rResGen.States() );
395  rNewIndices.push_back(*( rResGen.States().Begin() ) );
396  return;
397  }
398 
399  // ensure generator is deterministic
400 #ifdef FAUDES_CHECKED
401  if(!rGen.IsDeterministic()) {
402  throw Exception("StateMin", "input automaton nondeterministic", 101);
403  }
404 #endif
405 
406  // use pointer pResGen to result rResGen; if rResGen is identical to
407  // one of the parameters, allocate temporary object and copy back later
408  Generator* pResGen = &rResGen;
409  if(&rResGen==&rGen) {
410  pResGen= pResGen->New();
411  }
412 
413  // prepare result
414  pResGen->Clear();
415  pResGen->Name(rGen.Name()+" [minstate]");
416  pResGen->InjectAlphabet(rGen.Alphabet());
417  bool stateNames= pResGen->StateNamesEnabled() && rGen.StateNamesEnabled();
418  // blocks B[i]
419  std::vector<StateSet>& b = rSubsets; // convenience notation "b"
420  Idx i, j;
421  // set of active b (iterators)
422  std::set<Idx> active;
423  std::set<Idx>::iterator ait;
424  // reverse gen transrel
425  TransSetEvX2X1 rtransrel;
426  rGen.TransRel(rtransrel);
427  TransSetEvX2X1::Iterator rtit, rtit_end;
428  // other stuff
429  StateSet::Iterator sit;
430  TransSet::Iterator tit, tit_end;
431 
432  // set up b "B[i]"
433  b.clear();
434  i = 0;
435  StateSet marked=rGen.MarkedStates()*acc;
436  if(marked.Size() > 0) { // tmoor 200909: conditional to prevent emty block
437  FD_DF("StateMin: new block B[" << i << "] = {" << marked.ToString() << "}");
438  b.push_back(marked); // Xm
439  active.insert(i++);
440  }
441  StateSet notmarked= acc - marked;
442  if(notmarked.Size() > 0) {
443  notmarked.Name("B[i]");
444  FD_DF("StateMin: new block B[" << i << "] = {" << notmarked.ToString() << "}");
445  b.push_back(notmarked); //X -Xm
446  active.insert(i++);
447  }
448  marked.Clear();
449  notmarked.Clear();
450 
451  // while there is an active block B
452  while(! active.empty()) {
453  FD_WPC(b.size()-active.size(), b.size(), "StateMin: blocks/active: " << b.size() << " / " << active.size());
454 #ifdef FAUDES_DEBUG_FUNCTION
455  FD_DF("StateMin: while there is an active block B...");
456  std::set<Idx>::iterator _it1;
457  std::stringstream str;
458  for (_it1 = active.begin(); _it1 != active.end(); ++_it1) {
459  str << *_it1 << " ";
460  }
461  FD_DF("StateMin: active: "+str.str());
462  std::vector<StateSet>::iterator _it2;
463  str.clear();
464  str.str("");
465  for (_it2 = b.begin(); _it2 != b.end(); ++_it2) {
466  str << "{" << _it2->ToString() << "} "<<std::endl;
467  }
468  str << std::endl;
469  FD_DF("B: "+str.str());
470 #endif
471  // current block B[i]
472  i = *(active.begin());
473  // inactivate B[i]
474  active.erase(active.begin());
475  FD_DF("StateMin: getting active block B[" << i << "] = {" <<
476  b.at(i).ToString() << "}");
477  // b_current <- B[i]
478  StateSet b_current = b.at(i);
479 
480  // compute C = f^-1(B[i]) for every event in B[i] (as b_current)
481  StateSet c;
482  EventSet::Iterator eit;
483  // iteration over alphabet
484  for (eit = rGen.AlphabetBegin(); eit != rGen.AlphabetEnd(); ++eit) {
485  c.Clear();
486  // iteration over states in current block
487  for (sit = b_current.Begin(); sit != b_current.End(); ++sit) {
488  // find predecessor states by current ev + x2
489  rtit = rtransrel.BeginByEvX2(*eit, *sit);
490  rtit_end = rtransrel.EndByEvX2(*eit, *sit);
491  for (; rtit != rtit_end; ++rtit) {
492  c.Insert(rtit->X1);
493  }
494  }
495  // if no predecessor states where found, try next event
496  if(c.Empty()) continue;
497  // search for block to be split
498  FD_DF("StateMin: computed predecessor states C = {" << c.ToString()
499  << "} for event " << rGen.EventName(*eit));
500  // foreach block D
501  for (j=0; j < b.size(); ++j) {
502  // d_current <- B[j]
503  const StateSet& d_current = b.at(j);
504  FD_DF("StateMin: examining block B[" << j << "] = {" <<
505  d_current.ToString() << "}");
506  // compute D' = D intersection C
507  StateSet d_ = d_current * c;
508  d_.Name("D'");
509  // check D split by B
510  if(d_.Empty() || (d_.Size()==d_current.Size())) {
511  FD_DF("StateMin: -> no split");
512  continue;
513  }
514  FD_DF("StateMin: -> split:");
515  // compute D'' = D intersected not C;
516  StateSet d__ = d_current - d_;
517  d__.Name("D''");
518  // record split block
519  b[j] = d_;
520  b.push_back(d__);
521  FD_DF("StateMin: new block B[" << j << "] = {" << d_.ToString() << "}");
522  FD_DF("StateMin: new block B[" << b.size()-1 << "] = {" << d__.ToString() << "}");
523  // if B[j] was active then mark both D', D'' active
524  if(active.find(j) != active.end()) {
525  active.insert((Idx)b.size()- 1);
526  FD_DF("StateMin: mark active: " << b.size()-1);
527  }
528  // else mark smaller of D', D'' active
529  else {
530  if (d_.Size() < d__.Size()) {
531  active.insert(j);
532  FD_DF("StateMin: mark active: " << j);
533  } else {
534  active.insert((Idx)b.size()-1);
535  FD_DF("StateMin: mark active: " << b.size()-1);
536  }
537  }
538  } // foreach block D
539  } // foreach event
540  } // while active blocks exist
541 
542  FD_DF("StateMin: *** building minimized generator ***");
543  // build minimized generator
544  std::map<Idx,Idx> minstatemap;
545  Idx newstate;
546  // loop over all blocks B
547  for (i = 0; i < b.size(); ++i) {
548  // create state in new generator for every block
549  newstate = pResGen->InsState();
550  rNewIndices.push_back(newstate);
551  FD_DF("StateMin: block {" << b.at(i).ToString()
552  << "} -> new state " << newstate);
553  std::ostringstream ostr;
554  for (sit = b.at(i).Begin(); sit != b.at(i).End(); ++sit) {
555  // set minstatemap entry for every state in gen
556  minstatemap[*sit] = newstate;
557  if(stateNames) {
558  if (rGen.StateName(*sit) == "") {
559  ostr << ToStringInteger(*sit) << ",";
560  }
561  else {
562  ostr << rGen.StateName(*sit) << ",";
563  }
564  }
565  // set istates
566  if(rGen.ExistsInitState(*sit)) {
567  pResGen->SetInitState(newstate);
568  FD_DF("StateMin: -> initial state");
569  }
570  // set mstates
571  if(rGen.ExistsMarkedState(*sit)) {
572  pResGen->SetMarkedState(newstate);
573  FD_DF("StatMmin: -> marked state");
574  }
575  }
576  if(stateNames) {
577  std::string statename = ostr.str();
578  if(statename!="") statename.erase(statename.length()-1);
579  statename = "{" + statename + "}";
580  pResGen->StateName(newstate, statename);
581  }
582  }
583  // create transition relation
584  for (tit = rGen.TransRelBegin(); tit != rGen.TransRelEnd(); ++tit) {
585  if(!acc.Exists(tit->X1)) continue;
586  if(!acc.Exists(tit->X2)) continue;
587  pResGen->SetTransition(minstatemap[tit->X1], tit->Ev, minstatemap[tit->X2]);
588  FD_DF("statemin: adding transition: "
589  << minstatemap[tit->X1] << "-" << tit->Ev << "-"
590  << minstatemap[tit->X2]);
591  }
592 
593  // if necessary, move pResGen to rResGen
594  if(pResGen != &rResGen) {
595  pResGen->Move(rResGen);
596  delete pResGen;
597  }
598 }
599 
600 
601 
602 
603 
604 /*
605 *********************************************************
606 Part 3: provide std function api, incl 2006 interface
607 [using revision 201508 tmoor]
608 *********************************************************
609 */
610 
611 
612 // StateMin(rGen, rResGen)
613 void StateMin(const Generator& rGen, Generator& rResGen) {
614  Hopcroft hc(rGen);
615  hc.Minimize();
616  hc.Partition(rResGen);
617 }
618 
619 // StateMin(rGen, rResGen, maps ...) ---- original interface except for "const"
620 void StateMin(const Generator& rGen, Generator& rResGen,
621  std::vector< StateSet >& rSubsets, std::vector<Idx>& rNewIndices){
622  Hopcroft hc(rGen);
623  hc.Minimize();
624  hc.Partition(rSubsets,rNewIndices);
625  hc.Partition(rResGen);
626 }
627 
628 // StateMin(rGen, rResGen)
629 void aStateMin(const Generator& rGen, Generator& rResGen) {
630  StateMin(rGen, rResGen);
631  rResGen.EventAttributes(rGen.Alphabet());
632 }
633 
634 // StateMin(rGen)
635 void aStateMin(Generator& rGen) {
636  aStateMin(rGen,rGen);
637 }
638 
639 
640 
641 
642 
643 
644 } // namespace faudes
#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.
Class Exception.
language projection
state space minimization
Faudes exception class.
void Partition(std::vector< StateSet > &rSubsets, std::vector< Idx > &rNewIndices)
std::vector< Idx > events
const Generator * gen
Keep reference to argument (symbolic names etc)
void Minimize(void)
Hopcroft iteration (invoke this only once, needs empty blocks vector)
std::vector< State > states
~Hopcroft(void)
Destruct.
void Partition(Generator &rResGen)
Hopcroft(const Generator &rGen)
Initialize from specified generator.
std::string setstr(const std::set< Idx > &sset)
plain stl set debugging output
std::vector< std::vector< Idx > > blocks
Hopcroft algorithm data structure: vector of blocks [revision 201508 tmoor: use plain stl vectors and...
Set of indices.
Definition: cfl_indexset.h:78
Idx Insert(void)
Insert new index to set.
Iterator class for high-level api to TBaseSet.
Definition: cfl_baseset.h:387
Set of Transitions.
Definition: cfl_transset.h:242
Iterator EndByEvX2(Idx ev, Idx x2) const
Iterator to first Transition after specified event and next state.
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
Iterator on transition.
Definition: cfl_transset.h:269
Iterator BeginByEvX2(Idx ev, Idx x2) const
Iterator to first Transition specified by event and next state.
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
Write configuration data to a string.
Definition: cfl_types.cpp:169
Base class of all FAUDES generators.
const TransSet & TransRel(void) const
Return reference to transition relation.
bool SetTransition(Idx x1, Idx ev, Idx x2)
Add a transition to generator by indices.
const StateSet & MarkedStates(void) const
Return const ref of marked states.
const EventSet & Alphabet(void) const
Return const reference to alphabet.
virtual void Move(vGenerator &rGen)
Destructive copy to other vGenerator.
TransSet::Iterator TransRelBegin(void) const
Iterator to Begin() of transition relation.
void RestrictStates(const StateSet &rStates)
Restrict states Cleans mpStates, mInitStates, mMarkedStates, mpTransrel, and mpStateSymboltable.
EventSet::Iterator AlphabetBegin(void) const
Iterator to Begin() of alphabet.
virtual vGenerator * New(void) const
Construct on heap.
void SetInitState(Idx index)
Set an existing state as initial state by index.
StateSet AccessibleSet(void) const
Compute set of accessible states.
std::string StateName(Idx index) const
State name lookup.
void Name(const std::string &rName)
Set the generator's name.
TransSet::Iterator TransRelEnd(void) const
Iterator to End() of transition relation.
bool IsDeterministic(void) const
Check if generator is deterministic.
Idx InsState(void)
Add new anonymous state to generator.
void SetMarkedState(Idx index)
Set an existing state as marked state by index.
virtual void EventAttributes(const EventSet &rEventSet)
Set attributes for existing events.
bool StateNamesEnabled(void) const
Whether libFAUEDS functions are requested to generate state names.
std::string EventName(Idx index) const
Event name lookup.
EventSet::Iterator AlphabetEnd(void) const
Iterator to End() of alphabet.
Idx Size(void) const
Get generator size (number of states)
bool ExistsInitState(Idx index) const
Test existence of state in mInitStates.
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.
Definition: cfl_baseset.h:1824
bool Exists(const T &rElem) const
Test existence of element.
Definition: cfl_baseset.h:2115
virtual void Clear(void)
Clear all set.
Definition: cfl_baseset.h:1902
Iterator End(void) const
Iterator to the end of set.
Definition: cfl_baseset.h:1896
Iterator Begin(void) const
Iterator to the begin of set.
Definition: cfl_baseset.h:1891
const std::string & Name(void) const
Return name of TBaseSet.
Definition: cfl_baseset.h:1755
Idx Size(void) const
Get Size of TBaseSet.
Definition: cfl_baseset.h:1819
void StateMin(const Generator &rGen, Generator &rResGen)
State set minimization.
void aStateMin(const Generator &rGen, Generator &rResGen)
State set minimization.
libFAUDES resides within the namespace faudes.
uint32_t Idx
Type definition for index type (allways 32bit)
void StateMin_org(const Generator &rGen, Generator &rResGen, std::vector< StateSet > &rSubsets, std::vector< Idx > &rNewIndices)
std::string ToStringInteger(Int number)
integer to string
Definition: cfl_helper.cpp:43
Internal representation of reverse transition relation with consecutive indexed states and events.
std::vector< std::vector< Idx > > pre

libFAUDES 2.32b --- 2024.03.01 --- c++ api documentaion by doxygen