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