libFAUDES
Sections
Index
|
cfl_project.cppGo to the documentation of this file.00001 /** @file cfl_project.cpp projection and subset construction */ 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_project.h" 00024 00025 namespace faudes { 00026 00027 // UniqueInit(rGen&) 00028 void UniqueInit(Generator& rGen) { 00029 Idx inituni; 00030 StateSet::Iterator lit; 00031 TransSet::Iterator tit; 00032 // check number of initial states 00033 if(rGen.InitStatesSize() == 1) return; 00034 // introduce new initial state 00035 if(rGen.StateNamesEnabled()) { 00036 std::string initname=rGen.UniqueStateName("InitUni"); 00037 inituni = rGen.InsState(initname); 00038 } else { 00039 inituni = rGen.InsState(); 00040 } 00041 FD_DF("UniqueInit: introducing new initial state: " << inituni); 00042 // introduce outgoing transitions from initial state 00043 FD_DF("UniqueInit: introduce outgoing transitions: "); 00044 for (lit = rGen.InitStatesBegin(); lit != rGen.InitStatesEnd(); ++lit) { 00045 for (tit = rGen.TransRelBegin(*lit); tit != rGen.TransRelEnd(*lit); ++tit) { 00046 rGen.SetTransition(inituni, tit->Ev, tit->X2); 00047 FD_DF("UniqueInit: " << inituni << "-" << tit->Ev << "-" << tit->X2); 00048 } 00049 } 00050 // mark the new init state if there exists an originally marked init state (tm 20101206) 00051 if(!(rGen.InitStates() * rGen.MarkedStates()).Empty()){ 00052 rGen.SetMarkedState(inituni); 00053 FD_DF("UniqueInit: set marked state: " << inituni); 00054 } 00055 // delete old istates 00056 rGen.ClearInitStates(); 00057 // set inituni as new initial state 00058 rGen.SetInitState(inituni); 00059 } 00060 00061 // UniqueInit(rGen&,rResGen&) 00062 void UniqueInit(const Generator& rGen, Generator& rResGen) { 00063 rResGen.Assign(rGen); 00064 UniqueInit(rResGen); 00065 } 00066 00067 // Deterministic(rGen&, rResGen&) 00068 void Deterministic(const Generator& rGen, Generator& rResGen) { 00069 // temporary vectors 00070 std::vector<StateSet> power_states; 00071 std::vector<Idx> det_states; 00072 Deterministic(rGen, power_states, det_states, rResGen); 00073 } 00074 00075 00076 // aDeterministic(rGen&, rResGen&) 00077 void aDeterministic(const Generator& rGen, Generator& rResGen) { 00078 // prepare result to keep original alphabet 00079 Generator* pResGen = &rResGen; 00080 if(&rResGen==&rGen) { 00081 pResGen= rResGen.New(); 00082 } 00083 // perform op 00084 Deterministic(rGen,*pResGen); 00085 // set old attributes 00086 pResGen->EventAttributes(rGen.Alphabet()); 00087 // copy result 00088 if(pResGen != &rResGen) { 00089 pResGen->Move(rResGen); 00090 delete pResGen; 00091 } 00092 } 00093 00094 00095 // Deterministic(rGen&, rEntryStatesMap&, rResGen&) 00096 void Deterministic(const Generator& rGen, std::map<Idx,StateSet>& rEntryStatesMap, 00097 Generator& rResGen) { 00098 // prepare result: 00099 rEntryStatesMap.clear(); 00100 // helpers: 00101 std::vector<StateSet> power_states; 00102 std::vector<Idx> det_states; 00103 // call Deterministic function 00104 Deterministic(rGen, power_states, det_states, rResGen); 00105 // build entry states map 00106 std::vector<StateSet>::size_type i; 00107 for (i = 0; i < power_states.size(); ++i) { 00108 rEntryStatesMap.insert(std::pair<Idx,StateSet>(det_states[i], power_states[i])); 00109 } 00110 } 00111 00112 00113 void Deterministic(const Generator& rGen, std::vector<StateSet>& rPowerStates, 00114 std::vector<Idx>& rDetStates, Generator& rResGen) { 00115 // FIXME: implement the hashtable as a map<Idx, list< vector<int>::size_type > > 00116 // or something like that 00117 00118 // note: there is a demonstrative description of the multiway merge 00119 // algorithm in the master thesis. (Bernd Opitz) 00120 00121 FD_DF("Deterministic(): core function #" << rGen.Size()); 00122 00123 // use pointer pResGen to result rResGen 00124 Generator* pResGen = &rResGen; 00125 if(&rResGen== &rGen) { 00126 pResGen= rResGen.New(); 00127 } 00128 00129 // prepare result 00130 pResGen->Clear(); 00131 rPowerStates.clear(); 00132 rDetStates.clear(); 00133 // set the name 00134 pResGen->Name(CollapsString("Det(" + rGen.Name() + ")")); 00135 // copy alphabet 00136 FD_DF("Deterministic A " << rGen.Alphabet().ToString()); 00137 pResGen->InjectAlphabet(rGen.Alphabet()); 00138 FD_DF("Deterministic B"); 00139 00140 // helpers 00141 TransSetEvX1X2 trel_evx1x2; 00142 rGen.TransRel(trel_evx1x2); 00143 typedef std::multimap< Idx,std::vector<StateSet>::size_type > T_HASHMAP; 00144 T_HASHMAP hashmap; 00145 std::vector<StateSet>::size_type current_vecindex; 00146 std::pair< std::map<StateSet,Idx>::iterator,bool > result; 00147 TransSet::Iterator transrel_end = rGen.TransRelEnd(); 00148 StateSet newset; 00149 StateSet::Iterator lit; 00150 const Idx max_idx = std::numeric_limits<Idx>::max(); 00151 00152 // bail out on empty input 00153 if(rGen.InitStatesEmpty()) { 00154 if(pResGen != &rResGen) { 00155 pResGen->Move(rResGen); 00156 delete pResGen; 00157 } 00158 FD_DF("Deterministic(): done (empty)"); 00159 return; 00160 } 00161 00162 Idx newstate = pResGen->InsInitState(); 00163 // initialize rPowerStates with subset of initial states 00164 for (lit = rGen.InitStatesBegin(); lit != rGen.InitStatesEnd(); ++lit) { 00165 // clear set and insert single state 00166 newset.Insert(*lit); 00167 // if marked state set in res generator 00168 if (rGen.ExistsMarkedState(*lit)) { 00169 pResGen->SetMarkedState(newstate); 00170 FD_DF("Deterministic: setting as mstate: " << rGen.SStr(newstate)); 00171 } 00172 } 00173 FD_DF("Deterministic: created subset of initial states {" 00174 << newset.ToString() << "} with deterministic state index " 00175 << rGen.SStr(newstate)); 00176 // insert newset in rPowerStates 00177 rPowerStates.push_back(newset); 00178 rDetStates.push_back(newstate); 00179 hashmap.insert(std::make_pair(newset.Signature(), (Idx)rPowerStates.size() - 1)); 00180 00181 // iteration over all states 00182 for (current_vecindex = 0; current_vecindex < rPowerStates.size(); 00183 ++current_vecindex) { 00184 FD_WPC(current_vecindex,rPowerStates.size(), "Deterministic(): current/size: "<< current_vecindex << " / " << rPowerStates.size()); 00185 FD_DF("Deterministic: current power set: {" 00186 << rPowerStates[current_vecindex].ToString() << "} -> " 00187 << rDetStates[current_vecindex]); 00188 00189 std::vector<StateSet> newset_vec; 00190 std::vector<Idx> event_vec; 00191 00192 // multiway merge begin 00193 FD_DF("Deterministic: starting multiway merge..."); 00194 std::list<TransSet::Iterator> merge_iterators; 00195 std::vector<Transition> trans_vec; 00196 00197 // add transset iterator at begin of each state's transitions 00198 TransSet::Iterator tit; 00199 for (lit = rPowerStates[current_vecindex].Begin(); 00200 lit != rPowerStates[current_vecindex].End(); ++lit) { 00201 tit = rGen.TransRelBegin(*lit); 00202 if (tit != rGen.TransRelEnd(*lit)) { 00203 merge_iterators.push_back(tit); 00204 FD_DF("Deterministic: added merge iterator: " << rGen.SStr(tit->X1) 00205 << "-" << rGen.EStr(tit->Ev) << "-" << rGen.SStr(tit->X2)); 00206 } 00207 } 00208 00209 // find first iterator with lowest event 00210 while (! merge_iterators.empty()) { 00211 Idx currentevent = max_idx; 00212 std::list<TransSet::Iterator>::iterator i; 00213 std::list<TransSet::Iterator>::iterator currentit = merge_iterators.end(); 00214 for (i = merge_iterators.begin(); i != merge_iterators.end(); ++i) { 00215 if ((*i)->Ev < currentevent) { 00216 currentevent = (*i)->Ev; 00217 currentit = i; 00218 } 00219 } 00220 // currentit now holds the iterator 00221 // currentevent holds the lowest event (lowest Idx) 00222 00223 // merge all transitions with currentevent at each iterator in a row 00224 // this is a modification of multiway merge as after projection the 00225 // automaton most likely holds states with many transitions that share 00226 // the same event. only merging the lowest transition and continue with 00227 // search for the lowest event again would be to slow here (because 00228 // of too much iterator dereferencing). 00229 Idx currentstate; 00230 while (currentit != merge_iterators.end()) { 00231 currentstate = (*currentit)->X1; 00232 TransSet::Iterator& j = *currentit; 00233 while (1) { 00234 // remove iterator if it reaches the end of the transition set 00235 if (j == transrel_end) { 00236 std::list<TransSet::Iterator>::iterator tmpit = currentit; 00237 ++currentit; 00238 merge_iterators.erase(tmpit); 00239 break; 00240 } 00241 // if current iterator is in its original state 00242 else if (j->X1 == currentstate) { 00243 // if the event is still the same add the transition 00244 if (j->Ev == currentevent) { 00245 trans_vec.push_back(*j); 00246 FD_DF("Deterine: adding transition to list: " 00247 << rGen.SStr(j->X1) << "-" << rGen.EStr(j->Ev) << "-" 00248 << rGen.SStr(j->X2)); 00249 } 00250 // else go to next iterator 00251 else { 00252 ++currentit; 00253 break; 00254 } 00255 } 00256 // if the iterator is beyond its original state remove it 00257 else { 00258 std::list<TransSet::Iterator>::iterator tmpit = currentit; 00259 ++currentit; 00260 merge_iterators.erase(tmpit); 00261 break; 00262 } 00263 ++j; 00264 } 00265 } 00266 } 00267 00268 // partition transition vector by events. optimizable? 00269 FD_DF("Deterministic: partitioning the transition vector..."); 00270 std::vector<Transition>::iterator tv_it; 00271 StateSet newset; 00272 Idx lastevent = 0; 00273 for (tv_it = trans_vec.begin(); tv_it != trans_vec.end(); ++tv_it) { 00274 if ((tv_it->Ev == lastevent) || (lastevent == 0)) { 00275 newset.Insert(tv_it->X2); 00276 lastevent = tv_it->Ev; 00277 } 00278 else { 00279 FD_DF("Deterministic: partition: {" << newset.ToString() 00280 << "} with event " << rGen.EStr(lastevent)); 00281 newset_vec.push_back(newset); 00282 event_vec.push_back(lastevent); 00283 newset.Clear(); 00284 newset.Insert(tv_it->X2); 00285 lastevent = tv_it->Ev; 00286 } 00287 } 00288 if (! newset.Empty()) { 00289 FD_DF("Deterministic: partition: {" << newset.ToString() 00290 << "} with event " << rGen.EStr(lastevent)); 00291 newset_vec.push_back(newset); 00292 event_vec.push_back(lastevent); 00293 } 00294 FD_DF("Deterministic: partitioning the transition vector finished"); 00295 FD_DF("Deterministic: multiway merge finished"); 00296 // multiway merge end 00297 00298 std::vector<StateSet>::size_type nsv_index; 00299 for (nsv_index = 0; nsv_index < newset_vec.size(); ++nsv_index) { 00300 StateSet& currentset = newset_vec[nsv_index]; 00301 Idx currentevent = event_vec[nsv_index]; 00302 Idx tmp_x2 = 0; 00303 Idx sig = currentset.Signature(); 00304 // test if newset signature is already known 00305 std::pair<T_HASHMAP::iterator,T_HASHMAP::iterator> phit 00306 = hashmap.equal_range(sig); 00307 T_HASHMAP::iterator hit = phit.first; 00308 for (hit = phit.first; hit != phit.second; ++hit) { 00309 // test set of every matching signature for equality 00310 if (currentset == rPowerStates[hit->second]) { 00311 tmp_x2 = rDetStates[hit->second]; 00312 break; 00313 } 00314 } 00315 00316 // if new set is unique within the existing power sets 00317 if (tmp_x2 == 0) { 00318 // create new state in res generator 00319 tmp_x2 = pResGen->InsState(); 00320 // insert newset in rPowerStates and get iterator,bool pair 00321 rPowerStates.push_back(currentset); 00322 rDetStates.push_back(tmp_x2); 00323 hashmap.insert(std::make_pair(sig, (Idx)rPowerStates.size() - 1)); 00324 FD_DF("Deterministic: added new state " 00325 << rGen.SStr(tmp_x2) 00326 << " for new subset {" << currentset.ToString() << "}"); 00327 // set marked if one of the states in current set is marked 00328 for (lit = currentset.Begin(); lit != currentset.End(); ++lit) { 00329 if (rGen.ExistsMarkedState(*lit)) { 00330 pResGen->SetMarkedState(tmp_x2); 00331 break; 00332 } 00333 } 00334 } 00335 // introduce transition 00336 pResGen->SetTransition(rDetStates[current_vecindex], currentevent, tmp_x2); 00337 } 00338 } 00339 // fix names 00340 if (rGen.StateNamesEnabled() && pResGen->StateNamesEnabled()) { 00341 FD_DF("Deterministic: fixing names..."); 00342 // rPowerStates / rDetStates index "iterator" 00343 std::vector<StateSet>::size_type i; 00344 // deterministic states iterator 00345 std::vector<Idx>::const_iterator dit; 00346 for (i = 0; i < rPowerStates.size(); ++i) { 00347 // temporary state name 00348 std::string name = "{"; 00349 for (lit = rPowerStates[i].Begin(); lit != rPowerStates[i].End(); ++lit) { 00350 if (rGen.StateName(*lit) != "") name = name + rGen.StateName(*lit) + ","; 00351 else name = name + ToStringInteger(*lit) + ","; 00352 } 00353 name.erase(name.length() - 1); 00354 name = name + "}"; 00355 FD_DF("Deterministic: setting state name \"" << name << "\" for index " 00356 << rDetStates[i]); 00357 pResGen->StateName(rDetStates[i], name); 00358 } 00359 } 00360 00361 // move pResGen to rResGen 00362 if(pResGen != &rResGen) { 00363 pResGen->Move(rResGen); 00364 delete pResGen; 00365 } 00366 00367 FD_DF("Deterministic(): core function: done"); 00368 00369 } 00370 00371 00372 00373 // ProjectNonDet(rGen&, rProjectAlphabet&) 00374 00375 // (version 2009/05, Barthel) 00376 void ProjectNonDet(Generator& rGen, const EventSet& rProjectAlphabet) { 00377 00378 // HELPERS: 00379 00380 StateSet reach, reachext; // StateSet for reachable states 00381 StateSet todo; // states todo 00382 StateSet done; // states done 00383 Idx currentstate; // the currently processed state 00384 StateSet::Iterator lit; 00385 StateSet::Iterator lit2; 00386 TransSet::Iterator tit; 00387 TransSet::Iterator tit_end; 00388 00389 // NAME 00390 std::string name=CollapsString("ProjectNonDet(" + rGen.Name() + ")"); 00391 00392 // ALGORITHM: 00393 00394 // set all locally reachable states to init states 00395 for(lit = rGen.InitStatesBegin(); lit != rGen.InitStatesEnd(); ++lit) { 00396 reach.Clear(); 00397 LocalAccessibleReach(rGen, rProjectAlphabet, *lit, reach); 00398 rGen.InsInitStates(reach); 00399 } 00400 FD_DF("ProjectNonDet: initial states: " << rGen.InitStates().ToString()); 00401 // initialize algorithm by adding init states to todo 00402 todo.InsertSet(rGen.InitStates()); 00403 00404 // process todo stack 00405 while(!todo.Empty()) { 00406 currentstate = *todo.Begin(); 00407 todo.Erase(*todo.Begin()); 00408 done.Insert(currentstate); // mark as done 00409 FD_DF("ProjectNonDet: current state: " << rGen.SStr(currentstate)); 00410 00411 // comp accessible reach 00412 reach.Clear(); 00413 LocalAccessibleReach(rGen, rProjectAlphabet, currentstate, reach); 00414 FD_DF("ProjectNonDet: local reach: " << reach.ToString()); 00415 00416 // relink outgoing transitions 00417 FD_DF("ProjectNonDet: relinking outgoing transitions..."); 00418 for(lit = reach.Begin(); lit != reach.End(); ++lit) { 00419 tit = rGen.TransRelBegin(*lit); 00420 tit_end = rGen.TransRelEnd(*lit); 00421 for(; tit != tit_end; ++tit) { 00422 if(rProjectAlphabet.Exists(tit->Ev)) { 00423 FD_DF("ProjectNonDet: relinking transition: " << rGen.TStr(*tit) << " to " << rGen.SStr(currentstate)); 00424 rGen.SetTransition(currentstate, tit->Ev, tit->X2); 00425 if (!done.Exists(tit->X2)) { 00426 FD_DF("ProjectNonDet: todo insert: " << rGen.SStr(tit->X2)); 00427 todo.Insert(tit->X2); 00428 } 00429 // add transistions to all states in extended local reach 00430 // tmoor 201308: I dont see why we need this ... 00431 reachext.Clear(); 00432 LocalAccessibleReach(rGen, rProjectAlphabet, tit->X2, reachext); 00433 FD_DF("ProjectNonDet: local reach from state " << tit->X2 << ": " << reachext.ToString()); 00434 for (lit2 = reachext.Begin(); lit2 != reachext.End(); ++lit2) { 00435 if (!rGen.ExistsTransition(tit->X2, tit->Ev, *lit2) && (tit->X2 != *lit2)) { 00436 rGen.SetTransition(tit->X1, tit->Ev, *lit2); 00437 FD_DF("ProjectNonDet: setting transition: " << rGen.SStr(tit->X1) << "-" << rGen.EStr(tit->Ev) << "-" << rGen.SStr(*lit2)); 00438 //if (!done.Exists(*lit2) && !todo.Exists(*lit2)) { 00439 if (!done.Exists(*lit2)) { 00440 FD_DF("ProjectNonDet: todo insert: " << rGen.SStr(tit->X2)); 00441 todo.Insert(*lit2); 00442 } 00443 } 00444 } 00445 } 00446 } 00447 // marked status test 00448 if(rGen.ExistsMarkedState(*lit)) { 00449 FD_DF("ProjectNonDet: setting marked state " << rGen.SStr(currentstate)); 00450 rGen.SetMarkedState(currentstate); 00451 } 00452 } 00453 00454 // remove all silent transitions that leave current state 00455 tit = rGen.TransRelBegin(currentstate); 00456 tit_end = rGen.TransRelEnd(currentstate); 00457 while(tit != tit_end) { 00458 FD_DF("ProjectNonDet: current transition: " << rGen.SStr(tit->X1) 00459 << "-" << rGen.EStr(tit->Ev) << "-" << rGen.SStr(tit->X2)); 00460 if(!rProjectAlphabet.Exists(tit->Ev)) { 00461 FD_DF("ProjectNonDet: deleting current transition"); 00462 rGen.ClrTransition(tit++); 00463 } else { 00464 ++tit; 00465 } 00466 } 00467 00468 }// todo loop 00469 00470 // inject projection alphabet, keep Attributes 00471 rGen.RestrictAlphabet(rProjectAlphabet); 00472 00473 // make accessile 00474 rGen.Accessible(); 00475 00476 // set name 00477 rGen.Name(name); 00478 } 00479 00480 /* 00481 00482 // Reference, 2008/12 (Opitz?) 00483 00484 // Project(rGen&, rProjectAlphabet&) 00485 void ProjectNonDet(Generator& rGen, const EventSet& rProjectAlphabet) { 00486 00487 // HELPERS: 00488 00489 StateSet reach; // StateSet for reachable states 00490 std::stack<Idx> todo; // todo stack 00491 StateSet done; // done set 00492 Idx currentstate; // the currently processed state 00493 StateSet::Iterator lit; 00494 TransSet::Iterator tit; 00495 TransSet::Iterator tit_end; 00496 00497 // ALGORITHM: 00498 // initialize algorithm by pushing init states on todo stack 00499 for (lit = rGen.InitStatesBegin(); lit != rGen.InitStatesEnd(); ++lit) { 00500 FD_DF("ProjectNonDet: todo add: " << rGen.SStr(*lit)); 00501 todo.push(*lit); 00502 } 00503 00504 // process todo stack 00505 while (! todo.empty()) { 00506 currentstate = todo.top(); 00507 todo.pop(); 00508 done.Insert(currentstate); // mark as done 00509 FD_DF("ProjectNonDet: current state: " << rGen.SStr(currentstate)); 00510 00511 // comp accessible reach 00512 reach.Clear(); 00513 LocalAccessibleReach(rGen, rProjectAlphabet, currentstate, reach); 00514 FD_DF("ProjectNonDet: local reach: " << reach.ToString()); 00515 00516 // remove all transitions that leave current state 00517 // with an invisible event 00518 tit = rGen.TransRelBegin(currentstate); 00519 tit_end = rGen.TransRelEnd(currentstate); 00520 while(tit != tit_end) { 00521 FD_DF("ProjectNonDet: current transition: " << rGen.SStr(tit->X1) 00522 << "-" << rGen.EStr(tit->Ev) << "-" << rGen.SStr(tit->X2)); 00523 if (! rProjectAlphabet.Exists(tit->Ev)) { 00524 FD_DF("ProjectNonDet: deleting current transition"); 00525 TransSet::Iterator tit_tmp = tit; 00526 ++tit; 00527 rGen.ClrTransition(tit_tmp); 00528 } else { 00529 ++tit; 00530 } 00531 } 00532 00533 // relink outgoing transitions 00534 FD_DF("ProjectNonDet: relinking outgoing transitions..."); 00535 for (lit = reach.Begin(); lit != reach.End(); ++lit) { 00536 tit = rGen.TransRelBegin(*lit); 00537 tit_end = rGen.TransRelEnd(*lit); 00538 for (; tit != tit_end; ++tit) { 00539 if (rProjectAlphabet.Exists(tit->Ev)) { 00540 FD_DF("ProjectNonDet: relinking transition: " << rGen.TStr(*tit) << " to " << rGen.SStr(currentstate)); 00541 rGen.SetTransition(currentstate, tit->Ev, tit->X2); 00542 if (! done.Exists(tit->X2)) { 00543 FD_DF("ProjectNonDet: todo push: " << rGen.SStr(tit->X2)); 00544 todo.push(tit->X2); 00545 } 00546 } 00547 } 00548 // marked status test 00549 if (rGen.ExistsMarkedState(*lit)) { 00550 FD_DF("ProjectNonDet: setting marked state " << rGen.SStr(currentstate)); 00551 rGen.SetMarkedState(currentstate); 00552 } 00553 } 00554 } 00555 00556 // inject projection alphabet 00557 rGen.InjectAlphabet(rProjectAlphabet); 00558 00559 // set name 00560 rGen.Name(CollapsString("Pro(" + rGen.Name() + ")")); 00561 } 00562 00563 */ 00564 00565 // Project(rGen, rProjectAlphabet, rResGen&) 00566 void Project(const Generator& rGen, const EventSet& rProjectAlphabet, Generator& rResGen) { 00567 FD_DF("Project(...)"); 00568 // temporarily assign rGen to rResGen 00569 if(&rResGen != &rGen) rResGen.Assign(rGen); 00570 // turn of state names 00571 bool se= rResGen.StateNamesEnabled(); 00572 rResGen.StateNamesEnabled(false); 00573 // project non det version 00574 ProjectNonDet(rResGen, rProjectAlphabet); 00575 // make deterministic 00576 Generator* g2 = rGen.New(); 00577 g2->StateNamesEnabled(false); 00578 Deterministic(rResGen, *g2); 00579 // minimize states (tmoor 201308: this is cosmetic ... 00580 // ... and turned out expensive when iterating on an observer 00581 // stateset; hence we do it only for small generators) 00582 if(g2->Size() < 20) 00583 StateMin(*g2,rResGen); 00584 else 00585 g2->Move(rResGen); 00586 delete g2; 00587 // restore state names 00588 rResGen.StateNamesEnabled(se); 00589 // set name 00590 rResGen.Name("Project("+CollapsString(rGen.Name()+")")); 00591 } 00592 00593 00594 // wrapper 00595 void aProjectNonDet(Generator& rGen, const EventSet& rProjectAlphabet) { 00596 ProjectNonDet(rGen,rProjectAlphabet); 00597 } 00598 00599 00600 // Project(rGen, rProjectAlphabet, rResGen&) 00601 void aProject(const Generator& rGen, const EventSet& rProjectAlphabet, Generator& rResGen) { 00602 // prepare result to keep original alphabet 00603 Generator* pResGen = &rResGen; 00604 if(&rResGen== &rGen) { 00605 pResGen= rResGen.New(); 00606 } 00607 // perform op 00608 Project(rGen,rProjectAlphabet,*pResGen); 00609 // set old attributes 00610 pResGen->EventAttributes(rGen.Alphabet()); 00611 // copy result 00612 if(pResGen != &rResGen) { 00613 pResGen->Move(rResGen); 00614 delete pResGen; 00615 } 00616 } 00617 00618 00619 00620 // Project(rGen, rProjectAlphabet, rEntryStatesMap&, rResGen&) 00621 void Project(const Generator& rGen, const EventSet& rProjectAlphabet, 00622 std::map<Idx,StateSet>& rEntryStatesMap, Generator& rResGen) { 00623 FD_DF("Project(...)"); 00624 // temporary entry state map 00625 std::map<Idx,StateSet> tmp_entrystatemap; 00626 // temporarily assign rGen to rResGen 00627 if(&rResGen != &rGen) rResGen.Assign(rGen); 00628 // project tmp with respect to palphabet 00629 ProjectNonDet(rResGen, rProjectAlphabet); 00630 // put deterministic result into tmp 00631 Generator* tmp = rGen.New(); 00632 Deterministic(rResGen, tmp_entrystatemap, *tmp); 00633 // write entry state map for minimized generator 00634 std::vector<StateSet> subsets; 00635 std::vector<Idx> newindices; 00636 // minimize states and rewrite result to rResGen 00637 StateMin(*tmp, rResGen, subsets, newindices); 00638 // build entry state map 00639 std::vector<StateSet>::size_type i; 00640 std::map<Idx,StateSet>::iterator esmit; 00641 StateSet::Iterator sit; 00642 for (i = 0; i < subsets.size(); ++i) { 00643 StateSet tmpstates; 00644 for (sit = subsets[i].Begin(); sit != subsets[i].End(); ++sit) { 00645 esmit = tmp_entrystatemap.find(*sit); 00646 #ifdef FAUDES_DEBUG_CODE 00647 if (esmit == tmp_entrystatemap.end()) { 00648 FD_DF("project internal error"); 00649 abort(); 00650 } 00651 #endif 00652 // insert entry states in temporary StateSet 00653 tmpstates.InsertSet(esmit->second); 00654 } 00655 00656 rEntryStatesMap.insert(std::make_pair(newindices[i], tmpstates)); 00657 } 00658 delete tmp; 00659 } 00660 00661 00662 // InvProject(rGen&, rProjectAlphabet) 00663 void InvProject(Generator& rGen, const EventSet& rProjectAlphabet) { 00664 // test if the alphabet of the generator is included in the given alphabet 00665 if(! (rProjectAlphabet >= (EventSet) rGen.Alphabet() ) ){ 00666 std::stringstream errstr; 00667 errstr << "Input alphabet has to contain alphabet of generator \"" << rGen.Name() << "\""; 00668 throw Exception("InvProject(Generator,EventSet)", errstr.str(), 506); 00669 } 00670 EventSet newevents = rProjectAlphabet - rGen.Alphabet(); 00671 // insert events into generator 00672 rGen.InsEvents(newevents); 00673 FD_DF("InvProject: adding events \"" << newevents.ToString() 00674 << "\" at every state"); 00675 StateSet::Iterator lit; 00676 EventSet::Iterator eit; 00677 for (lit = rGen.StatesBegin(); lit != rGen.StatesEnd(); ++lit) { 00678 LoopCallback(); // should only be an issue for very large generators 00679 for (eit = newevents.Begin(); eit != newevents.End(); ++eit) { 00680 rGen.SetTransition(*lit, *eit, *lit); 00681 } 00682 } 00683 } 00684 00685 // InvProject(rGen&, rProjectAlphabet) 00686 void aInvProject(Generator& rGen, const EventSet& rProjectAlphabet) { 00687 FD_DF("aInvProject(..)"); 00688 // see whether the generator can digest attribues 00689 if(!rGen.Alphabet().AttributeTry(rProjectAlphabet.Attribute())) { 00690 InvProject(rGen,rProjectAlphabet); 00691 return; 00692 } 00693 // record extra events 00694 EventSet newevents = rProjectAlphabet - rGen.Alphabet(); 00695 // perform 00696 InvProject(rGen,rProjectAlphabet); 00697 // copy all attributes from input alphabets 00698 FD_DF("aInvProject(..): fixing attributes: source " << typeid(rProjectAlphabet.Attribute()).name() << 00699 " dest " << typeid(rGen.Alphabet().Attribute()).name()); 00700 for(EventSet::Iterator eit=newevents.Begin(); eit!=newevents.End(); ++eit) 00701 rGen.EventAttribute(*eit,rProjectAlphabet.Attribute(*eit)); 00702 } 00703 00704 00705 // InvProject 00706 void aInvProject( 00707 const Generator& rGen, 00708 const EventSet& rProjectAlphabet, 00709 Generator& rResGen) 00710 { 00711 rResGen.Assign(rGen); 00712 aInvProject(rResGen, rProjectAlphabet); 00713 } 00714 00715 00716 00717 00718 // CreateEntryStatesMap(rRevEntryStatesMap, rEntryStatesMap) 00719 void CreateEntryStatesMap(const std::map<StateSet,Idx>& rRevEntryStatesMap, 00720 std::map<Idx,StateSet>& rEntryStatesMap) { 00721 std::map<StateSet,Idx>::const_iterator it; 00722 for (it = rRevEntryStatesMap.begin(); it != rRevEntryStatesMap.end(); ++it) { 00723 rEntryStatesMap.insert(std::make_pair(it->second, it->first)); 00724 } 00725 } 00726 00727 00728 00729 } // namespace faudes |
libFAUDES 2.22s --- 2013.10.07 --- c++ source docu by doxygen