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("<< rGen.Name() << "," << rAlphabet.Name() << ")");
00197     
00198   // extend rGen.Alphabet() by rAlphabet
00199   rGen.InjectAlphabet(rGen.Alphabet()+rAlphabet);
00200     
00201   // remove states that do not represent prefixes of marked strings
00202   rGen.Coaccessible();
00203     
00204   // the automaton for the empty language Lm={} contains only the dump state,
00205   // which, in this case, represents Sigma*
00206   if(EmptyLanguage(rGen)){
00207         
00208     // remember generator name
00209     std::string name; 
00210     name=rGen.Name();
00211         
00212     FullLanguage(rGen.Alphabet(),rGen);
00213     if (rGen.StateNamesEnabled()) {
00214       rGen.StateName(*(rGen.InitStatesBegin()),"dump");
00215     }
00216     // the dump state is not marked
00217     rGen.ClearMarkedStates();
00218         
00219     // set generator name
00220     rGen.Name(CollapsString("Automaton(" + name + "," + rAlphabet.Name() + ")"));
00221     return;
00222   }
00223     
00224   // for correct result, rGen has to be deterministic!
00225 #ifdef FAUDES_CHECKED
00226   if ( !(rGen.IsDeterministic()) ) {
00227     FD_WARN("Automaton(): nondeterministic parameter " << rGen.Name() <<".");
00228   }
00229 #endif 
00230     
00231   // prepare result
00232   rGen.Name(CollapsString("Automaton(" + rGen.Name() + "," + rAlphabet.Name() + ")"));
00233     
00234   // introduce dump state
00235   Idx dump;
00236   if (rGen.StateNamesEnabled()) {
00237     std::string dumpstr=rGen.UniqueStateName("dump");
00238     dump = rGen.InsState(dumpstr);
00239   } else {
00240     dump = rGen.InsState();
00241   }
00242   
00243   // introduce transitions to dumpstate
00244   StateSet::Iterator sit;
00245   EventSet::Iterator eit;
00246   bool dumpNotReached=true; // indicate that dumpstate is not reached
00247   for (sit = rGen.StatesBegin(); sit != rGen.StatesEnd(); ++sit) {        
00248     for (eit = rGen.Alphabet().Begin(); eit != rGen.Alphabet().End(); ++eit) {
00249       // If no transition is defined for this state and event, insert respective
00250       // transition to dump state (note that dump state itself is also treated here
00251       // and thus provided with selfloops)
00252       if (rGen.TransRelBegin(*sit, *eit) == rGen.TransRelEnd(*sit, *eit)) {
00253   rGen.SetTransition(*sit, *eit, dump);
00254   // indicate that dumstate was reached
00255   if(*sit!=dump) dumpNotReached=false;
00256       }
00257     }        
00258   }
00259     
00260   // if no transition was introduced (except for selfloops), remove dump state
00261   if(dumpNotReached) 
00262     rGen.DelState(dump);
00263 }
00264 
00265 // Automaton(rGen)
00266 void Automaton(vGenerator& rGen) {
00267   FD_DF("Automaton("<< rGen.Name() << ")");
00268   std::string name=rGen.Name();
00269   Automaton(rGen,rGen.Alphabet());    
00270   rGen.Name(CollapsString("Automaton(" + name + ")"));
00271 }
00272 
00273 // LanguageComplement(rGen,rAlphabet)
00274 void LanguageComplement(vGenerator& rGen, const EventSet& rAlphabet) {
00275   FD_DF("LanguageComplement("<< rGen.Name() << "," << rAlphabet.Name() << ")");
00276 
00277   // fix name
00278   std::string name = rGen.Name();  
00279   
00280   // convert to automaton (avoiding statename "dump")
00281   bool stateNamesEnabled=rGen.StateNamesEnabled(); 
00282   rGen.StateNamesEnabled(false); 
00283   Automaton(rGen,rAlphabet);
00284   rGen.StateNamesEnabled(stateNamesEnabled); 
00285     
00286   // invert marking
00287   rGen.InjectMarkedStates(rGen.States() - rGen.MarkedStates());
00288 
00289   // set name    
00290   rGen.Name(CollapsString("Complement(" + name + "," + rAlphabet.Name() + ")"));
00291 }
00292 
00293 // LanguageComplement(rGen)
00294 void LanguageComplement(vGenerator& rGen) {
00295   FD_DF("LanguageComplement("<< rGen.Name() << ")");
00296   std::string name=rGen.Name();
00297   LanguageComplement(rGen,rGen.Alphabet());
00298   rGen.Name(CollapsString("Complement(" + name + ")"));
00299   return;    
00300 }
00301 
00302 //LanguageDifference(rGen1, rGen2, rResGen)
00303 void LanguageDifference(
00304    const vGenerator& rGen1, 
00305    const vGenerator& rGen2,
00306    vGenerator& rResGen) {
00307          
00308      FD_DF("LanguageDifference("<< rGen1.Name() << "," << rGen2.Name() << ")");
00309      
00310     // use pointer pResGen to result rResGen; if rResGen is identical to
00311     // one of the parameters, allocate temporary object and copy back later 
00312      vGenerator* pResGen = &rResGen;
00313      if(&rResGen == &rGen1 || &rResGen== &rGen2) {
00314          pResGen = rResGen.NewP();
00315          }    
00316     
00317     // due to the use of LanguageComplement(), rGen2 has to be deterministic
00318     #ifdef FAUDES_CHECKED
00319     if(!(rGen2.IsDeterministic())){
00320         std::stringstream errstr;
00321         errstr << "Nondeterministic parameter " << rGen2.Name() << ".";
00322          throw Exception("LanguageDifference()", errstr.str(), 101);
00323         }
00324     #endif
00325           
00326     // prepare result
00327     pResGen->Clear();
00328      
00329     // calculate "Lm1-Lm2" by building the intersection of Lm1 with the complement of Lm2
00330         
00331     *pResGen=rGen2;
00332     // for correct result, complement has to be computed wrt the alphabet of Lm1!
00333     LanguageComplement(*pResGen,rGen1.Alphabet());
00334     LanguageIntersection(rGen1, *pResGen, *pResGen);
00335         
00336     pResGen->Name(CollapsString("LanguageDifference(" + rGen1.Name() + "," + rGen2.Name() + ")"));
00337   
00338     // if necessary, move pResGen to rResGen
00339     if(pResGen != &rResGen) {
00340         pResGen->Move(rResGen);
00341         delete pResGen;
00342         } 
00343     
00344     return;
00345 }
00346 
00347 // LanguageConcatenateNonDet(rGen1, rGen2, rResGen)
00348 void LanguageConcatenateNonDet(const vGenerator& rGen1, const vGenerator& rGen2, 
00349              vGenerator& rResGen) {
00350   FD_DF("LanguageConcatenateNonDet(" << rGen1.Name() << "," << rGen2.Name() << ")");
00351             
00352   // are state names enabled in result?
00353   bool stateNamesEnabled=rResGen.StateNamesEnabled();
00354     
00355   // use pointer pResGen to result rResGen; if rResGen is identical to
00356   // one of the parameters, allocate temporary object and copy back later
00357   vGenerator* pResGen = &rResGen;
00358   if(&rResGen== &rGen1 || &rResGen== &rGen2) {
00359     pResGen= rResGen.NewP();
00360   }
00361 
00362   // prepare result
00363   pResGen->Clear();
00364     
00365   // union of alphabets
00366   pResGen->InjectAlphabet(rGen1.Alphabet() + rGen2.Alphabet());
00367 
00368   // Maps from states of rGen1 and rGen2 to states of ResGen
00369   std::map<Idx,Idx> Gen1StatesMap;
00370   std::map<Idx,Idx> Gen2StatesMap;
00371 
00372   // helpers
00373   StateSet::Iterator sit;
00374   StateSet::Iterator sit1m, sit2i; // rGen1 marked states, rGen2 initial states
00375   TransSet::Iterator tit;
00376     
00377   // "union" of states: insert states representing the states of rGen1 and rGen2
00378   for (sit = rGen1.StatesBegin(); sit != rGen1.StatesEnd(); ++sit) {
00379     if (stateNamesEnabled) {
00380       Gen1StatesMap[*sit] = pResGen->InsState(pResGen->UniqueStateName(rGen1.StateName(*sit)+"(1)"));
00381     }
00382     else {
00383       Gen1StatesMap[*sit] = pResGen->InsState();
00384     }
00385   }
00386   for (sit = rGen2.StatesBegin(); sit != rGen2.StatesEnd(); ++sit) {
00387     if (stateNamesEnabled) {
00388       Gen2StatesMap[*sit] = pResGen->InsState(pResGen->UniqueStateName(rGen2.StateName(*sit)+"(2)"));
00389     }
00390     else {
00391       Gen2StatesMap[*sit] = pResGen->InsState();
00392     }
00393   }
00394 
00395   // remove rGen2 init states from pResGen->stateset and Gen2StatesMap as they are "replaced"
00396   // by the marked states of rGen1. Also remember, if at least one init state of rGen2
00397   // is marked; in this case, the marked states of rGen1 remain marked, as epsilon is
00398   // concatenated to Lm1.
00399   bool concatenateEpsilon=false;
00400   for (sit = rGen2.InitStatesBegin(); sit != rGen2.InitStatesEnd(); ++sit) {
00401     pResGen->DelState(Gen2StatesMap[*sit]);
00402     Gen2StatesMap.erase(*sit);
00403     if (rGen2.ExistsMarkedState(*sit)) {
00404       concatenateEpsilon=true;
00405     }
00406   }
00407     
00408   // set pResGen init states corresponding to rGen1 init states using Gen1StatesMap
00409   for (sit = rGen1.InitStatesBegin(); sit != rGen1.InitStatesEnd(); ++sit) {
00410     pResGen->SetInitState(Gen1StatesMap[*sit]);
00411   }
00412     
00413   // add rGen1 transitions
00414   for (tit = rGen1.TransRelBegin(); tit != rGen1.TransRelEnd(); ++tit) {
00415     pResGen->SetTransition(Gen1StatesMap[tit->X1], tit->Ev, Gen1StatesMap[tit->X2]);
00416   }
00417     
00418   // add rGen2 transitions starting at initial states at each state corresponding to a 
00419   // marked state of rGen1.
00420   for (sit2i = rGen2.InitStatesBegin(); sit2i != rGen2.InitStatesEnd(); ++sit2i) {
00421     for (tit = rGen2.TransRelBegin(*sit2i); tit != rGen2.TransRelEnd(*sit2i); ++tit) {
00422       // iterate over rGen1 mstates
00423         for (sit1m = rGen1.MarkedStatesBegin(); sit1m != rGen1.MarkedStatesEnd(); ++sit1m) {
00424             // If the rGen2 transition tit leads to an init state of rGen2, then the respective
00425             // pResGen transition has to lead to the current marked state of rGen1 (as selfloop)
00426             if(rGen2.ExistsInitState(tit->X2)){
00427                 pResGen->SetTransition(Gen1StatesMap[*sit1m], tit->Ev, Gen1StatesMap[*sit1m]);
00428             }
00429             else {
00430                 pResGen->SetTransition(Gen1StatesMap[*sit1m], tit->Ev, Gen2StatesMap[tit->X2]);
00431             }
00432             // note: in this state, there might already be a transition from rGen1 with the
00433             // same event. Hence, the transitions inserted above can cause nondeterminism in pResGen.
00434         }
00435     }
00436   }
00437     
00438   // add rGen2 transitions not starting at initial states
00439   for (tit = rGen2.TransRelBegin(); tit != rGen2.TransRelEnd(); ++tit) {
00440     // transitions from init states have already been done above.
00441     if (rGen2.ExistsInitState(tit->X1)) {
00442       continue;
00443     }
00444     pResGen->SetTransition(Gen2StatesMap[tit->X1], tit->Ev, Gen2StatesMap[tit->X2]);
00445   }
00446     
00447   // set pResGen marked states corresponding to rGen2 marked states using Gen2StatesMap
00448   for (sit = rGen2.MarkedStatesBegin(); sit != rGen2.MarkedStatesEnd(); ++sit) {
00449     if(!(rGen2.ExistsInitState(*sit))) {
00450       pResGen->SetMarkedState(Gen2StatesMap[*sit]);
00451     }
00452   }
00453 
00454   // if epsilon is concatenated to Lm1, additionally set pResGen marked 
00455   // states corresponding to rGen1 marked states using Gen1StatesMap
00456   if(concatenateEpsilon){
00457     for (sit = rGen1.MarkedStatesBegin(); sit != rGen1.MarkedStatesEnd(); ++sit) {
00458       pResGen->SetMarkedState(Gen1StatesMap[*sit]);
00459     }
00460   }
00461     
00462   // remove blocking states as they provide no useful meaning.
00463   pResGen->Coaccessible();
00464   pResGen->Name("ConcatenateNonDet("+rGen1.Name()+","+rGen2.Name()+")");
00465     
00466   // if necessary, move pResGen to rResGen
00467   if(pResGen != &rResGen) {
00468     pResGen->Move(rResGen);
00469     delete pResGen;
00470   }
00471     
00472 }
00473 
00474 // LanguageConcatenate(rGen1, rGen2, rResGen)
00475 void LanguageConcatenate(const vGenerator& rGen1, const vGenerator& rGen2, 
00476        vGenerator& rResGen) {
00477 
00478   FD_DF("LanguageConcatenate("<< rGen1.Name() 
00479   << "," << rGen2.Name() << ")");
00480     
00481   // perform nondeterministic language concatenation
00482   LanguageConcatenateNonDet(rGen1, rGen2, rResGen);
00483     
00484   // make deterministic if necessary
00485   if(!(rResGen.IsDeterministic())){
00486     Deterministic(rResGen, rResGen);
00487   }
00488 
00489   // set name of result
00490   rResGen.Name("Concatenate("+rGen1.Name()+","+rGen2.Name()+")");
00491     
00492   return;    
00493 }
00494 
00495 // FullLanguage(rAlphabet, rResGen)
00496 void FullLanguage(const EventSet& rAlphabet, vGenerator& rResGen) {
00497   FD_DF("FullLanguage("<< rAlphabet.Name() 
00498   << "," << rResGen.Name() << ")");
00499   
00500   // prepare result
00501   rResGen.Clear();
00502   
00503   // helpers
00504   Idx state;
00505   EventSet::Iterator evit;
00506   
00507   // alphabet
00508   rResGen.InjectAlphabet(rAlphabet);
00509   
00510   // insert marked initial state
00511   if(rResGen.StateNamesEnabled()){
00512     state = rResGen.InsInitState("1");
00513   } else{
00514     state = rResGen.InsInitState();
00515   }
00516   rResGen.SetMarkedState(state);
00517   
00518   // create selfloop for each event
00519   for (evit = rAlphabet.Begin(); evit != rAlphabet.End(); ++evit) {
00520     rResGen.SetTransition(state, *evit, state);
00521   }
00522   
00523   // set name of result
00524   rResGen.Name("FullLanguage("+rAlphabet.Name()+")");
00525     
00526   return;
00527 }
00528 
00529 // AlphabetLanguage(rAlphabet, rResGen)
00530 void AlphabetLanguage(const EventSet& rAlphabet, vGenerator& rResGen) {
00531   FD_DF("AlphabetLanguage("<< rAlphabet.Name() 
00532   << "," << rResGen.Name() << ")");
00533   
00534   // prepare result
00535   rResGen.Clear();
00536       
00537   // set name of result
00538   rResGen.Name("AlphabetLanguage("+rAlphabet.Name()+")");
00539     
00540   // if alphabet is empty, leave generator empty
00541   if(rAlphabet.Empty()){
00542     FD_WARN("AlphabetLanguage: empty alphabet.");
00543     return;
00544   }
00545     
00546   // helpers
00547   Idx istate, mstate;
00548   EventSet::Iterator evit;
00549   
00550   // alphabet
00551   rResGen.InjectAlphabet(rAlphabet);
00552   
00553   // insert one initial state and one marked state
00554   if(rResGen.StateNamesEnabled()){
00555     istate = rResGen.InsInitState("1");
00556     mstate = rResGen.InsMarkedState("2");
00557   }
00558   else{
00559     istate = rResGen.InsInitState();
00560     mstate = rResGen.InsMarkedState();
00561   }
00562   
00563   // for each event from rAlphabet, inserted transition leading from init state to marked state
00564   for (evit = rAlphabet.Begin(); evit != rAlphabet.End(); ++evit) {
00565     rResGen.SetTransition(istate, *evit, mstate);
00566   }
00567     
00568   return;
00569 }
00570 
00571 // EmptyStringLanguage(rAlphabet, rResGen)
00572 void EmptyStringLanguage(const EventSet& rAlphabet, vGenerator& rResGen) {
00573   FD_DF("EmptyStringLanguage("<< rAlphabet.Name() 
00574   << "," << rResGen.Name() << ")");
00575   
00576   // prepare result
00577   rResGen.Clear();
00578   
00579   // helpers
00580   Idx state;
00581   
00582   // alphabet
00583   rResGen.InjectAlphabet(rAlphabet);
00584   
00585   // insert marked initial state
00586   if(rResGen.StateNamesEnabled()){
00587     state = rResGen.InsInitState("1");
00588   }
00589   else{
00590     state = rResGen.InsInitState();
00591   }
00592   rResGen.SetMarkedState(state);
00593   
00594   // set name of result
00595   rResGen.Name("EmptyStringLanguage("+rAlphabet.Name()+")");
00596     
00597   return;
00598 }
00599 
00600 // EmptyLanguage(rAlphabet, rResGen)
00601 void EmptyLanguage(const EventSet& rAlphabet, vGenerator& rResGen) {
00602   FD_DF("EmptyStringLanguage("<< rAlphabet.Name() 
00603   << "," << rResGen.Name() << ")");
00604   
00605   // prepare result
00606   rResGen.Clear();
00607   
00608   // alphabet
00609   rResGen.InjectAlphabet(rAlphabet);
00610 
00611   // set name of result
00612   rResGen.Name("EmptyLanguage("+rAlphabet.Name()+")");
00613     
00614   return;
00615 }
00616 
00617 // EmptyLanguage(rGen)
00618 bool EmptyLanguage(const vGenerator& rGen) {
00619   // case a) check if set of marked states is empty
00620   if(rGen.MarkedStatesSize()==0) return true;
00621   // case b) check if no marked state is accessible (reachable)
00622   return (rGen.AccessibleSet()*rGen.MarkedStates()).Empty();
00623 }
00624 
00625 // LanguageInclusion(rGen1, rGen2)
00626 bool LanguageInclusion(const vGenerator& rGen1, const vGenerator& rGen2) {
00627     
00628   FD_DF("LanguageInclusion("<< rGen1.Name() << "," << rGen2.Name() << ")"); 
00629     
00630   // check if there is no string in Lm1 that is not in Lm2, which means Lm1<=Lm2
00631   Generator NotrGen2=rGen2;
00632   // note: complement w.r.t. union of alphabets to ensure that elementwise 
00633   // inclusion of Lm1 in Lm2 is tested
00634   LanguageComplement(NotrGen2 , rGen1.Alphabet()+rGen2.Alphabet());
00635   return EmptyLanguageIntersection(rGen1,NotrGen2);        
00636 }
00637 
00638 // LanguageEquality(rGen1, rGen2)
00639 bool LanguageEquality(const vGenerator& rGen1, const vGenerator& rGen2) {
00640     
00641   FD_DF("LanguageEquality("<< rGen1.Name() << "," << rGen2.Name() << ")");
00642 
00643   // Check for equality by testing mutual inclusion
00644   return LanguageInclusion(rGen1,rGen2) && LanguageInclusion(rGen2,rGen1);
00645 }
00646 
00647 // KleeneClosure(rGen, rResGen)
00648 void KleeneClosure(vGenerator& rGen) {
00649    
00650   FD_DF("KleeneClosure("<< rGen.Name() << ")");
00651 
00652   // fix name 
00653   std::string name=CollapsString("KleeneClosure(" + rGen.Name() + ")");
00654 
00655   // The Kleene Closure of the empty set is the empty set
00656   if(EmptyLanguage(rGen)){
00657     rGen.Name(name);
00658     return;
00659   }
00660 
00661   // run nondet version    
00662   KleeneClosureNonDet(rGen);
00663   Deterministic(rGen, rGen);
00664 
00665   // set name
00666   rGen.Name(name);
00667 }
00668 
00669 // KleeneClosureNonDet(rGen)
00670 void KleeneClosureNonDet(vGenerator& rGen) {
00671     
00672   FD_DF("KleeneClosureNonDet("<< rGen.Name()  << ")");
00673     
00674   // set name 
00675   rGen.Name(CollapsString("KleeneClosureNonDet("+ rGen.Name() + ")"));
00676     
00677   // The Kleene Closure of the empty set is the empty set
00678   if(EmptyLanguage(rGen)) return;
00679     
00680   // helpers
00681   TransSet::Iterator tit;
00682   StateSet::Iterator init = rGen.InitStatesBegin();
00683   TransSet TransToInsert;
00684     
00685   // for all transitions leading from a state x1 to a marked state: insert a transition
00686   // with the same event that leads to (one of) the initial state(s). This step makes
00687   // rGen nondeterministic.
00688   // first, find respective transitions in rGen and update TransToInsert with new
00689   // transitions to insert
00690   for (tit = rGen.TransRelBegin(); tit != rGen.TransRelEnd(); ++tit) {
00691   
00692     if(rGen.ExistsMarkedState(tit->X2)) {
00693       if( !(rGen.ExistsTransition(tit->X1, tit->Ev, *init)) ){
00694   TransToInsert.Insert(tit->X1, tit->Ev, *init);
00695       }
00696     }
00697         
00698   }
00699   // now, extend rGen by transitions of TransToInsert
00700   for (tit = TransToInsert.Begin(); tit != TransToInsert.End(); ++tit) {
00701     rGen.SetTransition(*tit);
00702   }
00703     
00704   // KleeneClosure of nonempty language always contains the empty string:
00705   // mark at least one initial state
00706   rGen.SetMarkedState(*init);
00707 }
00708 
00709 // PrefixClosure(rGen)
00710 void PrefixClosure(vGenerator& rGen) {
00711     
00712   FD_DF("PrefixClosure("<< rGen.Name() << ")");
00713 
00714   // fix name
00715   std::string name=CollapsString("PrefixClosure("+ rGen.Name() + ")");
00716     
00717   // remove all states that do net represent prefixes of marked strings
00718   rGen.Coaccessible();
00719     
00720   // mark all remaining states
00721   rGen.InjectMarkedStates(rGen.States());
00722    
00723   // set name 
00724   rGen.Name(name);
00725     
00726 }
00727 
00728 // SelfLoop(rGen,rAlphabet)
00729 void SelfLoop(vGenerator& rGen,const EventSet& rAlphabet) {
00730     
00731   FD_DF("SelfLoop(" << rGen.Name() << "," << rAlphabet.Name() << ")");
00732 
00733   // fix name
00734   std::string name = CollapsString("SelfLoop(" + rGen.Name() + "," + rAlphabet.Name() + ")");
00735   // extend alphabet of rGen
00736   rGen.InjectAlphabet(rGen.Alphabet()+rAlphabet);
00737     
00738   //helpers
00739   EventSet::Iterator evit,evbegin,evend;
00740   evbegin = rAlphabet.Begin();
00741   evend = rAlphabet.End();  
00742   StateSet::Iterator sit;
00743     
00744   // iterate over all states and insert selfloop for each event of rAlphabet
00745   for (sit = rGen.StatesBegin(); sit != rGen.StatesEnd(); ++sit) {
00746     for(evit = evbegin; evit != evend; ++evit){
00747       rGen.SetTransition(*sit, *evit, *sit);
00748     }
00749   }
00750     
00751   // set name
00752   rGen.Name(name);
00753 }
00754 
00755 // SelfLoopMarkedStates(rGen,rAlphabet)
00756 void SelfLoopMarkedStates(vGenerator& rGen,const EventSet& rAlphabet) {
00757     
00758   FD_DF("SelfLoopMarkedStates(" << rGen.Name() << "," << rAlphabet.Name() << ")");
00759 
00760   // fix name
00761   std::string name = CollapsString("SelfLoopMarkedStates(" + rGen.Name() 
00762      + "," + rAlphabet.Name() + ")");
00763 
00764   // extend alphabet of rGen
00765   rGen.InjectAlphabet(rGen.Alphabet()+rAlphabet);
00766     
00767   //helpers
00768   EventSet::Iterator evit,evbegin,evend;
00769   evbegin = rAlphabet.Begin();
00770   evend = rAlphabet.End();  
00771   StateSet::Iterator sit;
00772     
00773   // iterate over all marked states and insert selfloop for each event of rAlphabet
00774   for (sit = rGen.MarkedStatesBegin(); sit != rGen.MarkedStatesEnd(); ++sit) {
00775     for(evit = evbegin; evit != evend; ++evit){
00776       rGen.SetTransition(*sit, *evit, *sit);
00777     }
00778   }
00779     
00780   // set name
00781   rGen.Name(name);
00782 }
00783 
00784 // SelfLoop(rGen,rAlphabet,rStates)
00785 void SelfLoop(vGenerator& rGen,const EventSet& rAlphabet,const StateSet& rStates) {
00786     
00787   FD_DF("SelfLoop(" << rGen.Name() << "," << rAlphabet.Name() << "," << rStates.Name() << ")");
00788 
00789   // fix name
00790   std::string name = CollapsString("SelfLoop(" + rGen.Name() 
00791      + "," + rAlphabet.Name() + "," + rStates.Name() + ")");
00792 
00793   // exception: rStates must be states of rGen
00794 #ifdef FAUDES_CHECKED
00795   if( !(rStates <= rGen.States()) ){
00796     std::stringstream errstr;
00797     errstr << "State set " << rStates.Name() << 
00798       " has to be included in state set of "<< rGen.Name() << ".";
00799     throw Exception("SelfLoop()", errstr.str(), 100);
00800   }
00801 #endif
00802     
00803   // extend alphabet of rGen
00804   rGen.InjectAlphabet(rGen.Alphabet()+rAlphabet);
00805     
00806   //helpers
00807   EventSet::Iterator evit,evbegin,evend;
00808   evbegin = rAlphabet.Begin();
00809   evend = rAlphabet.End();    
00810   StateSet::Iterator sit;
00811     
00812   // iterate over all marked states and insert selfloop for each event of rAlphabet
00813   for (sit = rStates.Begin(); sit != rStates.End(); ++sit) {
00814     for(evit = evbegin; evit != evend; ++evit){
00815       rGen.SetTransition(*sit, *evit, *sit);
00816     }
00817   }
00818     
00819   // set name
00820   rGen.Name(name);
00821 }
00822 
00823 } // namespace faudes
00824 
00825 #undef Move //see define above for comment
00826 #undef Product //see define above for comment

Generated on Mon Nov 10 08:13:15 2008 for libFAUDES 2.11v by  doxygen 1.4.4