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