syn_supcon.cpp

Go to the documentation of this file.
00001 /** @file syn_supcon.cpp Supremal controllable sublanguage */
00002 
00003 /* FAU Discrete Event Systems Library (libfaudes)
00004 
00005    Copyright (C) 2006  Bernd Opitz
00006    Exclusive copyright is granted to Klaus Schmidt
00007 
00008    This library is free software; you can redistribute it and/or
00009    modify it under the terms of the GNU Lesser General Public
00010    License as published by the Free Software Foundation; either
00011    version 2.1 of the License, or (at your option) any later version.
00012 
00013    This library is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016    Lesser General Public License for more details.
00017 
00018    You should have received a copy of the GNU Lesser General Public
00019    License along with this library; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00021    
00022 
00023 #include "syn_supcon.h"
00024 
00025 
00026 namespace faudes {
00027 
00028 
00029 
00030 
00031 /*
00032 ***************************************************************************************
00033 ***************************************************************************************
00034  Implementation
00035 ***************************************************************************************
00036 ***************************************************************************************
00037 */
00038 
00039 
00040 /*
00041 Revision fro libFAUDES 2.20b:
00042 
00043 SupCon and IsControllable used to share the same algorithm to identify critical
00044 states, implemented as IsControllableUnchecked().
00045 
00046 The implementation, however, was only correct under the assumption that the state set of the 
00047 supervisor/candidate H would also distinguish plant states. The later assumption is
00048 true in the context of SupCon, where the candidate is build as the parallel composition. 
00049 It is not true in general.
00050 
00051 Thus, in libFAUDES 2.20b the original algorithm was moved from  IsControllableUnchecked to
00052 SupConClosedUnchecked and IsControllableUnchecked was reimplemented.
00053 */
00054 
00055 
00056 // SupConClosedUnchecked(rPlantGen, rCAlph, rSupCandGen)
00057 void SupConClosedUnchecked(
00058   const Generator& rPlantGen,  // aka G
00059   const EventSet& rCAlph,  
00060   Generator& rSupCandGen       // aka H
00061 ) 
00062 {
00063   FD_DF("SupConClosedUnchecked(" << &rSupCandGen << "," << &rPlantGen << ")");
00064 
00065   // bail out if plant or candidate contain no initial states
00066   if(rPlantGen.InitStatesEmpty() || rSupCandGen.InitStatesEmpty()) 
00067     return;
00068    
00069   // todo stack (pairs of states)
00070   std::stack<Idx> todog, todoh;
00071   // set of already processed states of H (this is where we need H-states to also distinguish G-states) 
00072   StateSet processed;
00073   // reverse sorted transition relation of H (to be built on the fly)
00074   TransSetX2EvX1 rtransrel;
00075   // critical states
00076   StateSet critical;
00077 
00078   // push combined initial state on todo stack
00079   todog.push(*rPlantGen.InitStatesBegin());
00080   todoh.push(*rSupCandGen.InitStatesBegin());
00081   FD_DF("SupCon: todo push: (" << rPlantGen.SStr(*rPlantGen.InitStatesBegin()) << "|"
00082      << rSupCandGen.SStr(*rSupCandGen.InitStatesBegin()) << ")");
00083 
00084   // process todo stack
00085   while (! todog.empty()) {
00086     // allow for user interrupt
00087     // LoopCallback();
00088     // allow for user interrupt, incl progress report
00089     FD_WPC(1,2,"Controllability(): iterating states"); 
00090     // get top element from todo stack
00091     Idx currentg = todog.top();
00092     Idx currenth = todoh.top();
00093     todog.pop();
00094     todoh.pop();
00095     FD_DF("SupCon: todo pop: (" << rPlantGen.SStr(currentg) << "|" 
00096        << rSupCandGen.SStr(currenth) << ")");
00097 
00098     // break on doublets (tmoor 201104)
00099     if(processed.Exists(currenth)) continue;
00100 
00101 #ifdef FAUDES_DEBUG_FUNCTION
00102     TransSet::Iterator _titg, _tith;
00103     // print all transitions of current states
00104     FD_DF("SupCon: transitions from current states:");
00105     for (_titg = rPlantGen.TransRelBegin(currentg); _titg != rPlantGen.TransRelEnd(currentg); ++_titg) 
00106        FD_DF("SupCon: g: " << rPlantGen.SStr(_titg->X1) << "-" 
00107      << rPlantGen.EStr(_titg->Ev) << "-" << rPlantGen.SStr(_titg->X2));
00108     for (_tith = rSupCandGen.TransRelBegin(currenth); _tith != rSupCandGen.TransRelEnd(currenth); ++_tith) 
00109        FD_DF("SupCon: h: " << rSupCandGen.SStr(_tith->X1) << "-" 
00110      << rSupCandGen.EStr(_tith->Ev) << "-" << rSupCandGen.SStr(_tith->X2));
00111 #endif 
00112 
00113     // process all h transitions while there could be matching g transitions
00114     TransSet::Iterator titg = rPlantGen.TransRelBegin(currentg);
00115     TransSet::Iterator titg_end = rPlantGen.TransRelEnd(currentg);
00116     TransSet::Iterator tith = rSupCandGen.TransRelBegin(currenth);
00117     TransSet::Iterator tith_end = rSupCandGen.TransRelEnd(currenth);
00118     while ((tith != tith_end) && (titg != titg_end)) {
00119       FD_DF("SupCon: processing g-transition: " << rPlantGen.SStr(titg->X1) 
00120       << "-" << rPlantGen.EStr(titg->Ev) << "-" << rPlantGen.SStr(titg->X2));
00121       FD_DF("SupCon: processing h-transition: " << rSupCandGen.SStr(tith->X1) 
00122             << "-" << rSupCandGen.EStr(tith->Ev) << "-" << rSupCandGen.SStr(tith->X2));
00123       // increment tith and titg case A: process common events
00124       if (titg->Ev == tith->Ev) {
00125   FD_DF("SupCon: processing common event " << rPlantGen.EStr(titg->Ev));
00126   // add to todo list if state not processed (tmoor 201104: record next H state on stack)
00127   if(!processed.Exists(tith->X2)) {
00128     todog.push(titg->X2);
00129     todoh.push(tith->X2);
00130     FD_DF("SupCon: todo push: (" << rPlantGen.SStr(titg->X2) << "|"
00131       << rSupCandGen.SStr(tith->X2) << ")");
00132   }
00133   // if h successor state is not critical add transition to rtransrel
00134   if (!critical.Exists(tith->X2)) {
00135     rtransrel.Insert(*tith);
00136     FD_DF("SupCon: incrementing g and h transrel");
00137     ++titg;
00138     ++tith;
00139   }
00140   // if successor state is critical and event uncontrollable 
00141   else if (!rCAlph.Exists(titg->Ev)) {
00142     FD_DF("SupCon: successor state " << rSupCandGen.SStr(tith->X2) << 
00143       " critical and event " << rPlantGen.EStr(titg->Ev) << " uncontrollable:");
00144     FD_DF("SupCon: TraverseUncontrollableBackwards(" << rSupCandGen.SStr(currenth) << ")");
00145       TraverseUncontrollableBackwards(rCAlph, rtransrel, critical, currenth);
00146 #ifdef FAUDES_CHECKED
00147       // just increment transrel iterators to find all h transitions not in g
00148       FD_DF("IsControllable: incrementing g an h transrel (FAUDES_CHECKED)");
00149       ++titg;
00150       ++tith;
00151       break;
00152 #else
00153             // exit all loops
00154       titg = titg_end;
00155       tith = tith_end;
00156       break;
00157 #endif
00158   }
00159         // if successor state is critical and event controllable
00160         else {
00161           FD_DF("SupCon: incrementing g and h transrel");
00162           ++titg;
00163           ++tith;
00164         }   
00165       }
00166       // increment tith and titg case B: process g event that is not enabled in h
00167       else if (titg->Ev < tith->Ev) {
00168   FD_DF("SupCon: asynchronous execution of event " 
00169            << rPlantGen.EStr(titg->Ev) << " in g while " << rSupCandGen.EStr(tith->Ev)
00170      << " in h");
00171         // if uncontrollable transition violates specification
00172         // delete state from rResGen and put into criticalset
00173         if (!rCAlph.Exists(titg->Ev)) {
00174     FD_DF("SupCon: asynchronous event " << rPlantGen.EStr(titg->Ev) 
00175          << " in g is uncontrollable");
00176     FD_DF("SupCon: TraverseUncontrollableBackwards(" << rSupCandGen.SStr(currenth) << ")");
00177     TraverseUncontrollableBackwards(rCAlph, rtransrel, critical, currenth);
00178     // exit all loops over g transrel
00179     titg = titg_end;
00180     break;
00181         }
00182   FD_DF("SupCon: incrementing g transrel");
00183   ++titg;
00184       }
00185       // increment tith and titg case C: process h event that is not enabled in g
00186       else {
00187        // #ifdef FAUDES_CHECKED
00188        // FD_WARN("SupCon: transition " << rSupCandGen.TStr(*tith) 
00189        //  << " in specification h not found in g");
00190        // #endif
00191        FD_DF("SupCon: incrementing h transrel");
00192        ++tith;
00193       }
00194     } // end while tith and titg
00195     // increment tith and titg case D: process leftover g events 
00196     while (titg != titg_end) {
00197       FD_DF("SupCon: asynchronous execution of event " 
00198           << rPlantGen.EStr(titg->Ev) << " in g at end of h");
00199       FD_DF("SupCon: actual g-transition: " << rPlantGen.SStr(titg->X1) 
00200     << "-" << rPlantGen.EStr(titg->Ev) << "-" << rPlantGen.SStr(titg->X2));
00201       FD_DF("SupCon: actual h-transition: end");
00202       // if uncontrollable transition violates specification
00203       if (!rCAlph.Exists(titg->Ev)) {
00204   FD_DF("SupCon: asynchronous execution of uncontrollable event "
00205       << rPlantGen.EStr(titg->Ev) << " in g");
00206   FD_DF("SupCon: TraverseUncontrollableBackwards(" << rPlantGen.SStr(currenth) << ")");
00207         TraverseUncontrollableBackwards(rCAlph, rtransrel, critical, currenth);
00208   // exit this loop
00209   break;
00210       }
00211       FD_DF("SupCon: incrementing g transrel");
00212       ++titg;
00213     }
00214     //#ifdef FAUDES_CHECKED
00215     // increment tith and titg case E: process leftover h events 
00216     //while (tith != tith_end) {
00217     //  FD_WARN("SupCon: transition " << rSupCandGen.TStr(*tith) << " in specification h not found in g");
00218     //  FD_DF("SupCon: incrementing h transrel");
00219     //  ++tith;
00220     //}
00221     //#endif
00222     processed.Insert(currenth);
00223   } //end while todog
00224 
00225   // remove all states that have been identified as critical or that have
00226   // been not processed
00227   critical = rSupCandGen.States() - ( processed - critical );
00228   rSupCandGen.DelStates(critical);
00229 }
00230 
00231 
00232 
00233 /*
00234 Revision for libFAUDES 2.20b:
00235 
00236 The re-implemented version will only report states as critical 
00237 if they disable an uncontrollable plant event. No reverse
00238 search is performed.
00239 */
00240 
00241 
00242 // IsControllableUnchecked(rPlantGen, rCAlph, rSupCandGen, rCriticalStates)
00243 bool IsControllableUnchecked(
00244   const Generator& rPlantGen,
00245   const EventSet& rCAlph,  
00246   const Generator& rSupCandGen, 
00247   StateSet& rCriticalStates) 
00248 {
00249   FD_DF("IsControllableUnchecked(" << &rSupCandGen << "," << &rPlantGen << ")");
00250 
00251   // todo stack
00252   std::stack< std::pair<Idx,Idx> > todo;
00253   // set of already processed states
00254   std::set< std::pair<Idx,Idx> > processed;
00255 
00256   // PREPARE RESULT:
00257   rCriticalStates.Clear();
00258   rCriticalStates.Name("CriticalStates");
00259 
00260   // return true (controllable) if there is no initial state
00261   if(rPlantGen.InitStatesEmpty() || rSupCandGen.InitStatesEmpty()) 
00262     return true;
00263 
00264   // push combined initial state on todo stack
00265   todo.push( std::make_pair(*rPlantGen.InitStatesBegin(),*rSupCandGen.InitStatesBegin()) );
00266   FD_DF("IsControllable: todo push: (" << rPlantGen.SStr(*rPlantGen.InitStatesBegin()) << "|"
00267      << rSupCandGen.SStr(*rSupCandGen.InitStatesBegin()) << ")");
00268 
00269   // process todo stack
00270   while (! todo.empty()) {
00271     // allow for user interrupt
00272     // LoopCallback();
00273     // allow for user interrupt, incl progress report
00274     FD_WPC(1,2,"Controllability(): iterating states"); 
00275     // get top element from todo stack
00276     std::pair<Idx,Idx> current = todo.top(); todo.pop();
00277     processed.insert(current);
00278     Idx currentg = current.first;
00279     Idx currenth = current.second;
00280     FD_DF("IsControllable: todo pop: (" << rPlantGen.SStr(currentg) << "|" 
00281        << rSupCandGen.SStr(currenth) << ")");
00282 
00283 #ifdef FAUDES_DEBUG_FUNCTION
00284     TransSet::Iterator _titg, _tith;
00285     // print all transitions of current states
00286     FD_DF("IsControllable: transitions from current states:");
00287     for (_titg = rPlantGen.TransRelBegin(currentg); _titg != rPlantGen.TransRelEnd(currentg); ++_titg) 
00288        FD_DF("IsControllable: g: " << rPlantGen.SStr(_titg->X1) << "-" 
00289      << rPlantGen.EStr(_titg->Ev) << "-" << rPlantGen.SStr(_titg->X2));
00290     for (_tith = rSupCandGen.TransRelBegin(currenth); _tith != rSupCandGen.TransRelEnd(currenth); ++_tith) 
00291        FD_DF("IsControllable: h: " << rSupCandGen.SStr(_tith->X1) << "-" 
00292      << rSupCandGen.EStr(_tith->Ev) << "-" << rSupCandGen.SStr(_tith->X2));
00293 #endif 
00294 
00295     // process all h transitions while there could be matching g transitions
00296     TransSet::Iterator titg = rPlantGen.TransRelBegin(currentg);
00297     TransSet::Iterator titg_end = rPlantGen.TransRelEnd(currentg);
00298     TransSet::Iterator tith = rSupCandGen.TransRelBegin(currenth);
00299     TransSet::Iterator tith_end = rSupCandGen.TransRelEnd(currenth);
00300     while ((tith != tith_end) && (titg != titg_end)) {
00301       FD_DF("IsControllable: processing g-transition: " << rPlantGen.SStr(titg->X1) 
00302       << "-" << rPlantGen.EStr(titg->Ev) << "-" << rPlantGen.SStr(titg->X2));
00303       FD_DF("IsControllable: processing h-transition: " << rSupCandGen.SStr(tith->X1) 
00304             << "-" << rSupCandGen.EStr(tith->Ev) << "-" << rSupCandGen.SStr(tith->X2));
00305       // increment tith and titg case A: process common events
00306       if (titg->Ev == tith->Ev) {
00307   FD_DF("IsControllable: processing common event " << rPlantGen.EStr(titg->Ev));
00308         // form next state and add to stack
00309         std::pair<Idx,Idx> next = std::make_pair(titg->X2,tith->X2);       
00310   // add to todo list if not processed so far 
00311       if(processed.find(next)==processed.end()) {
00312     FD_DF("IsControllable: todo push: (" << rPlantGen.SStr(titg->X2) << "|"
00313       << rSupCandGen.SStr(tith->X2) << ")");
00314           todo.push(next);
00315   }
00316         // proceed
00317   ++titg;
00318   ++tith;
00319       }
00320       // increment tith and titg case B: process g event that is not enabled in h
00321       else if (titg->Ev < tith->Ev) {
00322   FD_DF("IsControllable: asynchronous execution of event " 
00323            << rPlantGen.EStr(titg->Ev) << " in g while " << rSupCandGen.EStr(tith->Ev)
00324      << " in h");
00325         // if uncontrollable transition violates specification
00326         // record that state as critical
00327         if (!rCAlph.Exists(titg->Ev)) {
00328     FD_DF("IsControllable: asynchronous event " << rPlantGen.EStr(titg->Ev) 
00329          << " in g is uncontrollable");
00330     FD_DF("IsControllable: TraverseUncontrollableBackwards(" << rSupCandGen.SStr(currenth) << ")");
00331     rCriticalStates.Insert(currenth);
00332     // exit all loops over g transrel
00333     titg = titg_end;
00334     break;
00335         }
00336   FD_DF("IsControllable: incrementing g transrel");
00337   ++titg;
00338       }
00339       // increment tith and titg case C: process h event that is not enabled in g
00340       else {
00341        // #ifdef FAUDES_CHECKED
00342        // FD_WARN("IsControllable: transition " << rSupCandGen.TStr(*tith) 
00343        //  << " in specification h not found in g");
00344        // #endif
00345        FD_DF("IsControllable: incrementing h transrel");
00346        ++tith;
00347       }
00348     } // end while tith and titg
00349     // increment tith and titg case D: process leftover g events 
00350     while (titg != titg_end) {
00351       FD_DF("IsControllable: asynchronous execution of event " 
00352           << rPlantGen.EStr(titg->Ev) << " in g at end of h");
00353       FD_DF("IsControllable: actual g-transition: " << rPlantGen.SStr(titg->X1) 
00354     << "-" << rPlantGen.EStr(titg->Ev) << "-" << rPlantGen.SStr(titg->X2));
00355       FD_DF("IsControllable: actual h-transition: end");
00356       // if uncontrollable transition violates specification
00357       if (!rCAlph.Exists(titg->Ev)) {
00358   FD_DF("IsControllable: asynchronous execution of uncontrollable event "
00359       << rPlantGen.EStr(titg->Ev) << " in g");
00360   FD_DF("IsControllable: TraverseUncontrollableBackwards(" << rPlantGen.SStr(currenth) << ")");
00361   rCriticalStates.Insert(currenth);
00362   // exit this loop
00363   break;
00364       }
00365       FD_DF("IsControllable: incrementing g transrel");
00366       ++titg;
00367     }
00368     //#ifdef FAUDES_CHECKED
00369     // increment tith and titg case E: process leftover h events 
00370     //while (tith != tith_end) {
00371     //  FD_WARN("IsControllable: transition " << rSupCandGen.TStr(*tith) << " in specification h not found in g");
00372     //  FD_DF("IsControllable: incrementing h transrel");
00373     //  ++tith;
00374     //}
00375     //#endif
00376   } //end while todo
00377 
00378 
00379   // return identified critical states
00380   return rCriticalStates.Empty();
00381 }
00382 
00383 
00384 
00385 // SupConProduct(rPlantGen, rCAlph, rSpecGen, rCompositionMap, rResGen)
00386 void SupConProduct(
00387   const Generator& rPlantGen, 
00388   const EventSet& rCAlph,
00389   const Generator& rSpecGen,
00390   std::map< std::pair<Idx,Idx>, Idx>& rCompositionMap, 
00391   Generator& rResGen) 
00392 {
00393   FD_DF("SupConProduct(" << &rPlantGen << "," << &rSpecGen << ")");
00394   
00395   // HELPERS:
00396 
00397   // todo stack
00398   std::stack< std::pair<Idx,Idx> > todo;
00399   // set of critical states
00400   StateSet critical;
00401   // current state, next state, as pair
00402   std::pair<Idx,Idx> currentp, nextp;
00403   // current state, next state, at result
00404   Idx currentt, nextt;
00405   std::map< std::pair<Idx,Idx>, Idx>::iterator rcmapit;
00406   StateSet::Iterator lit1, lit2;
00407   TransSet::Iterator titg, titg_end, tith, tith_end;
00408 
00409   // prepare
00410   rResGen.ClearStates();
00411   rCompositionMap.clear();
00412 
00413   // ALGORITHM:  
00414   if (rPlantGen.InitStatesEmpty()) {
00415     FD_DF("SupConProduct: plant got no initial states. "
00416             << "parallel composition contains empty language.");
00417     return;
00418   }
00419   if (rSpecGen.InitStatesEmpty()) {
00420     FD_DF("SupConProduct: spec got no initial states. "
00421               << "parallel composition contains empty language.");
00422     return;
00423   }
00424 
00425   // create initial state
00426   currentp = std::make_pair(*rPlantGen.InitStatesBegin(), *rSpecGen.InitStatesBegin());
00427   todo.push(currentp);
00428   rCompositionMap[currentp] = rResGen.InsInitState();
00429   FD_DF("SupConProduct: insert initial state: (" 
00430      << rPlantGen.SStr(currentp.first) 
00431      << "|" << rSpecGen.SStr(currentp.second) << ") as idx " 
00432      << rCompositionMap[currentp]);
00433   if(rPlantGen.ExistsMarkedState(*rPlantGen.InitStatesBegin()) 
00434                 && rSpecGen.ExistsMarkedState(*rSpecGen.InitStatesBegin())) {
00435     rResGen.SetMarkedState(rCompositionMap[currentp]);
00436      FD_DF("SupConProduct: initial state is marked");
00437   }
00438 
00439   // do parallel composition of reachable states while avoiding critical states
00440   // this creates an accessible generator
00441 
00442   FD_DF("SupConProduct: *** processing reachable states ***");
00443   while (! todo.empty()) {
00444     // allow for user interrupt
00445     // LoopCallback();
00446     // allow for user interrupt, incl progress report
00447     FD_WPC(rCompositionMap.size(),rCompositionMap.size()+todo.size(),"SupConProduct(): processing"); 
00448     // get next reachable pair of states from todo stack
00449     currentp = todo.top();
00450     todo.pop();
00451     currentt = rCompositionMap[currentp];
00452     FD_DF("SupConProduct: todo pop: (" 
00453         << rPlantGen.SStr(currentp.first) 
00454   << "|" << rSpecGen.SStr(currentp.second) << ") as idx " 
00455         << currentt);
00456     // might have been indicated to be critical
00457     if(critical.Exists(currentt)) continue;    
00458     // set up transition relation iterators 
00459     titg = rPlantGen.TransRelBegin(currentp.first);
00460     titg_end = rPlantGen.TransRelEnd(currentp.first);
00461     tith = rSpecGen.TransRelBegin(currentp.second);
00462     tith_end = rSpecGen.TransRelEnd(currentp.second);
00463 
00464 #ifdef FAUDES_DEBUG_FUNCTION
00465     // print all transitions of current states
00466     FD_DF("SupConParallel: transitions from current state:");
00467     for (;titg != titg_end; ++titg) 
00468       FD_DF("SupConParallel: g: " << rPlantGen.TStr(*titg));
00469     for (;tith != tith_end; ++tith) {
00470       FD_DF("SupConParallel: h: " << rSpecGen.TStr(*tith));
00471     }
00472     titg = rPlantGen.TransRelBegin(currentp.first);
00473     tith = rSpecGen.TransRelBegin(currentp.second);
00474 #endif                                                                      
00475 
00476     // process all h transitions while there could be matching g transitions
00477     while((tith != tith_end) && (titg != titg_end)) {
00478       FD_DF("SupConProduct: current g-transition: " << rPlantGen.TStr(*titg) );
00479       FD_DF("SupConProduct: current h-transition: " << rSpecGen.TStr(*tith));
00480  
00481       // case A: execute common events
00482       if(titg->Ev == tith->Ev) {
00483   FD_DF("SupConProduct: executing common event "  << rPlantGen.EStr(titg->Ev));
00484   nextp = std::make_pair(titg->X2, tith->X2);
00485   rcmapit = rCompositionMap.find(nextp);
00486   // if state is new ...
00487   if(rcmapit == rCompositionMap.end()) {
00488           // ... add on todo stack
00489     todo.push(nextp);
00490           // ... insert in result
00491         nextt = rResGen.InsState();
00492     rCompositionMap[nextp] = nextt;
00493     FD_DF("SupConProduct: insert state: (" << 
00494              rPlantGen.SStr(nextp.first) << "|" 
00495        << rSpecGen.SStr(nextp.second) << ") as idx " 
00496              << nextt);
00497     // .. mark synchronously
00498     if(rPlantGen.ExistsMarkedState(nextp.first) && 
00499     rSpecGen.ExistsMarkedState(nextp.second)) {
00500       rResGen.SetMarkedState(nextt);
00501       FD_DF("SupConProduct: marked nes state")
00502     }
00503   }
00504   // if state already exists
00505   else {
00506     nextt = rcmapit->second;
00507   }
00508   // if successor state is not critical add transition and proceed
00509   if(!critical.Exists(nextt)) {
00510     FD_DF("SupConProduct: set transition " << 
00511     rResGen.TStr(Transition(currentt,titg->Ev,nextt)));
00512     rResGen.SetTransition(currentt, titg->Ev, nextt);
00513     FD_DF("SupConProduct: incrementing g and h transrel");
00514     ++titg;
00515     ++tith;
00516   }
00517   // if successor state is critical and event is uncontrollable then this state becomes critical, too
00518   else if (!rCAlph.Exists(titg->Ev)) {
00519     FD_DF("SupConProduct: successor in critical with uncntr. shared event " << rSpecGen.EStr(titg->Ev)) 
00520     FD_DF("SupConProduct: critical insert, exit loop");
00521     critical.Insert(currentt);
00522     // exit all loops
00523     titg = titg_end;
00524     tith = tith_end;
00525         }
00526         // else if successor state is critical and event controllable we may proceed
00527         else {
00528     FD_DF("SupConProduct: incrementing g and h transrel");
00529           ++titg;
00530           ++tith;
00531         }
00532       } // end: shared event (case A) 
00533 
00534       // case B: process g event that is not enabled for h
00535       else if (titg->Ev < tith->Ev) {
00536   FD_DF("SupConProduct: event only enabled in g: " << rPlantGen.EStr(titg->Ev));
00537   // when uncontrollable, current state is critical
00538   if(!rCAlph.Exists(titg->Ev)) {
00539     FD_DF("SupConProduct: asynchronous event is uncontrollable, critical insert, exit loop");
00540     critical.Insert(currentt);
00541     // exit all loops
00542     titg = titg_end;
00543     tith = tith_end;
00544     break;
00545   }
00546   FD_DF("SupConProduct: incrementing g transrel");
00547   ++titg;
00548       } 
00549 
00550       // case C: process h event that is not enabled for g
00551       else {
00552   FD_DF("SupConProduct: incrementing h transrel");
00553   ++tith;
00554       }
00555     } // end while incrementing both tith and titg 
00556 
00557     // case D: process leftover events of g
00558     while (titg != titg_end) {
00559       FD_DF("SupConProduct: event only enabled in g: " << rPlantGen.EStr(titg->Ev));
00560       // if uncontrollable transition leaves specification
00561       if (!rCAlph.Exists(titg->Ev)) {
00562   FD_DF("SupConProduct: asynchronous event is uncontrollable, critical insert, exit loop");
00563   critical.Insert(currentt);
00564   // exit all loops
00565   break;
00566       }
00567       FD_DF("SupConProduct: incrementing g transrel");
00568       ++titg;
00569     }
00570     //#ifdef FAUDES_CHECKED
00571     // increment titg and titg, case E: process leftover events of h
00572     //while (txoith != tith_end) {
00573     //  FD_WARN("SupConProduct:  transition " << rSpecGen.TStr(*tith)  << " in specification h not found in g");
00574     //  FD_DF("SupConProduct: incrementing h transrel");
00575     //  ++tith;
00576     //}
00577     //#endif
00578   } // while todo
00579   FD_DF("SupConProduct: deleting critical states...");
00580   rResGen.DelStates(critical);
00581 }
00582 
00583 
00584 
00585 // SupConNBUnchecked(rPlantGen, rCAlph, rSpecGen, rCompositionMap, rResGen)
00586 void SupConNBUnchecked(
00587   const Generator& rPlantGen,
00588   const EventSet& rCAlph,  
00589   const Generator& rSpecGen,
00590   std::map< std::pair<Idx,Idx>, Idx>& rCompositionMap, 
00591   Generator& rResGen) 
00592 {
00593   FD_DF("SupConNB(" << &rPlantGen << "," << &rSpecGen << ")");
00594 
00595   // PREPARE RESULT:  
00596   Generator* pResGen = &rResGen;
00597   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00598     pResGen= rResGen.New();
00599   }
00600   pResGen->Clear();
00601   pResGen->Name(CollapsString("SupConNB(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"));
00602   pResGen->InjectAlphabet(rPlantGen.Alphabet());
00603 
00604   // controllable events
00605   FD_DF("SupConNB: controllable events: "   << rCAlph.ToString());
00606 
00607   // ALGORITHM:
00608   SupConProduct(rPlantGen, rCAlph, rSpecGen, rCompositionMap, *pResGen);
00609 
00610   // make resulting generator trim until it's fully controllable
00611   while(true) {
00612     if(pResGen->Empty()) break;
00613     Idx state_num = pResGen->Size();
00614     SupConClosedUnchecked(rPlantGen, rCAlph, *pResGen);
00615     pResGen->Trim();
00616     if(pResGen->Size() == state_num) break;
00617   }
00618 
00619   // convenience state names
00620   if(rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && rResGen.StateNamesEnabled()) 
00621     SetComposedStateNames(rPlantGen, rSpecGen, rCompositionMap, *pResGen);
00622   else
00623     pResGen->StateNamesEnabled(false);
00624 
00625   // copy result
00626   if(pResGen != &rResGen) {
00627     pResGen->Move(rResGen);
00628     delete pResGen;
00629   }
00630 
00631 }
00632 
00633 // ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen)
00634 void ControlProblemConsistencyCheck(
00635   const Generator& rPlantGen,
00636   const EventSet& rCAlph, 
00637   const Generator& rSpecGen) 
00638 {
00639 
00640   // alphabets must match
00641   if ( rPlantGen.Alphabet() != rSpecGen.Alphabet()) {
00642     EventSet only_in_plant = rPlantGen.Alphabet() - rSpecGen.Alphabet();
00643     EventSet only_in_spec = rSpecGen.Alphabet() - rPlantGen.Alphabet();
00644     only_in_plant.Name("Only_In_Plant");
00645     only_in_spec.Name("Only_In_Specification");
00646     std::stringstream errstr;
00647     errstr << "Alphabets of generators do not match.";
00648     if(!only_in_plant.Empty())
00649       errstr << " " << only_in_plant.ToString() << ".";
00650     if(!only_in_spec.Empty())
00651       errstr << " " << only_in_spec.ToString() << ".";
00652     throw Exception("SupCon/SupConNB", errstr.str(), 100);
00653   }
00654   
00655   // controllable events have to be subset of Sigma
00656   if(!(rCAlph<=rPlantGen.Alphabet())) {
00657     EventSet only_in_CAlph = rCAlph - rPlantGen.Alphabet();
00658     std::stringstream errstr;
00659     errstr << "Not all controllable events are contained in Sigma: " 
00660        << only_in_CAlph.ToString() << ".";
00661     throw Exception("ControllProblemConsistencyCheck", errstr.str(), 100);
00662   } 
00663 
00664   // TODO: check symboltables to match
00665 
00666   // plant and spec must be deterministic
00667   bool plant_det = rPlantGen.IsDeterministic();
00668   bool spec_det = rSpecGen.IsDeterministic();
00669 
00670   if ((plant_det == false) && (spec_det == true)) {
00671     std::stringstream errstr;
00672     errstr << "Plant generator must be deterministic, "
00673       << "but is nondeterministic";
00674     throw Exception("ControllableConsistencyCheck", errstr.str(), 201);
00675   }
00676   else if ((plant_det == true) && (spec_det == false)) {
00677     std::stringstream errstr;
00678     errstr << "Spec generator must be deterministic, "
00679        << "but is nondeterministic";
00680     throw Exception("ControllableConsistencyCheck", errstr.str(), 203);
00681   }
00682   else if ((plant_det == false) && (spec_det == false)) {
00683     std::stringstream errstr;
00684     errstr << "Plant and spec generator must be deterministic, "
00685        << "but both are nondeterministic";
00686     throw Exception("ControllableConsistencyCheck", errstr.str(), 204);
00687   }
00688 }
00689 
00690 // ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen)
00691 void ControlProblemConsistencyCheck(
00692   const Generator& rPlantGen,
00693   const EventSet& rCAlph, 
00694   const EventSet& rOAlph, 
00695   const Generator& rSpecGen) 
00696 {
00697   // std test
00698   ControlProblemConsistencyCheck(rPlantGen,rCAlph,rSpecGen);
00699   // observable events have to be subset of Sigma
00700   if(!(rOAlph<=rPlantGen.Alphabet())) {
00701     EventSet only_in_OAlph = rOAlph - rPlantGen.Alphabet();
00702     std::stringstream errstr;
00703     errstr << "Not all observable events are contained in Sigma: " 
00704        << only_in_OAlph.ToString() << ".";
00705     throw Exception("ControllProblemConsistencyCheck", errstr.str(), 100);
00706   } 
00707 }
00708 
00709 
00710 /*
00711 ****************************************
00712 * SUPCON: WRAPPER / USER FUNCTIONS     *
00713 ****************************************
00714 */
00715 
00716 
00717 // IsControllable(rPlantGen, rCAlph, rSupCandGen)
00718 bool IsControllable(
00719   const Generator& rPlantGen, 
00720   const EventSet& rCAlph, 
00721   const Generator& rSupCandGen) 
00722 {
00723   FD_DF("IsControllable(" << &rSupCandGen << "," << &rPlantGen << ")");
00724 
00725   // HELPERS:
00726   FD_DF("IsControllable: controllable events: " << rCAlph.ToString());
00727 
00728   // critical set
00729   StateSet critical;
00730 
00731   // CONSISTENCY CHECKS:
00732   ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSupCandGen);
00733 
00734   // ALGORITHM:
00735   return IsControllableUnchecked(rPlantGen, rCAlph, rSupCandGen, critical);
00736 }
00737 
00738 
00739 // IsControllable(rPlantGen, rCAlph, rSupCandGen, critical)
00740 bool IsControllable(
00741   const Generator& rPlantGen, 
00742   const EventSet& rCAlph, 
00743   const Generator& rSupCandGen, 
00744   StateSet& rCriticalStates) 
00745 {
00746   FD_DF("IsControllable(" << &rSupCandGen << "," << &rPlantGen << ")");
00747 
00748   // CONSISTENCY CHECKS:
00749   ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSupCandGen);
00750 
00751   // ALGORITHM:
00752   return IsControllableUnchecked(rPlantGen, rCAlph, rSupCandGen, rCriticalStates);
00753 }
00754 
00755 
00756 // SupConNB(rPlantGen, rCAlph, rSpecGen, rResGen)
00757 void SupConNB(
00758   const Generator& rPlantGen, 
00759   const EventSet& rCAlph, 
00760   const Generator& rSpecGen, 
00761   Generator& rResGen) 
00762 {
00763 
00764   // CONSISTENCY CHECK:
00765   ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen);
00766 
00767   // HELPERS:
00768   std::map< std::pair<Idx,Idx>, Idx> rcmap;
00769 
00770   // ALGORITHM:
00771   SupConNBUnchecked(rPlantGen, rCAlph, rSpecGen, rcmap, rResGen);
00772 }
00773 
00774 
00775 
00776 
00777 // SupConClosed(rPlantGen, rCAlph, rSpecGen, rResGen)
00778 void SupConClosed(
00779   const Generator& rPlantGen, 
00780   const EventSet& rCAlph,
00781   const Generator& rSpecGen, 
00782   Generator& rResGen) 
00783 {
00784   // HELPERS:
00785   std::map< std::pair<Idx,Idx>, Idx> rcmap;
00786 
00787   // ALGORITHM:
00788   SupConClosed(rPlantGen, rCAlph, rSpecGen, rcmap, rResGen);
00789 }
00790 
00791 
00792 // SupConClosed(rPlantGen, rCAlph, rSpecGen, rCompositionMap, rResGen)
00793 void SupConClosed(
00794   const Generator& rPlantGen, 
00795   const EventSet& rCAlph,
00796   const Generator& rSpecGen,
00797   std::map< std::pair<Idx,Idx>, Idx>& rCompositionMap, 
00798   Generator& rResGen) 
00799 {
00800   FD_DF("SupConClosed(" << &rPlantGen << "," << &rSpecGen << ")");
00801 
00802   // PREPARE RESULT:
00803   
00804   // prepare result
00805   Generator* pResGen = &rResGen;
00806   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00807     pResGen= rResGen.New();
00808   }
00809   pResGen->Clear();
00810   pResGen->Name(CollapsString("SupConClosed(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"));
00811   pResGen->InjectAlphabet(rPlantGen.Alphabet());
00812   
00813   // HELPERS:
00814   FD_DF("SupCon: controllable events: " << rCAlph.ToString());
00815 
00816   // CONSISTENCY CHECK:
00817   ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen);
00818 
00819   // ALGORITHM:
00820 
00821   // product composition
00822   SupConProduct(rPlantGen, rCAlph, rSpecGen, rCompositionMap, *pResGen);
00823   // make resulting generator controllable
00824   SupConClosedUnchecked(rPlantGen, rCAlph, *pResGen);
00825 
00826   // restrict composition map
00827   std::map< std::pair<Idx,Idx>, Idx>::iterator rcmapit = rCompositionMap.begin();
00828   while(rcmapit != rCompositionMap.end()) 
00829     if(!rResGen.ExistsState(rcmapit->second)) rCompositionMap.erase(rcmapit++);
00830     else rcmapit++;
00831 
00832   // convenience state names
00833   if (rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && rResGen.StateNamesEnabled()) 
00834     SetComposedStateNames(rPlantGen, rSpecGen, rCompositionMap, *pResGen);
00835   else
00836     pResGen->StateNamesEnabled(false);
00837 
00838   // copy result
00839   if(pResGen != &rResGen) {
00840     pResGen->Move(rResGen);
00841     delete pResGen;
00842   }
00843 }
00844 
00845 
00846 // TraverseUncontrollableBackwards(rCAlph, rtransrel, critical, current)
00847 void TraverseUncontrollableBackwards(
00848   const EventSet& rCAlph, 
00849   TransSetX2EvX1& rtransrel, 
00850   StateSet& rCriticalStates, 
00851   Idx current) {
00852   FD_DF("TraverseUncontrollableBackwards: " << rCriticalStates.Str(current));
00853 
00854   // HELPERS:
00855   std::stack<Idx> todo;
00856   TransSetX2EvX1::Iterator rtit = rtransrel.BeginByX2(current);
00857   TransSetX2EvX1::Iterator rtit_end = rtransrel.EndByX2(current);
00858 
00859   // ALGORITHM:
00860   rCriticalStates.Insert(current);
00861   todo.push(current);
00862   FD_DF("TraverseUncontrollableBackwards: current rCriticalStates set: " 
00863      << rCriticalStates.ToString());
00864   // process todo stack
00865   while(! todo.empty()) {
00866     // get top state from todo stack
00867     current = todo.top(); todo.pop();
00868     // iteration over all transitions with x2 == current
00869     rtit_end = rtransrel.EndByX2(current);
00870     rtit = rtransrel.BeginByX2(current);
00871     for(; rtit != rtit_end; ++rtit) {
00872       // if uncontrollable event and predecessor state not already critical
00873       if((!rCAlph.Exists(rtit->Ev)) && (! rCriticalStates.Exists(rtit->X1))) {
00874         FD_DF("TraverseUncontrollableBackwards: todo push " << rCriticalStates.Str(rtit->X1));
00875   todo.push(rtit->X1);
00876   FD_DF("TraverseUncontrollableBackwards: critical insert: " << rCriticalStates.Str(rtit->X1));
00877   rCriticalStates.Insert(rtit->X1);
00878       }
00879     }
00880   } // end while todo
00881 }
00882 
00883 
00884 // controllability test for System plant
00885 bool IsControllable(
00886   const System& rPlantGen, 
00887   const Generator& rSupCandGen)
00888 {
00889   return IsControllable(rPlantGen, rPlantGen.ControllableEvents(), rSupCandGen);
00890 }
00891 
00892 
00893 // supcon for Systems:
00894 // uses and maintains controllablity from plant 
00895 void SupConNB(
00896   const System& rPlantGen, 
00897   const Generator& rSpecGen, 
00898   Generator& rResGen) {
00899 
00900   // prepare result
00901   Generator* pResGen = &rResGen;
00902   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00903     pResGen= rResGen.New();
00904   }
00905 
00906   // execute 
00907   SupConNB(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,*pResGen);
00908 
00909   // copy all attributes of input alphabet
00910   pResGen->EventAttributes(rPlantGen.Alphabet());
00911 
00912   // copy result
00913   if(pResGen != &rResGen) {
00914     pResGen->Move(rResGen);
00915     delete pResGen;
00916   }
00917 
00918 }
00919 
00920 // supcon for Systems
00921 // uses and maintains controllablity from plant 
00922 void SupConClosed(
00923   const System& rPlantGen, 
00924   const Generator& rSpecGen, 
00925   Generator& rResGen) {
00926 
00927   // prepare result
00928   Generator* pResGen = &rResGen;
00929   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00930     pResGen= rResGen.New();
00931   }
00932 
00933   // execute
00934   SupConClosed(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,*pResGen);
00935 
00936   // copy all attributes of input alphabet
00937   pResGen->EventAttributes(rPlantGen.Alphabet());
00938 
00939   // copy result
00940   if(pResGen != &rResGen) {
00941     pResGen->Move(rResGen);
00942     delete pResGen;
00943   }
00944 
00945 }
00946 
00947 } // name space 

libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen