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) != "") { 00351 name = name + rGen.StateName(*lit) + ","; 00352 } 00353 else { 00354 name = name + ToStringInteger(*lit) + ","; 00355 } 00356 } 00357 name.erase(name.length() - 1); 00358 name = name + "}"; 00359 FD_DF("Deterministic: setting state name \"" << name << "\" for index " 00360 << rDetStates[i]); 00361 pResGen->StateName(rDetStates[i], name); 00362 } 00363 } 00364 00365 // move pResGen to rResGen 00366 if(pResGen != &rResGen) { 00367 pResGen->Move(rResGen); 00368 delete pResGen; 00369 } 00370 00371 FD_DF("Deterministic(): core function: done"); 00372 00373 } 00374 00375 00376 00377 // ProjectNonDet(rGen&, rProjectAlphabet&) 00378 // (version 2009/05, Barthel) 00379 void ProjectNonDet(Generator& rGen, const EventSet& rProjectAlphabet) { 00380 00381 // HELPERS: 00382 00383 StateSet reach, reachext; // StateSet for reachable states 00384 StateSet todo; // states todo 00385 StateSet done; // states done 00386 Idx currentstate; // the currently processed state 00387 StateSet::Iterator lit; 00388 StateSet::Iterator lit2; 00389 TransSet::Iterator tit; 00390 TransSet::Iterator tit_end; 00391 00392 // NAME 00393 std::string name=CollapsString("ProjectNonDet(" + rGen.Name() + ")"); 00394 00395 // ALGORITHM: 00396 // set all locally reachable states to init states 00397 for (lit = rGen.InitStatesBegin(); lit != rGen.InitStatesEnd(); ++lit) { 00398 reach.Clear(); 00399 LocalAccessibleReach(rGen, rProjectAlphabet, *lit, reach); 00400 for (lit2 = reach.Begin(); lit2 != reach.End(); ++lit2) { 00401 if (!rGen.InitStates().Exists(*lit2)) { 00402 FD_DF("ProjectNonDet: set initial state: " << rGen.SStr(*lit2)); 00403 rGen.SetInitState(*lit2); 00404 } 00405 } 00406 } 00407 // initialize algorithm by adding init states to todo 00408 for (lit = rGen.InitStatesBegin(); lit != rGen.InitStatesEnd(); ++lit) { 00409 FD_DF("ProjectNonDet: todo add: " << rGen.SStr(*lit)); 00410 todo.Insert(*lit); 00411 } 00412 00413 // process todo stack 00414 while (!todo.Empty()) { 00415 currentstate = *todo.Begin(); 00416 todo.Erase(*todo.Begin()); 00417 done.Insert(currentstate); // mark as done 00418 //std::cout << "###" << std::endl; 00419 FD_DF("ProjectNonDet: current state: " << rGen.SStr(currentstate)); 00420 00421 // comp accessible reach 00422 reach.Clear(); 00423 LocalAccessibleReach(rGen, rProjectAlphabet, currentstate, reach); 00424 FD_DF("ProjectNonDet: local reach: " << reach.ToString()); 00425 00426 // relink outgoing transitions 00427 FD_DF("ProjectNonDet: relinking outgoing transitions..."); 00428 for (lit = reach.Begin(); lit != reach.End(); ++lit) { 00429 tit = rGen.TransRelBegin(*lit); 00430 tit_end = rGen.TransRelEnd(*lit); 00431 for (; tit != tit_end; ++tit) { 00432 if (rProjectAlphabet.Exists(tit->Ev)) { 00433 FD_DF("ProjectNonDet: relinking transition: " << rGen.TStr(*tit) << " to " << rGen.SStr(currentstate)); 00434 rGen.SetTransition(currentstate, tit->Ev, tit->X2); 00435 //if (!done.Exists(tit->X2) && !todo.Exists(*lit2)) { 00436 if (!done.Exists(tit->X2)) { 00437 FD_DF("ProjectNonDet: todo insert: " << rGen.SStr(tit->X2)); 00438 todo.Insert(tit->X2); 00439 } 00440 // add transistions to all states in extended local reach 00441 reachext.Clear(); 00442 LocalAccessibleReach(rGen, rProjectAlphabet, tit->X2, reachext); 00443 FD_DF("ProjectNonDet: local reach from state " << tit->X2 << ": " << reachext.ToString()); 00444 for (lit2 = reachext.Begin(); lit2 != reachext.End(); ++lit2) { 00445 if (!rGen.ExistsTransition(tit->X2, tit->Ev, *lit2) && (tit->X2 != *lit2)) { 00446 rGen.SetTransition(tit->X1, tit->Ev, *lit2); 00447 FD_DF("ProjectNonDet: setting transition: " << rGen.SStr(tit->X1) << "-" << rGen.EStr(tit->Ev) << "-" << rGen.SStr(*lit2)); 00448 //if (!done.Exists(*lit2) && !todo.Exists(*lit2)) { 00449 if (!done.Exists(*lit2)) { 00450 FD_DF("ProjectNonDet: todo insert: " << rGen.SStr(tit->X2)); 00451 todo.Insert(*lit2); 00452 } 00453 } 00454 } 00455 //std::cout << "---" << std::endl; 00456 } 00457 } 00458 // marked status test 00459 if (rGen.ExistsMarkedState(*lit)) { 00460 FD_DF("ProjectNonDet: setting marked state " << rGen.SStr(currentstate)); 00461 rGen.SetMarkedState(currentstate); 00462 } 00463 } 00464 00465 // remove all transitions that leave current state 00466 // with an invisible event 00467 tit = rGen.TransRelBegin(currentstate); 00468 tit_end = rGen.TransRelEnd(currentstate); 00469 while(tit != tit_end) { 00470 FD_DF("ProjectNonDet: current transition: " << rGen.SStr(tit->X1) 00471 << "-" << rGen.EStr(tit->Ev) << "-" << rGen.SStr(tit->X2)); 00472 if (! rProjectAlphabet.Exists(tit->Ev)) { 00473 FD_DF("ProjectNonDet: deleting current transition"); 00474 TransSet::Iterator tit_tmp = tit; 00475 ++tit; 00476 rGen.ClrTransition(tit_tmp); 00477 } else { 00478 ++tit; 00479 } 00480 } 00481 00482 }// todo loop 00483 00484 // inject projection alphabet, keep Attributes 00485 rGen.RestrictAlphabet(rProjectAlphabet); 00486 00487 // make accessile 00488 rGen.Accessible(); 00489 00490 // set name 00491 rGen.Name(name); 00492 } 00493 00494 // wrapper 00495 void aProjectNonDet(Generator& rGen, const EventSet& rProjectAlphabet) { 00496 ProjectNonDet(rGen,rProjectAlphabet); 00497 } 00498 00499 /* 00500 00501 // reference, 2008/12 00502 00503 // Project(rGen&, rProjectAlphabet&) 00504 void ProjectNonDet(Generator& rGen, const EventSet& rProjectAlphabet) { 00505 00506 // HELPERS: 00507 00508 StateSet reach; // StateSet for reachable states 00509 std::stack<Idx> todo; // todo stack 00510 StateSet done; // done set 00511 Idx currentstate; // the currently processed state 00512 StateSet::Iterator lit; 00513 TransSet::Iterator tit; 00514 TransSet::Iterator tit_end; 00515 00516 // ALGORITHM: 00517 // initialize algorithm by pushing init states on todo stack 00518 for (lit = rGen.InitStatesBegin(); lit != rGen.InitStatesEnd(); ++lit) { 00519 FD_DF("ProjectNonDet: todo add: " << rGen.SStr(*lit)); 00520 todo.push(*lit); 00521 } 00522 00523 // process todo stack 00524 while (! todo.empty()) { 00525 currentstate = todo.top(); 00526 todo.pop(); 00527 done.Insert(currentstate); // mark as done 00528 FD_DF("ProjectNonDet: current state: " << rGen.SStr(currentstate)); 00529 00530 // comp accessible reach 00531 reach.Clear(); 00532 LocalAccessibleReach(rGen, rProjectAlphabet, currentstate, reach); 00533 FD_DF("ProjectNonDet: local reach: " << reach.ToString()); 00534 00535 // remove all transitions that leave current state 00536 // with an invisible event 00537 tit = rGen.TransRelBegin(currentstate); 00538 tit_end = rGen.TransRelEnd(currentstate); 00539 while(tit != tit_end) { 00540 FD_DF("ProjectNonDet: current transition: " << rGen.SStr(tit->X1) 00541 << "-" << rGen.EStr(tit->Ev) << "-" << rGen.SStr(tit->X2)); 00542 if (! rProjectAlphabet.Exists(tit->Ev)) { 00543 FD_DF("ProjectNonDet: deleting current transition"); 00544 TransSet::Iterator tit_tmp = tit; 00545 ++tit; 00546 rGen.ClrTransition(tit_tmp); 00547 } else { 00548 ++tit; 00549 } 00550 } 00551 00552 // relink outgoing transitions 00553 FD_DF("ProjectNonDet: relinking outgoing transitions..."); 00554 for (lit = reach.Begin(); lit != reach.End(); ++lit) { 00555 tit = rGen.TransRelBegin(*lit); 00556 tit_end = rGen.TransRelEnd(*lit); 00557 for (; tit != tit_end; ++tit) { 00558 if (rProjectAlphabet.Exists(tit->Ev)) { 00559 FD_DF("ProjectNonDet: relinking transition: " << rGen.TStr(*tit) << " to " << rGen.SStr(currentstate)); 00560 rGen.SetTransition(currentstate, tit->Ev, tit->X2); 00561 if (! done.Exists(tit->X2)) { 00562 FD_DF("ProjectNonDet: todo push: " << rGen.SStr(tit->X2)); 00563 todo.push(tit->X2); 00564 } 00565 } 00566 } 00567 // marked status test 00568 if (rGen.ExistsMarkedState(*lit)) { 00569 FD_DF("ProjectNonDet: setting marked state " << rGen.SStr(currentstate)); 00570 rGen.SetMarkedState(currentstate); 00571 } 00572 } 00573 } 00574 00575 // inject projection alphabet 00576 rGen.InjectAlphabet(rProjectAlphabet); 00577 00578 // set name 00579 rGen.Name(CollapsString("Pro(" + rGen.Name() + ")")); 00580 } 00581 00582 */ 00583 00584 // Project(rGen, rProjectAlphabet, rResGen&) 00585 void Project(const Generator& rGen, const EventSet& rProjectAlphabet, Generator& rResGen) { 00586 FD_DF("Project(...)"); 00587 // temporarily assign rGen to rResGen 00588 if(&rResGen != &rGen) rResGen.Assign(rGen); 00589 // turn of state names 00590 bool se= rResGen.StateNamesEnabled(); 00591 rResGen.StateNamesEnabled(false); 00592 // project non det version 00593 ProjectNonDet(rResGen, rProjectAlphabet); 00594 // make deterministic 00595 Generator* g2 = rGen.New(); 00596 g2->StateNamesEnabled(false); 00597 Deterministic(rResGen, *g2); 00598 // minimize states and write result to rResGen 00599 StateMin(*g2, rResGen); 00600 delete g2; 00601 // restore state names 00602 rResGen.StateNamesEnabled(se); 00603 // set name 00604 rResGen.Name("Project("+CollapsString(rGen.Name()+")")); 00605 } 00606 00607 00608 // Project(rGen, rProjectAlphabet, rResGen&) 00609 void aProject(const Generator& rGen, const EventSet& rProjectAlphabet, Generator& rResGen) { 00610 // prepare result to keep original alphabet 00611 Generator* pResGen = &rResGen; 00612 if(&rResGen== &rGen) { 00613 pResGen= rResGen.New(); 00614 } 00615 // perform op 00616 Project(rGen,rProjectAlphabet,*pResGen); 00617 // set old attributes 00618 pResGen->EventAttributes(rGen.Alphabet()); 00619 // copy result 00620 if(pResGen != &rResGen) { 00621 pResGen->Move(rResGen); 00622 delete pResGen; 00623 } 00624 } 00625 00626 00627 00628 // Project(rGen, rProjectAlphabet, rEntryStatesMap&, rResGen&) 00629 void Project(const Generator& rGen, const EventSet& rProjectAlphabet, 00630 std::map<Idx,StateSet>& rEntryStatesMap, Generator& rResGen) { 00631 FD_DF("Project(...)"); 00632 // temporary entry state map 00633 std::map<Idx,StateSet> tmp_entrystatemap; 00634 // temporarily assign rGen to rResGen 00635 if(&rResGen != &rGen) rResGen.Assign(rGen); 00636 // project tmp with respect to palphabet 00637 ProjectNonDet(rResGen, rProjectAlphabet); 00638 // put deterministic result into tmp 00639 Generator* tmp = rGen.New(); 00640 Deterministic(rResGen, tmp_entrystatemap, *tmp); 00641 // write entry state map for minimized generator 00642 std::vector<StateSet> subsets; 00643 std::vector<Idx> newindices; 00644 // minimize states and rewrite result to rResGen 00645 StateMin(*tmp, rResGen, subsets, newindices); 00646 // build entry state map 00647 std::vector<StateSet>::size_type i; 00648 std::map<Idx,StateSet>::iterator esmit; 00649 StateSet::Iterator sit; 00650 for (i = 0; i < subsets.size(); ++i) { 00651 StateSet tmpstates; 00652 for (sit = subsets[i].Begin(); sit != subsets[i].End(); ++sit) { 00653 esmit = tmp_entrystatemap.find(*sit); 00654 #ifdef FAUDES_DEBUG_CODE 00655 if (esmit == tmp_entrystatemap.end()) { 00656 FD_DF("project internal error"); 00657 abort(); 00658 } 00659 #endif 00660 // insert entry states in temporary StateSet 00661 tmpstates.InsertSet(esmit->second); 00662 } 00663 00664 rEntryStatesMap.insert(std::make_pair(newindices[i], tmpstates)); 00665 } 00666 delete tmp; 00667 } 00668 00669 00670 // InvProject(rGen&, rProjectAlphabet) 00671 void InvProject(Generator& rGen, const EventSet& rProjectAlphabet) { 00672 // test if the alphabet of the generator is included in the given alphabet 00673 if(! (rProjectAlphabet >= (EventSet) rGen.Alphabet() ) ){ 00674 std::stringstream errstr; 00675 errstr << "Input alphabet has to contain alphabet of generator \"" << rGen.Name() << "\""; 00676 throw Exception("InvProject(Generator,EventSet)", errstr.str(), 506); 00677 } 00678 EventSet newevents = rProjectAlphabet - rGen.Alphabet(); 00679 // insert events into generator 00680 rGen.InsEvents(newevents); 00681 FD_DF("InvProject: adding events \"" << newevents.ToString() 00682 << "\" at every state"); 00683 StateSet::Iterator lit; 00684 EventSet::Iterator eit; 00685 for (lit = rGen.StatesBegin(); lit != rGen.StatesEnd(); ++lit) { 00686 for (eit = newevents.Begin(); eit != newevents.End(); ++eit) { 00687 rGen.SetTransition(*lit, *eit, *lit); 00688 } 00689 } 00690 } 00691 00692 // InvProject(rGen&, rProjectAlphabet) 00693 void aInvProject(Generator& rGen, const EventSet& rProjectAlphabet) { 00694 FD_DF("aInvProject(..)"); 00695 // see whether the generator can digest attribues 00696 if(!rGen.Alphabet().AttributeTry(rProjectAlphabet.Attribute())) { 00697 InvProject(rGen,rProjectAlphabet); 00698 return; 00699 } 00700 // record extra events 00701 EventSet newevents = rProjectAlphabet - rGen.Alphabet(); 00702 // perform 00703 InvProject(rGen,rProjectAlphabet); 00704 // copy all attributes from input alphabets 00705 FD_DF("aInvProject(..): fixing attributes: source " << typeid(rProjectAlphabet.Attribute()).name() << 00706 " dest " << typeid(rGen.Alphabet().Attribute()).name()); 00707 for(EventSet::Iterator eit=newevents.Begin(); eit!=newevents.End(); ++eit) 00708 rGen.EventAttribute(*eit,rProjectAlphabet.Attribute(*eit)); 00709 } 00710 00711 00712 // InvProject 00713 void aInvProject( 00714 const Generator& rGen, 00715 const EventSet& rProjectAlphabet, 00716 Generator& rResGen) 00717 { 00718 rResGen.Assign(rGen); 00719 aInvProject(rResGen, rProjectAlphabet); 00720 } 00721 00722 00723 00724 00725 // CreateEntryStatesMap(rRevEntryStatesMap, rEntryStatesMap) 00726 void CreateEntryStatesMap(const std::map<StateSet,Idx>& rRevEntryStatesMap, 00727 std::map<Idx,StateSet>& rEntryStatesMap) { 00728 std::map<StateSet,Idx>::const_iterator it; 00729 for (it = rRevEntryStatesMap.begin(); it != rRevEntryStatesMap.end(); ++it) { 00730 rEntryStatesMap.insert(std::make_pair(it->second, it->first)); 00731 } 00732 } 00733 00734 00735 00736 } // namespace faudes |
libFAUDES 2.20d --- 2011.04.26 --- c++ source docu by doxygen