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

libFAUDES 2.34g --- 2026.03.30 --- c++ api documentaion by doxygen