|
libFAUDES
Sections
Index
|
mtc_supcon.cppGo to the documentation of this file.00001 /** @file mtc_supcon.cpp 00002 00003 Supremal controllable sublanguage and controllablity 00004 00005 */ 00006 00007 /* FAU Discrete Event Systems Library (libfaudes) 00008 00009 Copyright (C) 2008 Matthias Singer 00010 Copyright (C) 2006 Bernd Opitz 00011 Exclusive copyright is granted to Klaus Schmidt 00012 00013 This library is free software; you can redistribute it and/or 00014 modify it under the terms of the GNU Lesser General Public 00015 License as published by the Free Software Foundation; either 00016 version 2.1 of the License, or (at your option) any later version. 00017 00018 This library is distributed in the hope that it will be useful, 00019 but WITHOUT ANY WARRANTY; without even the implied warranty of 00020 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00021 Lesser General Public License for more details. 00022 00023 You should have received a copy of the GNU Lesser General Public 00024 License along with this library; if not, write to the Free Software 00025 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 00026 00027 00028 #include "mtc_supcon.h" 00029 #include "syn_include.h" 00030 00031 namespace faudes { 00032 00033 /* 00034 ****************************** 00035 * SUPCON: USER FUNCTIONS * 00036 ****************************** 00037 */ 00038 00039 00040 // mtcSupConNB(rPlantGen, rSpecGen, rResGen) 00041 void mtcSupConNB(const mtcGenerator& rPlantGen, const mtcGenerator& rSpecGen, mtcGenerator& rResGen) { 00042 // HELPERS: 00043 std::map< std::pair<Idx,Idx>, Idx> rcmap; 00044 // ALGORITHM: 00045 mtcSupConNB(rPlantGen, rSpecGen, rcmap, rResGen); 00046 } 00047 00048 00049 // mtcSupConNB(rPlantGen, rSpecGen, rReverseCompositionMap, rResGen) 00050 void mtcSupConNB(const mtcGenerator& rPlantGen, const mtcGenerator& rSpecGen, 00051 std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, mtcGenerator& rResGen) { 00052 FD_DF("mtcSupConNB(" << &rPlantGen << "," << &rSpecGen << ")"); 00053 00054 // PREPARE RESULT: 00055 00056 rResGen.Clear(); 00057 rResGen.Name("mtcSupConNB(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"); 00058 rResGen.InjectAlphabet(rPlantGen.Alphabet()); 00059 00060 rResGen.SetControllable(rPlantGen.ControllableEvents()); 00061 rResGen.SetForcible(rPlantGen.ForcibleEvents()); 00062 rResGen.ClrObservable(rPlantGen.UnobservableEvents()); 00063 00064 // HELPERS: 00065 00066 // controllable events 00067 const EventSet ualph = rPlantGen.UncontrollableEvents(); 00068 FD_DF("mtcSupConNB: controllable events: " << rPlantGen.ControllableEvents().ToString()); 00069 FD_DF("mtcSupConNB: uncontrollable events: " << ualph.ToString()); 00070 00071 // CONSISTENCY CHECK: 00072 00073 // alphabets must match 00074 if (rPlantGen.Alphabet() != rSpecGen.Alphabet()) { 00075 EventSet only_in_plant = rPlantGen.Alphabet() - rSpecGen.Alphabet(); 00076 EventSet only_in_spec = rSpecGen.Alphabet() - rPlantGen.Alphabet(); 00077 std::stringstream errstr; 00078 errstr << "Alphabets of generators do not match. Only in plant: " << only_in_plant.ToString() 00079 << ". Only in spec: " << only_in_spec.ToString() << "."; 00080 throw Exception("mtcSupConNB", errstr.str(), 500); 00081 } 00082 00083 // plant and spec must be deterministic 00084 bool plant_det = rPlantGen.IsDeterministic(); 00085 bool spec_det = rSpecGen.IsDeterministic(); 00086 00087 if ((plant_det == false) && (spec_det == true)) { 00088 std::stringstream errstr; 00089 errstr << "Plant generator must be deterministic, " 00090 << "but is nondeterministic"; 00091 throw Exception("mtcSupConNB", errstr.str(), 501); 00092 } 00093 else if ((plant_det == true) && (spec_det == false)) { 00094 std::stringstream errstr; 00095 errstr << "Spec generator must be deterministic, " 00096 << "but is nondeterministic"; 00097 throw Exception("mtcSupConNB", errstr.str(), 503); 00098 } 00099 else if ((plant_det == false) && (spec_det == false)) { 00100 std::stringstream errstr; 00101 errstr << "Plant and spec generator must be deterministic, " 00102 << "but both are nondeterministic"; 00103 throw Exception("mtcSupConNB", errstr.str(), 504); 00104 } 00105 00106 // ALGORITHM: 00107 00108 mtcSupConParallel(rPlantGen, rSpecGen, ualph, rReverseCompositionMap, rResGen); 00109 FD_DF("mtcSupConNB: mtcSupConParallel passed..."); 00110 00111 // make resulting generator trim until it's fully controllable 00112 while (1) { 00113 if (rResGen.Empty()) { 00114 return; 00115 } 00116 Idx state_num = rResGen.Size(); 00117 bool supcon = SupConUnchecked(rPlantGen, rPlantGen.ControllableEvents(), rResGen); 00118 bool trim = rResGen.StronglyTrim(); 00119 if (supcon && trim && (rResGen.Size() == state_num)) { 00120 return; 00121 } 00122 FD_DF("mtcSupConNB: rResGen.Size() = " << ToStringInteger(rResGen.Size()) << ", state_num = " << ToStringInteger(state_num)); 00123 } 00124 } 00125 00126 // mtcSupCon(rPlantGen, rSpecGen, rResGen) 00127 void mtcSupCon(const mtcGenerator& rPlantGen, const mtcGenerator& rSpecGen, mtcGenerator& rResGen) { 00128 // HELPERS: 00129 std::map< std::pair<Idx,Idx>, Idx> rcmap; 00130 00131 // ALGORITHM: 00132 mtcSupCon(rPlantGen, rSpecGen, rcmap, rResGen); 00133 } 00134 00135 00136 // mtcSupCon(rPlantGen, rSpecGen, rReverseCompositionMap, rResGen) 00137 void mtcSupCon(const mtcGenerator& rPlantGen, const mtcGenerator& rSpecGen, 00138 std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, mtcGenerator& rResGen) { 00139 FD_DF("mtcSupCon(" << &rPlantGen << "," << &rSpecGen << ")"); 00140 00141 // PREPARE RESULT: 00142 rResGen.Clear(); 00143 rResGen.Name("mtcSupCon(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"); 00144 00145 rResGen.InjectAlphabet(rPlantGen.Alphabet()); 00146 00147 rResGen.SetControllable(rPlantGen.ControllableEvents()); 00148 rResGen.SetForcible(rPlantGen.ForcibleEvents()); 00149 rResGen.ClrObservable(rPlantGen.UnobservableEvents()); 00150 00151 // HELPERS: 00152 00153 // controllable events 00154 const EventSet ualph = rPlantGen.UncontrollableEvents(); 00155 FD_DF("mtcSupCon: controllable events: " << rPlantGen.ControllableEvents().ToString()); 00156 FD_DF("mtcSupCon: uncontrollable events: " << ualph.ToString()); 00157 00158 // CONSISTENCY CHECK: 00159 00160 // alphabets must match 00161 if (rPlantGen.Alphabet() != rSpecGen.Alphabet()) { 00162 EventSet only_in_plant = rPlantGen.Alphabet() - rSpecGen.Alphabet(); 00163 EventSet only_in_spec = rSpecGen.Alphabet() - rPlantGen.Alphabet(); 00164 std::stringstream errstr; 00165 errstr << "Alphabets of generators do not match. Only in plant: " 00166 << only_in_plant.ToString() << ". Only in spec: " 00167 << only_in_spec.ToString() << "."; 00168 throw Exception("mtcSupCon", errstr.str(), 500); 00169 } 00170 00171 // plant and spec must be deterministic 00172 bool plant_det = rPlantGen.IsDeterministic(); 00173 bool spec_det = rSpecGen.IsDeterministic(); 00174 00175 if ((plant_det == false) && (spec_det == true)) { 00176 std::stringstream errstr; 00177 errstr << "Plant generator must be deterministic, " << "but is nondeterministic"; 00178 throw Exception("mtcSupCon", errstr.str(), 501); 00179 } 00180 else if ((plant_det == true) && (spec_det == false)) { 00181 std::stringstream errstr; 00182 errstr << "Spec generator must be deterministic, " << "but is nondeterministic"; 00183 throw Exception("mtcSupCon", errstr.str(), 503); 00184 } 00185 else if ((plant_det == false) && (spec_det == false)) { 00186 std::stringstream errstr; 00187 errstr << "Plant and spec generator must be deterministic, " 00188 << "but both are nondeterministic"; 00189 throw Exception("mtcSupConNB", errstr.str(), 504); 00190 } 00191 00192 // ALGORITHM: 00193 00194 // parallel composition 00195 mtcSupConParallel(rPlantGen, rSpecGen, ualph, rReverseCompositionMap, rResGen); 00196 // make resulting generator controllable 00197 mtcSupConUnchecked(rPlantGen, rPlantGen.ControllableEvents(), rResGen); 00198 } 00199 00200 00201 00202 /* 00203 ******************************************** 00204 * Fast parallel composition for mtcSupCon * 00205 ******************************************** 00206 */ 00207 00208 00209 // mtcSupConParallel(rPlantGen, rSpecGen, rUAlph, rReverseCompositionMap, rResGen) 00210 void mtcSupConParallel(const mtcGenerator& rPlantGen, const mtcGenerator& rSpecGen, const EventSet& rUAlph, 00211 std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, mtcGenerator& rResGen) { 00212 FD_DF("mtcSupConParallel(" << &rPlantGen << "," << &rSpecGen << ")"); 00213 00214 // HELPERS: 00215 00216 // todo stack 00217 std::stack< std::pair<Idx,Idx> > todo; 00218 // set of forbidden states 00219 StateSet forbidden; 00220 // actual pair, new pair 00221 std::pair<Idx,Idx> currentstates, newstates; 00222 // other stuff 00223 Idx tmpstate; 00224 std::map< std::pair<Idx,Idx>, Idx>::iterator rcmapit; 00225 StateSet::Iterator lit1, lit2; 00226 TransSet::Iterator titg, titg_end, tith, tith_end; 00227 00228 // ALGORITHM: 00229 if (rPlantGen.InitStatesEmpty()) { 00230 FD_DF("SupconParallel: plant got no initial states. " 00231 << "parallel composition contains empty language."); 00232 return; 00233 } 00234 00235 if (rSpecGen.InitStatesEmpty()) { 00236 FD_DF("mtcSupConParallel: spec got no initial states. " 00237 << "parallel composition contains empty language."); 00238 return; 00239 } 00240 ColorSet plantColors = rPlantGen.Colors(); 00241 ColorSet specColors = rSpecGen.Colors(); 00242 // create initial state 00243 currentstates = std::make_pair(*rPlantGen.InitStatesBegin(), *rSpecGen.InitStatesBegin()); 00244 todo.push(currentstates); 00245 ColorSet ComposedSet; 00246 ComposedColorSet(rPlantGen, currentstates.first, plantColors, rSpecGen, currentstates.second, 00247 specColors, ComposedSet); 00248 if (! ComposedSet.Empty() ) { 00249 Idx StateIndex = rResGen.InsInitState(); 00250 rReverseCompositionMap[currentstates] = StateIndex; 00251 rResGen.InsColors(StateIndex, ComposedSet); 00252 FD_DF("mtcSupConParallel: NEW IMSTATE: (" << rPlantGen.SStr(currentstates.first) 00253 << "|" << rSpecGen.SStr(currentstates.second) << ") -> " << rReverseCompositionMap[currentstates]); 00254 } 00255 else { 00256 rReverseCompositionMap[currentstates] = rResGen.InsInitState(); 00257 FD_DF("mtcSupConParallel: NEW ISTATE: (" << rPlantGen.SStr(currentstates.first) 00258 << "|" << rSpecGen.SStr(currentstates.second) << ") -> " << rReverseCompositionMap[currentstates]); 00259 } 00260 00261 // first do parallel composition of allowed states 00262 // by deleting forbidden states on the fly. 00263 // this creates an accessible new generator 00264 FD_DF("mtcSupConParallel: *** processing reachable states ***"); 00265 while (! todo.empty()) { 00266 // get next reachable pair of states from todo stack 00267 currentstates = todo.top(); 00268 todo.pop(); 00269 FD_DF("mtcSupConParallel: todo pop: (" << rPlantGen.SStr(currentstates.first) 00270 << "|" << rSpecGen.SStr(currentstates.second) << ") -> " << rReverseCompositionMap[currentstates]); 00271 00272 titg = rPlantGen.TransRelBegin(currentstates.first); 00273 titg_end = rPlantGen.TransRelEnd(currentstates.first); 00274 tith = rSpecGen.TransRelBegin(currentstates.second); 00275 tith_end = rSpecGen.TransRelEnd(currentstates.second); 00276 00277 #ifdef FAUDES_DEBUG_FUNCTION 00278 // print all transitions of current states 00279 FD_DF("mtcSupConParallel: transitions from current states:"); 00280 for (;titg != titg_end; ++titg) { 00281 FD_DF("mtcSupConParallel: g: " << rPlantGen.SStr(titg->X1) << "-" << rPlantGen.EStr(titg->Ev) 00282 << "-" << rPlantGen.SStr(titg->X2)); 00283 } 00284 for (;tith != tith_end; ++tith) { 00285 FD_DF("mtcSupConParallel: h: " << rSpecGen.SStr(tith->X1) << "-" << rSpecGen.EStr(tith->Ev) 00286 << "-" << rSpecGen.SStr(tith->X2)); 00287 } 00288 titg = rPlantGen.TransRelBegin(currentstates.first); 00289 tith = rSpecGen.TransRelBegin(currentstates.second); 00290 #endif 00291 // process all h transitions while there could be matching g transitions 00292 while ((tith != tith_end) && (titg != titg_end)) { 00293 FD_DF("mtcSupConParallel: actual g-transition: " << rPlantGen.SStr(titg->X1) 00294 << "-" << rPlantGen.EStr(titg->Ev) << "-" << rPlantGen.SStr(titg->X2)); 00295 FD_DF("mtcSupConParallel: actual h-transition: " << rSpecGen.SStr(tith->X1) 00296 << "-" << rSpecGen.EStr(tith->Ev) << "-" << rSpecGen.SStr(tith->X2)); 00297 // execute common events 00298 if (titg->Ev == tith->Ev) { 00299 FD_DF("mtcSupConParallel: executing common event " 00300 << rPlantGen.EStr(titg->Ev)); 00301 newstates = std::make_pair(titg->X2, tith->X2); 00302 rcmapit = rReverseCompositionMap.find(newstates); 00303 // add to todo list if state is new 00304 if (rcmapit == rReverseCompositionMap.end()) { 00305 todo.push(newstates); 00306 // if colored state 00307 ComposedColorSet(rPlantGen, newstates.first, plantColors, rSpecGen, newstates.second, 00308 specColors, ComposedSet); 00309 if (not ComposedSet.Empty() ) { 00310 tmpstate = rResGen.InsState(); 00311 rResGen.InsColors(tmpstate, ComposedSet); 00312 FD_DF("mtcSupConParallel: NEW MSTATE: (" 00313 << rPlantGen.SStr(newstates.first) << "|" 00314 << rSpecGen.SStr(newstates.second) << ") -> " << tmpstate); 00315 } 00316 // if "normal" state 00317 else { 00318 tmpstate = rResGen.InsState(); 00319 FD_DF("mtcSupConParallel: NEW STATE: (" 00320 << rPlantGen.SStr(newstates.first) << "|" 00321 << rSpecGen.SStr(newstates.second) << ") -> " << tmpstate); 00322 } 00323 rReverseCompositionMap[newstates] = tmpstate; 00324 FD_DF("mtcSupConParallel: todo push: (" << rPlantGen.SStr(newstates.first) 00325 << "|" << rSpecGen.SStr(newstates.second) << ") -> " << tmpstate); 00326 } 00327 // if state already exists 00328 else { 00329 tmpstate = rcmapit->second; 00330 } 00331 // if successor state not in forbidden set add transition 00332 if (! forbidden.Exists(tmpstate)) { 00333 FD_DF("mtcSupConParallel: ADDING TRANSITION " 00334 << rPlantGen.SStr(rReverseCompositionMap[currentstates]) << "-" << rPlantGen.EStr(titg->Ev) 00335 << "-" << rPlantGen.SStr(tmpstate)); 00336 rResGen.SetTransition(rReverseCompositionMap[currentstates], titg->Ev, tmpstate); 00337 FD_DF("mtcSupConParallel: incrementing g transrel"); 00338 ++titg; 00339 FD_DF("mtcSupConParallel: incrementing h transrel"); 00340 ++tith; 00341 } 00342 // if successor state in forbidden and event uncontrollable 00343 // delete state 00344 else if (rUAlph.Exists(titg->Ev)) { 00345 FD_DF("mtcSupConParallel: successor " << rSpecGen.SStr(tmpstate) 00346 << "in forbidden and common event " << rSpecGen.EStr(titg->Ev) 00347 << " uncontrollable:"); 00348 FD_DF("mtcSupConParallel: forbidden insert" << rPlantGen.SStr(tmpstate)); 00349 forbidden.Insert(tmpstate); 00350 #ifdef FAUDES_CHECKED 00351 // do not end while loops here for detecting all h transitions 00352 // not in g 00353 FD_DF("mtcSupConParallel: incrementing g transrel (FAUDES_CHECKED)"); 00354 ++titg; 00355 FD_DF("mtcSupConParallel: incrementing h transrel (FAUDES_CHECKED)"); 00356 ++tith; 00357 #else 00358 // exit all loops 00359 titg = titg_end; 00360 tith = tith_end; 00361 #endif 00362 } 00363 // else if successor state in forbidden and event controllable 00364 else { 00365 FD_DF("mtcSupConParallel: incrementing g transrel"); 00366 ++titg; 00367 FD_DF("mtcSupConParallel: incrementing h transrel"); 00368 ++tith; 00369 } 00370 } 00371 // if g got some more transitions try to resync events 00372 else if (titg->Ev < tith->Ev) { 00373 FD_DF("mtcSupConParallel: asynchronous execution of event " 00374 << rPlantGen.EStr(titg->Ev) << " in g while " << rSpecGen.EStr(tith->Ev) 00375 << " in h"); 00376 // if uncontrollable transition leaves specification 00377 // delete state from res and put into forbiddenset 00378 if (rUAlph.Exists(titg->Ev)) { 00379 FD_DF("mtcSupConParallel: asynchronous event " << rPlantGen.EStr(titg->Ev) 00380 << " in g is uncontrollable"); 00381 tmpstate = rReverseCompositionMap[currentstates]; 00382 FD_DF("mtcSupConParallel: forbidden insert" << rPlantGen.SStr(tmpstate)); 00383 forbidden.Insert(tmpstate); 00384 // exit all loops 00385 titg = titg_end; 00386 tith = tith_end; 00387 break; 00388 } 00389 FD_DF("mtcSupConParallel: incrementing g transrel"); 00390 ++titg; 00391 } // if specification leaves plant model emit warning 00392 else { 00393 #ifdef FAUDES_CHECKED 00394 // FD_WARN("mtcSupConParallel: transition " << rSpecGen.SStr(tith->X1) 00395 // << "-" << rSpecGen.EStr(tith->Ev) << "-" << rSpecGen.SStr(tith->X2) 00396 // << " in specification h not found in g"); 00397 #endif 00398 FD_DF("mtcSupConParallel: incrementing h transrel"); 00399 ++tith; 00400 } 00401 } 00402 if (rResGen.InitStates().Empty()) FD_DF("mtcSupConParallel: rResGen has no initial states... (2)"); 00403 00404 // if g got some more transitions not in h 00405 while (titg != titg_end) { 00406 FD_DF("mtcSupConParallel: asynchronous execution of event " 00407 << rPlantGen.EStr(titg->Ev) << " in g at end of h"); 00408 FD_DF("mtcSupConParallel: actual g-transition: " << rPlantGen.SStr(titg->X1) 00409 << "-" << rPlantGen.EStr(titg->Ev) << "-" << rPlantGen.SStr(titg->X2)); 00410 FD_DF("mtcSupConParallel: actual h-transition: end"); 00411 // if uncontrollable transition leaves specification 00412 if (rUAlph.Exists(titg->Ev)) { 00413 tmpstate = rReverseCompositionMap[currentstates]; 00414 FD_DF("mtcSupConParallel: asynchron executed uncontrollable end " 00415 << "event " << rPlantGen.EStr(titg->Ev) << " leaves specification:"); 00416 FD_DF("mtcSupConParallel: forbidden insert" << rPlantGen.SStr(tmpstate)); 00417 forbidden.Insert(tmpstate); 00418 // exit this loop 00419 // if FAUDES_CHECKED not defined this means exiting all loops 00420 break; 00421 } 00422 FD_DF("mtcSupConParallel: incrementing g transrel"); 00423 ++titg; 00424 } 00425 #ifdef FAUDES_CHECKED 00426 // if h got some more transitions not in g 00427 // while (tith != tith_end) { 00428 // FD_WARN("mtcSupConParallel: transition " << rSpecGen.SStr(tith->X1) << "-" 00429 // << rSpecGen.EStr(tith->Ev) << "-" << rSpecGen.SStr(tith->X2) 00430 // << "in specification h not found in g"); 00431 // FD_DF("mtcSupConParallel: incrementing h transrel"); 00432 // ++tith; 00433 // } 00434 #endif 00435 } 00436 FD_DF("mtcSupConParallel: deleting forbidden states..."); 00437 // remove attributes belonging to forbidden states 00438 StateSet::Iterator st_it; 00439 for(st_it = forbidden.Begin(); st_it != forbidden.End(); ++st_it){ 00440 rResGen.ClrStateAttribute(*st_it); 00441 } 00442 // remove forbidden states from stateset 00443 rResGen.DelStates(forbidden); 00444 } 00445 00446 /* 00447 ***************************************** 00448 * mtcSupConUnchecked: REAL SUPCON FUNCTION * 00449 ***************************************** 00450 */ 00451 00452 00453 // mtcSupConUnchecked(rPlantGen, rSupGen) 00454 bool mtcSupConUnchecked(const mtcGenerator& rPlantGen, const EventSet& rCAlph, mtcGenerator& rSupGen) { 00455 FD_DF("mtcSupConUnchecked..."); 00456 00457 // HELPERS: 00458 00459 // set of forbidden states 00460 StateSet forbidden; 00461 00462 // ALGORITHM: 00463 00464 // return true if plant or parallelcomp contain no initial states 00465 if (rPlantGen.InitStatesEmpty() || rSupGen.InitStatesEmpty()) { 00466 FD_DF("mtcSupConUnchecked: no initial states..."); 00467 return true; 00468 } 00469 00470 IsControllable(rPlantGen, rCAlph, rSupGen, forbidden); 00471 00472 // remove attributes belonging to forbidden states 00473 StateSet::Iterator st_it; 00474 for(st_it = forbidden.Begin(); st_it != forbidden.End(); ++st_it){ 00475 rSupGen.ClrStateAttribute(*st_it); 00476 } 00477 // remove forbidden states from stateset 00478 rSupGen.DelStates(forbidden); 00479 00480 // return true if no states had to be deleted 00481 if (forbidden.Empty()) { 00482 FD_DF("mtcSupCon: controllable"); 00483 return true; 00484 } 00485 // return false if states had to be deleted 00486 else { 00487 FD_DF("mtcSupCon: not controllable"); 00488 return false; 00489 } 00490 } 00491 00492 00493 // IsControllableUnchecked(rPlantGen, rSpecGen, rUAlph, forbidden) 00494 bool IsControllableUnchecked(const mtcGenerator& rPlantGen, 00495 const mtcGenerator& rSpecGen, const EventSet& rUAlph, StateSet& forbidden) { 00496 FD_DF("IsControllableUnchecked(" << &rSpecGen << "," << &rPlantGen << ")"); 00497 00498 // HELPERS: 00499 00500 // todo stack 00501 std::stack<Idx> todog, todoh; 00502 // set of already discovered states 00503 StateSet discovered; 00504 // reverse sorted transition relation build on the fly 00505 TransSetX2EvX1 rtransrel; 00506 00507 // PREPARE RESULT: 00508 forbidden.Clear(); 00509 00510 // ALGORITHM: 00511 00512 // return false (uncontrollable) if there is no initial state 00513 if (rPlantGen.InitStatesEmpty() || rSpecGen.InitStatesEmpty()) { 00514 return false; 00515 } 00516 00517 // push combined initial state on todo stack 00518 todog.push(*rPlantGen.InitStatesBegin()); 00519 todoh.push(*rSpecGen.InitStatesBegin()); 00520 FD_DF("IsControllable: todo push: (" << rPlantGen.SStr(*rPlantGen.InitStatesBegin()) << "|" 00521 << rSpecGen.SStr(*rSpecGen.InitStatesBegin()) << ")"); 00522 00523 // process todo stack 00524 while (! todog.empty()) { 00525 // get top elements from todo stack 00526 Idx currentg = todog.top(); 00527 Idx currenth = todoh.top(); 00528 todog.pop(); 00529 todoh.pop(); 00530 FD_DF("IsControllable: todo pop: (" << rPlantGen.SStr(currentg) << "|" 00531 << rSpecGen.SStr(currenth) << ")"); 00532 00533 #ifdef FAUDES_DEBUG_FUNCTION 00534 TransSet::Iterator _titg, _tith; 00535 // print all transitions of current states 00536 FD_DF("IsControllable: transitions from current states:"); 00537 for (_titg = rPlantGen.TransRelBegin(currentg); _titg != rPlantGen.TransRelEnd(currentg); ++_titg) 00538 FD_DF("IsControllable: g: " << rPlantGen.SStr(_titg->X1) << "-" 00539 << rPlantGen.EStr(_titg->Ev) << "-" << rPlantGen.SStr(_titg->X2)); 00540 for (_tith = rSpecGen.TransRelBegin(currenth); _tith != rSpecGen.TransRelEnd(currenth); ++_tith) 00541 FD_DF("IsControllable: h: " << rSpecGen.SStr(_tith->X1) << "-" 00542 << rSpecGen.EStr(_tith->Ev) << "-" << rSpecGen.SStr(_tith->X2)); 00543 #endif 00544 00545 // process all h transitions while there could be matching g transitions 00546 TransSet::Iterator titg = rPlantGen.TransRelBegin(currentg); 00547 TransSet::Iterator titg_end = rPlantGen.TransRelEnd(currentg); 00548 TransSet::Iterator tith = rSpecGen.TransRelBegin(currenth); 00549 TransSet::Iterator tith_end = rSpecGen.TransRelEnd(currenth); 00550 while ((tith != tith_end) && (titg != titg_end)) { 00551 FD_DF("IsControllable: actual g-transition: " << rPlantGen.SStr(titg->X1) 00552 << "-" << rPlantGen.EStr(titg->Ev) << "-" << rPlantGen.SStr(titg->X2)); 00553 FD_DF("IsControllable: actual h-transition: " << rSpecGen.SStr(tith->X1) 00554 << "-" << rSpecGen.EStr(tith->Ev) << "-" << rSpecGen.SStr(tith->X2)); 00555 // execute common events 00556 if (titg->Ev == tith->Ev) { 00557 FD_DF("IsControllable: executing common event " << rPlantGen.EStr(titg->Ev)); 00558 // add to todo list if state is undiscovered 00559 if (! discovered.Exists(currenth)) { 00560 todog.push(titg->X2); 00561 todoh.push(tith->X2); 00562 FD_DF("IsControllable: todo push: (" << rPlantGen.SStr(titg->X2) << "|" 00563 << rSpecGen.SStr(tith->X2) << ")"); 00564 } 00565 // if h successor state not in forbidden set add transition to rtransrel 00566 if (! forbidden.Exists(tith->X2)) { 00567 rtransrel.Insert(*tith); 00568 FD_DF("IsControllable: incrementing g transrel"); 00569 ++titg; 00570 FD_DF("IsControllable: incrementing h transrel"); 00571 ++tith; 00572 } 00573 // if successor state is forbidden and event uncontrollable 00574 else if (rUAlph.Exists(titg->Ev)) { 00575 FD_DF("IsControllable: successor state " << rSpecGen.SStr(tith->X2) << 00576 " forbidden and event " << rPlantGen.EStr(titg->Ev) << " uncontrollable:"); 00577 FD_DF("IsControllable: TraverseUncontrollableBackwards(" << rSpecGen.SStr(currenth) << ")"); 00578 TraverseUncontrollableBackwards(rUAlph, rtransrel, forbidden, currenth); 00579 #ifdef FAUDES_CHECKED 00580 // just increment transrel iterators to find all h transitions not in g 00581 FD_DF("IsControllable: incrementing g transrel (FAUDES_CHECKED)"); 00582 ++titg; 00583 FD_DF("IsControllable: incrementing h transrel (FAUDES_CHECKED)"); 00584 ++tith; 00585 #else 00586 // exit all loops 00587 titg = titg_end; 00588 tith = tith_end; 00589 #endif 00590 break; 00591 } 00592 // else if successor state in forbidden and event controllable 00593 else { 00594 FD_DF("IsControllable: incrementing g transrel"); 00595 ++titg; 00596 FD_DF("IsControllable: incrementing h transrel"); 00597 ++tith; 00598 } 00599 } 00600 // if g got some more transitions try to resync events 00601 else if (titg->Ev < tith->Ev) { 00602 FD_DF("IsControllable: asynchronous execution of event " 00603 << rPlantGen.EStr(titg->Ev) << " in g while " << rSpecGen.EStr(tith->Ev) 00604 << " in h"); 00605 // if uncontrollable transition leaves specification 00606 // delete state from rResGen and put into forbiddenset 00607 if (rUAlph.Exists(titg->Ev)) { 00608 FD_DF("IsControllable: asynchronous event " << rPlantGen.EStr(titg->Ev) 00609 << " in g is uncontrollable"); 00610 FD_DF("IsControllable: TraverseUncontrollableBackwards(" << rSpecGen.SStr(currenth) << ")"); 00611 TraverseUncontrollableBackwards(rUAlph, rtransrel, forbidden, currenth); 00612 // exit all loops over g transrel 00613 titg = titg_end; 00614 break; 00615 } 00616 FD_DF("IsControllable: incrementing g transrel"); 00617 ++titg; 00618 } 00619 // if specification leaves plant model emit warning 00620 else { 00621 #ifdef FAUDES_CHECKED 00622 FD_WARN("IsControllable: transition " << rSpecGen.SStr(tith->X1) << "-" 00623 << rSpecGen.EStr(tith->Ev) << "-" << rSpecGen.SStr(tith->X2) 00624 << "in specification h not found in g"); 00625 #endif 00626 FD_DF("IsControllable: incrementing h transrel"); 00627 ++tith; 00628 } 00629 } 00630 // process other transitions not in h 00631 while (titg != titg_end) { 00632 FD_DF("IsControllable: asynchronous execution of event " 00633 << rPlantGen.EStr(titg->Ev) << " in g at end of h"); 00634 FD_DF("IsControllable: actual g-transition: " << rPlantGen.SStr(titg->X1) 00635 << "-" << rPlantGen.EStr(titg->Ev) << "-" << rPlantGen.SStr(titg->X2)); 00636 FD_DF("IsControllable: actual h-transition: end"); 00637 // if uncontrollable transition leaves specification 00638 if (rUAlph.Exists(titg->Ev)) { 00639 FD_DF("IsControllable: asynchronous execution of uncontrollable event " 00640 << rPlantGen.EStr(titg->Ev) << " in g"); 00641 FD_DF("IsControllable: TraverseUncontrollableBackwards(" << rPlantGen.SStr(currenth) << ")"); 00642 TraverseUncontrollableBackwards(rUAlph, rtransrel, forbidden, currenth); 00643 // exit this loop 00644 break; 00645 } 00646 FD_DF("IsControllable: incrementing g transrel"); 00647 ++titg; 00648 } 00649 #ifdef FAUDES_CHECKED 00650 // process other transitions not in g 00651 while (tith != tith_end) { 00652 FD_WARN("IsControllable: transition " << rSpecGen.SStr(tith->X1) << "-" 00653 << rSpecGen.EStr(tith->Ev) << "-" << rSpecGen.SStr(tith->X2) 00654 << "in specification h not found in g"); 00655 FD_DF("IsControllable: incrementing h transrel"); 00656 ++tith; 00657 } 00658 #endif 00659 discovered.Insert(currenth); 00660 } 00661 00662 // compute complete set of forbidden states 00663 forbidden = rSpecGen.States() - ( discovered - forbidden ); 00664 00665 if (forbidden.Empty()) { 00666 FD_DF("IsControllable: controllable"); 00667 return true; 00668 } 00669 else { 00670 FD_DF("IsControllable: not controllable"); 00671 return false; 00672 } 00673 } 00674 00675 } // namespace faudes |
libFAUDES 2.18b --- 2010-12-17 --- c++ source docu by doxygen 1.6.3