|
libFAUDES
Sections
Index
|
cfl_parallel.cppGo to the documentation of this file.00001 /** @file cfl_parallel.cpp parallel composition */ 00002 00003 /* FAU Discrete Event Systems Library (libfaudes) 00004 00005 Copyright (C) 2006 Bernd Opitz 00006 Exclusive copyright is granted to Klaus Schmidt 00007 00008 This library is free software; you can redistribute it and/or 00009 modify it under the terms of the GNU Lesser General Public 00010 License as published by the Free Software Foundation; either 00011 version 2.1 of the License, or (at your option) any later version. 00012 00013 This library is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 Lesser General Public License for more details. 00017 00018 You should have received a copy of the GNU Lesser General Public 00019 License along with this library; if not, write to the Free Software 00020 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 00021 00022 00023 #include "cfl_parallel.h" 00024 00025 namespace faudes { 00026 00027 // Parallel(rGen1, rGen2, res) 00028 void Parallel(const vGenerator& rGen1, const vGenerator& rGen2, vGenerator& rResGen) { 00029 // helpers: 00030 std::map< std::pair<Idx,Idx>, Idx> rcmap; 00031 // prepare result 00032 vGenerator* pResGen = &rResGen; 00033 if(&rResGen== &rGen1 || &rResGen== &rGen2) { 00034 pResGen= rResGen.New(); 00035 } 00036 // doit 00037 Parallel(rGen1, rGen2, rcmap, *pResGen); 00038 // set statenames 00039 if (rGen1.StateNamesEnabled() && rGen2.StateNamesEnabled() && rResGen.StateNamesEnabled()) 00040 SetComposedStateNames(rGen1, rGen2, rcmap, *pResGen); 00041 else 00042 pResGen->ClearStateNames(); 00043 // copy result 00044 if(pResGen != &rResGen) { 00045 rResGen = *pResGen; 00046 delete pResGen; 00047 } 00048 } 00049 00050 00051 // Parallel for vGenerators, transparent for event attributes. 00052 void aParallel( 00053 const vGenerator& rGen1, 00054 const vGenerator& rGen2, 00055 vGenerator& rResGen) 00056 { 00057 00058 // inputs have to agree on attributes of shared events: 00059 bool careattr=rGen1.Alphabet().EqualAttributes(rGen2.Alphabet()); 00060 00061 // prepare result 00062 vGenerator* pResGen = &rResGen; 00063 if(&rResGen== &rGen1 || &rResGen== &rGen2) { 00064 pResGen= rResGen.New(); 00065 } 00066 00067 // make product composition of inputs 00068 Parallel(rGen1,rGen2,*pResGen); 00069 00070 // copy all attributes of input alphabets 00071 if(careattr) { 00072 pResGen->EventAttributes(rGen1.Alphabet()); 00073 pResGen->EventAttributes(rGen2.Alphabet()); 00074 } 00075 00076 // copy result 00077 if(pResGen != &rResGen) { 00078 pResGen->Move(rResGen); 00079 delete pResGen; 00080 } 00081 00082 } 00083 00084 00085 // Parallel for multiple vGenerators, transparent for event attributes. 00086 void aParallel( 00087 const GeneratorVector& rGenVec, 00088 vGenerator& rResGen) 00089 { 00090 00091 // inputs have to agree on attributes of pairwise shared events: 00092 bool careattr=true; 00093 for(GeneratorVector::Position i=0; i<rGenVec.Size(); i++) 00094 for(GeneratorVector::Position j=0; j<i; j++) 00095 if(!rGenVec.At(i).Alphabet().EqualAttributes(rGenVec.At(j).Alphabet())) 00096 careattr=false; 00097 00098 // ignore empty 00099 if(rGenVec.Size()==0) { 00100 return; 00101 } 00102 00103 // copy first 00104 rResGen=rGenVec.At(0); 00105 00106 // run parallel on others 00107 for(GeneratorVector::Position i=1; i<rGenVec.Size(); i++) 00108 Parallel(rGenVec.At(i),rResGen,rResGen); 00109 00110 // fix alphabet 00111 if(careattr) { 00112 for(GeneratorVector::Position i=0; i<rGenVec.Size(); i++) 00113 rResGen.EventAttributes(rGenVec.At(i).Alphabet()); 00114 } 00115 00116 } 00117 00118 00119 // Parallel(rGen1, rGen2, rReverseCompositionMap, mark1, mark2, res) 00120 void Parallel( 00121 const vGenerator& rGen1, const vGenerator& rGen2, 00122 std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, 00123 StateSet& rMark1, 00124 StateSet& rMark2, 00125 vGenerator& rResGen) 00126 { 00127 00128 // do the composition 00129 Parallel(rGen1,rGen2,rReverseCompositionMap,rResGen); 00130 00131 // clear marking 00132 rMark1.Clear(); 00133 rMark2.Clear(); 00134 00135 // catch special cases: a 00136 if(rGen1.AlphabetSize()==0) { 00137 rMark2=rGen2.MarkedStates(); 00138 return; 00139 } 00140 00141 // catch special cases: b 00142 if(rGen2.AlphabetSize()==0) { 00143 rMark1=rGen1.MarkedStates(); 00144 return; 00145 } 00146 00147 // retrieve marking from reverse composition map 00148 std::map< std::pair<Idx,Idx>, Idx>::iterator rit; 00149 for(rit=rReverseCompositionMap.begin(); rit!=rReverseCompositionMap.end(); ++rit){ 00150 if(rGen1.ExistsMarkedState(rit->first.first)) rMark1.Insert(rit->second); 00151 if(rGen2.ExistsMarkedState(rit->first.second)) rMark2.Insert(rit->second); 00152 } 00153 } 00154 00155 00156 // Parallel(rGen1, rGen2, rReverseCompositionMap, mark1, mark2, res) 00157 void Parallel( 00158 const vGenerator& rGen1, const vGenerator& rGen2, 00159 std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, 00160 vGenerator& rResGen) 00161 { 00162 FD_DF("Parallel(" << &rGen1 << "," << &rGen2 << ")"); 00163 00164 // special case: empty alphabet 00165 if(rGen1.AlphabetSize()==0) { 00166 rResGen=rGen2; 00167 rResGen.Name(rGen2.Name()); 00168 return; 00169 } 00170 00171 // special case: empty alphabet 00172 if(rGen2.AlphabetSize()==0) { 00173 rResGen=rGen1; 00174 rResGen.Name(rGen1.Name()); 00175 return; 00176 } 00177 00178 // prepare result 00179 vGenerator* pResGen = &rResGen; 00180 if(&rResGen== &rGen1 || &rResGen== &rGen2) { 00181 pResGen= rResGen.New(); 00182 } 00183 pResGen->Clear(); 00184 pResGen->Name(CollapsString(rGen1.Name()+"||"+rGen2.Name())); 00185 00186 // create res alphabet 00187 EventSet::Iterator eit; 00188 for (eit = rGen1.AlphabetBegin(); eit != rGen1.AlphabetEnd(); ++eit) { 00189 pResGen->InsEvent(*eit); 00190 } 00191 for (eit = rGen2.AlphabetBegin(); eit != rGen2.AlphabetEnd(); ++eit) { 00192 pResGen->InsEvent(*eit); 00193 } 00194 FD_DF("Parallel: inserted indices in rResGen.alphabet( " 00195 << pResGen->AlphabetToString() << ")"); 00196 00197 // shared events 00198 EventSet sharedalphabet = rGen1.Alphabet() * rGen2.Alphabet(); 00199 FD_DF("Parallel: shared events: " << sharedalphabet.ToString()); 00200 00201 // todo stack 00202 std::stack< std::pair<Idx,Idx> > todo; 00203 // current pair, new pair 00204 std::pair<Idx,Idx> currentstates, newstates; 00205 // state 00206 Idx tmpstate; 00207 StateSet::Iterator lit1, lit2; 00208 TransSet::Iterator tit1, tit1_end, tit2, tit2_end; 00209 std::map< std::pair<Idx,Idx>, Idx>::iterator rcit; 00210 00211 // push all combinations of initial states on todo stack 00212 FD_DF("Parallel: adding all combinations of initial states to todo:"); 00213 for (lit1 = rGen1.InitStatesBegin(); lit1 != rGen1.InitStatesEnd(); ++lit1) { 00214 for (lit2 = rGen2.InitStatesBegin(); lit2 != rGen2.InitStatesEnd(); ++lit2) { 00215 currentstates = std::make_pair(*lit1, *lit2); 00216 todo.push(currentstates); 00217 tmpstate = pResGen->InsInitState(); 00218 rReverseCompositionMap[currentstates] = tmpstate; 00219 FD_DF("Parallel: (" << *lit1 << "|" << *lit2 << ") -> " 00220 << rReverseCompositionMap[currentstates]); 00221 } 00222 } 00223 00224 // start algorithm 00225 FD_DF("Parallel: processing reachable states:"); 00226 while (! todo.empty()) { 00227 // allow for user interrupt 00228 LoopCallback(); 00229 // get next reachable state from todo stack 00230 currentstates = todo.top(); 00231 todo.pop(); 00232 FD_DF("Parallel: processing (" << currentstates.first << "|" 00233 << currentstates.second << ") -> " 00234 << rReverseCompositionMap[currentstates]); 00235 // iterate over all rGen1 transitions 00236 // (includes execution of shared events) 00237 tit1 = rGen1.TransRelBegin(currentstates.first); 00238 tit1_end = rGen1.TransRelEnd(currentstates.first); 00239 for (; tit1 != tit1_end; ++tit1) { 00240 // if event not shared 00241 if (! sharedalphabet.Exists(tit1->Ev)) { 00242 FD_DF("Parallel: exists only in rGen1"); 00243 newstates = std::make_pair(tit1->X2, currentstates.second); 00244 // add to todo list if composition state is new 00245 rcit = rReverseCompositionMap.find(newstates); 00246 if (rcit == rReverseCompositionMap.end()) { 00247 todo.push(newstates); 00248 tmpstate = pResGen->InsState(); 00249 rReverseCompositionMap[newstates] = tmpstate; 00250 FD_DF("Parallel: todo push: (" << newstates.first << "|" 00251 << newstates.second << ") -> " 00252 << rReverseCompositionMap[newstates]); 00253 } 00254 else { 00255 tmpstate = rcit->second; 00256 } 00257 pResGen->SetTransition(rReverseCompositionMap[currentstates], tit1->Ev, 00258 tmpstate); 00259 FD_DF("Parallel: add transition to new generator: " 00260 << rReverseCompositionMap[currentstates] << "-" << tit1->Ev << "-" 00261 << tmpstate); 00262 } 00263 // if shared event 00264 else { 00265 FD_DF("Parallel: common event"); 00266 // find shared transitions 00267 tit2 = rGen2.TransRelBegin(currentstates.second, tit1->Ev); 00268 tit2_end = rGen2.TransRelEnd(currentstates.second, tit1->Ev); 00269 for (; tit2 != tit2_end; ++tit2) { 00270 newstates = std::make_pair(tit1->X2, tit2->X2); 00271 // add to todo list if composition state is new 00272 rcit = rReverseCompositionMap.find(newstates); 00273 if (rcit == rReverseCompositionMap.end()) { 00274 todo.push(newstates); 00275 tmpstate = pResGen->InsState(); 00276 rReverseCompositionMap[newstates] = tmpstate; 00277 FD_DF("Parallel: todo push: (" << newstates.first << "|" 00278 << newstates.second << ") -> " 00279 << rReverseCompositionMap[newstates]); 00280 } 00281 else { 00282 tmpstate = rcit->second; 00283 } 00284 pResGen->SetTransition(rReverseCompositionMap[currentstates], 00285 tit1->Ev, tmpstate); 00286 FD_DF("Parallel: add transition to new generator: " 00287 << rReverseCompositionMap[currentstates] << "-" 00288 << tit1->Ev << "-" << tmpstate); 00289 } 00290 } 00291 } 00292 // iterate over all rGen2 transitions 00293 // (without execution of shared events) 00294 tit2 = rGen2.TransRelBegin(currentstates.second); 00295 tit2_end = rGen2.TransRelEnd(currentstates.second); 00296 for (; tit2 != tit2_end; ++tit2) { 00297 if (! sharedalphabet.Exists(tit2->Ev)) { 00298 FD_DF("Parallel: exists only in rGen2"); 00299 newstates = std::make_pair(currentstates.first, tit2->X2); 00300 // add to todo list if composition state is new 00301 rcit = rReverseCompositionMap.find(newstates); 00302 if (rcit == rReverseCompositionMap.end()) { 00303 todo.push(newstates); 00304 tmpstate = pResGen->InsState(); 00305 rReverseCompositionMap[newstates] = tmpstate; 00306 FD_DF("Parallel: todo push: (" << newstates.first << "|" 00307 << newstates.second << ") -> " 00308 << rReverseCompositionMap[newstates]); 00309 } 00310 else { 00311 tmpstate = rcit->second; 00312 } 00313 pResGen->SetTransition(rReverseCompositionMap[currentstates], 00314 tit2->Ev, tmpstate); 00315 FD_DF("Parallel: add transition to new generator: " 00316 << rReverseCompositionMap[currentstates] << "-" 00317 << tit2->Ev << "-" << tmpstate); 00318 } 00319 } 00320 } 00321 00322 // set marked states 00323 for (lit1 = rGen1.MarkedStatesBegin(); 00324 lit1 != rGen1.MarkedStatesEnd(); ++lit1) { 00325 for (lit2 = rGen2.MarkedStatesBegin(); 00326 lit2 != rGen2.MarkedStatesEnd(); ++lit2) { 00327 currentstates = std::make_pair(*lit1, *lit2); 00328 rcit = rReverseCompositionMap.find(currentstates); 00329 if (rcit != rReverseCompositionMap.end()) { 00330 pResGen->SetMarkedState(rcit->second); 00331 } 00332 } 00333 } 00334 FD_DF("Parallel: set marked states at the end: " 00335 << pResGen->MarkedStatesToString()); 00336 // copy result 00337 if(pResGen != &rResGen) { 00338 rResGen = *pResGen; 00339 delete pResGen; 00340 } 00341 } 00342 00343 00344 // Product(rGen1, rGen2, res) 00345 void Product(const vGenerator& rGen1, const vGenerator& rGen2, vGenerator& rResGen) { 00346 std::map< std::pair<Idx,Idx>, Idx> rcmap; 00347 // doit 00348 Product(rGen1, rGen2, rcmap, rResGen); 00349 // set statenames 00350 if (rGen1.StateNamesEnabled() && rGen2.StateNamesEnabled() && rResGen.StateNamesEnabled()) 00351 SetComposedStateNames(rGen1, rGen2, rcmap, rResGen); 00352 else 00353 rResGen.ClearStateNames(); 00354 } 00355 00356 00357 // Product for vGenerators, transparent for event attributes. 00358 void aProduct( 00359 const vGenerator& rGen1, 00360 const vGenerator& rGen2, 00361 vGenerator& rResGen) 00362 { 00363 00364 // inputs have to agree on attributes of shared events: 00365 bool careattr=rGen1.Alphabet().EqualAttributes(rGen2.Alphabet()); 00366 00367 // prepare result 00368 vGenerator* pResGen = &rResGen; 00369 if(&rResGen== &rGen1 || &rResGen== &rGen2) { 00370 pResGen= rResGen.New(); 00371 } 00372 00373 // make product composition of inputs 00374 Product(rGen1,rGen2,*pResGen); 00375 00376 // copy all attributes of input alphabets 00377 if(careattr) { 00378 pResGen->EventAttributes(rGen1.Alphabet()); 00379 pResGen->EventAttributes(rGen2.Alphabet()); 00380 } 00381 00382 // copy result 00383 if(pResGen != &rResGen) { 00384 pResGen->Move(rResGen); 00385 delete pResGen; 00386 } 00387 00388 } 00389 00390 00391 // Product(rGen1, rGen2, rReverseCompositionMap, mark1, mark2, res) 00392 void Product( 00393 const vGenerator& rGen1, const vGenerator& rGen2, 00394 std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, 00395 StateSet& rMark1, 00396 StateSet& rMark2, 00397 vGenerator& rResGen) 00398 { 00399 00400 // do the composition 00401 Product(rGen1,rGen2,rReverseCompositionMap,rResGen); 00402 00403 // clear marking 00404 rMark1.Clear(); 00405 rMark2.Clear(); 00406 00407 // retrieve marking from reverse composition map 00408 std::map< std::pair<Idx,Idx>, Idx>::iterator rit; 00409 for(rit=rReverseCompositionMap.begin(); rit!=rReverseCompositionMap.end(); ++rit){ 00410 if(rGen1.ExistsMarkedState(rit->first.first)) rMark1.Insert(rit->second); 00411 if(rGen2.ExistsMarkedState(rit->first.second)) rMark2.Insert(rit->second); 00412 } 00413 } 00414 00415 00416 // Product(rGen1, rGen2, rReverseCompositionMap, res) 00417 void Product( 00418 const vGenerator& rGen1, const vGenerator& rGen2, 00419 std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, 00420 vGenerator& rResGen) 00421 { 00422 FD_DF("Product(" << &rGen1 << "," << &rGen2 << ")"); 00423 00424 // prepare result 00425 vGenerator* pResGen = &rResGen; 00426 if(&rResGen== &rGen1 || &rResGen== &rGen2) { 00427 pResGen= rResGen.New(); 00428 } 00429 pResGen->Clear(); 00430 00431 // shared alphabet 00432 pResGen->InjectAlphabet(rGen1.Alphabet() * rGen2.Alphabet()); 00433 FD_DF("Product: shared alphabet: " 00434 << (rGen1.Alphabet() * rGen2.Alphabet()).ToString()); 00435 00436 // todo stack 00437 std::stack< std::pair<Idx,Idx> > todo; 00438 // current pair, new pair 00439 std::pair<Idx,Idx> currentstates, newstates; 00440 // state 00441 Idx tmpstate; 00442 00443 StateSet::Iterator lit1, lit2; 00444 TransSet::Iterator tit1, tit1_end, tit2, tit2_end; 00445 std::map< std::pair<Idx,Idx>, Idx>::iterator rcit; 00446 00447 // push all combinations of initial states on todo stack 00448 FD_DF("Product: adding all combinations of initial states to todo:"); 00449 for (lit1 = rGen1.InitStatesBegin(); 00450 lit1 != rGen1.InitStatesEnd(); ++lit1) { 00451 for (lit2 = rGen2.InitStatesBegin(); 00452 lit2 != rGen2.InitStatesEnd(); ++lit2) { 00453 currentstates = std::make_pair(*lit1, *lit2); 00454 todo.push(currentstates); 00455 rReverseCompositionMap[currentstates] = pResGen->InsInitState(); 00456 FD_DF("Product: (" << *lit1 << "|" << *lit2 << ") -> " 00457 << rReverseCompositionMap[currentstates]); 00458 } 00459 } 00460 00461 // start algorithm 00462 FD_DF("Product: processing reachable states:"); 00463 while (! todo.empty()) { 00464 // allow for user interrupt 00465 LoopCallback(); 00466 // get next reachable state from todo stack 00467 currentstates = todo.top(); 00468 todo.pop(); 00469 FD_DF("Product: processing (" << currentstates.first << "|" 00470 << currentstates.second << ") -> " << rReverseCompositionMap[currentstates]); 00471 // iterate over all rGen1 transitions 00472 tit1 = rGen1.TransRelBegin(currentstates.first); 00473 tit1_end = rGen1.TransRelEnd(currentstates.first); 00474 tit2 = rGen2.TransRelBegin(currentstates.second); 00475 tit2_end = rGen2.TransRelEnd(currentstates.second); 00476 while ((tit1 != tit1_end) && (tit2 != tit2_end)) { 00477 // shared event 00478 if (tit1->Ev == tit2->Ev) { 00479 newstates = std::make_pair(tit1->X2, tit2->X2); 00480 // add to todo list if composition state is new 00481 rcit = rReverseCompositionMap.find(newstates); 00482 if (rcit == rReverseCompositionMap.end()) { 00483 todo.push(newstates); 00484 tmpstate = pResGen->InsState(); 00485 rReverseCompositionMap[newstates] = tmpstate; 00486 FD_DF("Product: todo push: (" << newstates.first << "|" 00487 << newstates.second << ") -> " << rReverseCompositionMap[newstates]); 00488 } 00489 else { 00490 tmpstate = rcit->second; 00491 } 00492 pResGen->SetTransition(rReverseCompositionMap[currentstates], tit1->Ev, tmpstate); 00493 FD_DF("Product: add transition to new generator: " 00494 << rReverseCompositionMap[currentstates] << "-" << tit1->Ev << "-" << tmpstate); 00495 ++tit1; 00496 ++tit2; 00497 } 00498 // try resync tit1 00499 else if (tit1->Ev < tit2->Ev) { 00500 ++tit1; 00501 } 00502 // try resync tit2 00503 else if (tit1->Ev > tit2->Ev) { 00504 ++tit2; 00505 } 00506 } 00507 } 00508 00509 // set marked states 00510 for (lit1 = rGen1.MarkedStatesBegin(); 00511 lit1 != rGen1.MarkedStatesEnd(); ++lit1) { 00512 for (lit2 = rGen2.MarkedStatesBegin(); 00513 lit2 != rGen2.MarkedStatesEnd(); ++lit2) { 00514 currentstates = std::make_pair(*lit1, *lit2); 00515 rcit = rReverseCompositionMap.find(currentstates); 00516 if (rcit != rReverseCompositionMap.end()) { 00517 pResGen->SetMarkedState(rcit->second); 00518 } 00519 } 00520 } 00521 FD_DF("Product: set marked states at the end: " 00522 << pResGen->MarkedStatesToString()); 00523 00524 00525 // copy result (TODO: use move) 00526 if(pResGen != &rResGen) { 00527 rResGen = *pResGen; 00528 delete pResGen; 00529 } 00530 } 00531 00532 00533 // SetParallelStateNames 00534 void SetComposedStateNames( 00535 const vGenerator& rGen1, const vGenerator& rGen2, 00536 const std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, 00537 vGenerator& rGen12) 00538 { 00539 std::map< std::pair<Idx,Idx>, Idx>::const_iterator rcit; 00540 for(rcit=rReverseCompositionMap.begin(); rcit!=rReverseCompositionMap.end(); rcit++) { 00541 Idx x1=rcit->first.first; 00542 Idx x2=rcit->first.second; 00543 Idx x12=rcit->second; 00544 if(!rGen12.ExistsState(x12)) continue; 00545 std::string name1= rGen1.StateName(x1); 00546 if(name1=="") name1=ToStringInteger(x1); 00547 std::string name2= rGen2.StateName(x2); 00548 if(name2=="") name2=ToStringInteger(x2); 00549 std::string name12= name1 + "|" + name2; 00550 name12=rGen12.UniqueStateName(name12); 00551 rGen12.StateName(x12,name12); 00552 } 00553 } 00554 00555 00556 // CompositionMap1 00557 void CompositionMap1( 00558 const std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, 00559 std::map<Idx,Idx>& rCompositionMap) 00560 { 00561 rCompositionMap.clear(); 00562 std::map< std::pair<Idx,Idx>, Idx>::const_iterator rcit; 00563 for(rcit=rReverseCompositionMap.begin(); rcit!=rReverseCompositionMap.end(); rcit++) 00564 rCompositionMap.insert(std::pair<Idx,Idx>(rcit->second,rcit->first.first)); 00565 } 00566 00567 00568 // CompositionMap2 00569 void CompositionMap2( 00570 const std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, 00571 std::map<Idx,Idx>& rCompositionMap) 00572 { 00573 rCompositionMap.clear(); 00574 std::map< std::pair<Idx,Idx>, Idx>::const_iterator rcit; 00575 for(rcit=rReverseCompositionMap.begin(); rcit!=rReverseCompositionMap.end(); rcit++) 00576 rCompositionMap.insert(std::pair<Idx,Idx>(rcit->second,rcit->first.second)); 00577 } 00578 00579 00580 } // name space |
libFAUDES 2.16b --- 2010-9-8 --- c++ source docu by doxygen 1.6.3