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 build 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 SupConClosedUnchecked and IsControllableUnchecked was reimplemented. 00053 */ 00054 00055 00056 // SupConClosedUnchecked(rPlantGen, rCAlph, rSupCandGen) 00057 void SupConClosedUnchecked( 00058 const Generator& rPlantGen, // aka G 00059 const EventSet& rCAlph, 00060 Generator& rSupCandGen // aka H 00061 ) 00062 { 00063 FD_DF("SupConClosedUnchecked(" << &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 for 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 // SupConProduct(rPlantGen, rCAlph, rSpecGen, rCompositionMap, rResGen) 00386 void SupConProduct( 00387 const Generator& rPlantGen, 00388 const EventSet& rCAlph, 00389 const Generator& rSpecGen, 00390 std::map< std::pair<Idx,Idx>, Idx>& rCompositionMap, 00391 Generator& rResGen) 00392 { 00393 FD_DF("SupConProduct(" << &rPlantGen << "," << &rSpecGen << ")"); 00394 00395 // HELPERS: 00396 00397 // todo stack 00398 std::stack< std::pair<Idx,Idx> > todo; 00399 // set of critical states 00400 StateSet critical; 00401 // current state, next state, as pair 00402 std::pair<Idx,Idx> currentp, nextp; 00403 // current state, next state, at result 00404 Idx currentt, nextt; 00405 std::map< std::pair<Idx,Idx>, Idx>::iterator rcmapit; 00406 StateSet::Iterator lit1, lit2; 00407 TransSet::Iterator titg, titg_end, tith, tith_end; 00408 00409 // prepare 00410 rResGen.ClearStates(); 00411 rCompositionMap.clear(); 00412 00413 // ALGORITHM: 00414 if (rPlantGen.InitStatesEmpty()) { 00415 FD_DF("SupConProduct: plant got no initial states. " 00416 << "parallel composition contains empty language."); 00417 return; 00418 } 00419 if (rSpecGen.InitStatesEmpty()) { 00420 FD_DF("SupConProduct: spec got no initial states. " 00421 << "parallel composition contains empty language."); 00422 return; 00423 } 00424 00425 // create initial state 00426 currentp = std::make_pair(*rPlantGen.InitStatesBegin(), *rSpecGen.InitStatesBegin()); 00427 todo.push(currentp); 00428 rCompositionMap[currentp] = rResGen.InsInitState(); 00429 FD_DF("SupConProduct: insert initial state: (" 00430 << rPlantGen.SStr(currentp.first) 00431 << "|" << rSpecGen.SStr(currentp.second) << ") as idx " 00432 << rCompositionMap[currentp]); 00433 if(rPlantGen.ExistsMarkedState(*rPlantGen.InitStatesBegin()) 00434 && rSpecGen.ExistsMarkedState(*rSpecGen.InitStatesBegin())) { 00435 rResGen.SetMarkedState(rCompositionMap[currentp]); 00436 FD_DF("SupConProduct: initial state is marked"); 00437 } 00438 00439 // do parallel composition of reachable states while avoiding critical states 00440 // this creates an accessible generator 00441 00442 FD_DF("SupConProduct: *** 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(rCompositionMap.size(),rCompositionMap.size()+todo.size(),"SupConProduct(): processing"); 00448 // get next reachable pair of states from todo stack 00449 currentp = todo.top(); 00450 todo.pop(); 00451 currentt = rCompositionMap[currentp]; 00452 FD_DF("SupConProduct: todo pop: (" 00453 << rPlantGen.SStr(currentp.first) 00454 << "|" << rSpecGen.SStr(currentp.second) << ") as idx " 00455 << currentt); 00456 // might have been indicated to be critical 00457 if(critical.Exists(currentt)) continue; 00458 // set up transition relation iterators 00459 titg = rPlantGen.TransRelBegin(currentp.first); 00460 titg_end = rPlantGen.TransRelEnd(currentp.first); 00461 tith = rSpecGen.TransRelBegin(currentp.second); 00462 tith_end = rSpecGen.TransRelEnd(currentp.second); 00463 00464 #ifdef FAUDES_DEBUG_FUNCTION 00465 // print all transitions of current states 00466 FD_DF("SupConParallel: transitions from current state:"); 00467 for (;titg != titg_end; ++titg) 00468 FD_DF("SupConParallel: g: " << rPlantGen.TStr(*titg)); 00469 for (;tith != tith_end; ++tith) { 00470 FD_DF("SupConParallel: h: " << rSpecGen.TStr(*tith)); 00471 } 00472 titg = rPlantGen.TransRelBegin(currentp.first); 00473 tith = rSpecGen.TransRelBegin(currentp.second); 00474 #endif 00475 00476 // process all h transitions while there could be matching g transitions 00477 while((tith != tith_end) && (titg != titg_end)) { 00478 FD_DF("SupConProduct: current g-transition: " << rPlantGen.TStr(*titg) ); 00479 FD_DF("SupConProduct: current h-transition: " << rSpecGen.TStr(*tith)); 00480 00481 // case A: execute common events 00482 if(titg->Ev == tith->Ev) { 00483 FD_DF("SupConProduct: executing common event " << rPlantGen.EStr(titg->Ev)); 00484 nextp = std::make_pair(titg->X2, tith->X2); 00485 rcmapit = rCompositionMap.find(nextp); 00486 // if state is new ... 00487 if(rcmapit == rCompositionMap.end()) { 00488 // ... add on todo stack 00489 todo.push(nextp); 00490 // ... insert in result 00491 nextt = rResGen.InsState(); 00492 rCompositionMap[nextp] = nextt; 00493 FD_DF("SupConProduct: insert state: (" << 00494 rPlantGen.SStr(nextp.first) << "|" 00495 << rSpecGen.SStr(nextp.second) << ") as idx " 00496 << nextt); 00497 // .. mark synchronously 00498 if(rPlantGen.ExistsMarkedState(nextp.first) && 00499 rSpecGen.ExistsMarkedState(nextp.second)) { 00500 rResGen.SetMarkedState(nextt); 00501 FD_DF("SupConProduct: marked nes state") 00502 } 00503 } 00504 // if state already exists 00505 else { 00506 nextt = rcmapit->second; 00507 } 00508 // if successor state is not critical add transition and proceed 00509 if(!critical.Exists(nextt)) { 00510 FD_DF("SupConProduct: set transition " << 00511 rResGen.TStr(Transition(currentt,titg->Ev,nextt))); 00512 rResGen.SetTransition(currentt, titg->Ev, nextt); 00513 FD_DF("SupConProduct: incrementing g and h transrel"); 00514 ++titg; 00515 ++tith; 00516 } 00517 // if successor state is critical and event is uncontrollable then this state becomes critical, too 00518 else if (!rCAlph.Exists(titg->Ev)) { 00519 FD_DF("SupConProduct: successor in critical with uncntr. shared event " << rSpecGen.EStr(titg->Ev)) 00520 FD_DF("SupConProduct: critical insert, exit loop"); 00521 critical.Insert(currentt); 00522 // exit all loops 00523 titg = titg_end; 00524 tith = tith_end; 00525 } 00526 // else if successor state is critical and event controllable we may proceed 00527 else { 00528 FD_DF("SupConProduct: incrementing g and h transrel"); 00529 ++titg; 00530 ++tith; 00531 } 00532 } // end: shared event (case A) 00533 00534 // case B: process g event that is not enabled for h 00535 else if (titg->Ev < tith->Ev) { 00536 FD_DF("SupConProduct: event only enabled in g: " << rPlantGen.EStr(titg->Ev)); 00537 // when uncontrollable, current state is critical 00538 if(!rCAlph.Exists(titg->Ev)) { 00539 FD_DF("SupConProduct: asynchronous event is uncontrollable, critical insert, exit loop"); 00540 critical.Insert(currentt); 00541 // exit all loops 00542 titg = titg_end; 00543 tith = tith_end; 00544 break; 00545 } 00546 FD_DF("SupConProduct: incrementing g transrel"); 00547 ++titg; 00548 } 00549 00550 // case C: process h event that is not enabled for g 00551 else { 00552 FD_DF("SupConProduct: incrementing h transrel"); 00553 ++tith; 00554 } 00555 } // end while incrementing both tith and titg 00556 00557 // case D: process leftover events of g 00558 while (titg != titg_end) { 00559 FD_DF("SupConProduct: event only enabled in g: " << rPlantGen.EStr(titg->Ev)); 00560 // if uncontrollable transition leaves specification 00561 if (!rCAlph.Exists(titg->Ev)) { 00562 FD_DF("SupConProduct: asynchronous event is uncontrollable, critical insert, exit loop"); 00563 critical.Insert(currentt); 00564 // exit all loops 00565 break; 00566 } 00567 FD_DF("SupConProduct: incrementing g transrel"); 00568 ++titg; 00569 } 00570 //#ifdef FAUDES_CHECKED 00571 // increment titg and titg, case E: process leftover events of h 00572 //while (txoith != tith_end) { 00573 // FD_WARN("SupConProduct: transition " << rSpecGen.TStr(*tith) << " in specification h not found in g"); 00574 // FD_DF("SupConProduct: incrementing h transrel"); 00575 // ++tith; 00576 //} 00577 //#endif 00578 } // while todo 00579 FD_DF("SupConProduct: deleting critical states..."); 00580 rResGen.DelStates(critical); 00581 } 00582 00583 00584 00585 // SupConNBUnchecked(rPlantGen, rCAlph, rSpecGen, rCompositionMap, rResGen) 00586 void SupConNBUnchecked( 00587 const Generator& rPlantGen, 00588 const EventSet& rCAlph, 00589 const Generator& rSpecGen, 00590 std::map< std::pair<Idx,Idx>, Idx>& rCompositionMap, 00591 Generator& rResGen) 00592 { 00593 FD_DF("SupConNB(" << &rPlantGen << "," << &rSpecGen << ")"); 00594 00595 // PREPARE RESULT: 00596 Generator* pResGen = &rResGen; 00597 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) { 00598 pResGen= rResGen.New(); 00599 } 00600 pResGen->Clear(); 00601 pResGen->Name(CollapsString("SupConNB(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))")); 00602 pResGen->InjectAlphabet(rPlantGen.Alphabet()); 00603 00604 // controllable events 00605 FD_DF("SupConNB: controllable events: " << rCAlph.ToString()); 00606 00607 // ALGORITHM: 00608 SupConProduct(rPlantGen, rCAlph, rSpecGen, rCompositionMap, *pResGen); 00609 00610 // make resulting generator trim until it's fully controllable 00611 while(true) { 00612 if(pResGen->Empty()) break; 00613 Idx state_num = pResGen->Size(); 00614 SupConClosedUnchecked(rPlantGen, rCAlph, *pResGen); 00615 pResGen->Trim(); 00616 if(pResGen->Size() == state_num) break; 00617 } 00618 00619 // convenience state names 00620 if(rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && rResGen.StateNamesEnabled()) 00621 SetComposedStateNames(rPlantGen, rSpecGen, rCompositionMap, *pResGen); 00622 else 00623 pResGen->StateNamesEnabled(false); 00624 00625 // copy result 00626 if(pResGen != &rResGen) { 00627 pResGen->Move(rResGen); 00628 delete pResGen; 00629 } 00630 00631 } 00632 00633 // ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen) 00634 void ControlProblemConsistencyCheck( 00635 const Generator& rPlantGen, 00636 const EventSet& rCAlph, 00637 const Generator& rSpecGen) 00638 { 00639 00640 // alphabets must match 00641 if ( rPlantGen.Alphabet() != rSpecGen.Alphabet()) { 00642 EventSet only_in_plant = rPlantGen.Alphabet() - rSpecGen.Alphabet(); 00643 EventSet only_in_spec = rSpecGen.Alphabet() - rPlantGen.Alphabet(); 00644 only_in_plant.Name("Only_In_Plant"); 00645 only_in_spec.Name("Only_In_Specification"); 00646 std::stringstream errstr; 00647 errstr << "Alphabets of generators do not match."; 00648 if(!only_in_plant.Empty()) 00649 errstr << " " << only_in_plant.ToString() << "."; 00650 if(!only_in_spec.Empty()) 00651 errstr << " " << only_in_spec.ToString() << "."; 00652 throw Exception("SupCon/SupConNB", errstr.str(), 100); 00653 } 00654 00655 // controllable events have to be subset of Sigma 00656 if(!(rCAlph<=rPlantGen.Alphabet())) { 00657 EventSet only_in_CAlph = rCAlph - rPlantGen.Alphabet(); 00658 std::stringstream errstr; 00659 errstr << "Not all controllable events are contained in Sigma: " 00660 << only_in_CAlph.ToString() << "."; 00661 throw Exception("ControllProblemConsistencyCheck", errstr.str(), 100); 00662 } 00663 00664 // TODO: check symboltables to match 00665 00666 // plant and spec must be deterministic 00667 bool plant_det = rPlantGen.IsDeterministic(); 00668 bool spec_det = rSpecGen.IsDeterministic(); 00669 00670 if ((plant_det == false) && (spec_det == true)) { 00671 std::stringstream errstr; 00672 errstr << "Plant generator must be deterministic, " 00673 << "but is nondeterministic"; 00674 throw Exception("ControllableConsistencyCheck", errstr.str(), 201); 00675 } 00676 else if ((plant_det == true) && (spec_det == false)) { 00677 std::stringstream errstr; 00678 errstr << "Spec generator must be deterministic, " 00679 << "but is nondeterministic"; 00680 throw Exception("ControllableConsistencyCheck", errstr.str(), 203); 00681 } 00682 else if ((plant_det == false) && (spec_det == false)) { 00683 std::stringstream errstr; 00684 errstr << "Plant and spec generator must be deterministic, " 00685 << "but both are nondeterministic"; 00686 throw Exception("ControllableConsistencyCheck", errstr.str(), 204); 00687 } 00688 } 00689 00690 // ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen) 00691 void ControlProblemConsistencyCheck( 00692 const Generator& rPlantGen, 00693 const EventSet& rCAlph, 00694 const EventSet& rOAlph, 00695 const Generator& rSpecGen) 00696 { 00697 // std test 00698 ControlProblemConsistencyCheck(rPlantGen,rCAlph,rSpecGen); 00699 // observable events have to be subset of Sigma 00700 if(!(rOAlph<=rPlantGen.Alphabet())) { 00701 EventSet only_in_OAlph = rOAlph - rPlantGen.Alphabet(); 00702 std::stringstream errstr; 00703 errstr << "Not all observable events are contained in Sigma: " 00704 << only_in_OAlph.ToString() << "."; 00705 throw Exception("ControllProblemConsistencyCheck", errstr.str(), 100); 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 00728 // critical set 00729 StateSet critical; 00730 00731 // CONSISTENCY CHECKS: 00732 ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSupCandGen); 00733 00734 // ALGORITHM: 00735 return IsControllableUnchecked(rPlantGen, rCAlph, rSupCandGen, critical); 00736 } 00737 00738 00739 // IsControllable(rPlantGen, rCAlph, rSupCandGen, critical) 00740 bool IsControllable( 00741 const Generator& rPlantGen, 00742 const EventSet& rCAlph, 00743 const Generator& rSupCandGen, 00744 StateSet& rCriticalStates) 00745 { 00746 FD_DF("IsControllable(" << &rSupCandGen << "," << &rPlantGen << ")"); 00747 00748 // CONSISTENCY CHECKS: 00749 ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSupCandGen); 00750 00751 // ALGORITHM: 00752 return IsControllableUnchecked(rPlantGen, rCAlph, rSupCandGen, rCriticalStates); 00753 } 00754 00755 00756 // SupConNB(rPlantGen, rCAlph, rSpecGen, rResGen) 00757 void SupConNB( 00758 const Generator& rPlantGen, 00759 const EventSet& rCAlph, 00760 const Generator& rSpecGen, 00761 Generator& rResGen) 00762 { 00763 00764 // CONSISTENCY CHECK: 00765 ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen); 00766 00767 // HELPERS: 00768 std::map< std::pair<Idx,Idx>, Idx> rcmap; 00769 00770 // ALGORITHM: 00771 SupConNBUnchecked(rPlantGen, rCAlph, rSpecGen, rcmap, rResGen); 00772 } 00773 00774 00775 00776 00777 // SupConClosed(rPlantGen, rCAlph, rSpecGen, rResGen) 00778 void SupConClosed( 00779 const Generator& rPlantGen, 00780 const EventSet& rCAlph, 00781 const Generator& rSpecGen, 00782 Generator& rResGen) 00783 { 00784 // HELPERS: 00785 std::map< std::pair<Idx,Idx>, Idx> rcmap; 00786 00787 // ALGORITHM: 00788 SupConClosed(rPlantGen, rCAlph, rSpecGen, rcmap, rResGen); 00789 } 00790 00791 00792 // SupConClosed(rPlantGen, rCAlph, rSpecGen, rCompositionMap, rResGen) 00793 void SupConClosed( 00794 const Generator& rPlantGen, 00795 const EventSet& rCAlph, 00796 const Generator& rSpecGen, 00797 std::map< std::pair<Idx,Idx>, Idx>& rCompositionMap, 00798 Generator& rResGen) 00799 { 00800 FD_DF("SupConClosed(" << &rPlantGen << "," << &rSpecGen << ")"); 00801 00802 // PREPARE RESULT: 00803 00804 // prepare result 00805 Generator* pResGen = &rResGen; 00806 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) { 00807 pResGen= rResGen.New(); 00808 } 00809 pResGen->Clear(); 00810 pResGen->Name(CollapsString("SupConClosed(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))")); 00811 pResGen->InjectAlphabet(rPlantGen.Alphabet()); 00812 00813 // HELPERS: 00814 FD_DF("SupCon: controllable events: " << rCAlph.ToString()); 00815 00816 // CONSISTENCY CHECK: 00817 ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen); 00818 00819 // ALGORITHM: 00820 00821 // product composition 00822 SupConProduct(rPlantGen, rCAlph, rSpecGen, rCompositionMap, *pResGen); 00823 // make resulting generator controllable 00824 SupConClosedUnchecked(rPlantGen, rCAlph, *pResGen); 00825 00826 // restrict composition map 00827 std::map< std::pair<Idx,Idx>, Idx>::iterator rcmapit = rCompositionMap.begin(); 00828 while(rcmapit != rCompositionMap.end()) 00829 if(!rResGen.ExistsState(rcmapit->second)) rCompositionMap.erase(rcmapit++); 00830 else rcmapit++; 00831 00832 // convenience state names 00833 if (rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && rResGen.StateNamesEnabled()) 00834 SetComposedStateNames(rPlantGen, rSpecGen, rCompositionMap, *pResGen); 00835 else 00836 pResGen->StateNamesEnabled(false); 00837 00838 // copy result 00839 if(pResGen != &rResGen) { 00840 pResGen->Move(rResGen); 00841 delete pResGen; 00842 } 00843 } 00844 00845 00846 // TraverseUncontrollableBackwards(rCAlph, rtransrel, critical, current) 00847 void TraverseUncontrollableBackwards( 00848 const EventSet& rCAlph, 00849 TransSetX2EvX1& rtransrel, 00850 StateSet& rCriticalStates, 00851 Idx current) { 00852 FD_DF("TraverseUncontrollableBackwards: " << rCriticalStates.Str(current)); 00853 00854 // HELPERS: 00855 std::stack<Idx> todo; 00856 TransSetX2EvX1::Iterator rtit = rtransrel.BeginByX2(current); 00857 TransSetX2EvX1::Iterator rtit_end = rtransrel.EndByX2(current); 00858 00859 // ALGORITHM: 00860 rCriticalStates.Insert(current); 00861 todo.push(current); 00862 FD_DF("TraverseUncontrollableBackwards: current rCriticalStates set: " 00863 << rCriticalStates.ToString()); 00864 // process todo stack 00865 while(! todo.empty()) { 00866 // get top state from todo stack 00867 current = todo.top(); todo.pop(); 00868 // iteration over all transitions with x2 == current 00869 rtit_end = rtransrel.EndByX2(current); 00870 rtit = rtransrel.BeginByX2(current); 00871 for(; rtit != rtit_end; ++rtit) { 00872 // if uncontrollable event and predecessor state not already critical 00873 if((!rCAlph.Exists(rtit->Ev)) && (! rCriticalStates.Exists(rtit->X1))) { 00874 FD_DF("TraverseUncontrollableBackwards: todo push " << rCriticalStates.Str(rtit->X1)); 00875 todo.push(rtit->X1); 00876 FD_DF("TraverseUncontrollableBackwards: critical insert: " << rCriticalStates.Str(rtit->X1)); 00877 rCriticalStates.Insert(rtit->X1); 00878 } 00879 } 00880 } // end while todo 00881 } 00882 00883 00884 // controllability test for System plant 00885 bool IsControllable( 00886 const System& rPlantGen, 00887 const Generator& rSupCandGen) 00888 { 00889 return IsControllable(rPlantGen, rPlantGen.ControllableEvents(), rSupCandGen); 00890 } 00891 00892 00893 // supcon for Systems: 00894 // uses and maintains controllablity from plant 00895 void SupConNB( 00896 const System& rPlantGen, 00897 const Generator& rSpecGen, 00898 Generator& rResGen) { 00899 00900 // prepare result 00901 Generator* pResGen = &rResGen; 00902 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) { 00903 pResGen= rResGen.New(); 00904 } 00905 00906 // execute 00907 SupConNB(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,*pResGen); 00908 00909 // copy all attributes of input alphabet 00910 pResGen->EventAttributes(rPlantGen.Alphabet()); 00911 00912 // copy result 00913 if(pResGen != &rResGen) { 00914 pResGen->Move(rResGen); 00915 delete pResGen; 00916 } 00917 00918 } 00919 00920 // supcon for Systems 00921 // uses and maintains controllablity from plant 00922 void SupConClosed( 00923 const System& rPlantGen, 00924 const Generator& rSpecGen, 00925 Generator& rResGen) { 00926 00927 // prepare result 00928 Generator* pResGen = &rResGen; 00929 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) { 00930 pResGen= rResGen.New(); 00931 } 00932 00933 // execute 00934 SupConClosed(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,*pResGen); 00935 00936 // copy all attributes of input alphabet 00937 pResGen->EventAttributes(rPlantGen.Alphabet()); 00938 00939 // copy result 00940 if(pResGen != &rResGen) { 00941 pResGen->Move(rResGen); 00942 delete pResGen; 00943 } 00944 00945 } 00946 00947 } // name space libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen |