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