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

libFAUDES 2.20d --- 2011.04.26 --- c++ source docu by doxygen