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 Generator& rGenPlant, 00043 const EventSet& rCAlph, 00044 const Generator& 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 System& rPlantGen, 00108 const Generator& 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 Generator& rPlantGen, 00125 const EventSet& rCAlph, 00126 const Generator& rSpecGen, 00127 Generator& 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 Generator* 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->StateNamesEnabled(false); 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 System& rPlantGen, 00183 const Generator& rSpecGen, 00184 Generator& 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 Generator& rPlantGen, 00210 const EventSet& rCAlph, 00211 const Generator& rSpecGen, 00212 Generator& 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 Generator* 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->StateNamesEnabled(false); 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 System& rPlantGen, 00270 const Generator& rSpecGen, 00271 Generator& 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 Generator& 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 StateSet astates = rMarkedPlantStates + rMarkedSpecStates; 00323 SccFilter umfilter(SccFilter::IgnoreTrivial | SccFilter::StatesAvoid, astates); 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 // LoopCallback(); 00341 // allow for user interrupt, incl progress report 00342 FD_WPC(1,2,"OmegaClosedLoopLiveness(): iterating states"); 00343 // test individual states 00344 FD_DF("OmegaClosedLoopLiveness(): iterate over states (#" << rSupCandGen.Size() << ")"); 00345 bool found=false; 00346 StateSet::Iterator sit = rSupCandGen.StatesBegin(); 00347 StateSet::Iterator sit_end = rSupCandGen.StatesEnd(); 00348 for(; sit!=sit_end; ++sit) { 00349 // goodstate anyway 00350 if(goodstates.Exists(*sit)) continue; 00351 // test transitions 00352 TransSet::Iterator tit = rSupCandGen.TransRelBegin(*sit); 00353 TransSet::Iterator tit_end = rSupCandGen.TransRelEnd(*sit); 00354 // no transitions at all 00355 if(tit==tit_end) continue; 00356 // loop over successors 00357 for(; tit!=tit_end; ++tit) { 00358 if(goodstates.Exists(tit->X2)) continue; 00359 if(rCAlph.Exists(tit->Ev)) continue; 00360 break; 00361 } 00362 // good states survive the loop 00363 if(tit==tit_end) { 00364 FD_DF("OmegaClosedLoopLiveness(): good state " << rSupCandGen.SStr(*sit)); 00365 goodstates.Insert(*sit); 00366 found=true; 00367 } 00368 } 00369 // test individual unmarked sccs 00370 FD_DF("OmegaClosedLoopLiveness(): iterate over unmarked sccs (#" << umsccs.size() <<")"); 00371 std::list<StateSet>::iterator ssit=umsccs.begin(); 00372 while(ssit!=umsccs.end()) { 00373 bool fail=false; 00374 bool positive=false; 00375 sit=ssit->Begin(); 00376 sit_end=ssit->End(); 00377 for(; sit!=sit_end; ++sit) { 00378 // goodstate anyway 00379 if(goodstates.Exists(*sit)) continue; 00380 // test transitions 00381 TransSet::Iterator tit = rSupCandGen.TransRelBegin(*sit); 00382 TransSet::Iterator tit_end = rSupCandGen.TransRelEnd(*sit); 00383 // no transitions at all 00384 if(tit==tit_end) continue; 00385 // loop over successors 00386 for(; tit!=tit_end; ++tit) { 00387 if(goodstates.Exists(tit->X2)) { positive=true; continue;} 00388 if(rCAlph.Exists(tit->X2)) continue; 00389 if(ssit->Exists(tit->X2)) continue; 00390 break; 00391 } 00392 // good states survive the loop 00393 if(tit!=tit_end) { 00394 fail=true; 00395 break; 00396 } 00397 } 00398 // prepare next scc iterator 00399 std::list<StateSet>::iterator ssitnext=ssit; 00400 ++ssitnext; 00401 bool lend= (ssitnext==umsccs.end()); 00402 // all states passed, then they are all good 00403 if(!fail && positive) { 00404 FD_DF("OmegaClosedLoopLiveness(): good scc " << ssit->ToString()); 00405 goodstates.InsertSet(*ssit); 00406 umsccs.erase(ssit); 00407 found=true; 00408 } 00409 // break on end of list 00410 if(lend) break; 00411 // progress 00412 ssit=ssitnext; 00413 } 00414 // exit 00415 if(!found) break; 00416 }; 00417 00418 00419 00420 // delete critical states 00421 FD_DF("OmegaClosedLoopLiveness(): good states: " << goodstates.ToString()) 00422 StateSet::Iterator sit = rSupCandGen.StatesBegin(); 00423 StateSet::Iterator sit_end = rSupCandGen.StatesEnd(); 00424 for(; sit!=sit_end; ++sit) { 00425 if(!goodstates.Exists(*sit)) 00426 rSupCandGen.DelState(*sit); 00427 } 00428 00429 // return true 00430 FD_DF("OmegaClosedLoopLiveness(): done"); 00431 return true; 00432 } 00433 00434 00435 // helper class 00436 class OPSState { 00437 public: 00438 // minimal interface 00439 OPSState() {}; 00440 OPSState(const Idx& rq1, const Idx& rq2, const bool& rf) : 00441 q1(rq1), q2(rq2), m1required(rf) {}; 00442 std::string Str(void) { return ToStringInteger(q1)+"|"+ 00443 ToStringInteger(q2)+"|"+ToStringInteger(m1required); }; 00444 // order 00445 bool operator < (const OPSState& other) const { 00446 if (q1 < other.q1) return(true); 00447 if (q1 > other.q1) return(false); 00448 if (q2 < other.q2) return(true); 00449 if (q2 > other.q2) return(false); 00450 if (m1required && !other.m1required) return(true); 00451 return(false); 00452 } 00453 // member variables 00454 Idx q1; 00455 Idx q2; 00456 bool m1required; 00457 }; 00458 00459 00460 // OmegaSupconParallel(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, rResGen) 00461 void OmegaSupconParallel( 00462 const Generator& rPlantGen, 00463 const EventSet& rCAlph, 00464 const Generator& rSpecGen, 00465 std::map< OPSState , Idx>& rReverseCompositionMap, 00466 StateSet& rMarkedPlantStates, 00467 StateSet& rMarkedSpecStates, 00468 Generator& rResGen) 00469 { 00470 FD_DF("OmegaSupconParallel(" << &rPlantGen << "," << &rSpecGen << ")"); 00471 00472 // prepare result 00473 rResGen.Clear(); 00474 rResGen.InjectAlphabet(rPlantGen.Alphabet()); 00475 00476 // trivial case 00477 if (rPlantGen.InitStatesEmpty()) { 00478 FD_DF("OmegaSupconParallel: plant got no initial states. " 00479 << "parallel composition contains empty language."); 00480 return; 00481 } 00482 if (rSpecGen.InitStatesEmpty()) { 00483 FD_DF("OmegaSupconParallel: spec got no initial states. " 00484 << "parallel composition contains empty language."); 00485 return; 00486 } 00487 00488 // todo stack 00489 std::stack< OPSState > todo; 00490 // current pair, new pair 00491 OPSState currentstates, newstates; 00492 // state 00493 Idx tmpstate; 00494 TransSet::Iterator ptit, ptit_end, stit, stit_end; 00495 std::map< OPSState, Idx>::iterator rcit; 00496 // critical states 00497 StateSet critical; 00498 00499 00500 // push initial state on todo stack 00501 currentstates = OPSState(*rPlantGen.InitStatesBegin(), *rSpecGen.InitStatesBegin(), true); 00502 todo.push(currentstates); 00503 tmpstate=rResGen.InsInitState(); 00504 rReverseCompositionMap[currentstates] = tmpstate; 00505 if(rPlantGen.ExistsMarkedState(currentstates.q1)) 00506 rMarkedPlantStates.Insert(tmpstate); 00507 if(rSpecGen.ExistsMarkedState(currentstates.q2)) 00508 rMarkedSpecStates.Insert(tmpstate); 00509 00510 // start algorithm 00511 FD_DF("OmegaSupconParallel: processing reachable states:"); 00512 while(!todo.empty()) { 00513 // allow for user interrupt 00514 // LoopCallback(); 00515 // allow for user interrupt, incl progress report 00516 FD_WPC(rReverseCompositionMap.size(),rReverseCompositionMap.size()+todo.size(),"OmegaSupconParallel(): processing"); 00517 // get next reachable state from todo stack 00518 currentstates = todo.top(); 00519 todo.pop(); 00520 FD_DF("OmegaSupconParallel: processing (" << currentstates.Str() << " -> " 00521 << rReverseCompositionMap[currentstates]<<")"); 00522 // iterate over all rPlantGen and rSpecGen transitions 00523 ptit = rPlantGen.TransRelBegin(currentstates.q1); 00524 ptit_end = rPlantGen.TransRelEnd(currentstates.q1); 00525 stit = rSpecGen.TransRelBegin(currentstates.q2); 00526 stit_end = rSpecGen.TransRelEnd(currentstates.q2); 00527 // process all transitions and increment iterators strategically 00528 while((ptit != ptit_end) && (stit != stit_end)) { 00529 FD_DF("OmegaSupconParallel: current plant-transition: " << rPlantGen.TStr(*ptit) ); 00530 FD_DF("OmegaSupconParallel: current spec-transition: " << rSpecGen.TStr(*stit)); 00531 // increment tit1 and tit2, case A: execute common event 00532 if(ptit->Ev == stit->Ev) { 00533 FD_DF("OmegaSupconParallel: executing common event " << rPlantGen.EStr(ptit->Ev)); 00534 newstates = OPSState(ptit->X2, stit->X2,currentstates.m1required); 00535 // track marking requirement 00536 if(currentstates.m1required) { 00537 if(rPlantGen.ExistsMarkedState(currentstates.q1)) 00538 newstates.m1required=false; 00539 } else { 00540 if(rSpecGen.ExistsMarkedState(currentstates.q2)) { 00541 newstates.m1required=true; 00542 } 00543 } 00544 rcit = rReverseCompositionMap.find(newstates); 00545 // if state is new: add to todo list and result 00546 if(rcit == rReverseCompositionMap.end()) { 00547 todo.push(newstates); 00548 tmpstate = rResGen.InsState(); 00549 rReverseCompositionMap[newstates] = tmpstate; 00550 if(!newstates.m1required) 00551 if(rSpecGen.ExistsMarkedState(newstates.q2)) 00552 rResGen.SetMarkedState(tmpstate); 00553 if(rPlantGen.ExistsMarkedState(newstates.q1)) 00554 rMarkedPlantStates.Insert(tmpstate); 00555 if(rSpecGen.ExistsMarkedState(newstates.q2)) 00556 rMarkedSpecStates.Insert(tmpstate); 00557 FD_DF("OmegaSupconParallel: todo push: (" << newstates.Str() << ") -> " 00558 << rReverseCompositionMap[newstates]); 00559 } else { 00560 tmpstate = rcit->second; 00561 } 00562 // if successor state is not critical add transition and increment iterators 00563 if(!critical.Exists(tmpstate)) { 00564 rResGen.SetTransition(rReverseCompositionMap[currentstates], 00565 ptit->Ev, tmpstate); 00566 FD_DF("OmegaSuperParallel: add transition to new generator: " << 00567 rResGen.TStr(Transition(rReverseCompositionMap[currentstates], ptit->Ev, tmpstate))); 00568 ++ptit; 00569 ++stit; 00570 } 00571 // if successor state is critical and event is uncontrollable then delete current state 00572 else if(!rCAlph.Exists(ptit->Ev)) { 00573 FD_DF("OmegaSupconOmegaParallel: successor " << rSpecGen.SStr(tmpstate) 00574 << "in critical and common event " << rSpecGen.EStr(stit->Ev) 00575 << " uncontrollable:"); 00576 FD_DF("OmegaSupconParallel: critical insert" << rPlantGen.SStr(tmpstate)); 00577 critical.Insert(tmpstate); 00578 #ifdef FAUDES_CHECKED 00579 // do not end while loops here for detecting all h transitions 00580 // not in spec 00581 FD_DF("OmegaSupconParallel: incrementing plant and spec transrel (FAUDES_CHECKED)"); 00582 ++ptit; 00583 ++stit; 00584 #else 00585 // exit all loops 00586 ptit = ptit_end; 00587 stit = stit_end; 00588 #endif 00589 } 00590 // else if successor state is critical and event controllable increment iterators 00591 else { 00592 FD_DF("OmegaSupconParallel: incrementing plant and spec transrel"); 00593 ++ptit; 00594 ++stit; 00595 } 00596 } // end: if processing common event 00597 // increment iterators case B: process plant event that is not enebled for h 00598 else if (ptit->Ev < stit->Ev) { 00599 FD_DF("SupconParallel: asynchronous execution of event " 00600 << rPlantGen.EStr(ptit->Ev) << " in plant while " << rSpecGen.EStr(stit->Ev) << " in spec"); 00601 // if uncontrollable transition leaves specification 00602 // delete state from res and put into criticalset 00603 if (!rCAlph.Exists(ptit->Ev)) { 00604 FD_DF("OmegaSupconParallel: asynchronous event " << rPlantGen.EStr(ptit->Ev) 00605 << " in g is uncontrollable"); 00606 tmpstate = rReverseCompositionMap[currentstates]; 00607 FD_DF("OmegaSupconParallel: critical insert" << rPlantGen.SStr(tmpstate)); 00608 critical.Insert(tmpstate); 00609 // exit all loops 00610 ptit = ptit_end; 00611 stit = stit_end; 00612 break; 00613 } 00614 FD_DF("OmegaSupconParallel: incrementing plant transrel"); 00615 ++ptit; 00616 } 00617 // increment titg and titg, case C: process h event that is not enabled for g 00618 else { 00619 //#ifdef FAUDES_CHECKED 00620 // FD_WARN("SupconParallel: transition " << rSpecGen.TStr(*tith) << " in specification h not found in g"); 00621 //#endif 00622 FD_DF("OmegaSupconParallel: incrementing spec transrel"); 00623 ++stit; 00624 } 00625 } // end while incrementing 00626 // increment iterators case D: process leftover events of plant 00627 while (ptit != ptit_end) { 00628 FD_DF("OmegaSupconParallel: asynchronous execution of event " 00629 << rPlantGen.EStr(ptit->Ev) << " in plant at end of spec"); 00630 FD_DF("OmegaSupconParallel: curremt g-transition: " << rPlantGen.SStr(ptit->X1) 00631 << "-" << rPlantGen.EStr(ptit->Ev) << "-" << rPlantGen.SStr(ptit->X2)); 00632 FD_DF("OmegaSupconParallel: current h-transition: end"); 00633 // if uncontrollable transition leaves specification 00634 if (!rCAlph.Exists(ptit->Ev)) { 00635 tmpstate = rReverseCompositionMap[currentstates]; 00636 FD_DF("OmegaSupconParallel: asynchron executed uncontrollable end " 00637 << "event " << rPlantGen.EStr(ptit->Ev) << " leaves specification:"); 00638 FD_DF("SupconParallel: critical insert" << rPlantGen.SStr(tmpstate)); 00639 critical.Insert(tmpstate); 00640 // exit this loop 00641 break; 00642 } 00643 FD_DF("OmegaSupconParallel: incrementing g transrel"); 00644 ++ptit; 00645 } 00646 } // while todo 00647 FD_DF("OmegaSupconParallel: deleting critical states: " << critical.ToString()); 00648 rResGen.DelStates(critical); 00649 rMarkedPlantStates.EraseSet(critical); 00650 rMarkedSpecStates.EraseSet(critical); 00651 00652 } 00653 00654 00655 00656 // OmegaSupConNBUnchecked(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, rResGen) 00657 void OmegaSupConNBUnchecked( 00658 const Generator& rPlantGen, 00659 const EventSet& rCAlph, 00660 const Generator& rSpecGen, 00661 std::map< OPSState , Idx>& rReverseCompositionMap, 00662 Generator& rResGen) 00663 { 00664 FD_DF("OmegaSupConNB(\"" << rPlantGen.Name() << "\", \"" << rSpecGen.Name() << "\")"); 00665 00666 // PREPARE RESULT: 00667 Generator* pResGen = &rResGen; 00668 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) { 00669 pResGen= rResGen.New(); 00670 } 00671 pResGen->Clear(); 00672 pResGen->Name(CollapsString("OmegaSupConNB(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))")); 00673 pResGen->InjectAlphabet(rPlantGen.Alphabet()); 00674 00675 // controllable events 00676 FD_DF("OmegaSupConNB: controllable events: " << rCAlph.ToString()); 00677 00678 // ALGORITHM: 00679 StateSet plantmarking; 00680 StateSet specmarking; 00681 OmegaSupconParallel(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, plantmarking, specmarking, *pResGen); 00682 00683 00684 00685 // fix statenames ... 00686 std::map< OPSState, Idx>::iterator rcit; 00687 for(rcit=rReverseCompositionMap.begin(); rcit!=rReverseCompositionMap.end(); rcit++) { 00688 Idx x1=rcit->first.q1; 00689 Idx x2=rcit->first.q2; 00690 bool m1requ=rcit->first.m1required; 00691 Idx x12=rcit->second; 00692 if(!pResGen->ExistsState(x12)) continue; 00693 std::string name1= rPlantGen.StateName(x1); 00694 if(name1=="") name1=ToStringInteger(x1); 00695 std::string name2= rSpecGen.StateName(x2); 00696 if(name2=="") name1=ToStringInteger(x2); 00697 std::string name12; 00698 if(m1requ) name12= name1 + "|" + name2 + "|r1m"; 00699 else name12= name1 + "|" + name2 + "|r2m"; 00700 name12=pResGen->UniqueStateName(name12); 00701 pResGen->StateName(x12,name12); 00702 } 00703 00704 #ifdef FAUDES_DEBUG_FUNCTION 00705 pResGen->DWrite(); 00706 pResGen->Write("tmp_syn_xxx_"+pResGen->Name()+".gen"); 00707 pResGen->WriteStateSet(specmarking); 00708 pResGen->WriteStateSet(plantmarking); 00709 #endif 00710 00711 // make resulting generator trim until it's fully controllable 00712 while (1) { 00713 if (pResGen->Empty()) { 00714 break; 00715 } 00716 Idx state_num = pResGen->Size(); 00717 SupConUnchecked(rPlantGen, rCAlph, *pResGen); 00718 pResGen->Trim(); 00719 pResGen->Complete(); 00720 OmegaControlledLiveness(*pResGen,rCAlph,plantmarking,specmarking); 00721 if(pResGen->Size() == state_num) { 00722 break; 00723 } 00724 } 00725 00726 // fix statenames ... 00727 //std::map< OPSState, Idx>::iterator rcit; 00728 if(rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && pResGen->StateNamesEnabled()) 00729 for(rcit=rReverseCompositionMap.begin(); rcit!=rReverseCompositionMap.end(); rcit++) { 00730 Idx x1=rcit->first.q1; 00731 Idx x2=rcit->first.q2; 00732 bool m1requ=rcit->first.m1required; 00733 Idx x12=rcit->second; 00734 if(!pResGen->ExistsState(x12)) continue; 00735 std::string name1= rPlantGen.StateName(x1); 00736 if(name1=="") name1=ToStringInteger(x1); 00737 std::string name2= rSpecGen.StateName(x2); 00738 if(name2=="") name1=ToStringInteger(x2); 00739 std::string name12; 00740 if(m1requ) name12= name1 + "|" + name2 + "|r1m"; 00741 else name12= name1 + "|" + name2 + "|r2m"; 00742 name12=pResGen->UniqueStateName(name12); 00743 pResGen->StateName(x12,name12); 00744 } 00745 00746 // .. or clear them (?) 00747 if(!(rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && pResGen->StateNamesEnabled())) 00748 pResGen->StateNamesEnabled(false); 00749 00750 // copy result 00751 if(pResGen != &rResGen) { 00752 pResGen->Move(rResGen); 00753 delete pResGen; 00754 } 00755 00756 } 00757 00758 00759 /* 00760 **************************************** 00761 * SUPCON: WRAPPER / USER FUNCTIONS * 00762 **************************************** 00763 */ 00764 00765 00766 // OmegaSupConNB(rPlantGen, rCAlph, rSpecGen, rResGen) 00767 void OmegaSupConNB( 00768 const Generator& rPlantGen, 00769 const EventSet& rCAlph, 00770 const Generator& rSpecGen, 00771 Generator& rResGen) 00772 { 00773 00774 // CONSISTENCY CHECK: 00775 ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen); 00776 00777 // HELPERS: 00778 std::map< OPSState , Idx> rcmap; 00779 00780 // ALGORITHM: 00781 OmegaSupConNBUnchecked(rPlantGen, rCAlph, rSpecGen, rcmap, rResGen); 00782 } 00783 00784 00785 00786 00787 00788 // omega supcon for Systems: 00789 // uses and maintains controllablity from plant 00790 void OmegaSupConNB( 00791 const System& rPlantGen, 00792 const Generator& rSpecGen, 00793 Generator& rResGen) { 00794 00795 // prepare result 00796 Generator* pResGen = &rResGen; 00797 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) { 00798 pResGen= rResGen.New(); 00799 } 00800 00801 // execute 00802 OmegaSupConNB(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,*pResGen); 00803 00804 // copy all attributes of input alphabet 00805 pResGen->EventAttributes(rPlantGen.Alphabet()); 00806 00807 // copy result 00808 if(pResGen != &rResGen) { 00809 pResGen->Move(rResGen); 00810 delete pResGen; 00811 } 00812 } 00813 00814 00815 } // name space |
libFAUDES 2.20s --- 2011.10.12 --- c++ source docu by doxygen