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

libFAUDES 2.33b --- 2025.05.07 --- c++ api documentaion by doxygen