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   StateSet::Iterator sit1m, sit2i; // rGen1 marked states, rGen2 initial states
00430   TransSet::Iterator tit;
00431     
00432   // "union" of states: insert states representing the states of rGen1 and rGen2
00433   for (sit = rGen1.StatesBegin(); sit != rGen1.StatesEnd(); ++sit) {
00434     if (stateNamesEnabled) {
00435       Gen1StatesMap[*sit] = pResGen->InsState(pResGen->UniqueStateName(rGen1.StateName(*sit)+"(1)"));
00436     } else {
00437       Gen1StatesMap[*sit] = pResGen->InsState();
00438     }
00439   }
00440   for (sit = rGen2.StatesBegin(); sit != rGen2.StatesEnd(); ++sit) {
00441     if (stateNamesEnabled) {
00442       Gen2StatesMap[*sit] = pResGen->InsState(pResGen->UniqueStateName(rGen2.StateName(*sit)+"(2)"));
00443     } else {
00444       Gen2StatesMap[*sit] = pResGen->InsState();
00445     }
00446   }
00447 
00448   // test whether L2 includes the empty string
00449   bool concatenateEpsilon=false;
00450   for (sit = rGen2.InitStatesBegin(); sit != rGen2.InitStatesEnd(); ++sit) {
00451     if (rGen2.ExistsMarkedState(*sit)) {
00452       concatenateEpsilon=true;
00453     }
00454   }
00455     
00456   // set pResGen init states corresponding to rGen1 init states using Gen1StatesMap
00457   for (sit = rGen1.InitStatesBegin(); sit != rGen1.InitStatesEnd(); ++sit) {
00458     pResGen->SetInitState(Gen1StatesMap[*sit]);
00459   }
00460     
00461   // add rGen1 transitions
00462   for (tit = rGen1.TransRelBegin(); tit != rGen1.TransRelEnd(); ++tit) {
00463     pResGen->SetTransition(Gen1StatesMap[tit->X1], tit->Ev, Gen1StatesMap[tit->X2]);
00464   }
00465     
00466   // add rGen2 transitions
00467   for (tit = rGen2.TransRelBegin(); tit != rGen2.TransRelEnd(); ++tit) {
00468     pResGen->SetTransition(Gen2StatesMap[tit->X1], tit->Ev, Gen2StatesMap[tit->X2]);
00469   }
00470     
00471   // add rGen2 transitions starting at initial states at each state corresponding to a 
00472   // marked state of rGen1.
00473   for (sit2i = rGen2.InitStatesBegin(); sit2i != rGen2.InitStatesEnd(); ++sit2i) {
00474     for (tit = rGen2.TransRelBegin(*sit2i); tit != rGen2.TransRelEnd(*sit2i); ++tit) {
00475       // iterate over rGen1 mstates
00476         for (sit1m = rGen1.MarkedStatesBegin(); sit1m != rGen1.MarkedStatesEnd(); ++sit1m) {
00477             // If the rGen2 transition tit leads to an init state of rGen2, then the respective
00478             // pResGen transition has to lead to the current marked state of rGen1 (as selfloop)
00479             if(rGen2.ExistsInitState(tit->X2)){
00480                 pResGen->SetTransition(Gen1StatesMap[*sit1m], tit->Ev, Gen1StatesMap[*sit1m]);
00481             }
00482             else {
00483                 pResGen->SetTransition(Gen1StatesMap[*sit1m], tit->Ev, Gen2StatesMap[tit->X2]);
00484             }
00485             // note: in this state, there might already be a transition from rGen1 with the
00486             // same event. Hence, the transitions inserted above can cause nondeterminism in pResGen.
00487         }
00488     }
00489   }
00490     
00491   // set pResGen marked states corresponding to rGen2 marked states using Gen2StatesMap
00492   for (sit = rGen2.MarkedStatesBegin(); sit != rGen2.MarkedStatesEnd(); ++sit) {
00493     if(!(rGen2.ExistsInitState(*sit))) {
00494       pResGen->SetMarkedState(Gen2StatesMap[*sit]);
00495     }
00496   }
00497 
00498   // if epsilon is concatenated to Lm1, additionally set pResGen marked 
00499   // states corresponding to rGen1 marked states using Gen1StatesMap
00500   if(concatenateEpsilon){
00501     for (sit = rGen1.MarkedStatesBegin(); sit != rGen1.MarkedStatesEnd(); ++sit) {
00502       pResGen->SetMarkedState(Gen1StatesMap[*sit]);
00503     }
00504   }
00505     
00506   // remove blocking states as they provide no useful meaning.
00507   pResGen->Trim();
00508   pResGen->Name("ConcatenateNonDet("+rGen1.Name()+","+rGen2.Name()+")");
00509     
00510   // if necessary, move pResGen to rResGen
00511   if(pResGen != &rResGen) {
00512     pResGen->Move(rResGen);
00513     delete pResGen;
00514   }
00515     
00516 }
00517 
00518 // LanguageConcatenate(rGen1, rGen2, rResGen)
00519 void LanguageConcatenate(const vGenerator& rGen1, const vGenerator& rGen2, 
00520        vGenerator& rResGen) {
00521 
00522   FD_DF("LanguageConcatenate("<< rGen1.Name() 
00523   << "," << rGen2.Name() << ")");
00524     
00525   // perform nondeterministic language concatenation
00526   LanguageConcatenateNonDet(rGen1, rGen2, rResGen);
00527     
00528   // make deterministic if necessary
00529   if(!(rResGen.IsDeterministic())){
00530     Deterministic(rResGen, rResGen);
00531   }
00532 
00533   // set name of result
00534   rResGen.Name("Concatenate("+rGen1.Name()+","+rGen2.Name()+")");
00535     
00536   return;    
00537 }
00538 
00539 // FullLanguage(rAlphabet, rResGen)
00540 void FullLanguage(const EventSet& rAlphabet, vGenerator& rResGen) {
00541   FD_DF("FullLanguage("<< rAlphabet.Name() 
00542   << "," << rResGen.Name() << ")");
00543   
00544   // prepare result
00545   rResGen.Clear();
00546   
00547   // helpers
00548   Idx state;
00549   EventSet::Iterator evit;
00550   
00551   // alphabet
00552   rResGen.InjectAlphabet(rAlphabet);
00553   
00554   // insert marked initial state
00555   if(rResGen.StateNamesEnabled()){
00556     state = rResGen.InsInitState("1");
00557   } else{
00558     state = rResGen.InsInitState();
00559   }
00560   rResGen.SetMarkedState(state);
00561   
00562   // create selfloop for each event
00563   for (evit = rAlphabet.Begin(); evit != rAlphabet.End(); ++evit) {
00564     rResGen.SetTransition(state, *evit, state);
00565   }
00566   
00567   // set name of result
00568   rResGen.Name("FullLanguage("+rAlphabet.Name()+")");
00569     
00570   return;
00571 }
00572 
00573 // AlphabetLanguage(rAlphabet, rResGen)
00574 void AlphabetLanguage(const EventSet& rAlphabet, vGenerator& rResGen) {
00575   FD_DF("AlphabetLanguage("<< rAlphabet.Name() 
00576   << "," << rResGen.Name() << ")");
00577   
00578   // prepare result
00579   rResGen.Clear();
00580       
00581   // set name of result
00582   rResGen.Name("AlphabetLanguage("+rAlphabet.Name()+")");
00583     
00584   // if alphabet is empty, leave generator empty
00585   if(rAlphabet.Empty()){
00586     FD_WARN("AlphabetLanguage: empty alphabet.");
00587     return;
00588   }
00589     
00590   // helpers
00591   Idx istate, mstate;
00592   EventSet::Iterator evit;
00593   
00594   // alphabet
00595   rResGen.InjectAlphabet(rAlphabet);
00596   
00597   // insert one initial state and one marked state
00598   if(rResGen.StateNamesEnabled()){
00599     istate = rResGen.InsInitState("1");
00600     mstate = rResGen.InsMarkedState("2");
00601   }
00602   else{
00603     istate = rResGen.InsInitState();
00604     mstate = rResGen.InsMarkedState();
00605   }
00606   
00607   // for each event from rAlphabet, inserted transition leading from init state to marked state
00608   for (evit = rAlphabet.Begin(); evit != rAlphabet.End(); ++evit) {
00609     rResGen.SetTransition(istate, *evit, mstate);
00610   }
00611     
00612   return;
00613 }
00614 
00615 // EmptyStringLanguage(rAlphabet, rResGen)
00616 void EmptyStringLanguage(const EventSet& rAlphabet, vGenerator& rResGen) {
00617   FD_DF("EmptyStringLanguage("<< rAlphabet.Name() 
00618   << "," << rResGen.Name() << ")");
00619   
00620   // prepare result
00621   rResGen.Clear();
00622   
00623   // helpers
00624   Idx state;
00625   
00626   // alphabet
00627   rResGen.InjectAlphabet(rAlphabet);
00628   
00629   // insert marked initial state
00630   if(rResGen.StateNamesEnabled()){
00631     state = rResGen.InsInitState("1");
00632   }
00633   else{
00634     state = rResGen.InsInitState();
00635   }
00636   rResGen.SetMarkedState(state);
00637   
00638   // set name of result
00639   rResGen.Name("EmptyStringLanguage("+rAlphabet.Name()+")");
00640     
00641   return;
00642 }
00643 
00644 // EmptyLanguage(rAlphabet, rResGen)
00645 void EmptyLanguage(const EventSet& rAlphabet, vGenerator& rResGen) {
00646   FD_DF("EmptyStringLanguage("<< rAlphabet.Name() 
00647   << "," << rResGen.Name() << ")");
00648   
00649   // prepare result
00650   rResGen.Clear();
00651   
00652   // alphabet and initial state
00653   rResGen.InsInitState();
00654   rResGen.InjectAlphabet(rAlphabet);
00655 
00656   // set name of result
00657   rResGen.Name("EmptyLanguage("+rAlphabet.Name()+")");
00658     
00659   return;
00660 }
00661 
00662 // EmptyLanguage(rGen)
00663 bool IsEmptyLanguage(const vGenerator& rGen) {
00664   // case a) check if set of marked states is empty
00665   if(rGen.MarkedStatesSize()==0) return true;
00666   // case b) check if no marked state is accessible (reachable)
00667   return (rGen.AccessibleSet()*rGen.MarkedStates()).Empty();
00668 }
00669 
00670 // LanguageInclusion(rGen1, rGen2)
00671 bool LanguageInclusion(const vGenerator& rGen1, const vGenerator& rGen2) {
00672     
00673   FD_DF("LanguageInclusion("<< rGen1.Name() << "," << rGen2.Name() << ")"); 
00674     
00675   // check if there is no string in Lm1 that is not in Lm2, which means Lm1<=Lm2
00676   Generator NotrGen2=rGen2;
00677   // note: complement w.r.t. union of alphabets to ensure that elementwise 
00678   // inclusion of Lm1 in Lm2 is tested
00679   LanguageComplement(NotrGen2 , rGen1.Alphabet()+rGen2.Alphabet());
00680   return EmptyLanguageIntersection(rGen1,NotrGen2);        
00681 }
00682 
00683 // LanguageEquality(rGen1, rGen2)
00684 bool LanguageEquality(const vGenerator& rGen1, const vGenerator& rGen2) {
00685     
00686   FD_DF("LanguageEquality("<< rGen1.Name() << "," << rGen2.Name() << ")");
00687 
00688   // Check for equality by testing mutual inclusion
00689   return LanguageInclusion(rGen1,rGen2) && LanguageInclusion(rGen2,rGen1);
00690 }
00691 
00692 // KleeneClosure(rGen, rResGen)
00693 void KleeneClosure(vGenerator& rGen) {
00694    
00695   FD_DF("KleeneClosure("<< rGen.Name() << ")");
00696 
00697   // fix name 
00698   std::string name=CollapsString("KleeneClosure(" + rGen.Name() + ")");
00699 
00700   // The Kleene Closure of the empty set is the empty set
00701   if(IsEmptyLanguage(rGen)){
00702     rGen.Name(name);
00703     return;
00704   }
00705 
00706   // run nondet version    
00707   KleeneClosureNonDet(rGen);
00708   Deterministic(rGen, rGen);
00709 
00710   // set name
00711   rGen.Name(name);
00712 }
00713 
00714 // KleeneClosureNonDet(rGen)
00715 void KleeneClosureNonDet(vGenerator& rGen) {
00716     
00717   FD_DF("KleeneClosureNonDet("<< rGen.Name()  << ")");
00718     
00719   // set name 
00720   rGen.Name(CollapsString("KleeneClosureNonDet("+ rGen.Name() + ")"));
00721     
00722   // The Kleene Closure of the empty set is the empty set
00723   if(IsEmptyLanguage(rGen)) return;
00724     
00725   // helpers
00726   TransSet::Iterator tit;
00727   StateSet::Iterator init = rGen.InitStatesBegin();
00728   TransSet TransToInsert;
00729     
00730   // for all transitions leading from a state x1 to a marked state: insert a transition
00731   // with the same event that leads to (one of) the initial state(s). This step makes
00732   // rGen nondeterministic.
00733   // first, find respective transitions in rGen and update TransToInsert with new
00734   // transitions to insert
00735   for (tit = rGen.TransRelBegin(); tit != rGen.TransRelEnd(); ++tit) {
00736   
00737     if(rGen.ExistsMarkedState(tit->X2)) {
00738       if( !(rGen.ExistsTransition(tit->X1, tit->Ev, *init)) ){
00739   TransToInsert.Insert(tit->X1, tit->Ev, *init);
00740       }
00741     }
00742         
00743   }
00744   // now, extend rGen by transitions of TransToInsert
00745   for (tit = TransToInsert.Begin(); tit != TransToInsert.End(); ++tit) {
00746     rGen.SetTransition(*tit);
00747   }
00748     
00749   // KleeneClosure of nonempty language always contains the empty string:
00750   // mark at least one initial state
00751   rGen.SetMarkedState(*init);
00752 }
00753 
00754 // PrefixClosure(rGen)
00755 void PrefixClosure(vGenerator& rGen) {
00756     
00757   FD_DF("PrefixClosure("<< rGen.Name() << ")");
00758 
00759   // fix name
00760   std::string name=CollapsString("PrefixClosure("+ rGen.Name() + ")");
00761     
00762   // remove all states that do net represent prefixes of marked strings
00763   rGen.Coaccessible();
00764     
00765   // mark all remaining states
00766   rGen.InjectMarkedStates(rGen.States());
00767    
00768   // set name 
00769   rGen.Name(name);
00770     
00771 }
00772 
00773 // IsPrefixClosed
00774 bool IsPrefixClosed(const vGenerator& rGen) {
00775   
00776   // figure relevant states
00777   StateSet relevant = rGen.AccessibleSet() * rGen.CoaccessibleSet();
00778 
00779   // test
00780   return relevant <= rGen.MarkedStates();
00781 
00782 }
00783 
00784 // IsNonblocking
00785 bool IsNonblocking(const vGenerator& rGen) {
00786   
00787   // test
00788   return rGen.AccessibleSet() <= rGen.CoaccessibleSet();
00789 
00790 }
00791 
00792 // IsNonblocking 
00793 bool IsNonblocking(const vGenerator& rGen1, const vGenerator& rGen2) {
00794   
00795   // build composition
00796   vGenerator parallel;
00797   Parallel(rGen1,rGen2,parallel);
00798 
00799   // test (parallel returns an accessible generator).
00800   return parallel.States() <= parallel.CoaccessibleSet();
00801 
00802 }
00803 
00804 
00805 
00806 // SelfLoop(rGen,rAlphabet)
00807 void SelfLoop(vGenerator& rGen,const EventSet& rAlphabet) {
00808     
00809   FD_DF("SelfLoop(" << rGen.Name() << "," << rAlphabet.Name() << ")");
00810 
00811   // fix name
00812   std::string name = CollapsString("SelfLoop(" + rGen.Name() + "," + rAlphabet.Name() + ")");
00813   // extend alphabet of rGen
00814   rGen.InjectAlphabet(rGen.Alphabet()+rAlphabet);
00815     
00816   //helpers
00817   EventSet::Iterator evit,evbegin,evend;
00818   evbegin = rAlphabet.Begin();
00819   evend = rAlphabet.End();  
00820   StateSet::Iterator sit;
00821     
00822   // iterate over all states and insert selfloop for each event of rAlphabet
00823   for (sit = rGen.StatesBegin(); sit != rGen.StatesEnd(); ++sit) {
00824     for(evit = evbegin; evit != evend; ++evit){
00825       rGen.SetTransition(*sit, *evit, *sit);
00826     }
00827   }
00828     
00829   // set name
00830   rGen.Name(name);
00831 }
00832 
00833 // SelfLoopMarkedStates(rGen,rAlphabet)
00834 void SelfLoopMarkedStates(vGenerator& rGen,const EventSet& rAlphabet) {
00835     
00836   FD_DF("SelfLoopMarkedStates(" << rGen.Name() << "," << rAlphabet.Name() << ")");
00837 
00838   // fix name
00839   std::string name = CollapsString("SelfLoopMarkedStates(" + rGen.Name() 
00840      + "," + rAlphabet.Name() + ")");
00841 
00842   // extend alphabet of rGen
00843   rGen.InjectAlphabet(rGen.Alphabet()+rAlphabet);
00844     
00845   //helpers
00846   EventSet::Iterator evit,evbegin,evend;
00847   evbegin = rAlphabet.Begin();
00848   evend = rAlphabet.End();  
00849   StateSet::Iterator sit;
00850     
00851   // iterate over all marked states and insert selfloop for each event of rAlphabet
00852   for (sit = rGen.MarkedStatesBegin(); sit != rGen.MarkedStatesEnd(); ++sit) {
00853     for(evit = evbegin; evit != evend; ++evit){
00854       rGen.SetTransition(*sit, *evit, *sit);
00855     }
00856   }
00857     
00858   // set name
00859   rGen.Name(name);
00860 }
00861 
00862 // SelfLoop(rGen,rAlphabet,rStates)
00863 void SelfLoop(vGenerator& rGen,const EventSet& rAlphabet,const StateSet& rStates) {
00864     
00865   FD_DF("SelfLoop(" << rGen.Name() << "," << rAlphabet.Name() << "," << rStates.Name() << ")");
00866 
00867   // fix name
00868   std::string name = CollapsString("SelfLoop(" + rGen.Name() 
00869      + "," + rAlphabet.Name() + "," + rStates.Name() + ")");
00870 
00871   // exception: rStates must be states of rGen
00872 #ifdef FAUDES_CHECKED
00873   if( !(rStates <= rGen.States()) ){
00874     std::stringstream errstr;
00875     errstr << "State set " << rStates.Name() << 
00876       " has to be included in state set of "<< rGen.Name() << ".";
00877     throw Exception("SelfLoop()", errstr.str(), 100);
00878   }
00879 #endif
00880     
00881   // extend alphabet of rGen
00882   rGen.InjectAlphabet(rGen.Alphabet()+rAlphabet);
00883     
00884   //helpers
00885   EventSet::Iterator evit,evbegin,evend;
00886   evbegin = rAlphabet.Begin();
00887   evend = rAlphabet.End();    
00888   StateSet::Iterator sit;
00889     
00890   // iterate over all marked states and insert selfloop for each event of rAlphabet
00891   for (sit = rStates.Begin(); sit != rStates.End(); ++sit) {
00892     for(evit = evbegin; evit != evend; ++evit){
00893       rGen.SetTransition(*sit, *evit, *sit);
00894     }
00895   }
00896     
00897   // set name
00898   rGen.Name(name);
00899 }
00900 
00901 
00902 } // namespace faudes
00903 
00904 #undef Product //see define above for comment

libFAUDES 2.16b --- 2010-9-8 --- c++ source docu by doxygen 1.6.3