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