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

libFAUDES 2.22k --- 2013.04.02 --- c++ source docu by doxygen