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 vGenerator& rGen1, const vGenerator& rGen2,
00040        vGenerator& rResGen) {
00041             
00042   FD_DF("LanguageUnionNonDet("<< rGen1.Name() 
00043   << "," << rGen2.Name() << ")");
00044     
00045   // are state names enabled?
00046   bool stateNamesEnabled=rResGen.StateNamesEnabled();
00047     
00048   // use pointer pResGen to result rResGen; if rResGen is identical to
00049   // one of the parameters, allocate temporary object and copy back later
00050   vGenerator* pResGen = &rResGen;
00051   if(&rResGen== &rGen1 || &rResGen== &rGen2) {
00052     pResGen= rResGen.New();
00053   }
00054 
00055   // prepare result
00056   pResGen->Clear();
00057 
00058   // union of alphabets
00059   pResGen->InjectAlphabet(rGen1.Alphabet()+rGen2.Alphabet());
00060     
00061   // Maps from states of rGen1 and rGen2 to states of ResGen
00062   std::map<Idx,Idx> Gen1StatesMap;
00063   std::map<Idx,Idx> Gen2StatesMap;
00064     
00065   // "union" of states: insert states representing the states of rGen1 and rGen2
00066   StateSet::Iterator sit;
00067   for (sit = rGen1.StatesBegin(); sit != rGen1.StatesEnd(); ++sit) {
00068     if (stateNamesEnabled) {
00069       Gen1StatesMap[*sit] = pResGen->InsState(pResGen->UniqueStateName(rGen1.StateName(*sit)+"(1)"));
00070     }
00071     else {
00072       Gen1StatesMap[*sit] = pResGen->InsState();
00073     }
00074   }
00075   for (sit = rGen2.StatesBegin(); sit != rGen2.StatesEnd(); ++sit) {
00076     if (stateNamesEnabled) {
00077       Gen2StatesMap[*sit] = pResGen->InsState(pResGen->UniqueStateName(rGen2.StateName(*sit)+"(2)"));
00078     }
00079     else {
00080       Gen2StatesMap[*sit] = pResGen->InsState();
00081     }
00082   }
00083     
00084   // "union" of transition relations
00085   TransSet::Iterator tit;
00086   for (tit = rGen1.TransRelBegin(); tit != rGen1.TransRelEnd(); ++tit) {
00087     pResGen->SetTransition(Gen1StatesMap[tit->X1], tit->Ev, Gen1StatesMap[tit->X2]);
00088   }
00089   for (tit = rGen2.TransRelBegin(); tit != rGen2.TransRelEnd(); ++tit) {
00090     pResGen->SetTransition(Gen2StatesMap[tit->X1], tit->Ev, Gen2StatesMap[tit->X2]);
00091   }
00092     
00093   // "union" of init states
00094   for (sit = rGen1.InitStatesBegin(); sit != rGen1.InitStatesEnd(); ++sit) {
00095     pResGen->SetInitState(Gen1StatesMap[*sit]);
00096   }
00097   for (sit = rGen2.InitStatesBegin(); sit != rGen2.InitStatesEnd(); ++sit) {
00098     pResGen->SetInitState(Gen2StatesMap[*sit]);
00099   }
00100     
00101   // "union" of marked states
00102   for (sit = rGen1.MarkedStatesBegin(); sit != rGen1.MarkedStatesEnd(); ++sit) {
00103     pResGen->SetMarkedState(Gen1StatesMap[*sit]);
00104   }
00105   for (sit = rGen2.MarkedStatesBegin(); sit != rGen2.MarkedStatesEnd(); ++sit) {
00106     pResGen->SetMarkedState(Gen2StatesMap[*sit]);
00107   }
00108     
00109   // set name of result
00110   pResGen->Name(CollapsString("UnionNonDet("+rGen1.Name()+","+rGen2.Name()+")"));
00111     
00112   // if necessary, move pResGen to rResGen
00113   if(pResGen != &rResGen) {
00114     pResGen->Move(rResGen);
00115     delete pResGen;
00116   }
00117     
00118 }
00119 
00120 // LanguageUnion(rGen1, rGen2, rResGen)
00121 void LanguageUnion(const vGenerator& rGen1, const vGenerator& rGen2, 
00122        vGenerator& rResGen) {
00123 
00124   FD_DF("LanguageUnion("<< rGen1.Name() 
00125   << "," << rGen2.Name() << ")");
00126    
00127   // fix name
00128   std::string name1 = rGen1.Name();
00129   std::string name2 = rGen2.Name();
00130 
00131   // avoid copy
00132   vGenerator* pTempGen = rResGen.New();
00133     
00134   // perform nondeterministic language union
00135   LanguageUnionNonDet(rGen1, rGen2, *pTempGen);
00136     
00137   // make deterministic
00138   Deterministic(*pTempGen, rResGen);
00139 
00140   // dispose temp
00141   delete pTempGen;
00142 
00143   // set name of result
00144   rResGen.Name(CollapsString("Union("+name1+","+name2+")"));
00145 
00146 }
00147 
00148 // LanguageUnion(rGenVec, rResGen)
00149 void LanguageUnion(const GeneratorVector& rGenVec, vGenerator& rResGen) {
00150 
00151   // ignore empty
00152   if(rGenVec.Size()==0) {
00153     return;
00154   }
00155 
00156   // avoid copy
00157   vGenerator* 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 vGenerator& rGen1, const vGenerator& rGen2, 
00179         vGenerator& 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, vGenerator& 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 vGenerator& rGen1, const vGenerator& 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 vGenerator& rGen1, const vGenerator& rGen2) {
00228   FD_DF("LanguageDisjoint("<< rGen1.Name() 
00229   << "," << rGen2.Name() << ")");
00230   return EmptyLanguageIntersection(rGen1,rGen2);
00231 }
00232 
00233 // Automaton(rGen)
00234 void Automaton(vGenerator& 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(vGenerator& 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(vGenerator& 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(vGenerator& 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 vGenerator& rGen, vGenerator& rRes) {
00343   rRes=rGen;
00344   LanguageComplement(rRes);
00345 }
00346 
00347 
00348 // language complement, uniform api
00349 void LanguageComplement(const vGenerator& rGen, const EventSet& rSigma, vGenerator& rRes) {
00350   rRes=rGen;
00351   LanguageComplement(rRes,rSigma);
00352 }
00353 
00354 
00355 
00356 
00357 //LanguageDifference(rGen1, rGen2, rResGen)
00358 void LanguageDifference(
00359    const vGenerator& rGen1, 
00360    const vGenerator& rGen2,
00361    vGenerator& rResGen) {
00362          
00363      FD_DF("LanguageDifference("<< rGen1.Name() << "," << rGen2.Name() << ")");
00364      
00365     // use pointer pResGen to result rResGen; if rResGen is identical to
00366     // one of the parameters, allocate temporary object and copy back later 
00367     vGenerator* pResGen = &rResGen;
00368     if(&rResGen == &rGen1 || &rResGen== &rGen2) {
00369       pResGen = rResGen.New();
00370     }    
00371     
00372     // due to the use of LanguageComplement(), rGen2 has to be deterministic
00373     #ifdef FAUDES_CHECKED
00374     if(!(rGen2.IsDeterministic())){
00375       std::stringstream errstr;
00376       errstr << "Nondeterministic parameter " << rGen2.Name() << ".";
00377       throw Exception("LanguageDifference()", errstr.str(), 101);
00378     }
00379     #endif
00380           
00381     // prepare result
00382     pResGen->Clear();
00383      
00384     // calculate "Lm1-Lm2" by building the intersection of Lm1 with the complement of Lm2
00385         
00386     *pResGen=rGen2;
00387     // for correct result, complement has to be computed wrt the alphabet of Lm1!
00388     LanguageComplement(*pResGen,rGen1.Alphabet());
00389     LanguageIntersection(rGen1, *pResGen, *pResGen);
00390         
00391     pResGen->Name(CollapsString("LanguageDifference(" + rGen1.Name() + "," + rGen2.Name() + ")"));
00392   
00393     // if necessary, move pResGen to rResGen
00394     if(pResGen != &rResGen) {
00395       pResGen->Move(rResGen);
00396       delete pResGen;
00397     } 
00398     
00399     return;
00400 }
00401 
00402 // LanguageConcatenateNonDet(rGen1, rGen2, rResGen)
00403 void LanguageConcatenateNonDet(const vGenerator& rGen1, const vGenerator& rGen2, 
00404              vGenerator& rResGen) {
00405   FD_DF("LanguageConcatenateNonDet(" << rGen1.Name() << "," << rGen2.Name() << ")");
00406             
00407   // are state names enabled in result?
00408   bool stateNamesEnabled=rResGen.StateNamesEnabled();
00409     
00410   // use pointer pResGen to result rResGen; if rResGen is identical to
00411   // one of the parameters, allocate temporary object and copy back later
00412   vGenerator* pResGen = &rResGen;
00413   if(&rResGen== &rGen1 || &rResGen== &rGen2) {
00414     pResGen= rResGen.New();
00415   }
00416 
00417   // prepare result
00418   pResGen->Clear();
00419     
00420   // union of alphabets
00421   pResGen->InjectAlphabet(rGen1.Alphabet() + rGen2.Alphabet());
00422 
00423   // Maps from states of rGen1 and rGen2 to states of ResGen
00424   std::map<Idx,Idx> Gen1StatesMap;
00425   std::map<Idx,Idx> Gen2StatesMap;
00426 
00427   // helpers
00428   StateSet::Iterator sit;
00429   TransSet::Iterator tit;
00430     
00431   // "union" of states: insert states representing the states of rGen1 and rGen2
00432   for (sit = rGen1.StatesBegin(); sit != rGen1.StatesEnd(); ++sit) {
00433     if (stateNamesEnabled) {
00434       Gen1StatesMap[*sit] = pResGen->InsState(pResGen->UniqueStateName(rGen1.StateName(*sit)+"(1)"));
00435     } else {
00436       Gen1StatesMap[*sit] = pResGen->InsState();
00437     }
00438   }
00439   for (sit = rGen2.StatesBegin(); sit != rGen2.StatesEnd(); ++sit) {
00440     if (stateNamesEnabled) {
00441       Gen2StatesMap[*sit] = pResGen->InsState(pResGen->UniqueStateName(rGen2.StateName(*sit)+"(2)"));
00442     } else {
00443       Gen2StatesMap[*sit] = pResGen->InsState();
00444     }
00445   }
00446 
00447   // "union" transitions: insert all rGen1 transitions
00448   for (tit = rGen1.TransRelBegin(); tit != rGen1.TransRelEnd(); ++tit) 
00449     pResGen->SetTransition(Gen1StatesMap[tit->X1], tit->Ev, Gen1StatesMap[tit->X2]);
00450     
00451   // "union" transitions: insert all rGen2 transitions
00452   for (tit = rGen2.TransRelBegin(); tit != rGen2.TransRelEnd(); ++tit) 
00453     pResGen->SetTransition(Gen2StatesMap[tit->X1], tit->Ev, Gen2StatesMap[tit->X2]);
00454     
00455 
00456   // initial state bug (detected by Tomas Masopust, fix by Klaus Schmidt)
00457   // 1) copy all transitions to the result, clear initial/marked status
00458   // 2) all initial states of G1 become initial states in the result
00459   // 3) if L1 contains the empty string, also all initial states of G2 become initial states
00460   //    in the result
00461   // 4) transition leading to a marked state in G1 also become transitions to all
00462   //    initial states of G2
00463   // 5) marked states of G2 become marked in the result
00464 
00465 
00466   // test whether L1 includes the empty string
00467   bool concatenateEpsilon1=false;
00468   for(sit = rGen1.InitStatesBegin(); sit != rGen1.InitStatesEnd(); ++sit) {
00469     if(rGen1.ExistsMarkedState(*sit)) {
00470       concatenateEpsilon1=true;
00471       break;
00472     }
00473   }
00474 
00475   // initial states of G1 become initial states in the result
00476   for (sit = rGen1.InitStatesBegin(); sit != rGen1.InitStatesEnd(); ++sit) 
00477     pResGen->SetInitState(Gen1StatesMap[*sit]);
00478     
00479   // if L1 contains the emtystring, G2 initial states become initial states in the result
00480   if(concatenateEpsilon1)
00481     for (sit = rGen2.InitStatesBegin(); sit != rGen2.InitStatesEnd(); ++sit) 
00482       pResGen->SetInitState(Gen2StatesMap[*sit]);
00483     
00484   // any G1 transition to a marked state must also lead to all initial states of G2
00485   for(tit = rGen1.TransRelBegin(); tit != rGen1.TransRelEnd(); ++tit) 
00486     if(rGen1.ExistsMarkedState(tit->X2)) 
00487       for(sit = rGen2.InitStatesBegin(); sit != rGen2.InitStatesEnd(); ++sit) 
00488         pResGen->SetTransition(Gen1StatesMap[tit->X1], tit->Ev, Gen2StatesMap[*sit]);
00489 
00490   // set pResGen marked states corresponding to rGen2 marked states using Gen2StatesMap
00491   for (sit = rGen2.MarkedStatesBegin(); sit != rGen2.MarkedStatesEnd(); ++sit) {
00492     if(!(rGen2.ExistsInitState(*sit))) {
00493       pResGen->SetMarkedState(Gen2StatesMap[*sit]);
00494     }
00495   }
00496 
00497   // remove blocking states as they provide no useful meaning.
00498   pResGen->Trim();
00499   pResGen->Name("ConcatenateNonDet("+rGen1.Name()+","+rGen2.Name()+")");
00500     
00501   // if necessary, move pResGen to rResGen
00502   if(pResGen != &rResGen) {
00503     pResGen->Move(rResGen);
00504     delete pResGen;
00505   }
00506     
00507 }
00508 
00509 // LanguageConcatenate(rGen1, rGen2, rResGen)
00510 void LanguageConcatenate(const vGenerator& rGen1, const vGenerator& rGen2, 
00511        vGenerator& rResGen) {
00512 
00513   FD_DF("LanguageConcatenate("<< rGen1.Name() 
00514   << "," << rGen2.Name() << ")");
00515     
00516   // perform nondeterministic language concatenation
00517   LanguageConcatenateNonDet(rGen1, rGen2, rResGen);
00518     
00519   // make deterministic if necessary
00520   if(!(rResGen.IsDeterministic())){
00521     Deterministic(rResGen, rResGen);
00522   }
00523 
00524   // set name of result
00525   rResGen.Name("Concatenate("+rGen1.Name()+","+rGen2.Name()+")");
00526     
00527   return;    
00528 }
00529 
00530 // FullLanguage(rAlphabet, rResGen)
00531 void FullLanguage(const EventSet& rAlphabet, vGenerator& rResGen) {
00532   FD_DF("FullLanguage("<< rAlphabet.Name() 
00533   << "," << rResGen.Name() << ")");
00534   
00535   // prepare result
00536   rResGen.Clear();
00537   
00538   // helpers
00539   Idx state;
00540   EventSet::Iterator evit;
00541   
00542   // alphabet
00543   rResGen.InjectAlphabet(rAlphabet);
00544   
00545   // insert marked initial state
00546   if(rResGen.StateNamesEnabled()){
00547     state = rResGen.InsInitState("1");
00548   } else{
00549     state = rResGen.InsInitState();
00550   }
00551   rResGen.SetMarkedState(state);
00552   
00553   // create selfloop for each event
00554   for (evit = rAlphabet.Begin(); evit != rAlphabet.End(); ++evit) {
00555     rResGen.SetTransition(state, *evit, state);
00556   }
00557   
00558   // set name of result
00559   rResGen.Name("FullLanguage("+rAlphabet.Name()+")");
00560     
00561   return;
00562 }
00563 
00564 // AlphabetLanguage(rAlphabet, rResGen)
00565 void AlphabetLanguage(const EventSet& rAlphabet, vGenerator& rResGen) {
00566   FD_DF("AlphabetLanguage("<< rAlphabet.Name() 
00567   << "," << rResGen.Name() << ")");
00568   
00569   // prepare result
00570   rResGen.Clear();
00571       
00572   // set name of result
00573   rResGen.Name("AlphabetLanguage("+rAlphabet.Name()+")");
00574     
00575   // if alphabet is empty, leave generator empty
00576   if(rAlphabet.Empty()){
00577     FD_WARN("AlphabetLanguage: empty alphabet.");
00578     return;
00579   }
00580     
00581   // helpers
00582   Idx istate, mstate;
00583   EventSet::Iterator evit;
00584   
00585   // alphabet
00586   rResGen.InjectAlphabet(rAlphabet);
00587   
00588   // insert one initial state and one marked state
00589   if(rResGen.StateNamesEnabled()){
00590     istate = rResGen.InsInitState("1");
00591     mstate = rResGen.InsMarkedState("2");
00592   }
00593   else{
00594     istate = rResGen.InsInitState();
00595     mstate = rResGen.InsMarkedState();
00596   }
00597   
00598   // for each event from rAlphabet, inserted transition leading from init state to marked state
00599   for (evit = rAlphabet.Begin(); evit != rAlphabet.End(); ++evit) {
00600     rResGen.SetTransition(istate, *evit, mstate);
00601   }
00602     
00603   return;
00604 }
00605 
00606 // EmptyStringLanguage(rAlphabet, rResGen)
00607 void EmptyStringLanguage(const EventSet& rAlphabet, vGenerator& rResGen) {
00608   FD_DF("EmptyStringLanguage("<< rAlphabet.Name() 
00609   << "," << rResGen.Name() << ")");
00610   
00611   // prepare result
00612   rResGen.Clear();
00613   
00614   // helpers
00615   Idx state;
00616   
00617   // alphabet
00618   rResGen.InjectAlphabet(rAlphabet);
00619   
00620   // insert marked initial state
00621   if(rResGen.StateNamesEnabled()){
00622     state = rResGen.InsInitState("1");
00623   }
00624   else{
00625     state = rResGen.InsInitState();
00626   }
00627   rResGen.SetMarkedState(state);
00628   
00629   // set name of result
00630   rResGen.Name("EmptyStringLanguage("+rAlphabet.Name()+")");
00631     
00632   return;
00633 }
00634 
00635 // EmptyLanguage(rAlphabet, rResGen)
00636 void EmptyLanguage(const EventSet& rAlphabet, vGenerator& rResGen) {
00637   FD_DF("EmptyStringLanguage("<< rAlphabet.Name() 
00638   << "," << rResGen.Name() << ")");
00639   
00640   // prepare result
00641   rResGen.Clear();
00642   
00643   // alphabet and initial state
00644   rResGen.InsInitState();
00645   rResGen.InjectAlphabet(rAlphabet);
00646 
00647   // set name of result
00648   rResGen.Name("EmptyLanguage("+rAlphabet.Name()+")");
00649     
00650   return;
00651 }
00652 
00653 // EmptyLanguage(rGen)
00654 bool IsEmptyLanguage(const vGenerator& rGen) {
00655   // case a) check if set of marked or initial states is empty
00656   if(rGen.MarkedStatesSize()==0) return true;
00657   if(rGen.InitStatesSize()==0) return true;
00658   // case b) check if no marked state is accessible (reachable)
00659   return (rGen.AccessibleSet()*rGen.MarkedStates()).Empty();
00660 }
00661 
00662 // LanguageInclusion(rGen1, rGen2)
00663 bool LanguageInclusion(const vGenerator& rGen1, const vGenerator& rGen2) {
00664     
00665   FD_DF("LanguageInclusion("<< rGen1.Name() << "," << rGen2.Name() << ")"); 
00666     
00667   // check if there is no string in Lm1 that is not in Lm2, which means Lm1<=Lm2
00668   Generator NotrGen2=rGen2;
00669   // note: complement w.r.t. union of alphabets to ensure that elementwise 
00670   // inclusion of Lm1 in Lm2 is tested
00671   LanguageComplement(NotrGen2 , rGen1.Alphabet()+rGen2.Alphabet());
00672   return EmptyLanguageIntersection(rGen1,NotrGen2);        
00673 }
00674 
00675 // LanguageEquality(rGen1, rGen2)
00676 bool LanguageEquality(const vGenerator& rGen1, const vGenerator& rGen2) {
00677     
00678   FD_DF("LanguageEquality("<< rGen1.Name() << "," << rGen2.Name() << ")");
00679 
00680   // Check for equality by testing mutual inclusion
00681   return LanguageInclusion(rGen1,rGen2) && LanguageInclusion(rGen2,rGen1);
00682 }
00683 
00684 // KleeneClosure(rGen)
00685 void KleeneClosure(vGenerator& rGen) {
00686    
00687   FD_DF("KleeneClosure("<< rGen.Name() << ")");
00688 
00689   // fix name 
00690   std::string name=CollapsString("KleeneClosure(" + rGen.Name() + ")");
00691 
00692   // The Kleene Closure of the empty set is the empty set
00693   if(IsEmptyLanguage(rGen)){
00694     rGen.Name(name);
00695     return;
00696   }
00697 
00698   // run nondet version    
00699   KleeneClosureNonDet(rGen);
00700   Deterministic(rGen, rGen);
00701 
00702   // set name
00703   rGen.Name(name);
00704 }
00705 
00706 // KleeneClosure(rGen, rResGen)
00707 void KleeneClosure(const vGenerator& rGen, vGenerator& rResGen) {
00708    
00709   FD_DF("KleeneClosure("<< rGen.Name() << ", ... )");
00710 
00711   // if arg and result match, call respective version
00712   if(&rGen==&rResGen) {
00713     KleeneClosure(rResGen);
00714     return;
00715   }
00716 
00717   // fix name 
00718   std::string name=CollapsString("KleeneClosure(" + rGen.Name() + ")");
00719 
00720   // The Kleene Closure of the empty set is the empty set
00721   if(IsEmptyLanguage(rGen)){
00722     rResGen.Clear();
00723     rResGen.Name(name);
00724     return;
00725   }
00726 
00727   // run nondet version with intermediate result
00728   vGenerator* pgen=rGen.Copy();   
00729   KleeneClosureNonDet(*pgen);
00730   Deterministic(*pgen, rResGen);
00731   delete pgen;
00732 
00733   // set name
00734   rResGen.Name(name);
00735 }
00736 
00737 // KleeneClosureNonDet(rGen)
00738 void KleeneClosureNonDet(vGenerator& rGen) {
00739     
00740   FD_DF("KleeneClosureNonDet("<< rGen.Name()  << ")");
00741     
00742   // set name 
00743   rGen.Name(CollapsString("KleeneClosureNonDet("+ rGen.Name() + ")"));
00744     
00745   // The Kleene Closure of the empty set is the empty set
00746   if(IsEmptyLanguage(rGen)) return;
00747     
00748   // helpers
00749   TransSet::Iterator tit;
00750   TransSet TransToInsert;
00751 
00752   // initial state bug (detected by Tomas Masopust, fix proposed by Klaus Schmidt)
00753   // 1. prepare the generator to have a unique initial state
00754   // 2. if the initial state fails to be marked, introduce a fake marked initial state.
00755   // 3. equip the fake markded initial state with the same transitions as the original initial state
00756   UniqueInit(rGen);
00757   Idx istate = *rGen.InitStatesBegin();
00758   Idx imstate = istate;
00759   if(!rGen.ExistsMarkedState(imstate)) {
00760     imstate=rGen.InsInitState();
00761     rGen.SetMarkedState(imstate);
00762     for(tit = rGen.TransRelBegin(istate); tit != rGen.TransRelEnd(istate); ++tit) { 
00763       TransToInsert.Insert(imstate, tit->Ev, tit->X2);
00764     }
00765   }
00766       
00767   // for all transitions leading from a state x1 to a marked state: insert a transition
00768   // with the same event that leads to the initial state(s). 
00769   for(tit = rGen.TransRelBegin(); tit != rGen.TransRelEnd(); ++tit) { 
00770     if(rGen.ExistsMarkedState(tit->X2)) {
00771       if(!(rGen.ExistsTransition(tit->X1, tit->Ev, imstate)) ){
00772   TransToInsert.Insert(tit->X1, tit->Ev, imstate);
00773       }
00774     }        
00775   }
00776   for (tit = TransToInsert.Begin(); tit != TransToInsert.End(); ++tit) {
00777     rGen.SetTransition(*tit);
00778   }
00779     
00780 }
00781 
00782 // PrefixClosure(rGen)
00783 void PrefixClosure(vGenerator& rGen) {
00784     
00785   FD_DF("PrefixClosure("<< rGen.Name() << ")");
00786 
00787   // fix name
00788   std::string name=CollapsString("PrefixClosure("+ rGen.Name() + ")");
00789     
00790   // remove all states that do net represent prefixes of marked strings
00791   rGen.Coaccessible();
00792     
00793   // mark all remaining states
00794   rGen.InjectMarkedStates(rGen.States());
00795    
00796   // set name 
00797   rGen.Name(name);
00798     
00799 }
00800 
00801 // IsPrefixClosed
00802 bool IsPrefixClosed(const vGenerator& rGen) {
00803   
00804   // figure relevant states
00805   StateSet relevant = rGen.AccessibleSet() * rGen.CoaccessibleSet();
00806 
00807   // test
00808   return relevant <= rGen.MarkedStates();
00809 
00810 }
00811 
00812 // IsNonblocking
00813 bool IsNonblocking(const vGenerator& rGen) {
00814   
00815   // test
00816   return rGen.AccessibleSet() <= rGen.CoaccessibleSet();
00817 
00818 }
00819 
00820 // IsNonblocking 
00821 bool IsNonblocking(const vGenerator& rGen1, const vGenerator& rGen2) {
00822   
00823   // build composition
00824   vGenerator parallel;
00825   Parallel(rGen1,rGen2,parallel);
00826 
00827   // test (parallel returns an accessible generator).
00828   return parallel.States() <= parallel.CoaccessibleSet();
00829 
00830 }
00831 
00832 
00833 
00834 // SelfLoop(rGen,rAlphabet)
00835 void SelfLoop(vGenerator& rGen,const EventSet& rAlphabet) {
00836     
00837   FD_DF("SelfLoop(" << rGen.Name() << "," << rAlphabet.Name() << ")");
00838 
00839   // fix name
00840   std::string name = CollapsString("SelfLoop(" + rGen.Name() + "," + rAlphabet.Name() + ")");
00841   // extend alphabet of rGen
00842   rGen.InjectAlphabet(rGen.Alphabet()+rAlphabet);
00843     
00844   //helpers
00845   EventSet::Iterator evit,evbegin,evend;
00846   evbegin = rAlphabet.Begin();
00847   evend = rAlphabet.End();  
00848   StateSet::Iterator sit;
00849     
00850   // iterate over all states and insert selfloop for each event of rAlphabet
00851   for (sit = rGen.StatesBegin(); sit != rGen.StatesEnd(); ++sit) {
00852     for(evit = evbegin; evit != evend; ++evit){
00853       rGen.SetTransition(*sit, *evit, *sit);
00854     }
00855   }
00856     
00857   // set name
00858   rGen.Name(name);
00859 }
00860 
00861 // SelfLoopMarkedStates(rGen,rAlphabet)
00862 void SelfLoopMarkedStates(vGenerator& rGen,const EventSet& rAlphabet) {
00863     
00864   FD_DF("SelfLoopMarkedStates(" << rGen.Name() << "," << rAlphabet.Name() << ")");
00865 
00866   // fix name
00867   std::string name = CollapsString("SelfLoopMarkedStates(" + rGen.Name() 
00868      + "," + rAlphabet.Name() + ")");
00869 
00870   // extend alphabet of rGen
00871   rGen.InjectAlphabet(rGen.Alphabet()+rAlphabet);
00872     
00873   //helpers
00874   EventSet::Iterator evit,evbegin,evend;
00875   evbegin = rAlphabet.Begin();
00876   evend = rAlphabet.End();  
00877   StateSet::Iterator sit;
00878     
00879   // iterate over all marked states and insert selfloop for each event of rAlphabet
00880   for (sit = rGen.MarkedStatesBegin(); sit != rGen.MarkedStatesEnd(); ++sit) {
00881     for(evit = evbegin; evit != evend; ++evit){
00882       rGen.SetTransition(*sit, *evit, *sit);
00883     }
00884   }
00885     
00886   // set name
00887   rGen.Name(name);
00888 }
00889 
00890 // SelfLoop(rGen,rAlphabet,rStates)
00891 void SelfLoop(vGenerator& rGen,const EventSet& rAlphabet,const StateSet& rStates) {
00892     
00893   FD_DF("SelfLoop(" << rGen.Name() << "," << rAlphabet.Name() << "," << rStates.Name() << ")");
00894 
00895   // fix name
00896   std::string name = CollapsString("SelfLoop(" + rGen.Name() 
00897      + "," + rAlphabet.Name() + "," + rStates.Name() + ")");
00898 
00899   // exception: rStates must be states of rGen
00900 #ifdef FAUDES_CHECKED
00901   if( !(rStates <= rGen.States()) ){
00902     std::stringstream errstr;
00903     errstr << "State set " << rStates.Name() << 
00904       " has to be included in state set of "<< rGen.Name() << ".";
00905     throw Exception("SelfLoop()", errstr.str(), 100);
00906   }
00907 #endif
00908     
00909   // extend alphabet of rGen
00910   rGen.InjectAlphabet(rGen.Alphabet()+rAlphabet);
00911     
00912   //helpers
00913   EventSet::Iterator evit,evbegin,evend;
00914   evbegin = rAlphabet.Begin();
00915   evend = rAlphabet.End();    
00916   StateSet::Iterator sit;
00917     
00918   // iterate over all marked states and insert selfloop for each event of rAlphabet
00919   for (sit = rStates.Begin(); sit != rStates.End(); ++sit) {
00920     for(evit = evbegin; evit != evend; ++evit){
00921       rGen.SetTransition(*sit, *evit, *sit);
00922     }
00923   }
00924     
00925   // set name
00926   rGen.Name(name);
00927 }
00928 
00929 
00930 } // namespace faudes
00931 
00932 #undef Product //see define above for comment

libFAUDES 2.18b --- 2010-12-17 --- c++ source docu by doxygen 1.6.3