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