regular.cpp

Go to the documentation of this file.
00001 
00013 /* FAU Discrete Event Systems Library (libfaudes)
00014 
00015 Copyright (C) 2006  Bernd Opitz
00016 Exclusive copyright is granted to Klaus Schmidt
00017 
00018 This library is free software; you can redistribute it and/or
00019 modify it under the terms of the GNU Lesser General Public
00020 License as published by the Free Software Foundation; either
00021 version 2.1 of the License, or (at your option) any later version.
00022 
00023 This library is distributed in the hope that it will be useful,
00024 but WITHOUT ANY WARRANTY; without even the implied warranty of
00025 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00026 Lesser General Public License for more details.
00027 
00028 You should have received a copy of the GNU Lesser General Public
00029 License along with this library; if not, write to the Free Software
00030 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00031 
00032   
00033 #include "regular.h"
00034 
00035 // A destructive version of the Generator::Copy() method named Move() is desired
00036 // but has not been implemented so far. In the meantime we use Copy() by the
00037 // following define.
00038 #define Move Copy
00039 
00040 // The function SParallel actually implements the product of two generators and
00041 // will be renamed as such. Moreover, Product will also accept nondeterministic
00042 // generators.
00043 #define Product SParallel
00044 
00045 namespace faudes {
00046 
00047 // LanguageUnionNonDet(rGen1, rGen2, rResGen)
00048 void LanguageUnionNonDet(const vGenerator& rGen1, const vGenerator& rGen2,
00049        vGenerator& rResGen) {
00050             
00051   FD_DF("LanguageUnionNonDet("<< rGen1.Name() 
00052   << "," << rGen2.Name() << ")");
00053     
00054   // are state names enabled?
00055   bool stateNamesEnabled=rResGen.StateNamesEnabled();
00056     
00057   // use pointer pResGen to result rResGen; if rResGen is identical to
00058   // one of the parameters, allocate temporary object and copy back later
00059   vGenerator* pResGen = &rResGen;
00060   if(&rResGen== &rGen1 || &rResGen== &rGen2) {
00061     pResGen= rResGen.NewP();
00062   }
00063 
00064   // prepare result
00065   pResGen->Clear();
00066 
00067   // union of alphabets
00068   pResGen->InjectAlphabet(rGen1.Alphabet()+rGen2.Alphabet());
00069     
00070   // Maps from states of rGen1 and rGen2 to states of ResGen
00071   std::map<Idx,Idx> Gen1StatesMap;
00072   std::map<Idx,Idx> Gen2StatesMap;
00073     
00074   // "union" of states: insert states representing the states of rGen1 and rGen2
00075   StateSet::Iterator sit;
00076   for (sit = rGen1.StatesBegin(); sit != rGen1.StatesEnd(); ++sit) {
00077     if (stateNamesEnabled) {
00078       Gen1StatesMap[*sit] = pResGen->InsState(pResGen->UniqueStateName(rGen1.StateName(*sit)+"(1)"));
00079     }
00080     else {
00081       Gen1StatesMap[*sit] = pResGen->InsState();
00082     }
00083   }
00084   for (sit = rGen2.StatesBegin(); sit != rGen2.StatesEnd(); ++sit) {
00085     if (stateNamesEnabled) {
00086       Gen2StatesMap[*sit] = pResGen->InsState(pResGen->UniqueStateName(rGen2.StateName(*sit)+"(2)"));
00087     }
00088     else {
00089       Gen2StatesMap[*sit] = pResGen->InsState();
00090     }
00091   }
00092     
00093   // "union" of transition relations
00094   TransSet::Iterator tit;
00095   for (tit = rGen1.TransRelBegin(); tit != rGen1.TransRelEnd(); ++tit) {
00096     pResGen->SetTransition(Gen1StatesMap[tit->X1], tit->Ev, Gen1StatesMap[tit->X2]);
00097   }
00098   for (tit = rGen2.TransRelBegin(); tit != rGen2.TransRelEnd(); ++tit) {
00099     pResGen->SetTransition(Gen2StatesMap[tit->X1], tit->Ev, Gen2StatesMap[tit->X2]);
00100   }
00101     
00102   // "union" of init states
00103   for (sit = rGen1.InitStatesBegin(); sit != rGen1.InitStatesEnd(); ++sit) {
00104     pResGen->SetInitState(Gen1StatesMap[*sit]);
00105   }
00106   for (sit = rGen2.InitStatesBegin(); sit != rGen2.InitStatesEnd(); ++sit) {
00107     pResGen->SetInitState(Gen2StatesMap[*sit]);
00108   }
00109     
00110   // "union" of marked states
00111   for (sit = rGen1.MarkedStatesBegin(); sit != rGen1.MarkedStatesEnd(); ++sit) {
00112     pResGen->SetMarkedState(Gen1StatesMap[*sit]);
00113   }
00114   for (sit = rGen2.MarkedStatesBegin(); sit != rGen2.MarkedStatesEnd(); ++sit) {
00115     pResGen->SetMarkedState(Gen2StatesMap[*sit]);
00116   }
00117     
00118   // set name of result
00119   pResGen->Name(CollapsString("UnionNonDet("+rGen1.Name()+","+rGen2.Name()+")"));
00120     
00121   // if necessary, move pResGen to rResGen
00122   if(pResGen != &rResGen) {
00123     pResGen->Move(rResGen);
00124     delete pResGen;
00125   }
00126     
00127 }
00128 
00129 // LanguageUnion(rGen1, rGen2, rResGen)
00130 void LanguageUnion(const vGenerator& rGen1, const vGenerator& rGen2, 
00131        vGenerator& rResGen) {
00132 
00133   FD_DF("LanguageUnion("<< rGen1.Name() 
00134   << "," << rGen2.Name() << ")");
00135    
00136   // fix name
00137   std::string name1 = rGen1.Name();
00138   std::string name2 = rGen2.Name();
00139 
00140   // avoid copy
00141   vGenerator* pTempGen = rResGen.NewP();
00142     
00143   // perform nondeterministic language union
00144   LanguageUnionNonDet(rGen1, rGen2, *pTempGen);
00145     
00146   // make deterministic
00147   Deterministic(*pTempGen, rResGen);
00148 
00149   // dispose temp
00150   delete pTempGen;
00151 
00152   // set name of result
00153   rResGen.Name(CollapsString("Union("+name1+","+name2+")"));
00154 
00155 }
00156 
00157 // LanguageIntersection(rGen1, rGen2, rResGen)
00158 void LanguageIntersection(const vGenerator& rGen1, const vGenerator& rGen2, 
00159         vGenerator& rResGen) {
00160   FD_DF("LanguageIntersection("<< rGen1.Name() 
00161   << "," << rGen2.Name() << ")");
00162     
00163   // fix name
00164   std::string name1 = rGen1.Name();
00165   std::string name2 = rGen2.Name();
00166 
00167   // the product of rGen1 and rGen2 implements the language intersection
00168   Product(rGen1, rGen2, rResGen);
00169   rResGen.Name(CollapsString("Intersection("+name1+","+name2+")"));
00170     
00171 }
00172 
00173 // EmptyLanguageIntersection(rGen1, rGen2)
00174 bool EmptyLanguageIntersection(const vGenerator& rGen1, const vGenerator& rGen2) {
00175   FD_DF("EmptyLanguageIntersection("<< rGen1.Name() 
00176   << "," << rGen2.Name() << ")");
00177     
00178   // The product of rGen1 and rGen2 implements the language intersection
00179   // Note: rather use a function that does not explicitely compute the product 
00180   // but that returns false as soon as a common transtion is found.
00181 
00182   Generator ProductGen;
00183   Product(rGen1, rGen2, ProductGen);
00184   return EmptyLanguage(ProductGen);
00185 }
00186 
00187 // LanguageDisjoint(rGen1, rGen2)
00188 bool LanguageDisjoint(const vGenerator& rGen1, const vGenerator& rGen2) {
00189   FD_DF("LanguageDisjoint("<< rGen1.Name() 
00190   << "," << rGen2.Name() << ")");
00191   return EmptyLanguageIntersection(rGen1,rGen2);
00192 }
00193 
00194 // Automaton(rGen)
00195 void Automaton(vGenerator& rGen, const EventSet& rAlphabet) {
00196   FD_DF("Automaton("<< rGen1.Name() << "," << rAlphabet.Name() << ")");
00197     
00198   // exception on alphabet mismatch
00199 #ifdef FAUDES_CHECKED
00200   if( !(rGen.Alphabet() <= rAlphabet) ){
00201     std::stringstream errstr;
00202     errstr << "Alphabet of generator " << rGen.Name() << 
00203       " has to be subset of alphabet "<< rAlphabet.Name() << ".";
00204     throw Exception("Automaton()", errstr.str(), 100);
00205   }
00206 #endif 
00207     
00208   // extend rGen.Alphabet() by rAlphabet
00209   rGen.InjectAlphabet(rGen.Alphabet()+rAlphabet);
00210     
00211   // remove states that do not represent prefixes of marked strings
00212   rGen.Coaccessible();
00213     
00214   // the automaton for the empty language Lm={} contains only the dump state,
00215   // which, in this case, represents Sigma*
00216   if(EmptyLanguage(rGen)){
00217         
00218     // remember generator name
00219     std::string name; 
00220     name=rGen.Name();
00221         
00222     FullLanguage(rGen.Alphabet(),rGen);
00223     if (rGen.StateNamesEnabled()) {
00224       rGen.StateName(*(rGen.InitStatesBegin()),"dump");
00225     }
00226     // the dump state is not marked
00227     rGen.ClearMarkedStates();
00228         
00229     // set generator name
00230     rGen.Name(CollapsString("Automaton(" + name + "," + rAlphabet.Name() + ")"));
00231     return;
00232   }
00233     
00234   // for correct result, rGen has to be deterministic!
00235 #ifdef FAUDES_CHECKED
00236   if ( !(rGen.IsDeterministic()) ) {
00237     FD_WARN("Automaton(): nondeterministic parameter " << rGen.Name() <<".");
00238   }
00239 #endif 
00240     
00241   // prepare result
00242   rGen.Name(CollapsString("Automaton(" + rGen.Name() + "," + rAlphabet.Name() + ")"));
00243     
00244   // introduce dump state
00245   Idx dump;
00246   if (rGen.StateNamesEnabled()) {
00247     std::string dumpstr=rGen.UniqueStateName("dump");
00248     dump = rGen.InsState(dumpstr);
00249   } else {
00250     dump = rGen.InsState();
00251   }
00252   
00253   // introduce transitions to dumpstate
00254   StateSet::Iterator sit;
00255   EventSet::Iterator eit;
00256   bool dumpNotReached=true; // indicate that dumpstate is not reached
00257   for (sit = rGen.StatesBegin(); sit != rGen.StatesEnd(); ++sit) {        
00258     for (eit = rGen.Alphabet().Begin(); eit != rGen.Alphabet().End(); ++eit) {
00259       // If no transition is defined for this state and event, insert respective
00260       // transition to dump state (note that dump state itself is also treated here
00261       // and thus provided with selfloops)
00262       if (rGen.TransRelBegin(*sit, *eit) == rGen.TransRelEnd(*sit, *eit)) {
00263   rGen.SetTransition(*sit, *eit, dump);
00264   // indicate that dumstate was reached
00265   if(*sit!=dump) dumpNotReached=false;
00266       }
00267     }        
00268   }
00269     
00270   // if no transition was introduced (except for selfloops), remove dump state
00271   if(dumpNotReached) 
00272     rGen.DelState(dump);
00273 }
00274 
00275 // Automaton(rGen)
00276 void Automaton(vGenerator& rGen) {
00277   FD_DF("Automaton("<< rGen1.Name() << ")");
00278   std::string name=rGen.Name();
00279   Automaton(rGen,rGen.Alphabet());    
00280   rGen.Name(CollapsString("Automaton(" + name + ")"));
00281 }
00282 
00283 // LanguageComplement(rGen,rAlphabet)
00284 void LanguageComplement(vGenerator& rGen, const EventSet& rAlphabet) {
00285   FD_DF("LanguageComplement("<< rGen1.Name() << "," << rAlphabet.Name() << ")");
00286 
00287   // exception on alphabet mismatch
00288 #ifdef FAUDES_CHECKED
00289   if( !(rGen.Alphabet() <= rAlphabet) ){
00290     std::stringstream errstr;
00291     errstr << "Alphabet of generator " << rGen.Name() << 
00292       " has to be subset of alphabet "<< rAlphabet.Name() << ".";
00293     throw Exception("LanguageComplement()", errstr.str(), 100);
00294   }
00295 #endif 
00296   // fix name
00297   std::string name = rGen.Name();  
00298   
00299   // convert to automaton (avoiding statename "dump")
00300   bool stateNamesEnabled=rGen.StateNamesEnabled(); 
00301   rGen.StateNamesEnabled(false); 
00302   Automaton(rGen,rAlphabet);
00303   rGen.StateNamesEnabled(stateNamesEnabled); 
00304     
00305   // invert marking
00306   rGen.InjectMarkedStates(rGen.States() - rGen.MarkedStates());
00307 
00308   // set name    
00309   rGen.Name(CollapsString("Complement(" + name + "," + rAlphabet.Name() + ")"));
00310 }
00311 
00312 // LanguageComplement(rGen)
00313 void LanguageComplement(vGenerator& rGen) {
00314   FD_DF("LanguageComplement("<< rGen1.Name() << ")");
00315   std::string name=rGen.Name();
00316   LanguageComplement(rGen,rGen.Alphabet());
00317   rGen.Name(CollapsString("Complement(" + name + ")"));
00318   return;    
00319 }
00320 
00321 // LanguageConcatenateNonDet(rGen1, rGen2, rResGen)
00322 void LanguageConcatenateNonDet(const vGenerator& rGen1, const vGenerator& rGen2, 
00323              vGenerator& rResGen) {
00324   FD_DF("LanguageConcatenateNonDet(" << rGen1.Name() << "," << rGen2.Name() << ")");
00325             
00326   // are state names enabled in result?
00327   bool stateNamesEnabled=rResGen.StateNamesEnabled();
00328     
00329   // use pointer pResGen to result rResGen; if rResGen is identical to
00330   // one of the parameters, allocate temporary object and copy back later
00331   vGenerator* pResGen = &rResGen;
00332   if(&rResGen== &rGen1 || &rResGen== &rGen2) {
00333     pResGen= rResGen.NewP();
00334   }
00335 
00336   // prepare result
00337   pResGen->Clear();
00338     
00339   // union of alphabets
00340   pResGen->InjectAlphabet(rGen1.Alphabet() + rGen2.Alphabet());
00341 
00342   // Maps from states of rGen1 and rGen2 to states of ResGen
00343   std::map<Idx,Idx> Gen1StatesMap;
00344   std::map<Idx,Idx> Gen2StatesMap;
00345 
00346   // helpers
00347   StateSet::Iterator sit;
00348   StateSet::Iterator sit1m, sit2i; // rGen1 marked states, rGen2 initial states
00349   TransSet::Iterator tit;
00350     
00351   // "union" of states: insert states representing the states of rGen1 and rGen2
00352   for (sit = rGen1.StatesBegin(); sit != rGen1.StatesEnd(); ++sit) {
00353     if (stateNamesEnabled) {
00354       Gen1StatesMap[*sit] = pResGen->InsState(pResGen->UniqueStateName(rGen1.StateName(*sit)+"(1)"));
00355     }
00356     else {
00357       Gen1StatesMap[*sit] = pResGen->InsState();
00358     }
00359   }
00360   for (sit = rGen2.StatesBegin(); sit != rGen2.StatesEnd(); ++sit) {
00361     if (stateNamesEnabled) {
00362       Gen2StatesMap[*sit] = pResGen->InsState(pResGen->UniqueStateName(rGen2.StateName(*sit)+"(2)"));
00363     }
00364     else {
00365       Gen2StatesMap[*sit] = pResGen->InsState();
00366     }
00367   }
00368 
00369   // remove rGen2 init states from pResGen->stateset and Gen2StatesMap as they are "replaced"
00370   // by the marked states of rGen1. Also remember, if at least one init state of rGen2
00371   // is marked; in this case, the marked states of rGen1 remain marked, as epsilon is
00372   // concatenated to Lm1.
00373   bool concatenateEpsilon=false;
00374   for (sit = rGen2.InitStatesBegin(); sit != rGen2.InitStatesEnd(); ++sit) {
00375     pResGen->DelState(Gen2StatesMap[*sit]);
00376     Gen2StatesMap.erase(*sit);
00377     if (rGen2.ExistsMarkedState(*sit)) {
00378       concatenateEpsilon=true;
00379     }
00380   }
00381     
00382     
00383   pResGen->InjectInitStates(rGen1.InitStates());
00384     
00385   // set pResGen init states corresponding to rGen1 init states using Gen1StatesMap
00386   for (sit = rGen1.InitStatesBegin(); sit != rGen1.InitStatesEnd(); ++sit) {
00387     pResGen->SetInitState(Gen1StatesMap[*sit]);
00388   }
00389     
00390   // add rGen1 transitions
00391   for (tit = rGen1.TransRelBegin(); tit != rGen1.TransRelEnd(); ++tit) {
00392     pResGen->SetTransition(Gen1StatesMap[tit->X1], tit->Ev, Gen1StatesMap[tit->X2]);
00393   }
00394     
00395   // add rGen2 transitions starting at initial states at each state corresponding to a 
00396   // marked state of rGen1.
00397   for (sit2i = rGen2.InitStatesBegin(); sit2i != rGen2.InitStatesEnd(); ++sit2i) {
00398     for (tit = rGen2.TransRelBegin(*sit2i); tit != rGen2.TransRelEnd(*sit2i); ++tit) {
00399       // iterate over rGen1 mstates
00400       for (sit1m = rGen1.MarkedStatesBegin(); sit1m != rGen1.MarkedStatesEnd(); ++sit1m) {
00401   // note: in this state, there might already be a transition from rGen1 with the
00402   // same event. Hence, the following line can cause nondeterminism in pResGen.
00403   pResGen->SetTransition(Gen1StatesMap[*sit1m], tit->Ev, Gen2StatesMap[tit->X2]);
00404       }
00405     }
00406   }
00407     
00408   // add rGen2 transitions not starting at initial states
00409   for (tit = rGen2.TransRelBegin(); tit != rGen2.TransRelEnd(); ++tit) {
00410     // transitions from init states have already been done above.
00411     if (rGen2.ExistsInitState(tit->X1)) {
00412       continue;
00413     }
00414     pResGen->SetTransition(Gen2StatesMap[tit->X1], tit->Ev, Gen2StatesMap[tit->X2]);
00415   }
00416     
00417   // set pResGen marked states corresponding to rGen2 marked states using Gen2StatesMap
00418   for (sit = rGen2.MarkedStatesBegin(); sit != rGen2.MarkedStatesEnd(); ++sit) {
00419     if(!(rGen2.ExistsInitState(*sit))) {
00420       pResGen->SetMarkedState(Gen2StatesMap[*sit]);
00421     }
00422   }
00423 
00424   // if epsilon is concatenated to Lm1, additionally set pResGen marked 
00425   // states corresponding to rGen1 marked states using Gen1StatesMap
00426   if(concatenateEpsilon){
00427     for (sit = rGen1.MarkedStatesBegin(); sit != rGen1.MarkedStatesEnd(); ++sit) {
00428       pResGen->SetMarkedState(Gen1StatesMap[*sit]);
00429     }
00430   }
00431     
00432   // remove blocking states as they provide no useful meaning.
00433   pResGen->Coaccessible();
00434   pResGen->Name("ConcatenateNonDet("+rGen1.Name()+","+rGen2.Name()+")");
00435     
00436   // if necessary, move pResGen to rResGen
00437   if(pResGen != &rResGen) {
00438     pResGen->Move(rResGen);
00439     delete pResGen;
00440   }
00441     
00442 }
00443 
00444 // LanguageConcatenate(rGen1, rGen2, rResGen)
00445 void LanguageConcatenate(const vGenerator& rGen1, const vGenerator& rGen2, 
00446        vGenerator& rResGen) {
00447 
00448   FD_DF("LanguageConcatenate("<< rGen1.Name() 
00449   << "," << rGen2.Name() << ")");
00450     
00451   // perform nondeterministic language concatenation
00452   LanguageConcatenateNonDet(rGen1, rGen2, rResGen);
00453     
00454   // make deterministic if necessary
00455   if(!(rResGen.IsDeterministic())){
00456     Deterministic(rResGen, rResGen);
00457   }
00458 
00459   // set name of result
00460   rResGen.Name("Concatenate("+rGen1.Name()+","+rGen2.Name()+")");
00461     
00462   return;    
00463 }
00464 
00465 // FullLanguage(rAlphabet, rResGen)
00466 void FullLanguage(const EventSet& rAlphabet, vGenerator& rResGen) {
00467   FD_DF("FullLanguage("<< rAlphabet.Name() 
00468   << "," << rResGen.Name() << ")");
00469   
00470   // prepare result
00471   rResGen.Clear();
00472   
00473   // helpers
00474   Idx state;
00475   EventSet::Iterator evit;
00476   
00477   // alphabet
00478   rResGen.InjectAlphabet(rAlphabet);
00479   
00480   // insert marked initial state
00481   if(rResGen.StateNamesEnabled()){
00482     state = rResGen.InsInitState("1");
00483   } else{
00484     state = rResGen.InsInitState();
00485   }
00486   rResGen.SetMarkedState(state);
00487   
00488   // create selfloop for each event
00489   for (evit = rAlphabet.Begin(); evit != rAlphabet.End(); ++evit) {
00490     rResGen.SetTransition(state, *evit, state);
00491   }
00492   
00493   // set name of result
00494   rResGen.Name("FullLanguage("+rAlphabet.Name()+")");
00495     
00496   return;
00497 }
00498 
00499 // AlphabetLanguage(rAlphabet, rResGen)
00500 void AlphabetLanguage(const EventSet& rAlphabet, vGenerator& rResGen) {
00501   FD_DF("AlphabetLanguage("<< rAlphabet.Name() 
00502   << "," << rResGen.Name() << ")");
00503   
00504   // prepare result
00505   rResGen.Clear();
00506       
00507   // set name of result
00508   rResGen.Name("AlphabetLanguage("+rAlphabet.Name()+")");
00509     
00510   // if alphabet is empty, leave generator empty
00511   if(rAlphabet.Empty()){
00512     FD_WARN("AlphabetLanguage: empty alphabet.");
00513     return;
00514   }
00515     
00516   // helpers
00517   Idx istate, mstate;
00518   EventSet::Iterator evit;
00519   
00520   // alphabet
00521   rResGen.InjectAlphabet(rAlphabet);
00522   
00523   // insert one initial state and one marked state
00524   if(rResGen.StateNamesEnabled()){
00525     istate = rResGen.InsInitState("1");
00526     mstate = rResGen.InsMarkedState("2");
00527   }
00528   else{
00529     istate = rResGen.InsInitState();
00530     mstate = rResGen.InsMarkedState();
00531   }
00532   
00533   // for each event from rAlphabet, inserted transition leading from init state to marked state
00534   for (evit = rAlphabet.Begin(); evit != rAlphabet.End(); ++evit) {
00535     rResGen.SetTransition(istate, *evit, mstate);
00536   }
00537     
00538   return;
00539 }
00540 
00541 // EmptyStringLanguage(rAlphabet, rResGen)
00542 void EmptyStringLanguage(const EventSet& rAlphabet, vGenerator& rResGen) {
00543   FD_DF("EmptyStringLanguage("<< rAlphabet.Name() 
00544   << "," << rResGen.Name() << ")");
00545   
00546   // prepare result
00547   rResGen.Clear();
00548   
00549   // helpers
00550   Idx state;
00551   
00552   // alphabet
00553   rResGen.InjectAlphabet(rAlphabet);
00554   
00555   // insert marked initial state
00556   if(rResGen.StateNamesEnabled()){
00557     state = rResGen.InsInitState("1");
00558   }
00559   else{
00560     state = rResGen.InsInitState();
00561   }
00562   rResGen.SetMarkedState(state);
00563   
00564   // set name of result
00565   rResGen.Name("EmptyStringLanguage("+rAlphabet.Name()+")");
00566     
00567   return;
00568 }
00569 
00570 // EmptyLanguage(rAlphabet, rResGen)
00571 void EmptyLanguage(const EventSet& rAlphabet, vGenerator& rResGen) {
00572   FD_DF("EmptyStringLanguage("<< rAlphabet.Name() 
00573   << "," << rResGen.Name() << ")");
00574   
00575   // prepare result
00576   rResGen.Clear();
00577   
00578   // alphabet
00579   rResGen.InjectAlphabet(rAlphabet);
00580 
00581   // set name of result
00582   rResGen.Name("EmptyLanguage("+rAlphabet.Name()+")");
00583     
00584   return;
00585 }
00586 
00587 // EmptyLanguage(rGen)
00588 bool EmptyLanguage(const vGenerator& rGen) {
00589   // case a) check if set of marked states is empty
00590   if(rGen.MarkedStatesSize()==0) return true;
00591   // case b) check if no marked state is accessible (reachable)
00592   return (rGen.AccessibleSet()*rGen.MarkedStates()).Empty();
00593 }
00594 
00595 // LanguageInclusion(rGen1, rGen2)
00596 bool LanguageInclusion(const vGenerator& rGen1, const vGenerator& rGen2) {
00597     
00598   FD_DF("LanguageInclusion("<< rGen1.Name() << "," << rGen2.Name() << ")"); 
00599     
00600   // check if there is no string in Lm1 that is not in Lm2, which means Lm1<=Lm2
00601   Generator NotrGen2=rGen2;
00602   // note: complement w.r.t. union of alphabets to ensure that elementwise 
00603   // inclusion of Lm1 in Lm2 is tested
00604   LanguageComplement(NotrGen2 , rGen1.Alphabet()+rGen2.Alphabet());
00605   return EmptyLanguageIntersection(rGen1,NotrGen2);        
00606 }
00607 
00608 // LanguageEquality(rGen1, rGen2)
00609 bool LanguageEquality(const vGenerator& rGen1, const vGenerator& rGen2) {
00610     
00611   FD_DF("LanguageEquality("<< rGen1.Name() << "," << rGen2.Name() << ")");
00612 
00613   // Check for equality by testing mutual inclusion
00614   return LanguageInclusion(rGen1,rGen2) && LanguageInclusion(rGen2,rGen1);
00615 }
00616 
00617 // KleeneClosure(rGen, rResGen)
00618 void KleeneClosure(vGenerator& rGen) {
00619    
00620   FD_DF("KleeneClosure("<< rGen.Name() << ")");
00621 
00622   // fix name 
00623   std::string name=CollapsString("KleeneClosure(" + rGen.Name() + ")");
00624 
00625   // The Kleene Closure of the empty set is the empty set
00626   if(EmptyLanguage(rGen)){
00627     rGen.Name(name);
00628     return;
00629   }
00630 
00631   // run nondet version    
00632   KleeneClosureNonDet(rGen);
00633   Deterministic(rGen, rGen);
00634 
00635   // set name
00636   rGen.Name(name);
00637 }
00638 
00639 // KleeneClosureNonDet(rGen)
00640 void KleeneClosureNonDet(vGenerator& rGen) {
00641     
00642   FD_DF("KleeneClosureNonDet("<< rGen.Name()  << ")");
00643     
00644   // set name 
00645   rGen.Name(CollapsString("KleeneClosureNonDet("+ rGen.Name() + ")"));
00646     
00647   // The Kleene Closure of the empty set is the empty set
00648   if(EmptyLanguage(rGen)) return;
00649     
00650   // helpers
00651   TransSet::Iterator tit;
00652   StateSet::Iterator init = rGen.InitStatesBegin();
00653   TransSet TransToInsert;
00654     
00655   // for all transitions leading from a state x1 to a marked state: insert a transition
00656   // with the same event that leads to (one of) the initial state(s). This step makes
00657   // rGen nondeterministic.
00658   // first, find respective transitions in rGen and update TransToInsert with new
00659   // transitions to insert
00660   for (tit = rGen.TransRelBegin(); tit != rGen.TransRelEnd(); ++tit) {
00661   
00662     if(rGen.ExistsMarkedState(tit->X2)) {
00663       if( !(rGen.ExistsTransition(tit->X1, tit->Ev, *init)) ){
00664   TransToInsert.Insert(tit->X1, tit->Ev, *init);
00665       }
00666     }
00667         
00668   }
00669   // now, extend rGen by transitions of TransToInsert
00670   for (tit = TransToInsert.Begin(); tit != TransToInsert.End(); ++tit) {
00671     rGen.SetTransition(*tit);
00672   }
00673     
00674   // KleeneClosure of nonempty language always contains the empty string:
00675   // mark at least one initial state
00676   rGen.SetMarkedState(*init);
00677 }
00678 
00679 // PrefixClosure(rGen)
00680 void PrefixClosure(vGenerator& rGen) {
00681     
00682   FD_DF("PrefixClosure("<< name << ")");
00683 
00684   // fix name
00685   std::string name=CollapsString("PrefixClosure("+ rGen.Name() + ")");
00686     
00687   // remove all states that do net represent prefixes of marked strings
00688   rGen.Coaccessible();
00689     
00690   // mark all remaining states
00691   rGen.InjectMarkedStates(rGen.States());
00692    
00693   // set name 
00694   rGen.Name(name);
00695     
00696 }
00697 
00698 // SelfLoop(rGen,rAlphabet)
00699 void SelfLoop(vGenerator& rGen,const EventSet& rAlphabet) {
00700     
00701   FD_DF("SelfLoop(" << rGen.Name() << "," << rAlphabet.Name() << ")");
00702 
00703   // fix name
00704   std::string name = CollapsString("SelfLoop(" + rGen.Name() + "," + rAlphabet.Name() + ")");
00705   // extend alphabet of rGen
00706   rGen.InjectAlphabet(rGen.Alphabet()+rAlphabet);
00707     
00708   //helpers
00709   EventSet::Iterator evit,evbegin,evend;
00710   evbegin = rAlphabet.Begin();
00711   evend = rAlphabet.End();  
00712   StateSet::Iterator sit;
00713     
00714   // iterate over all states and insert selfloop for each event of rAlphabet
00715   for (sit = rGen.StatesBegin(); sit != rGen.StatesEnd(); ++sit) {
00716     for(evit = evbegin; evit != evend; ++evit){
00717       rGen.SetTransition(*sit, *evit, *sit);
00718     }
00719   }
00720     
00721   // set name
00722   rGen.Name(name);
00723 }
00724 
00725 // SelfLoopMarkedStates(rGen,rAlphabet)
00726 void SelfLoopMarkedStates(vGenerator& rGen,const EventSet& rAlphabet) {
00727     
00728   FD_DF("SelfLoopMarkedStates(" << rGen.Name() << "," << rAlphabet.Name() << ")");
00729 
00730   // fix name
00731   std::string name = CollapsString("SelfLoopMarkedStates(" + rGen.Name() 
00732      + "," + rAlphabet.Name() + ")");
00733 
00734   // extend alphabet of rGen
00735   rGen.InjectAlphabet(rGen.Alphabet()+rAlphabet);
00736     
00737   //helpers
00738   EventSet::Iterator evit,evbegin,evend;
00739   evbegin = rAlphabet.Begin();
00740   evend = rAlphabet.End();  
00741   StateSet::Iterator sit;
00742     
00743   // iterate over all marked states and insert selfloop for each event of rAlphabet
00744   for (sit = rGen.MarkedStatesBegin(); sit != rGen.MarkedStatesEnd(); ++sit) {
00745     for(evit = evbegin; evit != evend; ++evit){
00746       rGen.SetTransition(*sit, *evit, *sit);
00747     }
00748   }
00749     
00750   // set name
00751   rGen.Name(name);
00752 }
00753 
00754 // SelfLoop(rGen,rAlphabet,rStates)
00755 void SelfLoop(vGenerator& rGen,const EventSet& rAlphabet,const StateSet& rStates) {
00756     
00757   FD_DF("SelfLoop(" << rGen.Name() << "," << rAlphabet.Name() << "," << rStates.Name() << ")");
00758 
00759   // fix name
00760   std::string name = CollapsString("SelfLoop(" + rGen.Name() 
00761      + "," + rAlphabet.Name() + "," + rStates.Name() + ")");
00762 
00763   // exception: rStates must be states of rGen
00764 #ifdef FAUDES_CHECKED
00765   if( !(rStates <= rGen.States()) ){
00766     std::stringstream errstr;
00767     errstr << "State set " << rStates.Name() << 
00768       " has to be included in state set of "<< rGen.Name() << ".";
00769     throw Exception("SelfLoop()", errstr.str(), 100);
00770   }
00771 #endif
00772     
00773   // extend alphabet of rGen
00774   rGen.InjectAlphabet(rGen.Alphabet()+rAlphabet);
00775     
00776   //helpers
00777   EventSet::Iterator evit,evbegin,evend;
00778   evbegin = rAlphabet.Begin();
00779   evend = rAlphabet.End();    
00780   StateSet::Iterator sit;
00781     
00782   // iterate over all marked states and insert selfloop for each event of rAlphabet
00783   for (sit = rStates.Begin(); sit != rStates.End(); ++sit) {
00784     for(evit = evbegin; evit != evend; ++evit){
00785       rGen.SetTransition(*sit, *evit, *sit);
00786     }
00787   }
00788     
00789   // set name
00790   rGen.Name(name);
00791 }
00792 
00793 } // namespace faudes
00794 
00795 #undef Move //see define above for comment
00796 #undef Product //see define above for comment

Generated on Fri May 9 11:26:47 2008 for libFAUDES 2.09b by  doxygen 1.4.4