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