libFAUDES
Sections
Index
|
syn_supcon.cppGo to the documentation of this file.00001 /** @file syn_supcon.cpp Supremal controllable sublanguage */ 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 "syn_supcon.h" 00024 00025 00026 namespace faudes { 00027 00028 00029 00030 00031 /* 00032 *************************************************************************************** 00033 *************************************************************************************** 00034 Implementation 00035 *************************************************************************************** 00036 *************************************************************************************** 00037 */ 00038 00039 00040 /* 00041 Revision fro libFAUDES 2.20b: 00042 00043 SupCon and IsControllable used to share the same algorithm to identify critical 00044 states, implemented as IsControllableUnchecked(). 00045 00046 The implementation, however, was only correct under the assumption that the state set of the 00047 supervisor/candidate H would also distinguish plant states. The later assumption is 00048 true in the context of SupCon, where the candidate is built as the parallel composition. 00049 It is not true in general. 00050 00051 Thus, in libFAUDES 2.20b the original algorithm was moved from IsControllableUnchecked to 00052 SupConUnchecked and IsControllableUnchecked was reimplemented. 00053 */ 00054 00055 00056 // SupConUnchecked(rPlantGen, rCAlph, rSupCandGen) 00057 void SupConUnchecked( 00058 const Generator& rPlantGen, // aka G 00059 const EventSet& rCAlph, 00060 Generator& rSupCandGen // aka H 00061 ) 00062 { 00063 FD_DF("SupConUnchecked(" << &rSupCandGen << "," << &rPlantGen << ")"); 00064 00065 // bail out if plant or candidate contain no initial states 00066 if(rPlantGen.InitStatesEmpty() || rSupCandGen.InitStatesEmpty()) 00067 return; 00068 00069 // todo stack (pairs of states) 00070 std::stack<Idx> todog, todoh; 00071 // set of already processed states of H (this is where we need H-states to also distinguish G-states) 00072 StateSet processed; 00073 // reverse sorted transition relation of H (to be built on the fly) 00074 TransSetX2EvX1 rtransrel; 00075 // critical states 00076 StateSet critical; 00077 00078 // push combined initial state on todo stack 00079 todog.push(*rPlantGen.InitStatesBegin()); 00080 todoh.push(*rSupCandGen.InitStatesBegin()); 00081 FD_DF("SupCon: todo push: (" << rPlantGen.SStr(*rPlantGen.InitStatesBegin()) << "|" 00082 << rSupCandGen.SStr(*rSupCandGen.InitStatesBegin()) << ")"); 00083 00084 // process todo stack 00085 while (! todog.empty()) { 00086 // allow for user interrupt 00087 // LoopCallback(); 00088 // allow for user interrupt, incl progress report 00089 FD_WPC(1,2,"Controllability(): iterating states"); 00090 // get top element from todo stack 00091 Idx currentg = todog.top(); 00092 Idx currenth = todoh.top(); 00093 todog.pop(); 00094 todoh.pop(); 00095 FD_DF("SupCon: todo pop: (" << rPlantGen.SStr(currentg) << "|" 00096 << rSupCandGen.SStr(currenth) << ")"); 00097 00098 // break on doublets (tmoor 201104) 00099 if(processed.Exists(currenth)) continue; 00100 00101 #ifdef FAUDES_DEBUG_FUNCTION 00102 TransSet::Iterator _titg, _tith; 00103 // print all transitions of current states 00104 FD_DF("SupCon: transitions from current states:"); 00105 for (_titg = rPlantGen.TransRelBegin(currentg); _titg != rPlantGen.TransRelEnd(currentg); ++_titg) 00106 FD_DF("SupCon: g: " << rPlantGen.SStr(_titg->X1) << "-" 00107 << rPlantGen.EStr(_titg->Ev) << "-" << rPlantGen.SStr(_titg->X2)); 00108 for (_tith = rSupCandGen.TransRelBegin(currenth); _tith != rSupCandGen.TransRelEnd(currenth); ++_tith) 00109 FD_DF("SupCon: h: " << rSupCandGen.SStr(_tith->X1) << "-" 00110 << rSupCandGen.EStr(_tith->Ev) << "-" << rSupCandGen.SStr(_tith->X2)); 00111 #endif 00112 00113 // process all h transitions while there could be matching g transitions 00114 TransSet::Iterator titg = rPlantGen.TransRelBegin(currentg); 00115 TransSet::Iterator titg_end = rPlantGen.TransRelEnd(currentg); 00116 TransSet::Iterator tith = rSupCandGen.TransRelBegin(currenth); 00117 TransSet::Iterator tith_end = rSupCandGen.TransRelEnd(currenth); 00118 while ((tith != tith_end) && (titg != titg_end)) { 00119 FD_DF("SupCon: processing g-transition: " << rPlantGen.SStr(titg->X1) 00120 << "-" << rPlantGen.EStr(titg->Ev) << "-" << rPlantGen.SStr(titg->X2)); 00121 FD_DF("SupCon: processing h-transition: " << rSupCandGen.SStr(tith->X1) 00122 << "-" << rSupCandGen.EStr(tith->Ev) << "-" << rSupCandGen.SStr(tith->X2)); 00123 // increment tith and titg case A: process common events 00124 if (titg->Ev == tith->Ev) { 00125 FD_DF("SupCon: processing common event " << rPlantGen.EStr(titg->Ev)); 00126 // add to todo list if state not processed (tmoor 201104: record next H state on stack) 00127 if(!processed.Exists(tith->X2)) { 00128 todog.push(titg->X2); 00129 todoh.push(tith->X2); 00130 FD_DF("SupCon: todo push: (" << rPlantGen.SStr(titg->X2) << "|" 00131 << rSupCandGen.SStr(tith->X2) << ")"); 00132 } 00133 // if h successor state is not critical add transition to rtransrel 00134 if (!critical.Exists(tith->X2)) { 00135 rtransrel.Insert(*tith); 00136 FD_DF("SupCon: incrementing g and h transrel"); 00137 ++titg; 00138 ++tith; 00139 } 00140 // if successor state is critical and event uncontrollable 00141 else if (!rCAlph.Exists(titg->Ev)) { 00142 FD_DF("SupCon: successor state " << rSupCandGen.SStr(tith->X2) << 00143 " critical and event " << rPlantGen.EStr(titg->Ev) << " uncontrollable:"); 00144 FD_DF("SupCon: TraverseUncontrollableBackwards(" << rSupCandGen.SStr(currenth) << ")"); 00145 TraverseUncontrollableBackwards(rCAlph, rtransrel, critical, currenth); 00146 #ifdef FAUDES_CHECKED 00147 // just increment transrel iterators to find all h transitions not in g 00148 FD_DF("IsControllable: incrementing g an h transrel (FAUDES_CHECKED)"); 00149 ++titg; 00150 ++tith; 00151 break; 00152 #else 00153 // exit all loops 00154 titg = titg_end; 00155 tith = tith_end; 00156 break; 00157 #endif 00158 } 00159 // if successor state is critical and event controllable 00160 else { 00161 FD_DF("SupCon: incrementing g and h transrel"); 00162 ++titg; 00163 ++tith; 00164 } 00165 } 00166 // increment tith and titg case B: process g event that is not enabled in h 00167 else if (titg->Ev < tith->Ev) { 00168 FD_DF("SupCon: asynchronous execution of event " 00169 << rPlantGen.EStr(titg->Ev) << " in g while " << rSupCandGen.EStr(tith->Ev) 00170 << " in h"); 00171 // if uncontrollable transition violates specification 00172 // delete state from rResGen and put into criticalset 00173 if (!rCAlph.Exists(titg->Ev)) { 00174 FD_DF("SupCon: asynchronous event " << rPlantGen.EStr(titg->Ev) 00175 << " in g is uncontrollable"); 00176 FD_DF("SupCon: TraverseUncontrollableBackwards(" << rSupCandGen.SStr(currenth) << ")"); 00177 TraverseUncontrollableBackwards(rCAlph, rtransrel, critical, currenth); 00178 // exit all loops over g transrel 00179 titg = titg_end; 00180 break; 00181 } 00182 FD_DF("SupCon: incrementing g transrel"); 00183 ++titg; 00184 } 00185 // increment tith and titg case C: process h event that is not enabled in g 00186 else { 00187 // #ifdef FAUDES_CHECKED 00188 // FD_WARN("SupCon: transition " << rSupCandGen.TStr(*tith) 00189 // << " in specification h not found in g"); 00190 // #endif 00191 FD_DF("SupCon: incrementing h transrel"); 00192 ++tith; 00193 } 00194 } // end while tith and titg 00195 // increment tith and titg case D: process leftover g events 00196 while (titg != titg_end) { 00197 FD_DF("SupCon: asynchronous execution of event " 00198 << rPlantGen.EStr(titg->Ev) << " in g at end of h"); 00199 FD_DF("SupCon: actual g-transition: " << rPlantGen.SStr(titg->X1) 00200 << "-" << rPlantGen.EStr(titg->Ev) << "-" << rPlantGen.SStr(titg->X2)); 00201 FD_DF("SupCon: actual h-transition: end"); 00202 // if uncontrollable transition violates specification 00203 if (!rCAlph.Exists(titg->Ev)) { 00204 FD_DF("SupCon: asynchronous execution of uncontrollable event " 00205 << rPlantGen.EStr(titg->Ev) << " in g"); 00206 FD_DF("SupCon: TraverseUncontrollableBackwards(" << rPlantGen.SStr(currenth) << ")"); 00207 TraverseUncontrollableBackwards(rCAlph, rtransrel, critical, currenth); 00208 // exit this loop 00209 break; 00210 } 00211 FD_DF("SupCon: incrementing g transrel"); 00212 ++titg; 00213 } 00214 //#ifdef FAUDES_CHECKED 00215 // increment tith and titg case E: process leftover h events 00216 //while (tith != tith_end) { 00217 // FD_WARN("SupCon: transition " << rSupCandGen.TStr(*tith) << " in specification h not found in g"); 00218 // FD_DF("SupCon: incrementing h transrel"); 00219 // ++tith; 00220 //} 00221 //#endif 00222 processed.Insert(currenth); 00223 } //end while todog 00224 00225 // remove all states that have been identified as critical or that have 00226 // been not processed 00227 critical = rSupCandGen.States() - ( processed - critical ); 00228 rSupCandGen.DelStates(critical); 00229 } 00230 00231 00232 00233 /* 00234 Revision fro libFAUDES 2.20b: 00235 00236 The re-implemented version will only report states as critical 00237 if they disable an uncontrollable plant event. No reverse 00238 search is performed. 00239 */ 00240 00241 00242 // IsControllableUnchecked(rPlantGen, rCAlph, rSupCandGen, rCriticalStates) 00243 bool IsControllableUnchecked( 00244 const Generator& rPlantGen, 00245 const EventSet& rCAlph, 00246 const Generator& rSupCandGen, 00247 StateSet& rCriticalStates) 00248 { 00249 FD_DF("IsControllableUnchecked(" << &rSupCandGen << "," << &rPlantGen << ")"); 00250 00251 // todo stack 00252 std::stack< std::pair<Idx,Idx> > todo; 00253 // set of already processed states 00254 std::set< std::pair<Idx,Idx> > processed; 00255 00256 // PREPARE RESULT: 00257 rCriticalStates.Clear(); 00258 rCriticalStates.Name("CriticalStates"); 00259 00260 // return true (controllable) if there is no initial state 00261 if(rPlantGen.InitStatesEmpty() || rSupCandGen.InitStatesEmpty()) 00262 return true; 00263 00264 // push combined initial state on todo stack 00265 todo.push( std::make_pair(*rPlantGen.InitStatesBegin(),*rSupCandGen.InitStatesBegin()) ); 00266 FD_DF("IsControllable: todo push: (" << rPlantGen.SStr(*rPlantGen.InitStatesBegin()) << "|" 00267 << rSupCandGen.SStr(*rSupCandGen.InitStatesBegin()) << ")"); 00268 00269 // process todo stack 00270 while (! todo.empty()) { 00271 // allow for user interrupt 00272 // LoopCallback(); 00273 // allow for user interrupt, incl progress report 00274 FD_WPC(1,2,"Controllability(): iterating states"); 00275 // get top element from todo stack 00276 std::pair<Idx,Idx> current = todo.top(); todo.pop(); 00277 processed.insert(current); 00278 Idx currentg = current.first; 00279 Idx currenth = current.second; 00280 FD_DF("IsControllable: todo pop: (" << rPlantGen.SStr(currentg) << "|" 00281 << rSupCandGen.SStr(currenth) << ")"); 00282 00283 #ifdef FAUDES_DEBUG_FUNCTION 00284 TransSet::Iterator _titg, _tith; 00285 // print all transitions of current states 00286 FD_DF("IsControllable: transitions from current states:"); 00287 for (_titg = rPlantGen.TransRelBegin(currentg); _titg != rPlantGen.TransRelEnd(currentg); ++_titg) 00288 FD_DF("IsControllable: g: " << rPlantGen.SStr(_titg->X1) << "-" 00289 << rPlantGen.EStr(_titg->Ev) << "-" << rPlantGen.SStr(_titg->X2)); 00290 for (_tith = rSupCandGen.TransRelBegin(currenth); _tith != rSupCandGen.TransRelEnd(currenth); ++_tith) 00291 FD_DF("IsControllable: h: " << rSupCandGen.SStr(_tith->X1) << "-" 00292 << rSupCandGen.EStr(_tith->Ev) << "-" << rSupCandGen.SStr(_tith->X2)); 00293 #endif 00294 00295 // process all h transitions while there could be matching g transitions 00296 TransSet::Iterator titg = rPlantGen.TransRelBegin(currentg); 00297 TransSet::Iterator titg_end = rPlantGen.TransRelEnd(currentg); 00298 TransSet::Iterator tith = rSupCandGen.TransRelBegin(currenth); 00299 TransSet::Iterator tith_end = rSupCandGen.TransRelEnd(currenth); 00300 while ((tith != tith_end) && (titg != titg_end)) { 00301 FD_DF("IsControllable: processing g-transition: " << rPlantGen.SStr(titg->X1) 00302 << "-" << rPlantGen.EStr(titg->Ev) << "-" << rPlantGen.SStr(titg->X2)); 00303 FD_DF("IsControllable: processing h-transition: " << rSupCandGen.SStr(tith->X1) 00304 << "-" << rSupCandGen.EStr(tith->Ev) << "-" << rSupCandGen.SStr(tith->X2)); 00305 // increment tith and titg case A: process common events 00306 if (titg->Ev == tith->Ev) { 00307 FD_DF("IsControllable: processing common event " << rPlantGen.EStr(titg->Ev)); 00308 // form next state and add to stack 00309 std::pair<Idx,Idx> next = std::make_pair(titg->X2,tith->X2); 00310 // add to todo list if not processed so far 00311 if(processed.find(next)==processed.end()) { 00312 FD_DF("IsControllable: todo push: (" << rPlantGen.SStr(titg->X2) << "|" 00313 << rSupCandGen.SStr(tith->X2) << ")"); 00314 todo.push(next); 00315 } 00316 // proceed 00317 ++titg; 00318 ++tith; 00319 } 00320 // increment tith and titg case B: process g event that is not enabled in h 00321 else if (titg->Ev < tith->Ev) { 00322 FD_DF("IsControllable: asynchronous execution of event " 00323 << rPlantGen.EStr(titg->Ev) << " in g while " << rSupCandGen.EStr(tith->Ev) 00324 << " in h"); 00325 // if uncontrollable transition violates specification 00326 // record that state as critical 00327 if (!rCAlph.Exists(titg->Ev)) { 00328 FD_DF("IsControllable: asynchronous event " << rPlantGen.EStr(titg->Ev) 00329 << " in g is uncontrollable"); 00330 FD_DF("IsControllable: TraverseUncontrollableBackwards(" << rSupCandGen.SStr(currenth) << ")"); 00331 rCriticalStates.Insert(currenth); 00332 // exit all loops over g transrel 00333 titg = titg_end; 00334 break; 00335 } 00336 FD_DF("IsControllable: incrementing g transrel"); 00337 ++titg; 00338 } 00339 // increment tith and titg case C: process h event that is not enabled in g 00340 else { 00341 // #ifdef FAUDES_CHECKED 00342 // FD_WARN("IsControllable: transition " << rSupCandGen.TStr(*tith) 00343 // << " in specification h not found in g"); 00344 // #endif 00345 FD_DF("IsControllable: incrementing h transrel"); 00346 ++tith; 00347 } 00348 } // end while tith and titg 00349 // increment tith and titg case D: process leftover g events 00350 while (titg != titg_end) { 00351 FD_DF("IsControllable: asynchronous execution of event " 00352 << rPlantGen.EStr(titg->Ev) << " in g at end of h"); 00353 FD_DF("IsControllable: actual g-transition: " << rPlantGen.SStr(titg->X1) 00354 << "-" << rPlantGen.EStr(titg->Ev) << "-" << rPlantGen.SStr(titg->X2)); 00355 FD_DF("IsControllable: actual h-transition: end"); 00356 // if uncontrollable transition violates specification 00357 if (!rCAlph.Exists(titg->Ev)) { 00358 FD_DF("IsControllable: asynchronous execution of uncontrollable event " 00359 << rPlantGen.EStr(titg->Ev) << " in g"); 00360 FD_DF("IsControllable: TraverseUncontrollableBackwards(" << rPlantGen.SStr(currenth) << ")"); 00361 rCriticalStates.Insert(currenth); 00362 // exit this loop 00363 break; 00364 } 00365 FD_DF("IsControllable: incrementing g transrel"); 00366 ++titg; 00367 } 00368 //#ifdef FAUDES_CHECKED 00369 // increment tith and titg case E: process leftover h events 00370 //while (tith != tith_end) { 00371 // FD_WARN("IsControllable: transition " << rSupCandGen.TStr(*tith) << " in specification h not found in g"); 00372 // FD_DF("IsControllable: incrementing h transrel"); 00373 // ++tith; 00374 //} 00375 //#endif 00376 } //end while todo 00377 00378 00379 // return identified critical states 00380 return rCriticalStates.Empty(); 00381 } 00382 00383 00384 00385 00386 00387 // SupconParallel(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, rResGen) 00388 void SupconParallel( 00389 const Generator& rPlantGen, 00390 const EventSet& rCAlph, 00391 const Generator& rSpecGen, 00392 std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, 00393 Generator& rResGen) 00394 { 00395 FD_DF("SupconParallel(" << &rPlantGen << "," << &rSpecGen << ")"); 00396 00397 // HELPERS: 00398 00399 // todo stack 00400 std::stack< std::pair<Idx,Idx> > todo; 00401 // set of critical states 00402 StateSet critical; 00403 // actual pair, new pair 00404 std::pair<Idx,Idx> currentstates, newstates; 00405 // other stuff 00406 Idx tmpstate; 00407 std::map< std::pair<Idx,Idx>, Idx>::iterator rcmapit; 00408 StateSet::Iterator lit1, lit2; 00409 TransSet::Iterator titg, titg_end, tith, tith_end; 00410 00411 // prepare 00412 rResGen.ClearStates(); 00413 00414 // ALGORITHM: 00415 00416 if (rPlantGen.InitStatesEmpty()) { 00417 FD_DF("SupconParallel: plant got no initial states. " 00418 << "parallel composition contains empty language."); 00419 return; 00420 } 00421 if (rSpecGen.InitStatesEmpty()) { 00422 FD_DF("SupconParallel: spec got no initial states. " 00423 << "parallel composition contains empty language."); 00424 return; 00425 } 00426 00427 // create initial state 00428 currentstates = std::make_pair(*rPlantGen.InitStatesBegin(), *rSpecGen.InitStatesBegin()); 00429 todo.push(currentstates); 00430 rReverseCompositionMap[currentstates] = rResGen.InsInitState(); 00431 FD_DF("SupconParallel: NEW ISTATE: (" << rPlantGen.SStr(currentstates.first) 00432 << "|" << rSpecGen.SStr(currentstates.second) << ") -> " 00433 << rReverseCompositionMap[currentstates]); 00434 if (rPlantGen.ExistsMarkedState(*rPlantGen.InitStatesBegin()) 00435 && rSpecGen.ExistsMarkedState(*rSpecGen.InitStatesBegin())) { 00436 rResGen.SetMarkedState(rReverseCompositionMap[currentstates]); 00437 FD_DF("SupconParallel: recent ISTATE Marked"); 00438 } 00439 00440 // do parallel composition of allowed states by deleting critical states on the fly. 00441 // this creates an accessible generator 00442 FD_DF("SupconParallel: *** processing reachable states ***"); 00443 while (! todo.empty()) { 00444 // allow for user interrupt 00445 // LoopCallback(); 00446 // allow for user interrupt, incl progress report 00447 FD_WPC(rReverseCompositionMap.size(),rReverseCompositionMap.size()+todo.size(),"SupconParallel(): processing"); 00448 // get next reachable pair of states from todo stack 00449 currentstates = todo.top(); 00450 todo.pop(); 00451 FD_DF("SupconParallel: todo pop: (" << rPlantGen.SStr(currentstates.first) 00452 << "|" << rSpecGen.SStr(currentstates.second) << ") -> " 00453 << rReverseCompositionMap[currentstates]); 00454 00455 titg = rPlantGen.TransRelBegin(currentstates.first); 00456 titg_end = rPlantGen.TransRelEnd(currentstates.first); 00457 tith = rSpecGen.TransRelBegin(currentstates.second); 00458 tith_end = rSpecGen.TransRelEnd(currentstates.second); 00459 00460 #ifdef FAUDES_DEBUG_FUNCTION 00461 // print all transitions of current states 00462 FD_DF("SupConParallel: transitions from current states:"); 00463 for (;titg != titg_end; ++titg) { 00464 FD_DF("SupConParallel: g: " << rPlantGen.SStr(titg->X1) << "-" << rPlantGen.EStr(titg->Ev) 00465 << "-" << rPlantGen.SStr(titg->X2)); 00466 } 00467 for (;tith != tith_end; ++tith) { 00468 FD_DF("SupConParallel: h: " << rSpecGen.SStr(tith->X1) << "-" << rSpecGen.EStr(tith->Ev) 00469 << "-" << rSpecGen.SStr(tith->X2)); 00470 } 00471 titg = rPlantGen.TransRelBegin(currentstates.first); 00472 tith = rSpecGen.TransRelBegin(currentstates.second); 00473 #endif 00474 00475 // process all h transitions while there could be matching g transitions 00476 while ((tith != tith_end) && (titg != titg_end)) { 00477 FD_DF("SupconParallel: current g-transition: " << rPlantGen.TStr(*titg) ); 00478 FD_DF("SupconParallel: actual h-transition: " << rSpecGen.TStr(*tith)); 00479 // increment titg and titg, case A: execute common events 00480 if (titg->Ev == tith->Ev) { 00481 FD_DF("SupconParallel: executing common event " << rPlantGen.EStr(titg->Ev)); 00482 newstates = std::make_pair(titg->X2, tith->X2); 00483 rcmapit = rReverseCompositionMap.find(newstates); 00484 // if state is new: add to todo list and result 00485 if (rcmapit == rReverseCompositionMap.end()) { 00486 todo.push(newstates); 00487 // if marked 00488 if (rPlantGen.ExistsMarkedState(newstates.first) && 00489 rSpecGen.ExistsMarkedState(newstates.second)) { 00490 tmpstate = rResGen.InsMarkedState(); 00491 FD_DF("SupconParallel: NEW MSTATE: (" << rPlantGen.SStr(newstates.first) << "|" 00492 << rSpecGen.SStr(newstates.second) << ") -> " << tmpstate); 00493 } 00494 // if not maked 00495 else { 00496 tmpstate = rResGen.InsState(); 00497 FD_DF("SupconParallel: NEW STATE: (" << rPlantGen.SStr(newstates.first) << "|" 00498 << rSpecGen.SStr(newstates.second) << ") -> " << tmpstate); 00499 } 00500 rReverseCompositionMap[newstates] = tmpstate; 00501 FD_DF("SupconParallel: todo push: (" << rPlantGen.SStr(newstates.first) 00502 << "|" << rSpecGen.SStr(newstates.second) << ") -> " << tmpstate); 00503 } 00504 // if state already exists 00505 else { 00506 tmpstate = rcmapit->second; 00507 } 00508 // if successor state is not critical add transition and increment titg and tith 00509 if (! critical.Exists(tmpstate)) { 00510 FD_DF("SupconParallel: ADDING TRANSITION " 00511 << rPlantGen.SStr(rReverseCompositionMap[currentstates]) << "-" << rPlantGen.EStr(titg->Ev) 00512 << "-" << rPlantGen.SStr(tmpstate)); 00513 rResGen.SetTransition(rReverseCompositionMap[currentstates], titg->Ev, tmpstate); 00514 FD_DF("SupconParallel: incrementing g and h transrel"); 00515 ++titg; 00516 ++tith; 00517 } 00518 // if successor state is critical and event is uncontrollable then delete current state 00519 else if (!rCAlph.Exists(titg->Ev)) { 00520 FD_DF("SupconParallel: successor " << rSpecGen.SStr(tmpstate) 00521 << "in critical and common event " << rSpecGen.EStr(titg->Ev) 00522 << " uncontrollable:"); 00523 FD_DF("SupconParallel: critical insert" << rPlantGen.SStr(tmpstate)); 00524 critical.Insert(tmpstate); 00525 #ifdef FAUDES_CHECKED 00526 // do not end while loops here for detecting all h transitions 00527 // not in g 00528 FD_DF("SupconParallel: incrementing g and h transrel (FAUDES_CHECKED)"); 00529 ++titg; 00530 ++tith; 00531 #else 00532 // exit all loops 00533 titg = titg_end; 00534 tith = tith_end; 00535 #endif 00536 } 00537 // else if successor state in critical and event controllable increment titg and tith 00538 else { 00539 FD_DF("SupconParallel: incrementing g and h transrel"); 00540 ++titg; 00541 ++tith; 00542 } 00543 } // end: if processing common event 00544 // increment titg and titg, case B: process g event that is not enebled for h 00545 else if (titg->Ev < tith->Ev) { 00546 FD_DF("SupconParallel: asynchronous execution of event " 00547 << rPlantGen.EStr(titg->Ev) << " in g while " << rSpecGen.EStr(tith->Ev) << " in h"); 00548 // if uncontrollable transition leaves specification 00549 // delete state from res and put into criticalset 00550 if (!rCAlph.Exists(titg->Ev)) { 00551 FD_DF("SupconParallel: asynchronous event " << rPlantGen.EStr(titg->Ev) 00552 << " in g is uncontrollable"); 00553 tmpstate = rReverseCompositionMap[currentstates]; 00554 FD_DF("SupconParallel: critical insert" << rPlantGen.SStr(tmpstate)); 00555 critical.Insert(tmpstate); 00556 // exit all loops 00557 titg = titg_end; 00558 tith = tith_end; 00559 break; 00560 } 00561 FD_DF("SupconParallel: incrementing g transrel"); 00562 ++titg; 00563 } 00564 // increment titg and titg, case C: process h event that is not enabled for g 00565 else { 00566 //#ifdef FAUDES_CHECKED 00567 // FD_WARN("SupconParallel: transition " << rSpecGen.TStr(*tith) << " in specification h not found in g"); 00568 //#endif 00569 FD_DF("SupconParallel: incrementing h transrel"); 00570 ++tith; 00571 } 00572 } // end while incrementing tith and titg 00573 // increment titg and titg, case D: process leftover events of g 00574 while (titg != titg_end) { 00575 FD_DF("SupconParallel: asynchronous execution of event " 00576 << rPlantGen.EStr(titg->Ev) << " in g at end of h"); 00577 FD_DF("SupconParallel: actual g-transition: " << rPlantGen.SStr(titg->X1) 00578 << "-" << rPlantGen.EStr(titg->Ev) << "-" << rPlantGen.SStr(titg->X2)); 00579 FD_DF("SupconParallel: actual h-transition: end"); 00580 // if uncontrollable transition leaves specification 00581 if (!rCAlph.Exists(titg->Ev)) { 00582 tmpstate = rReverseCompositionMap[currentstates]; 00583 FD_DF("SupconParallel: asynchron executed uncontrollable end " 00584 << "event " << rPlantGen.EStr(titg->Ev) << " leaves specification:"); 00585 FD_DF("SupconParallel: critical insert" << rPlantGen.SStr(tmpstate)); 00586 critical.Insert(tmpstate); 00587 // exit this loop 00588 break; 00589 } 00590 FD_DF("SupconParallel: incrementing g transrel"); 00591 ++titg; 00592 } 00593 //#ifdef FAUDES_CHECKED 00594 // increment titg and titg, case E: process leftover events of h 00595 //while (txoith != tith_end) { 00596 // FD_WARN("SupconParallel: transition " << rSpecGen.TStr(*tith) << " in specification h not found in g"); 00597 // FD_DF("SupconParallel: incrementing h transrel"); 00598 // ++tith; 00599 //} 00600 //#endif 00601 } // while todo 00602 FD_DF("SupconParallel: deleting critical states..."); 00603 StateSet::Iterator sit; 00604 for(sit = critical.Begin(); sit!= critical.End(); ++sit) 00605 rResGen.DelState(*sit); 00606 //rResGen.DelStates(critical); 00607 } 00608 00609 00610 00611 // SupConNBUnchecked(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, rResGen) 00612 void SupConNBUnchecked( 00613 const Generator& rPlantGen, 00614 const EventSet& rCAlph, 00615 const Generator& rSpecGen, 00616 std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, 00617 Generator& rResGen) 00618 { 00619 FD_DF("SupConNB(" << &rPlantGen << "," << &rSpecGen << ")"); 00620 00621 // PREPARE RESULT: 00622 Generator* pResGen = &rResGen; 00623 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) { 00624 pResGen= rResGen.New(); 00625 } 00626 pResGen->Clear(); 00627 pResGen->Name(CollapsString("SupConNB(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))")); 00628 pResGen->InjectAlphabet(rPlantGen.Alphabet()); 00629 00630 // controllable events 00631 FD_DF("SupConNB: controllable events: " << rCAlph.ToString()); 00632 00633 // ALGORITHM: 00634 SupconParallel(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, *pResGen); 00635 00636 // make resulting generator trim until it's fully controllable 00637 while (1) { 00638 if(pResGen->Empty()) break; 00639 Idx state_num = pResGen->Size(); 00640 SupConUnchecked(rPlantGen, rCAlph, *pResGen); 00641 pResGen->Trim(); 00642 if(pResGen->Size() == state_num) break; 00643 } 00644 00645 // convenience state names 00646 if(rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && rResGen.StateNamesEnabled()) 00647 SetComposedStateNames(rPlantGen, rSpecGen, rReverseCompositionMap, *pResGen); 00648 else 00649 pResGen->ClearStateNames(); 00650 00651 // copy result 00652 if(pResGen != &rResGen) { 00653 pResGen->Move(rResGen); 00654 delete pResGen; 00655 } 00656 00657 } 00658 00659 // ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen) 00660 void ControlProblemConsistencyCheck( 00661 const Generator& rPlantGen, 00662 const EventSet& rCAlph, 00663 const Generator& rSpecGen) 00664 { 00665 00666 // alphabets must match 00667 if ( rPlantGen.Alphabet() != rSpecGen.Alphabet()) { 00668 EventSet only_in_plant = rPlantGen.Alphabet() - rSpecGen.Alphabet(); 00669 EventSet only_in_spec = rSpecGen.Alphabet() - rPlantGen.Alphabet(); 00670 only_in_plant.Name("Only_In_Plant"); 00671 only_in_spec.Name("Only_In_Specification"); 00672 std::stringstream errstr; 00673 errstr << "Alphabets of generators do not match."; 00674 if(!only_in_plant.Empty()) 00675 errstr << " " << only_in_plant.ToString() << "."; 00676 if(!only_in_spec.Empty()) 00677 errstr << " " << only_in_spec.ToString() << "."; 00678 throw Exception("SupCon/SupConNB", errstr.str(), 100); 00679 } 00680 00681 // TODO: add test for rCAlph <= Alphabet 00682 00683 // TODO: check symboltables to match 00684 00685 // plant and spec must be deterministic 00686 bool plant_det = rPlantGen.IsDeterministic(); 00687 bool spec_det = rSpecGen.IsDeterministic(); 00688 00689 if ((plant_det == false) && (spec_det == true)) { 00690 std::stringstream errstr; 00691 errstr << "Plant generator must be deterministic, " 00692 << "but is nondeterministic"; 00693 throw Exception("ControllableConsistencyCheck", errstr.str(), 201); 00694 } 00695 else if ((plant_det == true) && (spec_det == false)) { 00696 std::stringstream errstr; 00697 errstr << "Spec generator must be deterministic, " 00698 << "but is nondeterministic"; 00699 throw Exception("ControllableConsistencyCheck", errstr.str(), 203); 00700 } 00701 else if ((plant_det == false) && (spec_det == false)) { 00702 std::stringstream errstr; 00703 errstr << "Plant and spec generator must be deterministic, " 00704 << "but both are nondeterministic"; 00705 throw Exception("ControllableConsistencyCheck", errstr.str(), 204); 00706 } 00707 } 00708 00709 00710 /* 00711 **************************************** 00712 * SUPCON: WRAPPER / USER FUNCTIONS * 00713 **************************************** 00714 */ 00715 00716 00717 // IsControllable(rPlantGen, rCAlph, rSupCandGen) 00718 bool IsControllable( 00719 const Generator& rPlantGen, 00720 const EventSet& rCAlph, 00721 const Generator& rSupCandGen) 00722 { 00723 FD_DF("IsControllable(" << &rSupCandGen << "," << &rPlantGen << ")"); 00724 00725 // HELPERS: 00726 FD_DF("IsControllable: controllable events: " << rCAlph.ToString()); 00727 // critical set 00728 StateSet critical; 00729 00730 // CONSISTENCY CHECKS: 00731 ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSupCandGen); 00732 00733 // ALGORITHM: 00734 return IsControllableUnchecked(rPlantGen, rCAlph, rSupCandGen, critical); 00735 } 00736 00737 00738 // IsControllable(rPlantGen, rCAlph, rSupCandGen, critical) 00739 bool IsControllable( 00740 const Generator& rPlantGen, 00741 const EventSet& rCAlph, 00742 const Generator& rSupCandGen, 00743 StateSet& rCriticalStates) 00744 { 00745 FD_DF("IsControllable(" << &rSupCandGen << "," << &rPlantGen << ")"); 00746 00747 // CONSISTENCY CHECKS: 00748 ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSupCandGen); 00749 00750 // ALGORITHM: 00751 return IsControllableUnchecked(rPlantGen, rCAlph, rSupCandGen, rCriticalStates); 00752 } 00753 00754 00755 // SupConNB(rPlantGen, rCAlph, rSpecGen, rResGen) 00756 void SupConNB( 00757 const Generator& rPlantGen, 00758 const EventSet& rCAlph, 00759 const Generator& rSpecGen, 00760 Generator& rResGen) 00761 { 00762 00763 // CONSISTENCY CHECK: 00764 ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen); 00765 00766 // HELPERS: 00767 std::map< std::pair<Idx,Idx>, Idx> rcmap; 00768 00769 // ALGORITHM: 00770 SupConNBUnchecked(rPlantGen, rCAlph, rSpecGen, rcmap, rResGen); 00771 } 00772 00773 00774 00775 00776 // SupConNBNonDet(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, 00777 // pDetPlantGen, pDetSpecGen, rResGen) 00778 void SupConNBNonDet( 00779 const Generator& rPlantGen, 00780 const EventSet& rCAlph, 00781 const Generator& rSpecGen, 00782 std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, 00783 Generator rDetPlantGen, 00784 Generator rDetSpecGen, 00785 std::map<Idx,StateSet>& rPowerStatesPlant, 00786 std::map<Idx,StateSet>& rPowerStatesSpec, 00787 bool& rDetPlantBool, 00788 bool& rDetSpecBool, 00789 Generator& rResGen) 00790 { 00791 FD_DF("SupConNBNonDet(" << &rPlantGen << "," << &rSpecGen << ")"); 00792 00793 // alphabets must match 00794 if (rPlantGen.Alphabet() != rSpecGen.Alphabet()) { 00795 throw Exception("SupConNBNonDet", "Alphabets of generators don't match", 100); 00796 } 00797 00798 // PREPARE RESULT: 00799 Generator* pResGen = &rResGen; 00800 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) { 00801 pResGen= rResGen.New(); 00802 } 00803 pResGen->Clear(); 00804 pResGen->Name(CollapsString("SupConNBNonDet(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))")); 00805 pResGen->InjectAlphabet(rPlantGen.Alphabet()); 00806 00807 // HELPERS: 00808 rPowerStatesPlant.clear(); 00809 rPowerStatesSpec.clear(); 00810 00811 // controllable events 00812 FD_DF("SupConNB: controllable events: " << rCAlph.ToString()); 00813 00814 // pointers to actual generators 00815 Generator* plantp; 00816 Generator* specp; 00817 00818 // plant and spec determinism 00819 rDetPlantBool = rPlantGen.IsDeterministic(); 00820 rDetSpecBool = rSpecGen.IsDeterministic(); 00821 00822 // create deterministic generators and set pointers to the actual ones 00823 plantp = const_cast<Generator*>(&rPlantGen); 00824 specp = const_cast<Generator*>(&rSpecGen); 00825 if (rDetPlantBool == false) { 00826 Deterministic(rPlantGen, rPowerStatesPlant, rDetPlantGen); 00827 plantp = &rDetPlantGen; 00828 } 00829 if (rDetSpecBool == false) { 00830 Deterministic(rSpecGen, rPowerStatesSpec, rDetSpecGen); 00831 specp = &rDetSpecGen; 00832 } 00833 00834 // ALGORITHM: 00835 00836 // compute supervisor 00837 SupconParallel(*plantp, rCAlph, *specp, rReverseCompositionMap, *pResGen); 00838 00839 // make resulting generator trim until it's fully controllable 00840 while(1) { 00841 if(pResGen->Empty()) break; 00842 Idx state_num = pResGen->Size(); 00843 SupConUnchecked(*plantp, rCAlph, *pResGen); 00844 pResGen->Trim(); 00845 if(pResGen->Size() == state_num) break; 00846 } 00847 00848 // copy result 00849 if(pResGen != &rResGen) { 00850 pResGen->Move(rResGen); 00851 delete pResGen; 00852 } 00853 } 00854 00855 // SupCon(rPlantGen, rCAlph, rSpecGen, rResGen) 00856 void SupCon( 00857 const Generator& rPlantGen, 00858 const EventSet& rCAlph, 00859 const Generator& rSpecGen, 00860 Generator& rResGen) 00861 { 00862 // HELPERS: 00863 std::map< std::pair<Idx,Idx>, Idx> rcmap; 00864 00865 // ALGORITHM: 00866 SupCon(rPlantGen, rCAlph, rSpecGen, rcmap, rResGen); 00867 } 00868 00869 00870 // SupCon(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, rResGen) 00871 void SupCon( 00872 const Generator& rPlantGen, 00873 const EventSet& rCAlph, 00874 const Generator& rSpecGen, 00875 std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, 00876 Generator& rResGen) 00877 { 00878 FD_DF("SupCon(" << &rPlantGen << "," << &rSpecGen << ")"); 00879 00880 // PREPARE RESULT: 00881 00882 00883 // prepare result 00884 Generator* pResGen = &rResGen; 00885 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) { 00886 pResGen= rResGen.New(); 00887 } 00888 pResGen->Clear(); 00889 pResGen->Name(CollapsString("SupCon(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))")); 00890 pResGen->InjectAlphabet(rPlantGen.Alphabet()); 00891 00892 // HELPERS: 00893 FD_DF("SupCon: controllable events: " << rCAlph.ToString()); 00894 00895 // CONSISTENCY CHECK: 00896 ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen); 00897 00898 // ALGORITHM: 00899 00900 // parallel composition 00901 SupconParallel(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, *pResGen); 00902 // make resulting generator controllable 00903 SupConUnchecked(rPlantGen, rCAlph, *pResGen); 00904 00905 // convenience state names 00906 if (rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && rResGen.StateNamesEnabled()) 00907 SetComposedStateNames(rPlantGen, rSpecGen, rReverseCompositionMap, *pResGen); 00908 else 00909 pResGen->ClearStateNames(); 00910 00911 // copy result 00912 if(pResGen != &rResGen) { 00913 pResGen->Move(rResGen); 00914 delete pResGen; 00915 } 00916 } 00917 00918 00919 // TraverseUncontrollableBackwards(rCAlph, rtransrel, critical, current) 00920 void TraverseUncontrollableBackwards( 00921 const EventSet& rCAlph, 00922 TransSetX2EvX1& rtransrel, 00923 StateSet& rCriticalStates, 00924 Idx current) { 00925 FD_DF("TraverseUncontrollableBackwards: " << rCriticalStates.Str(current)); 00926 00927 // HELPERS: 00928 std::stack<Idx> todo; 00929 TransSetX2EvX1::Iterator rtit = rtransrel.BeginByX2(current); 00930 TransSetX2EvX1::Iterator rtit_end = rtransrel.EndByX2(current); 00931 00932 // ALGORITHM: 00933 rCriticalStates.Insert(current); 00934 todo.push(current); 00935 FD_DF("TraverseUncontrollableBackwards: current rCriticalStates set: " 00936 << rCriticalStates.ToString()); 00937 // process todo stack 00938 while (! todo.empty()) { 00939 // get top state from todo stack 00940 current = todo.top(); todo.pop(); 00941 // iteration over all transitions with x2 == current 00942 rtit_end = rtransrel.EndByX2(current); 00943 rtit = rtransrel.BeginByX2(current); 00944 for (; rtit != rtit_end; ++rtit) { 00945 // if uncontrollable event and predecessor state not already critical 00946 if ((!rCAlph.Exists(rtit->Ev)) && (! rCriticalStates.Exists(rtit->X1))) { 00947 FD_DF("TraverseUncontrollableBackwards: todo push " << rCriticalStates.Str(rtit->X1)); 00948 todo.push(rtit->X1); 00949 FD_DF("TraverseUncontrollableBackwards: critical insert: " << rCriticalStates.Str(rtit->X1)); 00950 rCriticalStates.Insert(rtit->X1); 00951 } 00952 } 00953 } // end while todo 00954 } 00955 00956 00957 // controllability test for System plant 00958 bool IsControllable( 00959 const System& rPlantGen, 00960 const Generator& rSupCandGen) 00961 { 00962 return IsControllable(rPlantGen, rPlantGen.ControllableEvents(), rSupCandGen); 00963 } 00964 00965 00966 // supcon for Systems: 00967 // uses and maintains controllablity from plant 00968 void SupConNB( 00969 const System& rPlantGen, 00970 const Generator& rSpecGen, 00971 Generator& rResGen) { 00972 00973 // prepare result 00974 Generator* pResGen = &rResGen; 00975 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) { 00976 pResGen= rResGen.New(); 00977 } 00978 00979 // execute 00980 SupConNB(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,*pResGen); 00981 00982 // copy all attributes of input alphabet 00983 pResGen->EventAttributes(rPlantGen.Alphabet()); 00984 00985 // copy result 00986 if(pResGen != &rResGen) { 00987 pResGen->Move(rResGen); 00988 delete pResGen; 00989 } 00990 00991 } 00992 00993 // supcon for Systems 00994 // uses and maintains controllablity from plant 00995 void SupCon( 00996 const System& rPlantGen, 00997 const Generator& rSpecGen, 00998 Generator& rResGen) { 00999 01000 // prepare result 01001 Generator* pResGen = &rResGen; 01002 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) { 01003 pResGen= rResGen.New(); 01004 } 01005 01006 // execute 01007 SupCon(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,*pResGen); 01008 01009 // copy all attributes of input alphabet 01010 pResGen->EventAttributes(rPlantGen.Alphabet()); 01011 01012 // copy result 01013 if(pResGen != &rResGen) { 01014 pResGen->Move(rResGen); 01015 delete pResGen; 01016 } 01017 01018 } 01019 01020 } // name space |
libFAUDES 2.20d --- 2011.04.26 --- c++ source docu by doxygen