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