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