About
User Reference
C++ API
luafaudes
Developer
Links
libFAUDES online
libFAUDES

Sections

Index

cfl_regular.cpp

Go to the documentation of this file.
00001 /** @file cfl_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 "cfl_regular.h"
00034 
00035 
00036 namespace faudes {
00037 
00038 // LanguageUnionNonDet(rGen1, rGen2, rResGen)
00039 void LanguageUnionNonDet(const Generator& rGen1, const Generator& rGen2,
00040        Generator& 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   Generator* 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 Generator& rGen1, const Generator& rGen2, 
00122        Generator& 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   Generator* 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 // LanguageUnion(rGenVec, rResGen)
00149 void LanguageUnion(const GeneratorVector& rGenVec, Generator& rResGen) {
00150 
00151   // ignore empty
00152   if(rGenVec.Size()==0) {
00153     return;
00154   }
00155 
00156   // avoid copy
00157   Generator* pTempGen = rResGen.New();
00158 
00159   // copy first
00160   *pTempGen=rGenVec.At(0);
00161 
00162   // run union on others
00163   for(GeneratorVector::Position i=1; i<rGenVec.Size(); i++) 
00164     LanguageUnionNonDet(rGenVec.At(i),*pTempGen,*pTempGen);
00165 
00166   // make deterministic
00167   Deterministic(*pTempGen, rResGen);
00168 
00169   // dispose temp
00170   delete pTempGen;
00171 
00172   // set name of result
00173   rResGen.Name(CollapsString("Union(...)"));
00174 }
00175 
00176 
00177 // LanguageIntersection(rGen1, rGen2, rResGen)
00178 void LanguageIntersection(const Generator& rGen1, const Generator& rGen2, 
00179         Generator& rResGen) {
00180   FD_DF("LanguageIntersection("<< rGen1.Name() 
00181   << "," << rGen2.Name() << ")");
00182     
00183   // fix name
00184   std::string name1 = rGen1.Name();
00185   std::string name2 = rGen2.Name();
00186 
00187   // the product of rGen1 and rGen2 implements the language intersection
00188   Product(rGen1, rGen2, rResGen);
00189   rResGen.Name(CollapsString("Intersection("+name1+","+name2+")"));
00190     
00191 }
00192 
00193 
00194 // LanguageIntersection(rGenVec, rResGen)
00195 void LanguageIntersection(const GeneratorVector& rGenVec, Generator& rResGen) 
00196 {
00197 
00198   // ignore empty
00199   if(rGenVec.Size()==0) {
00200     return;
00201   }
00202 
00203   // copy first
00204   rResGen=rGenVec.At(0);
00205 
00206   // run product on others
00207   for(GeneratorVector::Position i=1; i<rGenVec.Size(); i++) 
00208     LanguageIntersection(rGenVec.At(i),rResGen,rResGen);
00209 }
00210 
00211 
00212 // EmptyLanguageIntersection(rGen1, rGen2)
00213 bool EmptyLanguageIntersection(const Generator& rGen1, const Generator& rGen2) {
00214   FD_DF("EmptyLanguageIntersection("<< rGen1.Name() 
00215   << "," << rGen2.Name() << ")");
00216     
00217   // The product of rGen1 and rGen2 implements the language intersection
00218   // Note: rather use a function that does not explicitely compute the product 
00219   // but that returns false as soon as a common transtion is found.
00220 
00221   Generator ProductGen;
00222   ProductGen.StateNamesEnabled(false);
00223   Product(rGen1, rGen2, ProductGen);
00224   return IsEmptyLanguage(ProductGen);
00225 }
00226 
00227 // LanguageDisjoint(rGen1, rGen2)
00228 bool LanguageDisjoint(const Generator& rGen1, const Generator& rGen2) {
00229   FD_DF("LanguageDisjoint("<< rGen1.Name() 
00230   << "," << rGen2.Name() << ")");
00231   return EmptyLanguageIntersection(rGen1,rGen2);
00232 }
00233 
00234 // Automaton(rGen)
00235 void Automaton(Generator& rGen, const EventSet& rAlphabet) {
00236   FD_DF("Automaton("<< rGen.Name() << "," << rAlphabet.Name() << ")");
00237     
00238   // extend rGen.Alphabet() by rAlphabet
00239   rGen.InjectAlphabet(rGen.Alphabet()+rAlphabet);
00240     
00241   // remove states that do not represent prefixes of marked strings
00242   rGen.Coaccessible();
00243     
00244   // the automaton for the empty language Lm={} contains only the dump state,
00245   // which, in this case, represents Sigma*
00246   if(IsEmptyLanguage(rGen)){
00247         
00248     // remember generator name
00249     std::string name; 
00250     name=rGen.Name();
00251         
00252     FullLanguage(rGen.Alphabet(),rGen);
00253     if (rGen.StateNamesEnabled()) {
00254       rGen.StateName(*(rGen.InitStatesBegin()),"dump");
00255     }
00256     // the dump state is not marked
00257     rGen.ClearMarkedStates();
00258         
00259     // set generator name
00260     rGen.Name(CollapsString("Automaton(" + name + "," + rAlphabet.Name() + ")"));
00261     return;
00262   }
00263     
00264   // for correct result, rGen has to be deterministic!
00265 #ifdef FAUDES_CHECKED
00266   if ( !(rGen.IsDeterministic()) ) {
00267     FD_WARN("Automaton(): nondeterministic parameter " << rGen.Name() <<".");
00268   }
00269 #endif 
00270     
00271   // prepare result
00272   rGen.Name(CollapsString("Automaton(" + rGen.Name() + "," + rAlphabet.Name() + ")"));
00273     
00274   // introduce dump state
00275   Idx dump;
00276   if (rGen.StateNamesEnabled()) {
00277     std::string dumpstr=rGen.UniqueStateName("dump");
00278     dump = rGen.InsState(dumpstr);
00279   } else {
00280     dump = rGen.InsState();
00281   }
00282   
00283   // introduce transitions to dumpstate
00284   StateSet::Iterator sit;
00285   EventSet::Iterator eit;
00286   bool dumpNotReached=true; // indicate that dumpstate is not reached
00287   for (sit = rGen.StatesBegin(); sit != rGen.StatesEnd(); ++sit) {        
00288     for (eit = rGen.Alphabet().Begin(); eit != rGen.Alphabet().End(); ++eit) {
00289       // If no transition is defined for this state and event, insert respective
00290       // transition to dump state (note that dump state itself is also treated here
00291       // and thus provided with selfloops)
00292       if (rGen.TransRelBegin(*sit, *eit) == rGen.TransRelEnd(*sit, *eit)) {
00293   rGen.SetTransition(*sit, *eit, dump);
00294   // indicate that dumstate was reached
00295   if(*sit!=dump) dumpNotReached=false;
00296       }
00297     }        
00298   }
00299     
00300   // if no transition was introduced (except for selfloops), remove dump state
00301   if(dumpNotReached) 
00302     rGen.DelState(dump);
00303 }
00304 
00305 // Automaton(rGen)
00306 void Automaton(Generator& rGen) {
00307   FD_DF("Automaton("<< rGen.Name() << ")");
00308   std::string name=rGen.Name();
00309   Automaton(rGen,rGen.Alphabet());    
00310   rGen.Name(CollapsString("Automaton(" + name + ")"));
00311 }
00312 
00313 // LanguageComplement(rGen,rAlphabet)
00314 void LanguageComplement(Generator& rGen, const EventSet& rAlphabet) {
00315   FD_DF("LanguageComplement("<< rGen.Name() << "," << rAlphabet.Name() << ")");
00316 
00317   // fix name
00318   std::string name = rGen.Name();  
00319   
00320   // convert to automaton (avoiding statename "dump")
00321   bool stateNamesEnabled=rGen.StateNamesEnabled(); 
00322   rGen.StateNamesEnabled(false); 
00323   Automaton(rGen,rAlphabet);
00324   rGen.StateNamesEnabled(stateNamesEnabled); 
00325     
00326   // invert marking
00327   rGen.InjectMarkedStates(rGen.States() - rGen.MarkedStates());
00328 
00329   // set name    
00330   rGen.Name(CollapsString("Complement(" + name + "," + rAlphabet.Name() + ")"));
00331 }
00332 
00333 // LanguageComplement(rGen)
00334 void LanguageComplement(Generator& rGen) {
00335   FD_DF("LanguageComplement("<< rGen.Name() << ")");
00336   std::string name=rGen.Name();
00337   LanguageComplement(rGen,rGen.Alphabet());
00338   rGen.Name(CollapsString("Complement(" + name + ")"));
00339   return;    
00340 }
00341 
00342 // language complement, uniform api
00343 void LanguageComplement(const Generator& rGen, Generator& rRes) {
00344   rRes=rGen;
00345   LanguageComplement(rRes);
00346 }
00347 
00348 
00349 // language complement, uniform api
00350 void LanguageComplement(const Generator& rGen, const EventSet& rSigma, Generator& rRes) {
00351   rRes=rGen;
00352   LanguageComplement(rRes,rSigma);
00353 }
00354 
00355 
00356 
00357 
00358 //LanguageDifference(rGen1, rGen2, rResGen)
00359 void LanguageDifference(
00360    const Generator& rGen1, 
00361    const Generator& rGen2,
00362    Generator& rResGen) {
00363          
00364      FD_DF("LanguageDifference("<< rGen1.Name() << "," << rGen2.Name() << ")");
00365 
00366     // incl. all-empty case
00367     if(IsEmptyLanguage(rGen2)) {
00368       rResGen.Assign(rGen1);
00369       rResGen.Name(CollapsString("LanguageDifference(" + rGen1.Name() + "," + rGen2.Name() + ")"));
00370       return;
00371     }
00372      
00373     // use pointer pResGen to result rResGen
00374     Generator* pResGen = &rResGen;
00375     if(&rResGen == &rGen1 || &rResGen== &rGen2) {
00376       pResGen = rResGen.New();
00377     }    
00378     
00379     // due to the use of LanguageComplement(), rGen2 has to be deterministic
00380     #ifdef FAUDES_CHECKED
00381     if(!(rGen2.IsDeterministic())){
00382       std::stringstream errstr;
00383       errstr << "Nondeterministic parameter " << rGen2.Name() << ".";
00384       throw Exception("LanguageDifference()", errstr.str(), 101);
00385     }
00386     #endif
00387           
00388     // prepare result
00389     pResGen->Clear();
00390      
00391     // calculate "Lm1-Lm2" by building the intersection of Lm1 with the complement of Lm2
00392     // for correct result, complement has to be computed wrt the alphabet of Lm1 (!)
00393         
00394     *pResGen=rGen2;
00395     LanguageComplement(*pResGen,rGen1.Alphabet());
00396     LanguageIntersection(rGen1, *pResGen, *pResGen);
00397         
00398   
00399     // if necessary, move pResGen to rResGen
00400     if(pResGen != &rResGen) {
00401       pResGen->Move(rResGen);
00402       delete pResGen;
00403     } 
00404     
00405     return;
00406 }
00407 
00408 // LanguageConcatenateNonDet(rGen1, rGen2, rResGen)
00409 void LanguageConcatenateNonDet(const Generator& rGen1, const Generator& rGen2, 
00410              Generator& rResGen) {
00411   FD_DF("LanguageConcatenateNonDet(" << rGen1.Name() << "," << rGen2.Name() << ")");
00412             
00413   // are state names enabled in result?
00414   bool stateNamesEnabled=rResGen.StateNamesEnabled();
00415     
00416   // use pointer pResGen to result rResGen
00417   Generator* pResGen = &rResGen;
00418   if(&rResGen== &rGen1 || &rResGen== &rGen2) {
00419     pResGen= rResGen.New();
00420   }
00421 
00422   // prepare result
00423   pResGen->Clear();
00424     
00425   // union of alphabets
00426   pResGen->InjectAlphabet(rGen1.Alphabet() + rGen2.Alphabet());
00427 
00428   // Maps from states of rGen1 and rGen2 to states of ResGen
00429   std::map<Idx,Idx> Gen1StatesMap;
00430   std::map<Idx,Idx> Gen2StatesMap;
00431 
00432   // helpers
00433   StateSet::Iterator sit;
00434   TransSet::Iterator tit;
00435     
00436   // "union" of states: insert states representing the states of rGen1 and rGen2
00437   for (sit = rGen1.StatesBegin(); sit != rGen1.StatesEnd(); ++sit) {
00438     if (stateNamesEnabled) {
00439       Gen1StatesMap[*sit] = pResGen->InsState(pResGen->UniqueStateName(rGen1.StateName(*sit)+"(1)"));
00440     } else {
00441       Gen1StatesMap[*sit] = pResGen->InsState();
00442     }
00443   }
00444   for (sit = rGen2.StatesBegin(); sit != rGen2.StatesEnd(); ++sit) {
00445     if (stateNamesEnabled) {
00446       Gen2StatesMap[*sit] = pResGen->InsState(pResGen->UniqueStateName(rGen2.StateName(*sit)+"(2)"));
00447     } else {
00448       Gen2StatesMap[*sit] = pResGen->InsState();
00449     }
00450   }
00451 
00452   // "union" transitions: insert all rGen1 transitions
00453   for (tit = rGen1.TransRelBegin(); tit != rGen1.TransRelEnd(); ++tit) 
00454     pResGen->SetTransition(Gen1StatesMap[tit->X1], tit->Ev, Gen1StatesMap[tit->X2]);
00455     
00456   // "union" transitions: insert all rGen2 transitions
00457   for (tit = rGen2.TransRelBegin(); tit != rGen2.TransRelEnd(); ++tit) 
00458     pResGen->SetTransition(Gen2StatesMap[tit->X1], tit->Ev, Gen2StatesMap[tit->X2]);
00459     
00460 
00461   // initial state bug (detected by Tomas Masopust, fix by Klaus Schmidt)
00462   // 1) copy all transitions to the result, clear initial/marked status
00463   // 2) all initial states of G1 become initial states in the result
00464   // 3) if L1 contains the empty string, also all initial states of G2 become initial states
00465   //    in the result
00466   // 4) transition leading to a marked state in G1 also become transitions to all
00467   //    initial states of G2
00468   // 5) marked states of G2 become marked in the result
00469 
00470 
00471   // test whether L1 includes the empty string
00472   bool concatenateEpsilon1=false;
00473   for(sit = rGen1.InitStatesBegin(); sit != rGen1.InitStatesEnd(); ++sit) {
00474     if(rGen1.ExistsMarkedState(*sit)) {
00475       concatenateEpsilon1=true;
00476       break;
00477     }
00478   }
00479 
00480   // initial states of G1 become initial states in the result
00481   for (sit = rGen1.InitStatesBegin(); sit != rGen1.InitStatesEnd(); ++sit) 
00482     pResGen->SetInitState(Gen1StatesMap[*sit]);
00483     
00484   // if L1 contains the emtystring, G2 initial states become initial states in the result
00485   if(concatenateEpsilon1)
00486     for (sit = rGen2.InitStatesBegin(); sit != rGen2.InitStatesEnd(); ++sit) 
00487       pResGen->SetInitState(Gen2StatesMap[*sit]);
00488     
00489   // any G1 transition to a marked state must also lead to all initial states of G2
00490   for(tit = rGen1.TransRelBegin(); tit != rGen1.TransRelEnd(); ++tit) 
00491     if(rGen1.ExistsMarkedState(tit->X2)) 
00492       for(sit = rGen2.InitStatesBegin(); sit != rGen2.InitStatesEnd(); ++sit) 
00493         pResGen->SetTransition(Gen1StatesMap[tit->X1], tit->Ev, Gen2StatesMap[*sit]);
00494 
00495   // set pResGen marked states corresponding to rGen2 marked states using Gen2StatesMap
00496   for(sit = rGen2.MarkedStatesBegin(); sit != rGen2.MarkedStatesEnd(); ++sit) {
00497     pResGen->SetMarkedState(Gen2StatesMap[*sit]);
00498   }
00499 
00500   // remove blocking states as they provide no useful meaning.
00501   pResGen->Trim();
00502   pResGen->Name("ConcatenateNonDet("+rGen1.Name()+","+rGen2.Name()+")");
00503     
00504   // if necessary, move pResGen to rResGen
00505   if(pResGen != &rResGen) {
00506     pResGen->Move(rResGen);
00507     delete pResGen;
00508   }
00509     
00510 }
00511 
00512 // LanguageConcatenate(rGen1, rGen2, rResGen)
00513 void LanguageConcatenate(const Generator& rGen1, const Generator& rGen2, 
00514        Generator& rResGen) {
00515 
00516   FD_DF("LanguageConcatenate("<< rGen1.Name() 
00517   << "," << rGen2.Name() << ")");
00518     
00519   // perform nondeterministic language concatenation
00520   LanguageConcatenateNonDet(rGen1, rGen2, rResGen);
00521     
00522   // make deterministic if necessary
00523   if(!(rResGen.IsDeterministic())){
00524     Deterministic(rResGen, rResGen);
00525   }
00526 
00527   // set name of result
00528   rResGen.Name("Concatenate("+rGen1.Name()+","+rGen2.Name()+")");
00529     
00530   return;    
00531 }
00532 
00533 // FullLanguage(rAlphabet, rResGen)
00534 void FullLanguage(const EventSet& rAlphabet, Generator& rResGen) {
00535   FD_DF("FullLanguage("<< rAlphabet.Name() 
00536   << "," << rResGen.Name() << ")");
00537   
00538   // prepare result
00539   rResGen.Clear();
00540   
00541   // helpers
00542   Idx state;
00543   EventSet::Iterator evit;
00544   
00545   // alphabet
00546   rResGen.InjectAlphabet(rAlphabet);
00547   
00548   // insert marked initial state
00549   if(rResGen.StateNamesEnabled()){
00550     state = rResGen.InsInitState("1");
00551   } else{
00552     state = rResGen.InsInitState();
00553   }
00554   rResGen.SetMarkedState(state);
00555   
00556   // create selfloop for each event
00557   for (evit = rAlphabet.Begin(); evit != rAlphabet.End(); ++evit) {
00558     rResGen.SetTransition(state, *evit, state);
00559   }
00560   
00561   // set name of result
00562   rResGen.Name("FullLanguage("+rAlphabet.Name()+")");
00563     
00564   return;
00565 }
00566 
00567 // AlphabetLanguage(rAlphabet, rResGen)
00568 void AlphabetLanguage(const EventSet& rAlphabet, Generator& rResGen) {
00569   FD_DF("AlphabetLanguage("<< rAlphabet.Name() 
00570   << "," << rResGen.Name() << ")");
00571   
00572   // prepare result
00573   rResGen.Clear();
00574       
00575   // set name of result
00576   rResGen.Name("AlphabetLanguage("+rAlphabet.Name()+")");
00577     
00578   // if alphabet is empty, leave generator empty
00579   if(rAlphabet.Empty()){
00580     FD_WARN("AlphabetLanguage: empty alphabet.");
00581     return;
00582   }
00583     
00584   // helpers
00585   Idx istate, mstate;
00586   EventSet::Iterator evit;
00587   
00588   // alphabet
00589   rResGen.InjectAlphabet(rAlphabet);
00590   
00591   // insert one initial state and one marked state
00592   if(rResGen.StateNamesEnabled()){
00593     istate = rResGen.InsInitState("1");
00594     mstate = rResGen.InsMarkedState("2");
00595   }
00596   else{
00597     istate = rResGen.InsInitState();
00598     mstate = rResGen.InsMarkedState();
00599   }
00600   
00601   // for each event from rAlphabet, inserted transition leading from init state to marked state
00602   for (evit = rAlphabet.Begin(); evit != rAlphabet.End(); ++evit) {
00603     rResGen.SetTransition(istate, *evit, mstate);
00604   }
00605     
00606   return;
00607 }
00608 
00609 // EmptyStringLanguage(rAlphabet, rResGen)
00610 void EmptyStringLanguage(const EventSet& rAlphabet, Generator& rResGen) {
00611   FD_DF("EmptyStringLanguage("<< rAlphabet.Name() 
00612   << "," << rResGen.Name() << ")");
00613   
00614   // prepare result
00615   rResGen.Clear();
00616   
00617   // helpers
00618   Idx state;
00619   
00620   // alphabet
00621   rResGen.InjectAlphabet(rAlphabet);
00622   
00623   // insert marked initial state
00624   if(rResGen.StateNamesEnabled()){
00625     state = rResGen.InsInitState("1");
00626   }
00627   else{
00628     state = rResGen.InsInitState();
00629   }
00630   rResGen.SetMarkedState(state);
00631   
00632   // set name of result
00633   rResGen.Name("EmptyStringLanguage("+rAlphabet.Name()+")");
00634     
00635   return;
00636 }
00637 
00638 // EmptyLanguage(rAlphabet, rResGen)
00639 void EmptyLanguage(const EventSet& rAlphabet, Generator& rResGen) {
00640   FD_DF("EmptyStringLanguage("<< rAlphabet.Name() 
00641   << "," << rResGen.Name() << ")");
00642   
00643   // prepare result
00644   rResGen.Clear();
00645   
00646   // set alphabet
00647   rResGen.InjectAlphabet(rAlphabet);
00648 
00649   // set name of result
00650   rResGen.Name("EmptyLanguage("+rAlphabet.Name()+")");
00651     
00652   return;
00653 }
00654 
00655 // EmptyLanguage(rGen)
00656 bool IsEmptyLanguage(const Generator& rGen) {
00657   // case a) check if set of marked or initial states is empty
00658   if(rGen.MarkedStatesSize()==0) return true;
00659   if(rGen.InitStatesSize()==0) return true;
00660   // case b) check if no marked state is accessible (reachable)
00661   return (rGen.AccessibleSet()*rGen.MarkedStates()).Empty();
00662 }
00663 
00664 // LanguageInclusion(rGen1, rGen2)
00665 bool LanguageInclusion(const Generator& rGen1, const Generator& rGen2) {
00666     
00667   FD_DF("LanguageInclusion("<< rGen1.Name() << "," << rGen2.Name() << ")"); 
00668     
00669   // check if there is no string in Lm1 that is not in Lm2, which means Lm1<=Lm2
00670   Generator NotrGen2=rGen2;
00671   NotrGen2.StateNamesEnabled(false);
00672   // note: complement w.r.t. union of alphabets to ensure that elementwise 
00673   // inclusion of Lm1 in Lm2 is tested
00674   LanguageComplement(NotrGen2 , rGen1.Alphabet()+rGen2.Alphabet());
00675   return EmptyLanguageIntersection(rGen1,NotrGen2);        
00676 }
00677 
00678 // LanguageEquality(rGen1, rGen2)
00679 bool LanguageEquality(const Generator& rGen1, const Generator& rGen2) {
00680     
00681   FD_DF("LanguageEquality("<< rGen1.Name() << "," << rGen2.Name() << ")");
00682 
00683   // Check for equality by testing mutual inclusion
00684   return LanguageInclusion(rGen1,rGen2) && LanguageInclusion(rGen2,rGen1);
00685 }
00686 
00687 // KleeneClosure(rGen)
00688 void KleeneClosure(Generator& rGen) {
00689    
00690   FD_DF("KleeneClosure("<< rGen.Name() << ")");
00691 
00692   // fix name 
00693   std::string name=CollapsString("KleeneClosure(" + rGen.Name() + ")");
00694 
00695   // The Kleene Closure of the empty set is the empty set
00696   if(IsEmptyLanguage(rGen)){
00697     rGen.Clear();
00698     rGen.Name(name);
00699     return;
00700   }
00701 
00702   // run nondet version    
00703   KleeneClosureNonDet(rGen);
00704   Deterministic(rGen, rGen);
00705 
00706   // set name
00707   rGen.Name(name);
00708 }
00709 
00710 // KleeneClosure(rGen, rResGen)
00711 void KleeneClosure(const Generator& rGen, Generator& rResGen) {
00712    
00713   FD_DF("KleeneClosure("<< rGen.Name() << ", ... )");
00714 
00715   // if arg and result match, call respective version
00716   if(&rGen==&rResGen) {
00717     KleeneClosure(rResGen);
00718     return;
00719   }
00720 
00721   // fix name 
00722   std::string name=CollapsString("KleeneClosure(" + rGen.Name() + ")");
00723 
00724   // The Kleene Closure of the empty set is the empty set
00725   if(IsEmptyLanguage(rGen)){
00726     rResGen.Clear();
00727     rResGen.Name(name);
00728     return;
00729   }
00730 
00731   // run nondet version with intermediate result
00732   Generator* pgen=rGen.Copy();   
00733   KleeneClosureNonDet(*pgen);
00734   Deterministic(*pgen, rResGen);
00735   delete pgen;
00736 
00737   // set name
00738   rResGen.Name(name);
00739 }
00740 
00741 // KleeneClosureNonDet(rGen)
00742 void KleeneClosureNonDet(Generator& rGen) {
00743     
00744   FD_DF("KleeneClosureNonDet("<< rGen.Name()  << ")");
00745     
00746   // set name 
00747   rGen.Name(CollapsString("KleeneClosureNonDet("+ rGen.Name() + ")"));
00748     
00749   // The Kleene Closure of the empty set is the empty set
00750   if(IsEmptyLanguage(rGen)) {
00751     rGen.Clear();
00752     return;
00753   }
00754     
00755   // helpers
00756   TransSet::Iterator tit;
00757   TransSet TransToInsert;
00758 
00759   // initial state bug (detected by Tomas Masopust, fix proposed by Klaus Schmidt)
00760   // 1. prepare the generator to have a unique initial state
00761   // 2. if the initial state fails to be marked, introduce a fake marked initial state.
00762   // 3. equip the fake markded initial state with the same transitions as the original initial state
00763   UniqueInit(rGen);
00764   Idx istate = *rGen.InitStatesBegin();
00765   Idx imstate = istate;
00766   if(!rGen.ExistsMarkedState(imstate)) {
00767     imstate=rGen.InsInitState();
00768     rGen.SetMarkedState(imstate);
00769     for(tit = rGen.TransRelBegin(istate); tit != rGen.TransRelEnd(istate); ++tit) { 
00770       TransToInsert.Insert(imstate, tit->Ev, tit->X2);
00771     }
00772   }
00773       
00774   // for all transitions leading from a state x1 to a marked state: insert a transition
00775   // with the same event that leads to the initial state(s). 
00776   for(tit = rGen.TransRelBegin(); tit != rGen.TransRelEnd(); ++tit) { 
00777     if(rGen.ExistsMarkedState(tit->X2)) {
00778       if(!(rGen.ExistsTransition(tit->X1, tit->Ev, imstate)) ){
00779   TransToInsert.Insert(tit->X1, tit->Ev, imstate);
00780       }
00781     }        
00782   }
00783   for (tit = TransToInsert.Begin(); tit != TransToInsert.End(); ++tit) {
00784     rGen.SetTransition(*tit);
00785   }
00786     
00787 }
00788 
00789 // PrefixClosure(rGen)
00790 void PrefixClosure(Generator& rGen) {
00791     
00792   FD_DF("PrefixClosure("<< rGen.Name() << ")");
00793 
00794   // fix name
00795   std::string name=CollapsString("PrefixClosure("+ rGen.Name() + ")");
00796     
00797   // remove all states that do net represent prefixes of marked strings
00798   rGen.Coaccessible();
00799     
00800   // mark all remaining states
00801   rGen.InjectMarkedStates(rGen.States());
00802    
00803   // set name 
00804   rGen.Name(name);
00805     
00806 }
00807 
00808 // IsPrefixClosed
00809 bool IsPrefixClosed(const Generator& rGen) {
00810   
00811   // figure relevant states
00812   StateSet relevant = rGen.AccessibleSet() * rGen.CoaccessibleSet();
00813 
00814   // test
00815   return relevant <= rGen.MarkedStates();
00816 
00817 }
00818 
00819 // IsNonblocking
00820 bool IsNonblocking(const Generator& rGen) {
00821   
00822   // test
00823   return rGen.AccessibleSet() <= rGen.CoaccessibleSet();
00824 
00825 }
00826 
00827 // IsNonblocking 
00828 bool IsNonblocking(const Generator& rGen1, const Generator& rGen2) {
00829   
00830   // build composition
00831   Generator parallel;
00832   parallel.StateNamesEnabled(false);
00833   Parallel(rGen1,rGen2,parallel);
00834 
00835   // test (parallel returns an accessible generator).
00836   return parallel.States() <= parallel.CoaccessibleSet();
00837 
00838 }
00839 
00840 
00841 
00842 // SelfLoop(rGen,rAlphabet)
00843 void SelfLoop(Generator& rGen,const EventSet& rAlphabet) {
00844     
00845   FD_DF("SelfLoop(" << rGen.Name() << "," << rAlphabet.Name() << ")");
00846 
00847   // fix name
00848   std::string name = CollapsString("SelfLoop(" + rGen.Name() + "," + rAlphabet.Name() + ")");
00849   // extend alphabet of rGen
00850   rGen.InjectAlphabet(rGen.Alphabet()+rAlphabet);
00851     
00852   //helpers
00853   EventSet::Iterator evit,evbegin,evend;
00854   evbegin = rAlphabet.Begin();
00855   evend = rAlphabet.End();  
00856   StateSet::Iterator sit;
00857     
00858   // iterate over all states and insert selfloop for each event of rAlphabet
00859   for (sit = rGen.StatesBegin(); sit != rGen.StatesEnd(); ++sit) {
00860     for(evit = evbegin; evit != evend; ++evit){
00861       rGen.SetTransition(*sit, *evit, *sit);
00862     }
00863   }
00864     
00865   // set name
00866   rGen.Name(name);
00867 }
00868 
00869 // SelfLoopMarkedStates(rGen,rAlphabet)
00870 void SelfLoopMarkedStates(Generator& rGen,const EventSet& rAlphabet) {
00871     
00872   FD_DF("SelfLoopMarkedStates(" << rGen.Name() << "," << rAlphabet.Name() << ")");
00873 
00874   // fix name
00875   std::string name = CollapsString("SelfLoopMarkedStates(" + rGen.Name() 
00876      + "," + rAlphabet.Name() + ")");
00877 
00878   // extend alphabet of rGen
00879   rGen.InjectAlphabet(rGen.Alphabet()+rAlphabet);
00880     
00881   //helpers
00882   EventSet::Iterator evit,evbegin,evend;
00883   evbegin = rAlphabet.Begin();
00884   evend = rAlphabet.End();  
00885   StateSet::Iterator sit;
00886     
00887   // iterate over all marked states and insert selfloop for each event of rAlphabet
00888   for (sit = rGen.MarkedStatesBegin(); sit != rGen.MarkedStatesEnd(); ++sit) {
00889     for(evit = evbegin; evit != evend; ++evit){
00890       rGen.SetTransition(*sit, *evit, *sit);
00891     }
00892   }
00893     
00894   // set name
00895   rGen.Name(name);
00896 }
00897 
00898 // SelfLoop(rGen,rAlphabet,rStates)
00899 void SelfLoop(Generator& rGen,const EventSet& rAlphabet,const StateSet& rStates) {
00900     
00901   FD_DF("SelfLoop(" << rGen.Name() << "," << rAlphabet.Name() << "," << rStates.Name() << ")");
00902 
00903   // fix name
00904   std::string name = CollapsString("SelfLoop(" + rGen.Name() 
00905      + "," + rAlphabet.Name() + "," + rStates.Name() + ")");
00906 
00907   // exception: rStates must be states of rGen
00908 #ifdef FAUDES_CHECKED
00909   if( !(rStates <= rGen.States()) ){
00910     std::stringstream errstr;
00911     errstr << "State set " << rStates.Name() << 
00912       " has to be included in state set of "<< rGen.Name() << ".";
00913     throw Exception("SelfLoop()", errstr.str(), 100);
00914   }
00915 #endif
00916     
00917   // extend alphabet of rGen
00918   rGen.InjectAlphabet(rGen.Alphabet()+rAlphabet);
00919     
00920   //helpers
00921   EventSet::Iterator evit,evbegin,evend;
00922   evbegin = rAlphabet.Begin();
00923   evend = rAlphabet.End();    
00924   StateSet::Iterator sit;
00925     
00926   // iterate over all marked states and insert selfloop for each event of rAlphabet
00927   for (sit = rStates.Begin(); sit != rStates.End(); ++sit) {
00928     for(evit = evbegin; evit != evend; ++evit){
00929       rGen.SetTransition(*sit, *evit, *sit);
00930     }
00931   }
00932     
00933   // set name
00934   rGen.Name(name);
00935 }
00936 
00937 
00938 } // namespace faudes
00939 
00940 #undef Product //see define above for comment

libFAUDES 2.20s --- 2011.10.12 --- c++ source docu by doxygen