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
5Copyright (C) 2006 Bernd Opitz
6Copyright (C) 2015 Thomas Moor
7Exclusive copyright is granted to Klaus Schmidt
8
9This library is free software; you can redistribute it and/or
10modify it under the terms of the GNU Lesser General Public
11License as published by the Free Software Foundation; either
12version 2.1 of the License, or (at your option) any later version.
13
14This library is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public
20License along with this library; if not, write to the Free Software
21Foundation, 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
30namespace faudes {
31
32/*
33*********************************************************
34Part 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
43class Hopcroft {
44
45public:
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 */
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*********************************************************
379Part 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)
387void 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*********************************************************
618Part 3: provide std function api, incl 2006 interface
619[using revision 201508 tmoor]
620*********************************************************
621*/
622
623
624// StateMin(rGen, rResGen)
625void 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"
632void 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)
641void aStateMin(const Generator& rGen, Generator& rResGen) {
642 StateMin(rGen, rResGen);
643 rResGen.EventAttributes(rGen.Alphabet());
644}
645
646// StateMin(rGen)
647void 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)
const std::string & Name(void) const
void Partition(std::vector< StateSet > &rSubsets, std::vector< Idx > &rNewIndices)
std::vector< Idx > events
const Generator * gen
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
Iterator BeginByEvX2(Idx ev, Idx x2) const
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
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
virtual 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
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
bool Exists(const T &rElem) const
virtual void Clear(void)
Iterator End(void) const
Iterator Begin(void) const
Idx Size(void) const
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.33k --- 2025.09.16 --- c++ api documentaion by doxygen