libFAUDES

Sections

Index

regular.cpp

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

libFAUDES 2.14g --- 2009-12-3 --- c++ source docu by doxygen 1.5.6