cfl_graphfncts.cpp

Go to the documentation of this file.
00001 /** @file cfl_graphfncts.cpp Operations on (directed) graphs. */
00002 
00003 /* FAU Discrete Event Systems Library (libfaudes)
00004 
00005    Copyright (C) 2009  Thomas Moor, Klaus Schmidt, Sebastian Perk
00006    Exclusive copyright is granted to Klaus Schmidt
00007 
00008    This library is free software; you can redistribute it and/or
00009    modify it under the terms of the GNU Lesser General Public
00010    License as published by the Free Software Foundation; either
00011    version 2.1 of the License, or (at your option) any later version.
00012 
00013    This library is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016    Lesser General Public License for more details.
00017 
00018    You should have received a copy of the GNU Lesser General Public
00019    License along with this library; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00021 
00022 
00023 #include "cfl_graphfncts.h"
00024 
00025 
00026 namespace faudes {
00027 
00028 /*
00029 **********************************************************************
00030 **********************************************************************
00031 **********************************************************************
00032 
00033 Search for strongly connected ycless components (SCC)
00034 
00035 **********************************************************************
00036 **********************************************************************
00037 **********************************************************************
00038 */
00039 
00040 // Filter class for SCC search: statics
00041 const StateSet SccFilter::msEmptyStates=StateSet();
00042 const EventSet SccFilter::msEmptyEvents=EventSet();
00043 
00044 // Filter class for SCC search: destructor
00045 SccFilter::~SccFilter(void) {
00046   if(mpStatesAvoid) delete mpStatesAvoid;
00047   if(mpStatesRequire) delete mpStatesRequire;
00048   if(mpEventsAvoid) delete mpEventsAvoid;
00049 }
00050 
00051 // Filter class for SCC search: constructors
00052 SccFilter::SccFilter(void) :
00053   mMode(0x00),
00054   pStatesAvoid(&msEmptyStates),
00055   pStatesRequire(&msEmptyStates),
00056   pEventsAvoid(&msEmptyEvents),
00057   mpStatesAvoid(0),
00058   mpStatesRequire(0),
00059   mpEventsAvoid(0)
00060 {}
00061 
00062 
00063 // Filter class for SCC search: constructors
00064 SccFilter::SccFilter(const SccFilter& rSrc) :
00065   mMode(rSrc.mMode),
00066   pStatesAvoid(rSrc.pStatesAvoid),
00067   pStatesRequire(rSrc.pStatesRequire),
00068   pEventsAvoid(rSrc.pEventsAvoid),
00069   mpStatesAvoid(0),
00070   mpStatesRequire(0),
00071   mpEventsAvoid(0)
00072 {}
00073 
00074 
00075 // Filter class for SCC search: constructors
00076 SccFilter::SccFilter(int mode, const EventSet& rEventsAvoid) :
00077   mMode(mode),
00078   pStatesAvoid(&msEmptyStates),
00079   pStatesRequire(&msEmptyStates),
00080   pEventsAvoid(&msEmptyEvents),
00081   mpStatesAvoid(0),
00082   mpStatesRequire(0),
00083   mpEventsAvoid(0)
00084 {
00085   // no special states
00086   mMode &= ~(FmStatesRequire | FmStatesAvoid);
00087   // use events for avoid
00088   mMode |= FmEventsAvoid;
00089   // record
00090   pEventsAvoid=&rEventsAvoid;
00091 }
00092 
00093 
00094 // Filter class for SCC search: constructors
00095 SccFilter::SccFilter(int mode, const StateSet& rStatesAvoidRequire) :
00096   mMode(mode),
00097   pStatesAvoid(&msEmptyStates),
00098   pStatesRequire(&msEmptyStates),
00099   pEventsAvoid(&msEmptyEvents),
00100   mpStatesAvoid(0),
00101   mpStatesRequire(0),
00102   mpEventsAvoid(0)
00103 {
00104   // no special events
00105   mMode &= ~FmEventsAvoid;
00106   // use states for require
00107   if(mMode & FmStatesRequire)
00108     pStatesRequire=&rStatesAvoidRequire;
00109   // use states for avoid
00110   if(mMode & FmStatesAvoid)
00111     pStatesAvoid=&rStatesAvoidRequire;
00112 }
00113 
00114 // Filter class for SCC search: constructors
00115 SccFilter::SccFilter(int mode, const StateSet& rStatesAvoid, const StateSet& rStatesRequire): 
00116   mMode(mode),
00117   pStatesAvoid(&msEmptyStates),
00118   pStatesRequire(&msEmptyStates),
00119   pEventsAvoid(&msEmptyEvents),
00120   mpStatesAvoid(0),
00121   mpStatesRequire(0),
00122   mpEventsAvoid(0)
00123 {
00124   // no special events
00125   mMode &= ~FmEventsAvoid;
00126   // but special states
00127   mMode |= FmStatesRequire;
00128   mMode |= FmStatesAvoid;
00129   // set internal pointers
00130   pStatesAvoid=&rStatesAvoid;
00131   pStatesRequire=&rStatesRequire;
00132 }
00133 
00134 
00135 // Filter class for SCC search: constructors
00136 SccFilter::SccFilter(int mode, const Generator& rGen) :
00137   mMode(mode),
00138   pStatesAvoid(&msEmptyStates),
00139   pStatesRequire(&msEmptyStates),
00140   pEventsAvoid(&msEmptyEvents),
00141   mpStatesAvoid(0),
00142   mpStatesRequire(0),
00143   mpEventsAvoid(0)
00144 {
00145   // sets all empty by default
00146   mMode &= ~(FmStatesAvoid | FmStatesRequire | FmEventsAvoid );
00147   // ignore livelocks ==> require at least one marked state
00148   if(mode & FmIgnoreLiveLocks) {
00149     pStatesRequire=&rGen.MarkedStates();
00150     mMode |= FmStatesRequire;
00151   }
00152   // livelocks only ==> avoid marked states
00153   if(mode & FmLiveLocksOnly) {
00154     pStatesAvoid=&rGen.MarkedStates();
00155     mMode |= FmStatesAvoid;
00156   }
00157   // accessible only ==> deal with this in api wrappers
00158   if(mode & FmIgnoreUnaccessible) {
00159     (void) mode;
00160   }  
00161 }
00162 
00163 
00164 // Filter class for SCC search: clear
00165 void SccFilter::Clear(void) {
00166   if(mpStatesAvoid) delete mpStatesAvoid;
00167   if(mpStatesRequire) delete mpStatesRequire;
00168   if(mpEventsAvoid) delete mpEventsAvoid;
00169   mpStatesAvoid=0;
00170   mpStatesRequire=0;
00171   mpEventsAvoid=0;
00172   mMode=0x00;
00173   pStatesAvoid=&msEmptyStates;
00174   pStatesRequire=&msEmptyStates;
00175   pEventsAvoid=&msEmptyEvents;
00176 }
00177 
00178 // Filter class for SCC search: edit
00179 void SccFilter::StatesAvoid(const StateSet& rStatesAvoid) {
00180   if(mpStatesAvoid) delete mpStatesAvoid;
00181   mpStatesAvoid=0;
00182   mMode |= FmStatesAvoid;
00183   pStatesAvoid=&rStatesAvoid;
00184 }
00185 
00186 // Filter class for SCC search: edit
00187 void SccFilter::StatesRequire(const StateSet& rStatesRequire) {
00188   if(mpStatesRequire) delete mpStatesRequire;
00189   mpStatesRequire=0;
00190   mMode |= FmStatesRequire;
00191   pStatesRequire=&rStatesRequire;
00192 }
00193 
00194 // Filter class for SCC search: edit
00195 void SccFilter::MergeStatesAvoid(const StateSet& rStatesAvoid) {
00196   if(mpStatesAvoid==0) mpStatesAvoid= new IndexSet(*pStatesAvoid);
00197   mpStatesAvoid->InsertSet(rStatesAvoid);
00198   mpStatesAvoid->Name("StatesAvoid");
00199   pStatesAvoid=mpStatesAvoid;
00200 } 
00201 
00202 // Filter class for SCC search: edit
00203 void SccFilter::EventsAvoid(const EventSet& rEventsAvoid) {
00204   if(mpEventsAvoid) delete mpEventsAvoid;
00205   mpEventsAvoid=0;
00206   mMode |= FmEventsAvoid;
00207   pEventsAvoid=&rEventsAvoid;
00208 }
00209 
00210 // Filter class for SCC search: edit
00211 void SccFilter::IgnoreTrivial(bool flag) {
00212   mMode &= ~FmIgnoreTrivial;
00213   if(flag) mMode |= FmIgnoreTrivial;
00214 }
00215 
00216 // Filter class for SCC search: edit
00217 void SccFilter::FindFirst(bool flag) {
00218   mMode &= ~FmFindFirst;
00219   if(flag) mMode |= FmFindFirst;
00220 }
00221 
00222 
00223 
00224 
00225 // Recursive function to search for SCCs.
00226 // The algorithm is a variation of the one prsented in
00227 //  -- Aho, Hopcroft, Ullman: The Design and Analysis of Computer Algorithms
00228 void SearchScc(
00229   const Idx vState,            // Current state under investigation
00230   int& vRcount,                // Depth count of recursion
00231   const Generator& rGen,       // Graph to inspect
00232   const SccFilter& rFilter,    // Filter to ignore transitions with specified events
00233   StateSet&  rTodo,            // States not dealt with so far
00234   std::stack<Idx>& rStack,     // Stack of currently considered states
00235   StateSet& rStackStates,      // Stack contents as set
00236   std::map<const Idx, int>& rDfn, // Map assigning to each state its depth-first count
00237   std::map<const Idx, int>& rLowLnk, // Map assigning to each state its LOWLINK Number
00238   std::list<StateSet>& rSccList,  // Record result: list of SCCs 
00239   StateSet& rRoots)             // Record result: one state per SCC
00240 {
00241   FD_DF("SerchScc: -- recursive search from state "<< vState << " at level " << vRcount << " --");
00242   // local variables (expensive for recursion)
00243   TransSet::Iterator tit;
00244   Idx ls;
00245   bool fl;
00246   // Take current state from todo list
00247   rTodo.Erase(vState);
00248   // Ignore filter: avoid states
00249   if(rFilter.mMode & SccFilter::FmStatesAvoid)
00250   if(rFilter.pStatesAvoid->Exists(vState)) return;
00251   // Ignore filter: break recursion on find first
00252   if(rFilter.mMode & SccFilter::FmFindFirst)
00253   if(!rSccList.empty()) return;
00254   // Record depth-first level for current state and initialise low-link level
00255   rDfn[vState]=vRcount;
00256   rLowLnk[vState]=vRcount;
00257   // Increment depth-first level
00258   vRcount++;
00259   // Push state on stack;
00260   rStack.push(vState);
00261   rStackStates.Insert(vState);
00262   /*
00263   std::list<Idx>::iterator vsit = --rStack.end();
00264   */
00265   // Investigate successor states  "L[state]" 
00266   tit=rGen.TransRelBegin(vState);
00267   for(; tit != rGen.TransRelEnd(); ++tit) {
00268     if(tit->X1!=vState) break;
00269     // Sucessor to investigate
00270     ls=tit->X2;
00271     // Ignore avoid: avoid states
00272     if(rFilter.mMode & SccFilter::FmStatesAvoid)
00273     if(rFilter.pStatesAvoid->Exists(ls)) continue;
00274     // Ignore filter: avoid events
00275     if(rFilter.mMode & SccFilter::FmEventsAvoid)
00276     if(rFilter.pEventsAvoid->Exists(tit->Ev)) continue;
00277     // Successors that are on the todo list get ... 
00278     if(rTodo.Exists(ls)) {        
00279        // ... searched recursively, and ...
00280        SearchScc(ls, vRcount, rGen, rFilter, rTodo, rStack, rStackStates, rDfn, rLowLnk, rSccList, rRoots);
00281        // ... the current low-link gets updated to the new minimum.
00282        if(rLowLnk[ls]<rLowLnk[vState]) rLowLnk[vState]=rLowLnk[ls];
00283     }
00284     // Successors that are not on the todo list ...
00285     else {
00286       // ... if they have a lower deph-first level ...
00287       if(rDfn[ls]<rDfn[vState])  
00288       // ... and if they are on the stack at all ...
00289       if(rStackStates.Exists(ls)) 
00290       // ... set the current low-link to the new minimum 
00291       if(rDfn[ls]<rLowLnk[vState]) rLowLnk[vState]=rDfn[ls];
00292     }
00293   }//end for: iterate successors
00294 
00295   // If the current state is the root of a SCC, record the result
00296   if((rLowLnk[vState]==rDfn[vState])) {
00297     // Retrieve SCC from stack
00298     FD_DF("SearchScc: retrieving SCC from stack, root " << vState);        
00299     rSccList.push_back(StateSet());
00300     rRoots.Insert(vState);
00301     do {
00302       // Pop top of stack
00303       ls=rStack.top();
00304       rStackStates.Erase(ls);
00305       rStack.pop();
00306       // Record
00307       rSccList.back().Insert(ls);
00308     } while(ls!=vState);
00309     // Invalidate for missed requirements
00310     fl=false;
00311     // .. required states.
00312     if(rFilter.mMode & SccFilter::FmStatesRequire)
00313       if(((*rFilter.pStatesRequire) * rSccList.back()).Empty()) 
00314         fl=true;
00315     // .. ignore trivial (singleton without relevant selfloop)
00316     if(rFilter.mMode & SccFilter::FmIgnoreTrivial) {
00317       if((!fl) && (rSccList.back().Size()==1)) {
00318   fl=true;
00319         tit = rGen.TransRelBegin(vState);
00320         for(; tit != rGen.TransRelEnd(); ++tit) {
00321           if(tit->X1!=vState) break;
00322           // no self loop
00323           if(tit->X2!=vState) continue;
00324           // avoid event self loop does not qualify
00325           if(rFilter.mMode & SccFilter::FmEventsAvoid) 
00326           if(rFilter.pEventsAvoid->Exists(tit->Ev)) 
00327             continue;
00328           // found relevant selfloop
00329           fl=false;
00330           break;
00331         }
00332       }
00333     }
00334     // Invalidate result
00335     if(fl) {
00336 #ifdef FAUDES_DEBUG_FUNCTION
00337       FD_DF("SearchScc: invalidate scc for filter condition");
00338 #endif
00339       rSccList.pop_back();
00340       rRoots.Erase(vState);
00341     }
00342   }
00343 }
00344 
00345 
00346 // ComputeScc(Generator, SccList, Roots)
00347 bool ComputeScc(
00348   const Generator& rGen,
00349   const SccFilter& rFilter,
00350   std::list<StateSet>& rSccList,
00351   StateSet& rRoots)
00352 {
00353   FD_DF("CompteScc(" << rGen.Name() << ")");
00354 
00355   // inititalize results:
00356   rRoots.Clear();
00357   rSccList.clear();
00358 
00359   // initialize counter for depthfirstnumbers(DFN):
00360   int count=1;
00361 
00362   // provide local variables 
00363   std::stack<Idx> stack;
00364   StateSet stackstates;
00365   StateSet todostates;
00366   std::map<const Idx, int> dfn;
00367   std::map<const Idx, int> lowlnk;
00368 
00369   // initialise todo list
00370   if(rFilter.Mode() & SccFilter::FmIgnoreUnaccessible)
00371     todostates=rGen.AccessibleSet();
00372   else
00373     todostates=rGen.States();
00374   if(rFilter.Mode() & SccFilter::FmStatesAvoid)
00375     todostates = todostates - rFilter.StatesAvoid();
00376 
00377   // each recursion level keeps transition iterators
00378   rGen.TransRel().Lock();
00379 
00380   // start recursive depth-first search for Scc's:
00381   while(!todostates.Empty()) {
00382     SearchScc(*todostates.Begin(), count, rGen, rFilter, todostates, stack, stackstates, 
00383       dfn, lowlnk,rSccList, rRoots);
00384   }
00385 
00386   // done
00387   return !rSccList.empty();
00388 }
00389 
00390 // ComputeScc(Generator, SccList, Roots)
00391 bool ComputeScc(
00392   const Generator& rGen,
00393   std::list<StateSet>& rSccList,
00394   StateSet& rRoots)
00395 {
00396   FD_DF("CompteScc(" << rGen.Name() << ") [std]");
00397 
00398   // dummy
00399   const static SccFilter msFilter = SccFilter();
00400 
00401   // doit
00402   return ComputeScc(rGen,msFilter,rSccList,rRoots);
00403 }
00404 
00405 
00406 // ComputeScc(Generator, Filter, q0, Scc)
00407 bool  ComputeScc(
00408   const Generator& rGen,
00409   const SccFilter& rFilter,
00410   Idx q0, 
00411   StateSet& rScc)
00412 {
00413   FD_DF("ComputeScc(" << rGen.Name() << ")");
00414 
00415   // inititalize result
00416   rScc.Clear();
00417 
00418   // initialize counter for depthfirstnumbers:
00419   int count=1;
00420 
00421   // provide local variables 
00422   std::stack<Idx> stack;
00423   StateSet stackstates;
00424   StateSet todostates;
00425   std::map<const Idx, int> dfn;
00426   std::map<const Idx, int> lowlnk;
00427   std::list<StateSet> scclist;
00428   StateSet roots;
00429 
00430   // initialise todo list
00431   if(rFilter.Mode() & SccFilter::FmIgnoreUnaccessible)
00432     todostates=rGen.AccessibleSet();
00433   else
00434     todostates=rGen.States();
00435   if(rFilter.Mode() & SccFilter::FmStatesAvoid)
00436     todostates = todostates - rFilter.StatesAvoid();
00437 
00438   // copy and edit the filter
00439   SccFilter filter(rFilter);
00440   filter.FindFirst(true);
00441   StateSet reqstate;
00442   reqstate.Insert(q0);
00443   filter.StatesRequire(reqstate);
00444 
00445   // each recursion level keeps transition iterators
00446   rGen.TransRel().Lock();
00447 
00448   // start recursive depth-first search for Scc's:
00449   while(!todostates.Empty()) {
00450     SearchScc(*todostates.Begin(), count, rGen, filter, todostates, stack, stackstates, 
00451       dfn, lowlnk, scclist, roots);
00452   }
00453 
00454   // copy (!) result
00455   if(!scclist.empty()) rScc=*scclist.begin();
00456 
00457   // done
00458   return !rScc.Empty();
00459 }
00460 
00461 
00462 // ComputeScc(Generator, Filter, Scc)
00463 bool ComputeScc(
00464   const Generator& rGen,
00465   const SccFilter& rFilter,
00466   StateSet& rScc)
00467 {
00468   FD_DF("ComputeScc(" << rGen.Name() << ")");
00469 
00470   // inititalize result
00471   rScc.Clear();
00472 
00473   // initialize counter for depthfirstnumbers:
00474   int count=1;
00475 
00476   // provide local variables 
00477   std::stack<Idx> stack;
00478   StateSet stackstates;
00479   StateSet todostates;
00480   std::map<const Idx, int> dfn;
00481   std::map<const Idx, int> lowlnk;
00482   std::list<StateSet> scclist;
00483   StateSet roots;
00484 
00485   // initialise todo list
00486   if(rFilter.Mode() & SccFilter::FmIgnoreUnaccessible)
00487     todostates=rGen.AccessibleSet();
00488   else
00489     todostates=rGen.States();
00490   if(rFilter.Mode() & SccFilter::FmStatesAvoid)
00491     todostates = todostates - rFilter.StatesAvoid();
00492 
00493   // copy and edit the filter
00494   SccFilter filter(rFilter);
00495   filter.FindFirst(true);
00496 
00497   // each recursion level keeps transition iterators
00498   rGen.TransRel().Lock();
00499 
00500   // start recursive depth-first search for Scc's:
00501   while(!todostates.Empty()) {
00502     SearchScc(*todostates.Begin(), count, rGen, filter, todostates, stack, stackstates, 
00503       dfn, lowlnk, scclist, roots);
00504   }
00505 
00506   // copy (!) result
00507   if(!scclist.empty()) rScc=*scclist.begin();
00508 
00509   // done
00510   return !rScc.Empty();
00511 }
00512 
00513 // HasScc(Generator, Filter)
00514 bool HasScc(
00515   const Generator& rGen,
00516   const SccFilter& rFilter)
00517 {
00518   FD_DF("HasScc(" << rGen.Name() << ") [boolean only]");
00519 
00520   // initialize counter for depthfirstnumbers:
00521   int count=1;
00522 
00523   // provide local variables 
00524   std::stack<Idx> stack;
00525   StateSet stackstates;
00526   StateSet todostates;
00527   std::map<const Idx, int> dfn;
00528   std::map<const Idx, int> lowlnk;
00529   std::list<StateSet> scclist;
00530   StateSet roots;
00531 
00532   // initialise todo list
00533   if(rFilter.Mode() & SccFilter::FmIgnoreUnaccessible)
00534     todostates=rGen.AccessibleSet();
00535   else
00536     todostates=rGen.States();
00537   if(rFilter.Mode() & SccFilter::FmStatesAvoid)
00538     todostates = todostates - rFilter.StatesAvoid();
00539 
00540   // copy and edit the filter
00541   SccFilter filter(rFilter);
00542   filter.FindFirst(true);
00543 
00544   // each recursion level keeps transition iterators
00545   rGen.TransRel().Lock();
00546 
00547   // start recursive depth-first search for Scc's:
00548   while(!todostates.Empty()) {
00549     SearchScc(*todostates.Begin(), count, rGen, filter, todostates, stack, stackstates, 
00550       dfn, lowlnk, scclist, roots);
00551   }
00552 
00553   // done
00554   return !scclist.empty();
00555 
00556 }
00557 
00558 
00559 // RTI wrapper
00560 bool ComputeNextScc(
00561   const Generator& rGen,
00562   SccFilter& rFilter,
00563   StateSet& rScc
00564 ) {
00565   // find first
00566   rFilter.FindFirst(true);
00567   bool res = ComputeScc(rGen,rFilter,rScc);
00568   // fix filter
00569   if(res) rFilter.MergeStatesAvoid(rScc);
00570   rFilter.FindFirst(false);
00571   // done
00572   return res;
00573 }
00574 
00575 
00576 
00577 /*
00578 
00579 // WriteStateSets(rStateSets)
00580 // Write set of StateSet's to console.
00581 void WriteStateSets(
00582   const std::set<StateSet>& rStateSets)
00583 {
00584   FD_DF("WriteStateSets()");
00585   std::cout<<std::endl;
00586   if(rStateSets.empty()) {
00587     std::cout<<"WriteStateSets: Set of state sets is empty."<<std::endl;
00588     FD_DF("WriteStateSets: Set of state sets is empty.");
00589     return;
00590   }
00591   std::cout<<">WriteStateSets: Set of state sets begin:"<< std::endl;
00592   std::set<StateSet>::iterator StateSetit = rStateSets.begin();
00593   std::set<StateSet>::iterator StateSetit_end = rStateSets.end();
00594   for (; StateSetit != StateSetit_end; ++StateSetit) {
00595     std::cout<<std::endl<<"  >> State set begin:"<< std::endl;
00596     StateSet::Iterator sit = StateSetit->Begin();
00597     StateSet::Iterator sit_end = StateSetit->End();
00598     for (; sit != sit_end; ++sit) {
00599       std::cout<<"  >> "<<*sit<<std::endl;
00600     }
00601     std::cout<<"  >> State set end."<< std::endl;
00602   }  
00603   std::cout<<std::endl<<">WriteStateSets: Set of state sets end."<<std::endl;
00604 }
00605 
00606 // WriteStateSets(rGen,rStateSets)
00607 // Write set of StateSet's to console.
00608 // Use rGen for symbolic state names
00609 void WriteStateSets(
00610   const Generator& rGen,
00611   const std::set<StateSet>& rStateSets)
00612 {
00613   FD_DF("WriteStateSets()");
00614   std::cout<<std::endl;
00615   if(rStateSets.empty()) {
00616     std::cout<<"WriteStateSets: Set of state sets is empty."<<std::endl;
00617     FD_DF("WriteStateSets: Set of state sets is empty.");
00618     return;
00619   }
00620   std::cout<<">WriteStateSets: Set of state sets begin:"<< std::endl;
00621   std::set<StateSet>::iterator StateSetit = rStateSets.begin();
00622   std::set<StateSet>::iterator StateSetit_end = rStateSets.end();
00623   for (; StateSetit != StateSetit_end; ++StateSetit) {
00624     std::cout<<std::endl<<"  >> State set begin:"<< std::endl;
00625     std::cout<<"  "<<rGen.StateSetToString(*StateSetit)<<std::endl;
00626     std::cout<<"  >> State set end."<< std::endl;
00627   }  
00628   std::cout<<std::endl<<">WriteStateSets: Set of state sets end."<<std::endl;
00629 }
00630 
00631 */
00632 
00633 }//namespace faudes
00634 

libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen