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