|
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 only_in_plant.Name("Only_In_Plant"); 00543 only_in_spec.Name("Only_In_Specification"); 00544 std::stringstream errstr; 00545 errstr << "Alphabets of generators do not match."; 00546 if(!only_in_plant.Empty()) 00547 errstr << " " << only_in_plant.ToString() << "."; 00548 if(!only_in_spec.Empty()) 00549 errstr << " " << only_in_spec.ToString() << "."; 00550 throw Exception("SupCon/SupConNB", errstr.str(), 100); 00551 } 00552 00553 // TODO: add test for rCAlph <= Alphabet 00554 00555 // TODO: check symboltables to match 00556 00557 // plant and spec must be deterministic 00558 bool plant_det = rPlantGen.IsDeterministic(); 00559 bool spec_det = rSpecGen.IsDeterministic(); 00560 00561 if ((plant_det == false) && (spec_det == true)) { 00562 std::stringstream errstr; 00563 errstr << "Plant generator must be deterministic, " 00564 << "but is nondeterministic"; 00565 throw Exception("ControllableConsistencyCheck", errstr.str(), 201); 00566 } 00567 else if ((plant_det == true) && (spec_det == false)) { 00568 std::stringstream errstr; 00569 errstr << "Spec generator must be deterministic, " 00570 << "but is nondeterministic"; 00571 throw Exception("ControllableConsistencyCheck", errstr.str(), 203); 00572 } 00573 else if ((plant_det == false) && (spec_det == false)) { 00574 std::stringstream errstr; 00575 errstr << "Plant and spec generator must be deterministic, " 00576 << "but both are nondeterministic"; 00577 throw Exception("ControllableConsistencyCheck", errstr.str(), 204); 00578 } 00579 } 00580 00581 00582 /* 00583 **************************************** 00584 * SUPCON: WRAPPER / USER FUNCTIONS * 00585 **************************************** 00586 */ 00587 00588 00589 // IsControllable(rPlantGen, rCAlph, rSupCandGen) 00590 bool IsControllable( 00591 const vGenerator& rPlantGen, 00592 const EventSet& rCAlph, 00593 const vGenerator& rSupCandGen) 00594 { 00595 FD_DF("IsControllable(" << &rSupCandGen << "," << &rPlantGen << ")"); 00596 00597 // HELPERS: 00598 FD_DF("IsControllable: controllable events: " << rCAlph.ToString()); 00599 // critical set 00600 StateSet critical; 00601 00602 // CONSISTENCY CHECKS: 00603 ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSupCandGen); 00604 00605 // ALGORITHM: 00606 return IsControllableUnchecked(rPlantGen, rCAlph, rSupCandGen, critical); 00607 } 00608 00609 00610 // IsControllable(rPlantGen, rCAlph, rSupCandGen, critical) 00611 bool IsControllable( 00612 const vGenerator& rPlantGen, 00613 const EventSet& rCAlph, 00614 const vGenerator& rSupCandGen, 00615 StateSet& rCriticalStates) 00616 { 00617 FD_DF("IsControllable(" << &rSupCandGen << "," << &rPlantGen << ")"); 00618 00619 // CONSISTENCY CHECKS: 00620 ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSupCandGen); 00621 00622 // ALGORITHM: 00623 return IsControllableUnchecked(rPlantGen, rCAlph, rSupCandGen, rCriticalStates); 00624 } 00625 00626 00627 // SupConNB(rPlantGen, rCAlph, rSpecGen, rResGen) 00628 void SupConNB( 00629 const vGenerator& rPlantGen, 00630 const EventSet& rCAlph, 00631 const vGenerator& rSpecGen, 00632 vGenerator& rResGen) 00633 { 00634 00635 // CONSISTENCY CHECK: 00636 ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen); 00637 00638 // HELPERS: 00639 std::map< std::pair<Idx,Idx>, Idx> rcmap; 00640 00641 // ALGORITHM: 00642 SupConNBUnchecked(rPlantGen, rCAlph, rSpecGen, rcmap, rResGen); 00643 } 00644 00645 00646 00647 00648 // SupConNBNonDet(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, 00649 // pDetPlantGen, pDetSpecGen, rResGen) 00650 void SupConNBNonDet( 00651 const vGenerator& rPlantGen, 00652 const EventSet& rCAlph, 00653 const vGenerator& rSpecGen, 00654 std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, 00655 Generator rDetPlantGen, 00656 Generator rDetSpecGen, 00657 std::map<Idx,StateSet>& rPowerStatesPlant, 00658 std::map<Idx,StateSet>& rPowerStatesSpec, 00659 bool& rDetPlantBool, 00660 bool& rDetSpecBool, 00661 vGenerator& rResGen) 00662 { 00663 FD_DF("SupConNBNonDet(" << &rPlantGen << "," << &rSpecGen << ")"); 00664 00665 // alphabets must match 00666 if (rPlantGen.Alphabet() != rSpecGen.Alphabet()) { 00667 throw Exception("SupConNBNonDet", "Alphabets of generators don't match", 100); 00668 } 00669 00670 // PREPARE RESULT: 00671 vGenerator* pResGen = &rResGen; 00672 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) { 00673 pResGen= rResGen.New(); 00674 } 00675 pResGen->Clear(); 00676 pResGen->Name(CollapsString("SupConNBNonDet(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))")); 00677 pResGen->InjectAlphabet(rPlantGen.Alphabet()); 00678 00679 // HELPERS: 00680 rPowerStatesPlant.clear(); 00681 rPowerStatesSpec.clear(); 00682 00683 // controllable events 00684 FD_DF("SupConNB: controllable events: " << rCAlph.ToString()); 00685 00686 // pointers to actual generators 00687 vGenerator* plantp; 00688 vGenerator* specp; 00689 00690 // plant and spec determinism 00691 rDetPlantBool = rPlantGen.IsDeterministic(); 00692 rDetSpecBool = rSpecGen.IsDeterministic(); 00693 00694 // create deterministic generators and set pointers to the actual ones 00695 plantp = const_cast<vGenerator*>(&rPlantGen); 00696 specp = const_cast<vGenerator*>(&rSpecGen); 00697 if (rDetPlantBool == false) { 00698 Deterministic(rPlantGen, rPowerStatesPlant, rDetPlantGen); 00699 plantp = &rDetPlantGen; 00700 } 00701 if (rDetSpecBool == false) { 00702 Deterministic(rSpecGen, rPowerStatesSpec, rDetSpecGen); 00703 specp = &rDetSpecGen; 00704 } 00705 00706 // ALGORITHM: 00707 00708 // compute supervisor 00709 SupconParallel(*plantp, rCAlph, *specp, rReverseCompositionMap, *pResGen); 00710 00711 // make resulting generator trim until it's fully controllable 00712 while (! (SupConUnchecked(*plantp, rCAlph, *pResGen) && pResGen->Trim())); 00713 00714 // copy result 00715 if(pResGen != &rResGen) { 00716 pResGen->Move(rResGen); 00717 delete pResGen; 00718 } 00719 } 00720 00721 // SupCon(rPlantGen, rCAlph, rSpecGen, rResGen) 00722 void SupCon( 00723 const vGenerator& rPlantGen, 00724 const EventSet& rCAlph, 00725 const vGenerator& rSpecGen, 00726 vGenerator& rResGen) 00727 { 00728 // HELPERS: 00729 std::map< std::pair<Idx,Idx>, Idx> rcmap; 00730 00731 // ALGORITHM: 00732 SupCon(rPlantGen, rCAlph, rSpecGen, rcmap, rResGen); 00733 } 00734 00735 00736 // SupCon(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, rResGen) 00737 void SupCon( 00738 const vGenerator& rPlantGen, 00739 const EventSet& rCAlph, 00740 const vGenerator& rSpecGen, 00741 std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, 00742 vGenerator& rResGen) 00743 { 00744 FD_DF("SupCon(" << &rPlantGen << "," << &rSpecGen << ")"); 00745 00746 // PREPARE RESULT: 00747 00748 00749 // prepare result 00750 vGenerator* pResGen = &rResGen; 00751 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) { 00752 pResGen= rResGen.New(); 00753 } 00754 pResGen->Clear(); 00755 pResGen->Name(CollapsString("SupCon(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))")); 00756 pResGen->InjectAlphabet(rPlantGen.Alphabet()); 00757 00758 // HELPERS: 00759 FD_DF("SupCon: controllable events: " << rCAlph.ToString()); 00760 00761 // CONSISTENCY CHECK: 00762 ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen); 00763 00764 // ALGORITHM: 00765 00766 // parallel composition 00767 SupconParallel(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, *pResGen); 00768 // make resulting generator controllable 00769 SupConUnchecked(rPlantGen, rCAlph, *pResGen); 00770 00771 // convenience state names 00772 if (rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && rResGen.StateNamesEnabled()) 00773 SetComposedStateNames(rPlantGen, rSpecGen, rReverseCompositionMap, *pResGen); 00774 else 00775 pResGen->ClearStateNames(); 00776 00777 // copy result 00778 if(pResGen != &rResGen) { 00779 pResGen->Move(rResGen); 00780 delete pResGen; 00781 } 00782 } 00783 00784 00785 // TraverseUncontrollableBackwards(rCAlph, rtransrel, critical, current) 00786 void TraverseUncontrollableBackwards( 00787 const EventSet& rCAlph, 00788 TransSetX2EvX1& rtransrel, 00789 StateSet& rCriticalStates, 00790 Idx current) { 00791 FD_DF("TraverseUncontrollableBackwards: " << rCriticalStates.Str(current)); 00792 00793 // HELPERS: 00794 std::stack<Idx> todo; 00795 TransSetX2EvX1::Iterator rtit = rtransrel.BeginByX2(current); 00796 TransSetX2EvX1::Iterator rtit_end = rtransrel.EndByX2(current); 00797 00798 // ALGORITHM: 00799 rCriticalStates.Insert(current); 00800 todo.push(current); 00801 FD_DF("TraverseUncontrollableBackwards: current rCriticalStates set: " 00802 << rCriticalStates.ToString()); 00803 // process todo stack 00804 while (! todo.empty()) { 00805 // get top state from todo stack 00806 current = todo.top(); todo.pop(); 00807 // iteration over all transitions with x2 == current 00808 rtit_end = rtransrel.EndByX2(current); 00809 rtit = rtransrel.BeginByX2(current); 00810 for (; rtit != rtit_end; ++rtit) { 00811 // if uncontrollable event and predecessor state not already critical 00812 if ((!rCAlph.Exists(rtit->Ev)) && (! rCriticalStates.Exists(rtit->X1))) { 00813 FD_DF("TraverseUncontrollableBackwards: todo push " << rCriticalStates.Str(rtit->X1)); 00814 todo.push(rtit->X1); 00815 FD_DF("TraverseUncontrollableBackwards: critical insert: " << rCriticalStates.Str(rtit->X1)); 00816 rCriticalStates.Insert(rtit->X1); 00817 } 00818 } 00819 } // end while todo 00820 } 00821 00822 00823 // controllability test for cGenerator plant 00824 bool IsControllable( 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 SupConNB( 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 SupCon( 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.16b --- 2010-9-8 --- c++ source docu by doxygen 1.6.3