|
libFAUDES
Sections
Index
|
cfl_regular.cppGo 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