|
libFAUDES
Sections
Index
|
mtc_project.cppGo to the documentation of this file.00001 /** @file mtc_project.cpp 00002 00003 Methods for computing the natural projection of multitasking generators 00004 00005 */ 00006 00007 /* FAU Discrete Event Systems Library (libfaudes) 00008 00009 Copyright (C) 2008 Matthias Singer 00010 Copyright (C) 2006 Bernd Opitz 00011 Exclusive copyright is granted to Klaus Schmidt 00012 00013 This library is free software; you can redistribute it and/or 00014 modify it under the terms of the GNU Lesser General Public 00015 License as published by the Free Software Foundation; either 00016 version 2.1 of the License, or (at your option) any later version. 00017 00018 This library is distributed in the hope that it will be useful, 00019 but WITHOUT ANY WARRANTY; without even the implied warranty of 00020 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00021 Lesser General Public License for more details. 00022 00023 You should have received a copy of the GNU Lesser General Public 00024 License along with this library; if not, write to the Free Software 00025 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 00026 00027 00028 #include "mtc_project.h" 00029 00030 namespace faudes { 00031 00032 // mtcUniqueInit(rGen&) 00033 void mtcUniqueInit(mtcGenerator& rGen) { 00034 Idx inituni; 00035 StateSet::Iterator lit; 00036 TransSet::Iterator tit; 00037 // check number of initial states 00038 if (rGen.InitStatesSize() <= 1) return; 00039 // introduce new initial state 00040 if (rGen.StateNamesEnabled()) { 00041 std::string initname=rGen.UniqueStateName("InitUni"); 00042 inituni = rGen.InsState(initname); 00043 } 00044 else { 00045 inituni = rGen.InsState(); 00046 } 00047 FD_DF("mtcUniqueInit: introducing new initial state: " << inituni); 00048 // introduce outgoing transitions from initial state 00049 FD_DF("mtcUniqueInit: introduce outgoing transitions: "); 00050 for (lit = rGen.InitStatesBegin(); lit != rGen.InitStatesEnd(); ++lit) { 00051 for (tit = rGen.TransRelBegin(*lit); tit != rGen.TransRelEnd(*lit); ++tit) { 00052 rGen.SetTransition(inituni, tit->Ev, tit->X2); 00053 FD_DF("mtcUniqueInit: " << inituni << "-" << tit->Ev << "-" << tit->X2); 00054 } 00055 // colored states 00056 const ColorSet& colors = rGen.Colors(*lit); 00057 rGen.InsColors(inituni, colors); 00058 // marked states 00059 if (!rGen.MarkedStatesEmpty()) { 00060 rGen.SetMarkedState(inituni); 00061 FD_DF("mtcUniqueInit: set marked state: " << inituni); 00062 } 00063 } 00064 // delete old istates 00065 rGen.ClearInitStates(); 00066 // set inituni as new initial state 00067 rGen.SetInitState(inituni); 00068 } 00069 00070 00071 // mtcDeterministic(rGen&, rResGen&) 00072 void mtcDeterministic(const mtcGenerator& rGen, mtcGenerator& rResGen) { 00073 // temporary vectors 00074 std::vector<StateSet> power_states; 00075 std::vector<Idx> det_states; 00076 mtcDeterministic(rGen, power_states, det_states, rResGen); 00077 } 00078 00079 00080 // mtcDeterministic(rGen&, rEntryStatesMap&, rResGen&) 00081 void mtcDeterministic(const mtcGenerator& rGen, std::map<Idx,StateSet>& rEntryStatesMap, 00082 mtcGenerator& rResGen) { 00083 // prepare result: 00084 rEntryStatesMap.clear(); 00085 // helpers: 00086 std::vector<StateSet> power_states; 00087 std::vector<Idx> det_states; 00088 // call Deterministic function 00089 mtcDeterministic(rGen, power_states, det_states, rResGen); 00090 // build entry states map 00091 std::vector<StateSet>::size_type i; 00092 for (i = 0; i < power_states.size(); ++i) { 00093 rEntryStatesMap.insert(std::pair<Idx,StateSet>(det_states[i], power_states[i])); 00094 } 00095 } 00096 00097 00098 void mtcDeterministic(const mtcGenerator& rGen, std::vector<StateSet>& rPowerStates, 00099 std::vector<Idx>& rDetStates, mtcGenerator& rResGen) { 00100 // set the name 00101 rResGen.Name("Det(" + rGen.Name() + ")"); 00102 00103 // prepare result 00104 rPowerStates.clear(); 00105 rDetStates.clear(); 00106 rResGen.Clear(); 00107 00108 // copy alphabet 00109 rResGen.InjectAlphabet(rGen.Alphabet()); 00110 00111 // helpers 00112 TransSetEvX1X2 trel_evx1x2; 00113 rGen.TransRel(trel_evx1x2); 00114 typedef std::multimap< Idx,std::vector<StateSet>::size_type > T_HASHMAP; 00115 T_HASHMAP hashmap; 00116 std::vector<StateSet>::size_type current_vecindex; 00117 std::pair< std::map<StateSet,Idx>::iterator,bool > result; 00118 TransSet::Iterator transrel_end = rGen.TransRelEnd(); 00119 StateSet newset; 00120 StateSet::Iterator lit; 00121 const Idx max_idx = std::numeric_limits<Idx>::max(); 00122 if (rGen.InitStatesEmpty()) { 00123 return; 00124 } 00125 // std::map<Idx,ColorSet> CopyMap = rGen.StateColorMap(); 00126 Idx newstate = rResGen.InsInitState(); 00127 // initialize rPowerStates with subset of initial states 00128 for (lit = rGen.InitStatesBegin(); lit != rGen.InitStatesEnd(); ++lit) { 00129 // clear set and insert single state 00130 newset.Insert(*lit); 00131 const ColorSet& colors = rGen.Colors(*lit); 00132 // set colored state if a member state is colored 00133 rResGen.InsColors(newstate,colors); 00134 } 00135 FD_DF("mtcDeterministic: created subset of initial states {" 00136 << newset.ToString() << "} with deterministic state index " << rGen.SStr(newstate)); 00137 // insert newset in rPowerStates 00138 rPowerStates.push_back(newset); 00139 rDetStates.push_back(newstate); 00140 hashmap.insert(std::make_pair(newset.Signature(), (Idx)rPowerStates.size() - 1)); 00141 00142 // iteration over all states 00143 for (current_vecindex = 0; current_vecindex < rPowerStates.size(); ++current_vecindex) { 00144 FD_DF("mtcDeterministic: current power set: {" << rPowerStates[current_vecindex].ToString() << 00145 "} -> " << rDetStates[current_vecindex]); 00146 00147 std::vector<StateSet> newset_vec; 00148 std::vector<Idx> event_vec; 00149 00150 // multiway merge begin 00151 FD_DF("mtcDeterministic: starting multiway merge..."); 00152 std::list<TransSet::Iterator> merge_iterators; 00153 std::vector<Transition> trans_vec; 00154 00155 // add transset iterator at begin of each state's transitions 00156 TransSet::Iterator tit; 00157 for (lit = rPowerStates[current_vecindex].Begin(); 00158 lit != rPowerStates[current_vecindex].End(); ++lit) { 00159 tit = rGen.TransRelBegin(*lit); 00160 if (tit != rGen.TransRelEnd(*lit)) { 00161 merge_iterators.push_back(tit); 00162 FD_DF("mtcDeterministic: added merge iterator: " << rGen.SStr(tit->X1) 00163 << "-" << rGen.EStr(tit->Ev) << "-" << rGen.SStr(tit->X2)); 00164 } 00165 } 00166 00167 // find first iterator with lowest event 00168 while (! merge_iterators.empty()) { 00169 Idx currentevent = max_idx; 00170 std::list<TransSet::Iterator>::iterator i; 00171 std::list<TransSet::Iterator>::iterator currentit = merge_iterators.end(); 00172 for (i = merge_iterators.begin(); i != merge_iterators.end(); ++i) { 00173 if ((*i)->Ev < currentevent) { 00174 currentevent = (*i)->Ev; 00175 currentit = i; 00176 } 00177 } 00178 // currentit now holds the iterator 00179 // currentevent holds the lowest event (lowest Idx) 00180 00181 // merge all transitions with currentevent at each iterator in a row 00182 // this is a modification of multiway merge as after projection the 00183 // automaton most likely holds states with many transitions that share 00184 // the same event. only merging the lowest transition and continue with 00185 // search for the lowest event again would be to slow here (because 00186 // of too much iterator dereferencing). 00187 Idx currentstate; 00188 while (currentit != merge_iterators.end()) { 00189 currentstate = (*currentit)->X1; 00190 TransSet::Iterator& j = *currentit; 00191 while (1) { 00192 // remove iterator if it reaches the end of the transition set 00193 if (j == transrel_end) { 00194 std::list<TransSet::Iterator>::iterator tmpit = currentit; 00195 ++currentit; 00196 merge_iterators.erase(tmpit); 00197 break; 00198 } 00199 // if current iterator is in its original state 00200 else if (j->X1 == currentstate) { 00201 // if the event is still the same add the transition 00202 if (j->Ev == currentevent) { 00203 trans_vec.push_back(*j); 00204 FD_DF("Determine: adding transition to list: " << rGen.SStr(j->X1) 00205 << "-" << rGen.EStr(j->Ev) << "-" << rGen.SStr(j->X2)); 00206 } 00207 // else go to next iterator 00208 else { 00209 ++currentit; 00210 break; 00211 } 00212 } 00213 // if the iterator is beyond its original state remove it 00214 else { 00215 std::list<TransSet::Iterator>::iterator tmpit = currentit; 00216 ++currentit; 00217 merge_iterators.erase(tmpit); 00218 break; 00219 } 00220 ++j; 00221 } 00222 } 00223 } 00224 00225 // partition transition vector by events. optimizable? 00226 FD_DF("mtcDeterministic: partitioning the transition vector..."); 00227 std::vector<Transition>::iterator tv_it; 00228 StateSet newset; 00229 Idx lastevent = 0; 00230 for (tv_it = trans_vec.begin(); tv_it != trans_vec.end(); ++tv_it) { 00231 if ((tv_it->Ev == lastevent) || (lastevent == 0)) { 00232 newset.Insert(tv_it->X2); 00233 lastevent = tv_it->Ev; 00234 } 00235 else { 00236 FD_DF("mtcDeterministic: partition: {" << newset.ToString() 00237 << "} with event " << rGen.EStr(lastevent)); 00238 newset_vec.push_back(newset); 00239 event_vec.push_back(lastevent); 00240 newset.Clear(); 00241 newset.Insert(tv_it->X2); 00242 lastevent = tv_it->Ev; 00243 } 00244 } 00245 if (! newset.Empty()) { 00246 FD_DF("mtcDeterministic: partition: {" << newset.ToString() 00247 << "} with event " << rGen.EStr(lastevent)); 00248 newset_vec.push_back(newset); 00249 event_vec.push_back(lastevent); 00250 } 00251 FD_DF("mtcDeterministic: partitioning the transition vector finished"); 00252 FD_DF("mtcDeterministic: multiway merge finished"); 00253 // multiway merge end 00254 00255 std::vector<StateSet>::size_type nsv_index; 00256 for (nsv_index = 0; nsv_index < newset_vec.size(); ++nsv_index) { 00257 StateSet& currentset = newset_vec[nsv_index]; 00258 Idx currentevent = event_vec[nsv_index]; 00259 Idx tmp_x2 = 0; 00260 Idx sig = currentset.Signature(); 00261 // test if newset signature is already known 00262 std::pair<T_HASHMAP::iterator,T_HASHMAP::iterator> phit 00263 = hashmap.equal_range(sig); 00264 T_HASHMAP::iterator hit = phit.first; 00265 for (hit = phit.first; hit != phit.second; ++hit) { 00266 // test set of every matching signature for equality 00267 if (currentset == rPowerStates[hit->second]) { 00268 tmp_x2 = rDetStates[hit->second]; 00269 break; 00270 } 00271 } 00272 00273 // if new set is unique within the existing power sets 00274 if (tmp_x2 == 0) { 00275 // create new state in res generator 00276 tmp_x2 = rResGen.InsState(); 00277 // insert newset in rPowerStates and get iterator,bool pair 00278 rPowerStates.push_back(currentset); 00279 rDetStates.push_back(tmp_x2); 00280 hashmap.insert(std::make_pair(sig, (Idx)rPowerStates.size() - 1)); 00281 FD_DF("mtcDeterministic: added new state " << rGen.SStr(tmp_x2) 00282 << " for new subset {" << currentset.ToString() << "}"); 00283 // set colored if one of the states in current set is colored 00284 for (lit = currentset.Begin(); lit != currentset.End(); ++lit) { 00285 const ColorSet& colors = rGen.Colors(*lit); 00286 rResGen.InsColors(tmp_x2,colors); 00287 FD_DF("mtcDeterministic: setting as colored: " << rGen.SStr(tmp_x2)); 00288 } 00289 } 00290 // introduce transition 00291 rResGen.SetTransition(rDetStates[current_vecindex], currentevent, tmp_x2); 00292 } 00293 } 00294 // fix names 00295 if (rGen.StateNamesEnabled() && rResGen.StateNamesEnabled()) { 00296 FD_DF("mtcDeterministic: fixing names..."); 00297 // rPowerStates / rDetStates index "iterator" 00298 std::vector<StateSet>::size_type i; 00299 // deterministic states iterator 00300 std::vector<Idx>::const_iterator dit; 00301 for (i = 0; i < rPowerStates.size(); ++i) { 00302 // temporary state name 00303 std::string name = "{"; 00304 for (lit = rPowerStates[i].Begin(); lit != rPowerStates[i].End(); ++lit) { 00305 if (rResGen.StateName(*lit) != "") { 00306 name = name + rResGen.StateName(*lit) + ","; 00307 } 00308 else { 00309 name = name + ToStringInteger(*lit) + ","; 00310 } 00311 } 00312 name.erase(name.length() - 1); 00313 name = name + "}"; 00314 rResGen.StateName(rDetStates[i], name); 00315 FD_DF("mtcDeterministic: setting state name \"" << name << "\" for index " << rDetStates[i]); 00316 } 00317 } 00318 // Delete unnecessary events and set event attributes 00319 rResGen.DelEvents(rResGen.UnusedEvents()); 00320 EventSet usedEvents = rResGen.UsedEvents(); 00321 rResGen.SetControllable(rGen.ControllableEvents()*usedEvents); 00322 rResGen.SetForcible(rGen.ForcibleEvents()*usedEvents); 00323 rResGen.ClrObservable(rGen.UnobservableEvents()*usedEvents); 00324 } 00325 00326 // mtcProjectNonDet(rGen&, rProjectAlphabet&) 00327 void mtcProjectNonDet(mtcGenerator& rGen, const EventSet& rProjectAlphabet) { 00328 00329 // HELPERS: 00330 StateSet reach; // StateSet for reachable states 00331 std::stack<Idx> todo; // todo stack 00332 StateSet done; // done set 00333 Idx currentstate; // the currently processed state 00334 StateSet::Iterator lit; 00335 TransSet::Iterator tit; 00336 TransSet::Iterator tit_end; 00337 00338 // ALGORITHM: 00339 // initialize algorithm by pushing init states on todo stack 00340 for (lit = rGen.InitStatesBegin(); lit != rGen.InitStatesEnd(); ++lit) { 00341 FD_DF("mtcProjectNonDet: todo add: " << rGen.SStr(*lit)); 00342 todo.push(*lit); 00343 } 00344 00345 // process todo stack 00346 while (! todo.empty()) { 00347 currentstate = todo.top(); 00348 todo.pop(); 00349 done.Insert(currentstate); // mark as done 00350 FD_DF("mtcProjectNonDet: current state: " << rGen.SStr(currentstate)); 00351 00352 // comp accessible reach 00353 reach.Clear(); 00354 LocalAccessibleReach(rGen, rProjectAlphabet, currentstate, reach); 00355 FD_DF("mtcProjectNonDet: local reach: " << reach.ToString()); 00356 00357 // remove all transitions that leave current state 00358 // with an invisible event 00359 tit = rGen.TransRelBegin(currentstate); 00360 tit_end = rGen.TransRelEnd(currentstate); 00361 while(tit != tit_end) { 00362 FD_DF("mtcProjectNonDet: current transition: " << rGen.SStr(tit->X1) 00363 << "-" << rGen.EStr(tit->Ev) << "-" << rGen.SStr(tit->X2)); 00364 if (! rProjectAlphabet.Exists(tit->Ev)) { 00365 FD_DF("mtcProjectNonDet: deleting current transition"); 00366 TransSet::Iterator tit_tmp = tit; 00367 ++tit; 00368 rGen.ClrTransition(tit_tmp); 00369 } 00370 else { 00371 ++tit; 00372 } 00373 } 00374 00375 // relink outgoing transitions 00376 FD_DF("mtcProjectNonDet: relinking outgoing transitions..."); 00377 for (lit = reach.Begin(); lit != reach.End(); ++lit) { 00378 tit = rGen.TransRelBegin(*lit); 00379 tit_end = rGen.TransRelEnd(*lit); 00380 for (; tit != tit_end; ++tit) { 00381 if (rProjectAlphabet.Exists(tit->Ev)) { 00382 FD_DF("mtcProjectNonDet: relinking transition: " << rGen.TStr(*tit) << " to " << rGen.SStr(currentstate) << "--(" << rGen.EStr(tit->Ev) << ")-->" << rGen.SStr(tit->X2)); 00383 rGen.SetTransition(currentstate, tit->Ev, tit->X2); 00384 if (! done.Exists(tit->X2)) { 00385 FD_DF("mtcProjectNonDet: todo push: " << rGen.SStr(tit->X2)); 00386 todo.push(tit->X2); 00387 } 00388 } 00389 } 00390 // colored status test 00391 const ColorSet& colors = rGen.Colors(*lit); 00392 if (!colors.Empty()) { 00393 FD_DF("mtcProjectNonDet: setting colored state " << rGen.SStr(currentstate)); 00394 rGen.InsColors(currentstate, colors); 00395 } 00396 } 00397 } 00398 00399 // inject projection alphabet 00400 rGen.InjectAlphabet(rProjectAlphabet); 00401 00402 EventSet unused = rGen.UnusedEvents(); 00403 EventSet::Iterator eit; 00404 for(eit = unused.Begin(); eit != unused.End(); ++eit){ 00405 rGen.ClrEventAttribute(*eit); 00406 rGen.EventSymbolTablep()->ClrEntry(*eit); 00407 rGen.DelEvent(*eit); 00408 } 00409 // set name 00410 rGen.Name("MtcPro(" + rGen.Name() + ")" ); 00411 } 00412 00413 // wrapper 00414 void mtcProjectNonDet(const mtcGenerator& rGen, const EventSet& rProjectAlphabet, mtcGenerator& rResGen) { 00415 rResGen=rGen; 00416 mtcProjectNonDet(rResGen,rProjectAlphabet); 00417 } 00418 00419 // mtcProject(rGen, rProjectAlphabet, rResGen&) 00420 void mtcProject(const mtcGenerator& rGen, const EventSet& rProjectAlphabet, mtcGenerator& rResGen) { 00421 // algorithm: 00422 // temporary copy of rGen 00423 mtcGenerator tmp; 00424 // temporarily assign rGen to rResGen 00425 mtcGenerator copyGen = mtcGenerator(rGen); 00426 // project rResGen with respect to rProjectAlphabet 00427 mtcProjectNonDet(copyGen, rProjectAlphabet); 00428 #ifdef FAUDES_DEBUG_FUNCTION 00429 FD_WARN("mtcProject: debug out") 00430 copyGen.Write("tmp_project_nd.gen"); 00431 #endif 00432 // put deterministic result into tmp 00433 mtcDeterministic(copyGen, tmp); 00434 #ifdef FAUDES_DEBUG_FUNCTION 00435 FD_WARN("mtcProject: debug out") 00436 tmp.Write("tmp_project_d.gen"); 00437 #endif 00438 // minimize states and rewrite result to rResGen 00439 mtcStateMin(tmp, rResGen); 00440 #ifdef FAUDES_DEBUG_FUNCTION 00441 FD_WARN("mtcProject: debug out") 00442 rResGen.Write("tmp_project_m.gen"); 00443 #endif 00444 // set controllability status TODO: other event attributes 00445 rResGen.SetControllable(rGen.ControllableEvents()*rProjectAlphabet); 00446 // set name 00447 rResGen.Name(rResGen.Name()+": mtcProject"); 00448 } 00449 00450 00451 // mtcProject(rGen, rProjectAlphabet, rEntryStatesMap&, rResGen&) 00452 void mtcProject(const mtcGenerator& rGen, const EventSet& rProjectAlphabet, 00453 std::map<Idx,StateSet>& rEntryStatesMap, mtcGenerator& rResGen) { 00454 // temporary copy of rGen 00455 mtcGenerator tmp; 00456 mtcGenerator copyGen = mtcGenerator(rGen); 00457 // temporary entry state map 00458 std::map<Idx,StateSet> tmp_entrystatemap; 00459 // temporarily assign rGen to rResGen 00460 // std::cout << " copied low-level generator " << std::endl; 00461 // copyGen.DWrite(); 00462 // project tmp with respect to palphabet 00463 mtcProjectNonDet(copyGen, rProjectAlphabet); 00464 00465 // put deterministic result into tmp 00466 mtcDeterministic(copyGen, tmp_entrystatemap, tmp); 00467 // write entry state map for minimized generator 00468 std::vector<StateSet> subsets; 00469 std::vector<Idx> newindices; 00470 // minimize states and rewrite result to rResGen 00471 mtcStateMin(tmp, rResGen, subsets, newindices); 00472 // rResGen.DWrite(); 00473 // build entry state map 00474 std::vector<StateSet>::size_type i; 00475 std::map<Idx,StateSet>::iterator esmit; 00476 StateSet::Iterator sit; 00477 for (i = 0; i < subsets.size(); ++i) { 00478 StateSet tmpstates; 00479 for (sit = subsets[i].Begin(); sit != subsets[i].End(); ++sit) { 00480 esmit = tmp_entrystatemap.find(*sit); 00481 #ifdef FD_CHECKED 00482 if (esmit == tmp_entrystatemap.end()) { 00483 FD_WARN("mtcproject internal error"); 00484 abort(); 00485 } 00486 #endif 00487 // insert entry states in temporary StateSet 00488 tmpstates.InsertSet(esmit->second); 00489 } 00490 00491 rEntryStatesMap.insert(std::make_pair(newindices[i], tmpstates)); 00492 } 00493 } 00494 00495 00496 // mtcInvProject(rGen&, rProjectAlphabet) 00497 void mtcInvProject(mtcGenerator& rGen, const EventSet& rProjectAlphabet) { 00498 // test if the alphabet of the generator is included in the given alphabet 00499 if(! (rProjectAlphabet >= rGen.Alphabet() ) ){ 00500 std::stringstream errstr; 00501 errstr << "Input alphabet has to contain alphabet of generator \"" << rGen.Name() << "\""; 00502 throw Exception("InvProject(Generator,EventSet)", errstr.str(), 506); 00503 } 00504 EventSet newevents = rProjectAlphabet - rGen.Alphabet(); 00505 // insert events into generator 00506 rGen.InsEvents(newevents); 00507 FD_DF("mtcInvProject: adding events \"" << newevents.ToString() << "\" at every state"); 00508 StateSet::Iterator lit; 00509 EventSet::Iterator eit; 00510 for (lit = rGen.StatesBegin(); lit != rGen.StatesEnd(); ++lit) { 00511 for (eit = newevents.Begin(); eit != newevents.End(); ++eit) 00512 rGen.SetTransition(*lit, *eit, *lit); 00513 } 00514 } 00515 00516 // RTI wrapper 00517 void mtcInvProject(const mtcGenerator& rGen, const EventSet& rProjectAlphabet, mtcGenerator& rResGen) { 00518 rResGen=rGen; 00519 mtcInvProject(rResGen,rProjectAlphabet); 00520 } 00521 00522 } // namespace faudes |
libFAUDES 2.16b --- 2010-9-8 --- c++ source docu by doxygen 1.6.3