54 std::vector< std::vector<Idx> >
pre;
62 std::string
setstr(
const std::set<Idx>& sset) {
63 std::set<Idx>::iterator ssit;
64 std::stringstream str;
66 for(ssit = sset.begin(); ssit != sset.end(); ++ssit)
76 std::vector< std::vector<Idx> >
blocks;
93 throw Exception(
"StateMin",
"input automaton non-deterministic", 101);
101 std::map<Idx,Idx> smap;
102 std::map<Idx,Idx> emap;
112 StateSet::Iterator sit=acc.
Begin();
113 for(; sit != acc.
End(); ++sit) {
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]);
125 FD_DF(
"Hopcroft::Initialize(): states #" <<
states.size()-1);
146 if(
states.size()-1 == 0) {
147 FD_DF(
"Hopcroft::Minimize(): generator size 0");
152 if(
states.size()-1 == 1) {
153 FD_DF(
"Hopcroft::Minimize(): generator size 1");
161 std::stack<Idx> active;
162 std::vector<Idx>::iterator ssit;
163 std::vector<Idx>::iterator ssit_end;
165 std::vector<Idx> dpp;
171 std::vector<Idx> bnm;
174 else bnm.push_back(q);
177 blocks.push_back(std::vector<Idx>());
179 active.push(
blocks.size()-1);
180 FD_DF(
"Hopcroft::Minimize(): initial partition not-marked #" <<
blocks.back().size());
183 blocks.push_back(std::vector<Idx>());
185 active.push(
blocks.size()-1);
186 FD_DF(
"Hopcroft::Minimize(): initial partition not-marked #" <<
blocks.back().size());
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());
195 std::vector<Idx> b_current(
blocks.at(active.top()));
196 FD_DF(
"StateMin: getting active block B[" << active.top() <<
"] = { #" << b_current.size() <<
"}");
201 for(; ev!=
events.size(); ++ev){
204 ssit = b_current.begin();
205 ssit_end = b_current.end();
206 for(; ssit != ssit_end; ++ssit) {
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);
213 std::sort(c.begin(),c.end());
215 if(c.empty())
continue;
217 FD_DF(
"StateMin: computed predecessor states C = {#" << c.size() <<
"} for event " <<
gen->
EventName(
events[ev]));
221 const std::vector<Idx>& d_current =
blocks[j];
223 if(d_current.size()==1)
continue;
224 FD_DF(
"StateMin: examining block D=B[" << j <<
"] = {#" << d_current.size() <<
"}");
227 std::set_intersection(d_current.begin(), d_current.end(), c.begin(), c.end(),
228 std::inserter(dp, dp.begin()));
230 if(dp.empty() || (dp.size()==d_current.size()))
continue;
231 FD_DF(
"StateMin: -> split:");
234 std::set_difference(d_current.begin(), d_current.end(), dp.begin(), dp.end(),
235 std::inserter(dpp,dpp.begin()));
237 if(dp.size() < dpp.size()) dp.swap(dpp);
241 blocks.push_back(std::vector<Idx>());
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));
263 FD_DF(
"Hopcroft:Partition: building minimized generator #" <<
blocks.size());
276 std::map<Idx,Idx> minstatemap;
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) {
289 minstatemap[orgstate] = newstate;
297 FD_DF(
"StateMin: -> initial state");
302 FD_DF(
"StateMmin: -> marked state");
306 std::string statename = ostr.str();
307 if(statename!=
"") statename.erase(statename.length()-1);
308 statename =
"{" + statename +
"}";
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;
323 if(pResGen != &rResGen) {
324 pResGen->
Move(rResGen);
337 void Partition(std::vector< StateSet >& rSubsets, std::vector<Idx>& rNewIndices){
339 FD_DF(
"Hopcroft:Partition: returning blocks #" <<
blocks.size());
345 rNewIndices.push_back(newstate);
347 std::vector<Idx>::iterator ssit =
blocks[i].begin();
348 std::vector<Idx>::iterator ssit_end =
blocks[i].end();
350 for(; ssit != ssit_end; ++ssit) {
354 rSubsets.push_back(block);
376 std::vector<StateSet>& rSubsets, std::vector<Idx>& rNewIndices) {
377 FD_DF(
"StateMin: *** computing state space minimization of generator "
380 FD_DF(
"StateMin: restrict to accessible states");
384 if(acc.
Size() == 0) {
385 FD_DF(
"StateMin: generator size 0. returning given generator");
390 if(rGen.
Size() == 1) {
391 FD_DF(
"StateMin: generator size 1. returning given generator");
394 rSubsets.push_back(rResGen.
States() );
395 rNewIndices.push_back(*( rResGen.
States().
Begin() ) );
400 #ifdef FAUDES_CHECKED
402 throw Exception(
"StateMin",
"input automaton nondeterministic", 101);
409 if(&rResGen==&rGen) {
410 pResGen= pResGen->
New();
415 pResGen->
Name(rGen.
Name()+
" [minstate]");
419 std::vector<StateSet>& b = rSubsets;
422 std::set<Idx> active;
423 std::set<Idx>::iterator ait;
429 StateSet::Iterator sit;
436 if(marked.
Size() > 0) {
437 FD_DF(
"StateMin: new block B[" << i <<
"] = {" << marked.
ToString() <<
"}");
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);
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) {
461 FD_DF(
"StateMin: active: "+str.str());
462 std::vector<StateSet>::iterator _it2;
465 for (_it2 = b.begin(); _it2 != b.end(); ++_it2) {
466 str <<
"{" << _it2->ToString() <<
"} "<<std::endl;
469 FD_DF(
"B: "+str.str());
472 i = *(active.begin());
474 active.erase(active.begin());
475 FD_DF(
"StateMin: getting active block B[" << i <<
"] = {" <<
476 b.at(i).ToString() <<
"}");
482 EventSet::Iterator eit;
487 for (sit = b_current.
Begin(); sit != b_current.
End(); ++sit) {
490 rtit_end = rtransrel.
EndByEvX2(*eit, *sit);
491 for (; rtit != rtit_end; ++rtit) {
496 if(c.
Empty())
continue;
498 FD_DF(
"StateMin: computed predecessor states C = {" << c.
ToString()
499 <<
"} for event " << rGen.
EventName(*eit));
501 for (j=0; j < b.size(); ++j) {
503 const StateSet& d_current = b.at(j);
504 FD_DF(
"StateMin: examining block B[" << j <<
"] = {" <<
511 FD_DF(
"StateMin: -> no split");
514 FD_DF(
"StateMin: -> split:");
521 FD_DF(
"StateMin: new block B[" << j <<
"] = {" << d_.
ToString() <<
"}");
522 FD_DF(
"StateMin: new block B[" << b.size()-1 <<
"] = {" << d__.
ToString() <<
"}");
524 if(active.find(j) != active.end()) {
525 active.insert((
Idx)b.size()- 1);
526 FD_DF(
"StateMin: mark active: " << b.size()-1);
532 FD_DF(
"StateMin: mark active: " << j);
534 active.insert((
Idx)b.size()-1);
535 FD_DF(
"StateMin: mark active: " << b.size()-1);
542 FD_DF(
"StateMin: *** building minimized generator ***");
544 std::map<Idx,Idx> minstatemap;
547 for (i = 0; i < b.size(); ++i) {
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) {
556 minstatemap[*sit] = newstate;
568 FD_DF(
"StateMin: -> initial state");
573 FD_DF(
"StatMmin: -> marked state");
577 std::string statename = ostr.str();
578 if(statename!=
"") statename.erase(statename.length()-1);
579 statename =
"{" + statename +
"}";
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]);
594 if(pResGen != &rResGen) {
595 pResGen->
Move(rResGen);
621 std::vector< StateSet >& rSubsets, std::vector<Idx>& rNewIndices){
#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.
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
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...
Idx Insert(void)
Insert new index to set.
Iterator class for high-level api to TBaseSet.
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.
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.
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.
bool Exists(const T &rElem) const
Test existence of element.
virtual void Clear(void)
Clear all set.
Iterator End(void) const
Iterator to the end of set.
Iterator Begin(void) const
Iterator to the begin of set.
const std::string & Name(void) const
Return name of TBaseSet.
Idx Size(void) const
Get Size of TBaseSet.
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
Internal representation of reverse transition relation with consecutive indexed states and events.
std::vector< std::vector< Idx > > pre