libFAUDES

Sections

Index

syn_wsupcon.cpp

Go 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