|
libFAUDES
Sections
Index
|
syn_wsupcon.cppGo to the documentation of this file.00001 /** @file syn_wsupcon.cpp Supremal controllable sublanguage for infinite time behaviours */ 00002 00003 /* FAU Discrete Event Systems Library (libfaudes) 00004 00005 Copyright (C) 2010 Thomas Moor 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Lesser General Public 00009 License as published by the Free Software Foundation; either 00010 version 2.1 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Lesser General Public License for more details. 00016 00017 You should have received a copy of the GNU Lesser General Public 00018 License along with this library; if not, write to the Free Software 00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 00020 00021 00022 //#define FAUDES_DEBUG_FUNCTION 00023 00024 #include "syn_wsupcon.h" 00025 #include "syn_supcon.h" 00026 #include "syn_functions.h" 00027 00028 00029 namespace faudes { 00030 00031 00032 /* 00033 *************************************************************************************** 00034 *************************************************************************************** 00035 Implementation IsOmegaControllabe 00036 *************************************************************************************** 00037 *************************************************************************************** 00038 */ 00039 00040 // IsOmegaControllable() 00041 bool IsOmegaControllable( 00042 const vGenerator& rGenPlant, 00043 const EventSet& rCAlph, 00044 const vGenerator& rGenCand) 00045 { 00046 FD_DF("IsOmegaControllable(\"" << rGenPlant.Name() << "\", \"" << rGenCand.Name() << "\")"); 00047 00048 // alphabets must match 00049 if ( rGenPlant.Alphabet() != rGenCand.Alphabet()) { 00050 std::stringstream errstr; 00051 errstr << "Alphabets of generators do not match."; 00052 throw Exception("IsOmegaControllable(..)", errstr.str(), 100); 00053 } 00054 00055 #ifdef FAUDES_CHECKED 00056 // generators are meant to be nonblocking 00057 if( !IsOmegaTrim(rGenCand) ) { 00058 std::stringstream errstr; 00059 errstr << "Argument \"" << rGenCand.Name() << "\" is not omega-trim."; 00060 throw Exception("IsOmegaControllable(..)", errstr.str(), 201); 00061 } 00062 if( !IsOmegaTrim(rGenPlant) ) { 00063 std::stringstream errstr; 00064 errstr << "Argument \"" << rGenPlant.Name() << "\" is not omega-trim."; 00065 throw Exception("IsOmegaControllable(..)", errstr.str(), 201); 00066 } 00067 #endif 00068 00069 // the trivial case: empty cand is fine 00070 // (we must treat this case because empty generators are not regarded deterministic) 00071 if(rGenCand.Empty()) { 00072 FD_DF("IsOmegaControllable(..): empty candidate, pass"); 00073 return true; 00074 } 00075 00076 // the trivial case: empty plant is fails 00077 // (we must treat this case because empty generators are not regarded deterministic) 00078 if(rGenPlant.Empty()) { 00079 FD_DF("IsOmegaControllable(..): empty plant, fail"); 00080 return false; 00081 } 00082 00083 #ifdef FAUDES_CHECKED 00084 // generators are meant to be deterministic 00085 if ( !IsDeterministic(rGenCand) || !IsDeterministic(rGenPlant)) { 00086 std::stringstream errstr; 00087 errstr << "Arguments are expected to be deterministic."; 00088 throw Exception("IsRelativelyOmegaClosed", errstr.str(), 202); 00089 } 00090 #endif 00091 00092 // test controllability 00093 StateSet dummy; 00094 if(!IsControllableUnchecked(rGenPlant,rCAlph,rGenCand,dummy)) return false; 00095 00096 // test relative closedness 00097 if(!IsRelativelyOmegaClosedUnchecked(rGenPlant,rGenPlant)) return false; 00098 00099 // pass 00100 FD_DF("IsOmegaControllable(...): passed"); 00101 return true; 00102 } 00103 00104 00105 // IsOmegaControllable() wrapper 00106 bool IsOmegaControllable( 00107 const cGenerator& rPlantGen, 00108 const vGenerator& rCandGen) 00109 { 00110 return IsOmegaControllable(rPlantGen,rPlantGen.ControllableEvents(),rCandGen); 00111 } 00112 00113 /* 00114 *************************************************************************************** 00115 *************************************************************************************** 00116 Implementation SupConComplete 00117 *************************************************************************************** 00118 *************************************************************************************** 00119 */ 00120 00121 00122 // supcon complete 00123 void SupConComplete( 00124 const vGenerator& rPlantGen, 00125 const EventSet& rCAlph, 00126 const vGenerator& rSpecGen, 00127 vGenerator& rResGen) 00128 { 00129 FD_DF("SupConComplete(" << rPlantGen.Name() << "," << rSpecGen.Name()<< ")"); 00130 00131 // exceptions on invalid parameters, same as std synthesis 00132 ControlProblemConsistencyCheck(rPlantGen,rCAlph,rSpecGen); 00133 00134 // prepare result 00135 vGenerator* pResGen = &rResGen; 00136 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) { 00137 pResGen= rResGen.New(); 00138 } 00139 pResGen->Clear(); 00140 pResGen->Name("SupConComplete("+rPlantGen.Name()+", "+rSpecGen.Name()+")"); 00141 pResGen->InjectAlphabet(rPlantGen.Alphabet()); 00142 00143 //check for trivial result 00144 if(rSpecGen.InitStatesEmpty()){ 00145 FD_DF("SupConComplete: empty language specification - empty result."); 00146 } 00147 00148 00149 // have a reverse composition map 00150 std::map< std::pair<Idx,Idx>, Idx> revmap; 00151 00152 // parallel composition (result is reachable) 00153 SupconParallel(rPlantGen, rCAlph, rSpecGen, revmap, *pResGen); 00154 00155 // make resulting generator complete and controllabel 00156 while(true) { 00157 Idx state_num = pResGen->Size(); 00158 if(pResGen->InitStates().Empty()) break; 00159 pResGen->Complete(); 00160 if(pResGen->InitStates().Empty()) break; 00161 SupConUnchecked(rPlantGen, rCAlph, *pResGen); 00162 if(pResGen->Size() == state_num) break; 00163 } 00164 00165 // convenience state names 00166 if(rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && rResGen.StateNamesEnabled()) 00167 SetComposedStateNames(rPlantGen, rSpecGen, revmap, *pResGen); 00168 else 00169 pResGen->ClearStateNames(); 00170 00171 // copy result 00172 if(pResGen != &rResGen) { 00173 pResGen->Move(rResGen); 00174 delete pResGen; 00175 } 00176 00177 } 00178 00179 00180 // user wrapper 00181 void SupConComplete( 00182 const cGenerator& rPlantGen, 00183 const vGenerator& rSpecGen, 00184 vGenerator& rResGen) 00185 { 00186 00187 // execute 00188 SupConComplete(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,rResGen); 00189 00190 // copy all attributes of input alphabet 00191 rResGen.EventAttributes(rPlantGen.Alphabet()); 00192 00193 } 00194 00195 00196 00197 00198 /* 00199 *************************************************************************************** 00200 *************************************************************************************** 00201 Implementation SupConCompleteNB 00202 *************************************************************************************** 00203 *************************************************************************************** 00204 */ 00205 00206 00207 // supcon complete 00208 void SupConCompleteNB( 00209 const vGenerator& rPlantGen, 00210 const EventSet& rCAlph, 00211 const vGenerator& rSpecGen, 00212 vGenerator& rResGen) 00213 { 00214 FD_DF("SupConCompleteNB(" << rPlantGen.Name() << "," << rSpecGen.Name()<< ")"); 00215 00216 // exceptions on invalid parameters, same as std synthesis 00217 ControlProblemConsistencyCheck(rPlantGen,rCAlph,rSpecGen); 00218 00219 // prepare result 00220 vGenerator* pResGen = &rResGen; 00221 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) { 00222 pResGen= rResGen.New(); 00223 } 00224 pResGen->Clear(); 00225 pResGen->Name("SupConCompleteNB("+rPlantGen.Name()+", "+rSpecGen.Name()+")"); 00226 pResGen->InjectAlphabet(rPlantGen.Alphabet()); 00227 00228 //check for trivial result 00229 if(rSpecGen.InitStatesEmpty()){ 00230 FD_DF("SupConCompleteNB: empty language specification - empty result."); 00231 } 00232 00233 00234 // have a reverse composition map 00235 std::map< std::pair<Idx,Idx>, Idx> revmap; 00236 00237 // parallel composition (result is reachable) 00238 SupconParallel(rPlantGen, rCAlph, rSpecGen, revmap, *pResGen); 00239 00240 // make resulting generator complete and controllabel and coaccessible 00241 while(true) { 00242 Idx state_num = pResGen->Size(); 00243 if(pResGen->InitStates().Empty()) break; 00244 pResGen->Coaccessible(); 00245 if(pResGen->InitStates().Empty()) break; 00246 pResGen->Complete(); 00247 if(pResGen->InitStates().Empty()) break; 00248 SupConUnchecked(rPlantGen, rCAlph, *pResGen); 00249 if(pResGen->Size() == state_num) break; 00250 } 00251 00252 // convenience state names 00253 if(rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && rResGen.StateNamesEnabled()) 00254 SetComposedStateNames(rPlantGen, rSpecGen, revmap, *pResGen); 00255 else 00256 pResGen->ClearStateNames(); 00257 00258 // copy result 00259 if(pResGen != &rResGen) { 00260 pResGen->Move(rResGen); 00261 delete pResGen; 00262 } 00263 00264 } 00265 00266 00267 // user wrapper 00268 void SupConCompleteNB( 00269 const cGenerator& rPlantGen, 00270 const vGenerator& rSpecGen, 00271 vGenerator& rResGen) 00272 { 00273 00274 // execute 00275 SupConCompleteNB(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,rResGen); 00276 00277 // copy all attributes of input alphabet 00278 rResGen.EventAttributes(rPlantGen.Alphabet()); 00279 00280 } 00281 00282 00283 00284 00285 /* 00286 *************************************************************************************** 00287 *************************************************************************************** 00288 Implementation (experimental) 00289 *************************************************************************************** 00290 *************************************************************************************** 00291 */ 00292 00293 00294 00295 00296 00297 // OmegaControlledLiveness(...) 00298 bool OmegaControlledLiveness( 00299 vGenerator& rSupCandGen, 00300 const EventSet& rCAlph, 00301 StateSet& rMarkedPlantStates, 00302 StateSet& rMarkedSpecStates) 00303 { 00304 FD_DF("OmegaClosedLoopLiveness(...)"); 00305 00306 00307 // set of critical states 00308 StateSet critical; 00309 00310 // return true if parallelcomp contains no initial states 00311 if(rSupCandGen.InitStatesEmpty()) { 00312 return true; 00313 } 00314 00315 #ifdef FAUDES_DEBUG_FUNCTION 00316 FD_DF("OmegaClosedLoopLiveness(): marked states: "); 00317 StateSet ssd= rMarkedPlantStates + rMarkedSpecStates; 00318 ssd.Write(); 00319 #endif 00320 00321 // find un-marked sccs 00322 SccFilter umfilter(SccFilter::IgnoreTrivial | SccFilter::StatesAvoid, 00323 rMarkedPlantStates + rMarkedSpecStates); 00324 std::list<StateSet> umsccs; 00325 StateSet umroots; 00326 ComputeScc(rSupCandGen,umfilter,umsccs,umroots); 00327 00328 // report 00329 std::list<StateSet>::iterator ssit=umsccs.begin(); 00330 for(;ssit!=umsccs.end(); ++ssit) { 00331 FD_DF("OmegaClosedLoopLiveness(): unmarked scc: " << ssit->ToString()); 00332 } 00333 00334 00335 // good-states iteration 00336 StateSet goodstates = rMarkedSpecStates; 00337 00338 // drive states to good states 00339 while(true) { 00340 // test individual states 00341 FD_DF("OmegaClosedLoopLiveness(): iterate over states (#" << rSupCandGen.Size() << ")"); 00342 bool found=false; 00343 StateSet::Iterator sit = rSupCandGen.StatesBegin(); 00344 StateSet::Iterator sit_end = rSupCandGen.StatesEnd(); 00345 for(; sit!=sit_end; ++sit) { 00346 // goodstate anyway 00347 if(goodstates.Exists(*sit)) continue; 00348 // test transitions 00349 TransSet::Iterator tit = rSupCandGen.TransRelBegin(*sit); 00350 TransSet::Iterator tit_end = rSupCandGen.TransRelEnd(*sit); 00351 // no transitions at all 00352 if(tit==tit_end) continue; 00353 // loop over successors 00354 for(; tit!=tit_end; ++tit) { 00355 if(goodstates.Exists(tit->X2)) continue; 00356 if(rCAlph.Exists(tit->Ev)) continue; 00357 break; 00358 } 00359 // good states survive the loop 00360 if(tit==tit_end) { 00361 FD_DF("OmegaClosedLoopLiveness(): good state " << rSupCandGen.SStr(*sit)); 00362 goodstates.Insert(*sit); 00363 found=true; 00364 } 00365 } 00366 // test individual unmarked sccs 00367 FD_DF("OmegaClosedLoopLiveness(): iterate over unmarked sccs (#" << umsccs.size() <<")"); 00368 std::list<StateSet>::iterator ssit=umsccs.begin(); 00369 while(ssit!=umsccs.end()) { 00370 bool fail=false; 00371 bool positive=false; 00372 sit=ssit->Begin(); 00373 sit_end=ssit->End(); 00374 for(; sit!=sit_end; ++sit) { 00375 // goodstate anyway 00376 if(goodstates.Exists(*sit)) continue; 00377 // test transitions 00378 TransSet::Iterator tit = rSupCandGen.TransRelBegin(*sit); 00379 TransSet::Iterator tit_end = rSupCandGen.TransRelEnd(*sit); 00380 // no transitions at all 00381 if(tit==tit_end) continue; 00382 // loop over successors 00383 for(; tit!=tit_end; ++tit) { 00384 if(goodstates.Exists(tit->X2)) { positive=true; continue;} 00385 if(rCAlph.Exists(tit->X2)) continue; 00386 if(ssit->Exists(tit->X2)) continue; 00387 break; 00388 } 00389 // good states survive the loop 00390 if(tit!=tit_end) { 00391 fail=true; 00392 break; 00393 } 00394 } 00395 // prepare next scc iterator 00396 std::list<StateSet>::iterator ssitnext=ssit; 00397 ++ssitnext; 00398 bool lend= (ssitnext==umsccs.end()); 00399 // all states passed, then they are all good 00400 if(!fail && positive) { 00401 FD_DF("OmegaClosedLoopLiveness(): good scc " << ssit->ToString()); 00402 goodstates.InsertSet(*ssit); 00403 umsccs.erase(ssit); 00404 found=true; 00405 } 00406 // break on end of list 00407 if(lend) break; 00408 // progress 00409 ssit=ssitnext; 00410 } 00411 // exit 00412 if(!found) break; 00413 }; 00414 00415 00416 00417 // delete critical states 00418 FD_DF("OmegaClosedLoopLiveness(): good states: " << goodstates.ToString()) 00419 StateSet::Iterator sit = rSupCandGen.StatesBegin(); 00420 StateSet::Iterator sit_end = rSupCandGen.StatesEnd(); 00421 for(; sit!=sit_end; ++sit) { 00422 if(!goodstates.Exists(*sit)) 00423 rSupCandGen.DelState(*sit); 00424 } 00425 00426 // return true 00427 FD_DF("OmegaClosedLoopLiveness(): done"); 00428 return true; 00429 } 00430 00431 00432 // helper class 00433 class OPSState { 00434 public: 00435 // minimal interface 00436 OPSState() {}; 00437 OPSState(const Idx& rq1, const Idx& rq2, const bool& rf) : 00438 q1(rq1), q2(rq2), m1required(rf) {}; 00439 std::string Str(void) { return ToStringInteger(q1)+"|"+ 00440 ToStringInteger(q2)+"|"+ToStringInteger(m1required); }; 00441 // order 00442 bool operator < (const OPSState& other) const { 00443 if (q1 < other.q1) return(true); 00444 if (q1 > other.q1) return(false); 00445 if (q2 < other.q2) return(true); 00446 if (q2 > other.q2) return(false); 00447 if (m1required && !other.m1required) return(true); 00448 return(false); 00449 } 00450 // member variables 00451 Idx q1; 00452 Idx q2; 00453 bool m1required; 00454 }; 00455 00456 00457 // OmegaSupconParallel(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, rResGen) 00458 void OmegaSupconParallel( 00459 const vGenerator& rPlantGen, 00460 const EventSet& rCAlph, 00461 const vGenerator& rSpecGen, 00462 std::map< OPSState , Idx>& rReverseCompositionMap, 00463 StateSet& rMarkedPlantStates, 00464 StateSet& rMarkedSpecStates, 00465 vGenerator& rResGen) 00466 { 00467 FD_DF("OmegaSupconParallel(" << &rPlantGen << "," << &rSpecGen << ")"); 00468 00469 // prepare result 00470 rResGen.Clear(); 00471 rResGen.InjectAlphabet(rPlantGen.Alphabet()); 00472 00473 // trivial case 00474 if (rPlantGen.InitStatesEmpty()) { 00475 FD_DF("OmegaSupconParallel: plant got no initial states. " 00476 << "parallel composition contains empty language."); 00477 return; 00478 } 00479 if (rSpecGen.InitStatesEmpty()) { 00480 FD_DF("OmegaSupconParallel: spec got no initial states. " 00481 << "parallel composition contains empty language."); 00482 return; 00483 } 00484 00485 // todo stack 00486 std::stack< OPSState > todo; 00487 // current pair, new pair 00488 OPSState currentstates, newstates; 00489 // state 00490 Idx tmpstate; 00491 TransSet::Iterator ptit, ptit_end, stit, stit_end; 00492 std::map< OPSState, Idx>::iterator rcit; 00493 // critical states 00494 StateSet critical; 00495 00496 00497 // push initial state on todo stack 00498 currentstates = OPSState(*rPlantGen.InitStatesBegin(), *rSpecGen.InitStatesBegin(), true); 00499 todo.push(currentstates); 00500 tmpstate=rResGen.InsInitState(); 00501 rReverseCompositionMap[currentstates] = tmpstate; 00502 if(rPlantGen.ExistsMarkedState(currentstates.q1)) 00503 rMarkedPlantStates.Insert(tmpstate); 00504 if(rSpecGen.ExistsMarkedState(currentstates.q2)) 00505 rMarkedSpecStates.Insert(tmpstate); 00506 00507 // start algorithm 00508 FD_DF("OmegaSupconParallel: processing reachable states:"); 00509 while(!todo.empty()) { 00510 // allow for user interrupt 00511 LoopCallback(); 00512 // get next reachable state from todo stack 00513 currentstates = todo.top(); 00514 todo.pop(); 00515 FD_DF("OmegaSupconParallel: processing (" << currentstates.Str() << " -> " 00516 << rReverseCompositionMap[currentstates]<<")"); 00517 // iterate over all rPlantGen and rSpecGen transitions 00518 ptit = rPlantGen.TransRelBegin(currentstates.q1); 00519 ptit_end = rPlantGen.TransRelEnd(currentstates.q1); 00520 stit = rSpecGen.TransRelBegin(currentstates.q2); 00521 stit_end = rSpecGen.TransRelEnd(currentstates.q2); 00522 // process all transitions and increment iterators strategically 00523 while((ptit != ptit_end) && (stit != stit_end)) { 00524 FD_DF("OmegaSupconParallel: current plant-transition: " << rPlantGen.TStr(*ptit) ); 00525 FD_DF("OmegaSupconParallel: current spec-transition: " << rSpecGen.TStr(*stit)); 00526 // increment tit1 and tit2, case A: execute common event 00527 if(ptit->Ev == stit->Ev) { 00528 FD_DF("OmegaSupconParallel: executing common event " << rPlantGen.EStr(ptit->Ev)); 00529 newstates = OPSState(ptit->X2, stit->X2,currentstates.m1required); 00530 // track marking requirement 00531 if(currentstates.m1required) { 00532 if(rPlantGen.ExistsMarkedState(currentstates.q1)) 00533 newstates.m1required=false; 00534 } else { 00535 if(rSpecGen.ExistsMarkedState(currentstates.q2)) { 00536 newstates.m1required=true; 00537 } 00538 } 00539 rcit = rReverseCompositionMap.find(newstates); 00540 // if state is new: add to todo list and result 00541 if(rcit == rReverseCompositionMap.end()) { 00542 todo.push(newstates); 00543 tmpstate = rResGen.InsState(); 00544 rReverseCompositionMap[newstates] = tmpstate; 00545 if(!newstates.m1required) 00546 if(rSpecGen.ExistsMarkedState(newstates.q2)) 00547 rResGen.SetMarkedState(tmpstate); 00548 if(rPlantGen.ExistsMarkedState(newstates.q1)) 00549 rMarkedPlantStates.Insert(tmpstate); 00550 if(rSpecGen.ExistsMarkedState(newstates.q2)) 00551 rMarkedSpecStates.Insert(tmpstate); 00552 FD_DF("OmegaSupconParallel: todo push: (" << newstates.Str() << ") -> " 00553 << rReverseCompositionMap[newstates]); 00554 } else { 00555 tmpstate = rcit->second; 00556 } 00557 // if successor state is not critical add transition and increment iterators 00558 if(!critical.Exists(tmpstate)) { 00559 rResGen.SetTransition(rReverseCompositionMap[currentstates], 00560 ptit->Ev, tmpstate); 00561 FD_DF("OmegaSuperParallel: add transition to new generator: " << 00562 rResGen.TStr(Transition(rReverseCompositionMap[currentstates], ptit->Ev, tmpstate))); 00563 ++ptit; 00564 ++stit; 00565 } 00566 // if successor state is critical and event is uncontrollable then delete current state 00567 else if(!rCAlph.Exists(ptit->Ev)) { 00568 FD_DF("OmegaSupconOmegaParallel: successor " << rSpecGen.SStr(tmpstate) 00569 << "in critical and common event " << rSpecGen.EStr(stit->Ev) 00570 << " uncontrollable:"); 00571 FD_DF("OmegaSupconParallel: critical insert" << rPlantGen.SStr(tmpstate)); 00572 critical.Insert(tmpstate); 00573 #ifdef FAUDES_CHECKED 00574 // do not end while loops here for detecting all h transitions 00575 // not in spec 00576 FD_DF("OmegaSupconParallel: incrementing plant and spec transrel (FAUDES_CHECKED)"); 00577 ++ptit; 00578 ++stit; 00579 #else 00580 // exit all loops 00581 ptit = ptit_end; 00582 stit = stit_end; 00583 #endif 00584 } 00585 // else if successor state is critical and event controllable increment iterators 00586 else { 00587 FD_DF("OmegaSupconParallel: incrementing plant and spec transrel"); 00588 ++ptit; 00589 ++stit; 00590 } 00591 } // end: if processing common event 00592 // increment iterators case B: process plant event that is not enebled for h 00593 else if (ptit->Ev < stit->Ev) { 00594 FD_DF("SupconParallel: asynchronous execution of event " 00595 << rPlantGen.EStr(ptit->Ev) << " in plant while " << rSpecGen.EStr(stit->Ev) << " in spec"); 00596 // if uncontrollable transition leaves specification 00597 // delete state from res and put into criticalset 00598 if (!rCAlph.Exists(ptit->Ev)) { 00599 FD_DF("OmegaSupconParallel: asynchronous event " << rPlantGen.EStr(ptit->Ev) 00600 << " in g is uncontrollable"); 00601 tmpstate = rReverseCompositionMap[currentstates]; 00602 FD_DF("OmegaSupconParallel: critical insert" << rPlantGen.SStr(tmpstate)); 00603 critical.Insert(tmpstate); 00604 // exit all loops 00605 ptit = ptit_end; 00606 stit = stit_end; 00607 break; 00608 } 00609 FD_DF("OmegaSupconParallel: incrementing plant transrel"); 00610 ++ptit; 00611 } 00612 // increment titg and titg, case C: process h event that is not enabled for g 00613 else { 00614 //#ifdef FAUDES_CHECKED 00615 // FD_WARN("SupconParallel: transition " << rSpecGen.TStr(*tith) << " in specification h not found in g"); 00616 //#endif 00617 FD_DF("OmegaSupconParallel: incrementing spec transrel"); 00618 ++stit; 00619 } 00620 } // end while incrementing 00621 // increment iterators case D: process leftover events of plant 00622 while (ptit != ptit_end) { 00623 FD_DF("OmegaSupconParallel: asynchronous execution of event " 00624 << rPlantGen.EStr(ptit->Ev) << " in plant at end of spec"); 00625 FD_DF("OmegaSupconParallel: curremt g-transition: " << rPlantGen.SStr(ptit->X1) 00626 << "-" << rPlantGen.EStr(ptit->Ev) << "-" << rPlantGen.SStr(ptit->X2)); 00627 FD_DF("OmegaSupconParallel: current h-transition: end"); 00628 // if uncontrollable transition leaves specification 00629 if (!rCAlph.Exists(ptit->Ev)) { 00630 tmpstate = rReverseCompositionMap[currentstates]; 00631 FD_DF("OmegaSupconParallel: asynchron executed uncontrollable end " 00632 << "event " << rPlantGen.EStr(ptit->Ev) << " leaves specification:"); 00633 FD_DF("SupconParallel: critical insert" << rPlantGen.SStr(tmpstate)); 00634 critical.Insert(tmpstate); 00635 // exit this loop 00636 break; 00637 } 00638 FD_DF("OmegaSupconParallel: incrementing g transrel"); 00639 ++ptit; 00640 } 00641 } // while todo 00642 FD_DF("OmegaSupconParallel: deleting critical states: " << critical.ToString()); 00643 rResGen.DelStates(critical); 00644 rMarkedPlantStates.EraseSet(critical); 00645 rMarkedSpecStates.EraseSet(critical); 00646 00647 } 00648 00649 00650 00651 // OmegaSupConNBUnchecked(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, rResGen) 00652 void OmegaSupConNBUnchecked( 00653 const vGenerator& rPlantGen, 00654 const EventSet& rCAlph, 00655 const vGenerator& rSpecGen, 00656 std::map< OPSState , Idx>& rReverseCompositionMap, 00657 vGenerator& rResGen) 00658 { 00659 FD_DF("OmegaSupConNB(\"" << rPlantGen.Name() << "\", \"" << rSpecGen.Name() << "\")"); 00660 00661 // PREPARE RESULT: 00662 vGenerator* pResGen = &rResGen; 00663 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) { 00664 pResGen= rResGen.New(); 00665 } 00666 pResGen->Clear(); 00667 pResGen->Name(CollapsString("OmegaSupConNB(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))")); 00668 pResGen->InjectAlphabet(rPlantGen.Alphabet()); 00669 00670 // controllable events 00671 FD_DF("OmegaSupConNB: controllable events: " << rCAlph.ToString()); 00672 00673 // ALGORITHM: 00674 StateSet plantmarking; 00675 StateSet specmarking; 00676 OmegaSupconParallel(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, plantmarking, specmarking, *pResGen); 00677 00678 00679 00680 // fix statenames ... 00681 std::map< OPSState, Idx>::iterator rcit; 00682 for(rcit=rReverseCompositionMap.begin(); rcit!=rReverseCompositionMap.end(); rcit++) { 00683 Idx x1=rcit->first.q1; 00684 Idx x2=rcit->first.q2; 00685 bool m1requ=rcit->first.m1required; 00686 Idx x12=rcit->second; 00687 if(!pResGen->ExistsState(x12)) continue; 00688 std::string name1= rPlantGen.StateName(x1); 00689 if(name1=="") name1=ToStringInteger(x1); 00690 std::string name2= rSpecGen.StateName(x2); 00691 if(name2=="") name1=ToStringInteger(x2); 00692 std::string name12; 00693 if(m1requ) name12= name1 + "|" + name2 + "|r1m"; 00694 else name12= name1 + "|" + name2 + "|r2m"; 00695 name12=pResGen->UniqueStateName(name12); 00696 pResGen->StateName(x12,name12); 00697 } 00698 00699 #ifdef FAUDES_DEBUG_FUNCTION 00700 pResGen->DWrite(); 00701 pResGen->Write("tmp_syn_xxx_"+pResGen->Name()+".gen"); 00702 pResGen->WriteStateSet(specmarking); 00703 pResGen->WriteStateSet(plantmarking); 00704 #endif 00705 00706 // make resulting generator trim until it's fully controllable 00707 while (1) { 00708 if (pResGen->Empty()) { 00709 break; 00710 } 00711 Idx state_num = pResGen->Size(); 00712 SupConUnchecked(rPlantGen, rCAlph, *pResGen); 00713 pResGen->Trim(); 00714 pResGen->Complete(); 00715 OmegaControlledLiveness(*pResGen,rCAlph,plantmarking,specmarking); 00716 if(pResGen->Size() == state_num) { 00717 break; 00718 } 00719 } 00720 00721 // fix statenames ... 00722 //std::map< OPSState, Idx>::iterator rcit; 00723 if(rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && pResGen->StateNamesEnabled()) 00724 for(rcit=rReverseCompositionMap.begin(); rcit!=rReverseCompositionMap.end(); rcit++) { 00725 Idx x1=rcit->first.q1; 00726 Idx x2=rcit->first.q2; 00727 bool m1requ=rcit->first.m1required; 00728 Idx x12=rcit->second; 00729 if(!pResGen->ExistsState(x12)) continue; 00730 std::string name1= rPlantGen.StateName(x1); 00731 if(name1=="") name1=ToStringInteger(x1); 00732 std::string name2= rSpecGen.StateName(x2); 00733 if(name2=="") name1=ToStringInteger(x2); 00734 std::string name12; 00735 if(m1requ) name12= name1 + "|" + name2 + "|r1m"; 00736 else name12= name1 + "|" + name2 + "|r2m"; 00737 name12=pResGen->UniqueStateName(name12); 00738 pResGen->StateName(x12,name12); 00739 } 00740 00741 // .. or clear them (?) 00742 if(!(rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && pResGen->StateNamesEnabled())) 00743 pResGen->ClearStateNames(); 00744 00745 // copy result 00746 if(pResGen != &rResGen) { 00747 pResGen->Move(rResGen); 00748 delete pResGen; 00749 } 00750 00751 } 00752 00753 00754 /* 00755 **************************************** 00756 * SUPCON: WRAPPER / USER FUNCTIONS * 00757 **************************************** 00758 */ 00759 00760 00761 // OmegaSupConNB(rPlantGen, rCAlph, rSpecGen, rResGen) 00762 void OmegaSupConNB( 00763 const vGenerator& rPlantGen, 00764 const EventSet& rCAlph, 00765 const vGenerator& rSpecGen, 00766 vGenerator& rResGen) 00767 { 00768 00769 // CONSISTENCY CHECK: 00770 ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen); 00771 00772 // HELPERS: 00773 std::map< OPSState , Idx> rcmap; 00774 00775 // ALGORITHM: 00776 OmegaSupConNBUnchecked(rPlantGen, rCAlph, rSpecGen, rcmap, rResGen); 00777 } 00778 00779 00780 00781 00782 00783 // omega supcon for cGenerators: 00784 // uses and maintains controllablity from plant 00785 void OmegaSupConNB( 00786 const cGenerator& rPlantGen, 00787 const vGenerator& rSpecGen, 00788 vGenerator& rResGen) { 00789 00790 // prepare result 00791 vGenerator* pResGen = &rResGen; 00792 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) { 00793 pResGen= rResGen.New(); 00794 } 00795 00796 // execute 00797 OmegaSupConNB(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,*pResGen); 00798 00799 // copy all attributes of input alphabet 00800 pResGen->EventAttributes(rPlantGen.Alphabet()); 00801 00802 // copy result 00803 if(pResGen != &rResGen) { 00804 pResGen->Move(rResGen); 00805 delete pResGen; 00806 } 00807 } 00808 00809 00810 } // name space |
libFAUDES 2.16b --- 2010-9-8 --- c++ source docu by doxygen 1.6.3