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