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