libFAUDES

Sections

Index

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 // IsControllableUnchecked(rPlantGen, rCAlph, rSupCandGen, rCriticalStates)
00042 bool IsControllableUnchecked(
00043   const vGenerator& rPlantGen,
00044   const EventSet& rCAlph,  
00045   const vGenerator& rSupCandGen, 
00046   StateSet& rCriticalStates) 
00047 {
00048   FD_DF("IsControllableUnchecked(" << &rSupCandGen << "," << &rPlantGen << ")");
00049 
00050   // HELPERS:
00051 
00052   // todo stack
00053   std::stack<Idx> todog, todoh;
00054   // set of already processed states
00055   StateSet processed;
00056   // reverse sorted transition relation of rSupCandGen (to be built on the fly)
00057   TransSetX2EvX1 rtransrel;
00058 
00059   // PREPARE RESULT:
00060   rCriticalStates.Clear();
00061 
00062   // ALGORITHM:
00063 
00064   // return false (uncontrollable) if there is no initial state
00065   if (rPlantGen.InitStatesEmpty() || rSupCandGen.InitStatesEmpty()) {
00066        return false;
00067   }
00068 
00069   // push combined initial state on todo stack
00070   todog.push(*rPlantGen.InitStatesBegin());
00071   todoh.push(*rSupCandGen.InitStatesBegin());
00072   FD_DF("IsControllable: todo push: (" << rPlantGen.SStr(*rPlantGen.InitStatesBegin()) << "|"
00073      << rSupCandGen.SStr(*rSupCandGen.InitStatesBegin()) << ")");
00074 
00075   // process todo stack
00076   while (! todog.empty()) {
00077     // get top element from todo stack
00078     Idx currentg = todog.top();
00079     Idx currenth = todoh.top();
00080     todog.pop();
00081     todoh.pop();
00082     FD_DF("IsControllable: todo pop: (" << rPlantGen.SStr(currentg) << "|" 
00083        << rSupCandGen.SStr(currenth) << ")");
00084 
00085 #ifdef FAUDES_DEBUG_FUNCTION
00086     TransSet::Iterator _titg, _tith;
00087     // print all transitions of current states
00088     FD_DF("IsControllable: transitions from current states:");
00089     for (_titg = rPlantGen.TransRelBegin(currentg); _titg != rPlantGen.TransRelEnd(currentg); ++_titg) 
00090        FD_DF("IsControllable: g: " << rPlantGen.SStr(_titg->X1) << "-" 
00091      << rPlantGen.EStr(_titg->Ev) << "-" << rPlantGen.SStr(_titg->X2));
00092     for (_tith = rSupCandGen.TransRelBegin(currenth); _tith != rSupCandGen.TransRelEnd(currenth); ++_tith) 
00093        FD_DF("IsControllable: h: " << rSupCandGen.SStr(_tith->X1) << "-" 
00094      << rSupCandGen.EStr(_tith->Ev) << "-" << rSupCandGen.SStr(_tith->X2));
00095 #endif 
00096 
00097     // process all h transitions while there could be matching g transitions
00098     TransSet::Iterator titg = rPlantGen.TransRelBegin(currentg);
00099     TransSet::Iterator titg_end = rPlantGen.TransRelEnd(currentg);
00100     TransSet::Iterator tith = rSupCandGen.TransRelBegin(currenth);
00101     TransSet::Iterator tith_end = rSupCandGen.TransRelEnd(currenth);
00102     while ((tith != tith_end) && (titg != titg_end)) {
00103       FD_DF("IsControllable: processing g-transition: " << rPlantGen.SStr(titg->X1) 
00104       << "-" << rPlantGen.EStr(titg->Ev) << "-" << rPlantGen.SStr(titg->X2));
00105       FD_DF("IsControllable: processing h-transition: " << rSupCandGen.SStr(tith->X1) 
00106             << "-" << rSupCandGen.EStr(tith->Ev) << "-" << rSupCandGen.SStr(tith->X2));
00107       // increment tith and titg case A: process common events
00108       if (titg->Ev == tith->Ev) {
00109   FD_DF("IsControllable: processing common event " << rPlantGen.EStr(titg->Ev));
00110   // add to todo list if state not processed // TODO: this may be incorrect !!!
00111   if (! processed.Exists(currenth)) {
00112     todog.push(titg->X2);
00113     todoh.push(tith->X2);
00114     FD_DF("IsControllable: todo push: (" << rPlantGen.SStr(titg->X2) << "|"
00115       << rSupCandGen.SStr(tith->X2) << ")");
00116   }
00117   // if h successor state is not critical add transition to rtransrel
00118   if (! rCriticalStates.Exists(tith->X2)) {
00119     rtransrel.Insert(*tith);
00120     FD_DF("IsControllable: incrementing g and h transrel");
00121     ++titg;
00122     ++tith;
00123   }
00124   // if successor state is critical and event uncontrollable 
00125   else if (!rCAlph.Exists(titg->Ev)) {
00126     FD_DF("IsControllable: successor state " << rSupCandGen.SStr(tith->X2) << 
00127       " critical and event " << rPlantGen.EStr(titg->Ev) << " uncontrollable:");
00128     FD_DF("IsControllable: TraverseUncontrollableBackwards(" << rSupCandGen.SStr(currenth) << ")");
00129       TraverseUncontrollableBackwards(rCAlph, rtransrel, rCriticalStates, currenth);
00130 #ifdef FAUDES_CHECKED
00131       // just increment transrel iterators to find all h transitions not in g
00132       FD_DF("IsControllable: incrementing g an h transrel (FAUDES_CHECKED)");
00133       ++titg;
00134       ++tith;
00135       break;
00136 #else
00137             // exit all loops
00138       titg = titg_end;
00139       tith = tith_end;
00140       break;
00141 #endif
00142   }
00143         // if successor state is critical and event controllable
00144         else {
00145           FD_DF("IsControllable: incrementing g and h transrel");
00146           ++titg;
00147           ++tith;
00148         }   
00149       }
00150       // increment tith and titg case B: process g event that is not enabled in h
00151       else if (titg->Ev < tith->Ev) {
00152   FD_DF("IsControllable: asynchronous execution of event " 
00153            << rPlantGen.EStr(titg->Ev) << " in g while " << rSupCandGen.EStr(tith->Ev)
00154      << " in h");
00155         // if uncontrollable transition violates specification
00156         // delete state from rResGen and put into criticalset
00157         if (!rCAlph.Exists(titg->Ev)) {
00158     FD_DF("IsControllable: asynchronous event " << rPlantGen.EStr(titg->Ev) 
00159          << " in g is uncontrollable");
00160     FD_DF("IsControllable: TraverseUncontrollableBackwards(" << rSupCandGen.SStr(currenth) << ")");
00161     TraverseUncontrollableBackwards(rCAlph, rtransrel, rCriticalStates, currenth);
00162     // exit all loops over g transrel
00163     titg = titg_end;
00164     break;
00165         }
00166   FD_DF("IsControllable: incrementing g transrel");
00167   ++titg;
00168       }
00169       // increment tith and titg case C: process h event that is not enabled in g
00170       else {
00171        // #ifdef FAUDES_CHECKED
00172        // FD_WARN("IsControllable: transition " << rSupCandGen.TStr(*tith) 
00173        //  << " in specification h not found in g");
00174        // #endif
00175        FD_DF("IsControllable: incrementing h transrel");
00176        ++tith;
00177       }
00178     } // end while tith and titg
00179     // increment tith and titg case D: process leftover g events 
00180     while (titg != titg_end) {
00181       FD_DF("IsControllable: asynchronous execution of event " 
00182           << rPlantGen.EStr(titg->Ev) << " in g at end of h");
00183       FD_DF("IsControllable: actual g-transition: " << rPlantGen.SStr(titg->X1) 
00184     << "-" << rPlantGen.EStr(titg->Ev) << "-" << rPlantGen.SStr(titg->X2));
00185       FD_DF("IsControllable: actual h-transition: end");
00186       // if uncontrollable transition violates specification
00187       if (!rCAlph.Exists(titg->Ev)) {
00188   FD_DF("IsControllable: asynchronous execution of uncontrollable event "
00189       << rPlantGen.EStr(titg->Ev) << " in g");
00190   FD_DF("IsControllable: TraverseUncontrollableBackwards(" << rPlantGen.SStr(currenth) << ")");
00191         TraverseUncontrollableBackwards(rCAlph, rtransrel, rCriticalStates, currenth);
00192   // exit this loop
00193   break;
00194       }
00195       FD_DF("IsControllable: incrementing g transrel");
00196       ++titg;
00197     }
00198     //#ifdef FAUDES_CHECKED
00199     // increment tith and titg case E: process leftover h events 
00200     //while (tith != tith_end) {
00201     //  FD_WARN("IsControllable: transition " << rSupCandGen.TStr(*tith) << " in specification h not found in g");
00202     //  FD_DF("IsControllable: incrementing h transrel");
00203     //  ++tith;
00204     //}
00205     //#endif
00206     processed.Insert(currenth);
00207   } //end while todog
00208 
00209   // compute overall set of critical states
00210   rCriticalStates = rSupCandGen.States() - ( processed - rCriticalStates );
00211   
00212   if (rCriticalStates.Empty()) {
00213     FD_DF("IsControllable: controllable");
00214     return true;
00215   }
00216   FD_DF("IsControllable: not controllable");
00217   return false;
00218 }
00219 
00220 
00221 
00222 
00223 // SupConUnchecked(rPlantGen, rCAlph, rSupCandGen)
00224 bool SupConUnchecked(
00225   const vGenerator& rPlantGen, 
00226   const EventSet& rCAlph,
00227   vGenerator& rSupCandGen) 
00228 {
00229   FD_DF("SupConUnchecked...");
00230 
00231   // HELPERS:
00232 
00233   // set of critical states
00234   StateSet critical;
00235 
00236   // ALGORITHM:
00237   
00238   // return true if plant or parallelcomp contain no initial states
00239   if(rPlantGen.InitStatesEmpty() || rSupCandGen.InitStatesEmpty()) {
00240     return true;
00241   }
00242    
00243   // test controllability
00244   IsControllable(rPlantGen, rCAlph, rSupCandGen, critical);
00245   FD_DF("SupCon: delete critical states: " << rSupCandGen.States().ToString());
00246   StateSet::Iterator sit;
00247   for(sit = critical.Begin(); sit != critical.End(); ++sit){
00248     rSupCandGen.DelState(*sit);
00249   }
00250 
00251   // return true if no states had to be deleted
00252   if(critical.Empty()) {
00253     FD_DF("SupCon: controllable");
00254     return true;
00255   }
00256   // return false if states had to be deleted
00257   FD_DF("SupCon: not controllable");
00258   return false;
00259 }
00260 
00261 
00262 // SupconParallel(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, rResGen)
00263 void SupconParallel(
00264   const vGenerator& rPlantGen, 
00265   const EventSet& rCAlph,
00266   const vGenerator& rSpecGen,
00267   std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, 
00268   vGenerator& rResGen) 
00269 {
00270   FD_DF("SupconParallel(" << &rPlantGen << "," << &rSpecGen << ")");
00271   
00272   // HELPERS:
00273 
00274   // todo stack
00275   std::stack< std::pair<Idx,Idx> > todo;
00276   // set of critical states
00277   StateSet critical;
00278   // actual pair, new pair
00279   std::pair<Idx,Idx> currentstates, newstates;
00280   // other stuff
00281   Idx tmpstate;
00282   std::map< std::pair<Idx,Idx>, Idx>::iterator rcmapit;
00283   StateSet::Iterator lit1, lit2;
00284   TransSet::Iterator titg, titg_end, tith, tith_end;
00285 
00286   // ALGORITHM:
00287   
00288   if (rPlantGen.InitStatesEmpty()) {
00289     FD_DF("SupconParallel: plant got no initial states. "
00290             << "parallel composition contains empty language.");
00291     return;
00292   }
00293   if (rSpecGen.InitStatesEmpty()) {
00294     FD_DF("SupconParallel: spec got no initial states. "
00295               << "parallel composition contains empty language.");
00296     return;
00297   }
00298 
00299   // create initial state
00300   currentstates = std::make_pair(*rPlantGen.InitStatesBegin(), *rSpecGen.InitStatesBegin());
00301   todo.push(currentstates);
00302   rReverseCompositionMap[currentstates] = rResGen.InsInitState();
00303   FD_DF("SupconParallel: NEW ISTATE: (" << rPlantGen.SStr(currentstates.first) 
00304       << "|" << rSpecGen.SStr(currentstates.second) << ") -> " 
00305                   << rReverseCompositionMap[currentstates]);
00306   if (rPlantGen.ExistsMarkedState(*rPlantGen.InitStatesBegin()) 
00307                 && rSpecGen.ExistsMarkedState(*rSpecGen.InitStatesBegin())) {
00308     rResGen.SetMarkedState(rReverseCompositionMap[currentstates]);
00309      FD_DF("SupconParallel: recent ISTATE Marked");
00310   }
00311 
00312   // do parallel composition of allowed states by deleting critical states on the fly.
00313   // this creates an accessible generator
00314   FD_DF("SupconParallel: *** processing reachable states ***");
00315   while (! todo.empty()) {
00316     // get next reachable pair of states from todo stack
00317     currentstates = todo.top();
00318     todo.pop();
00319     FD_DF("SupconParallel: todo pop: (" << rPlantGen.SStr(currentstates.first) 
00320          << "|" << rSpecGen.SStr(currentstates.second) << ") -> " 
00321                << rReverseCompositionMap[currentstates]);
00322     
00323     titg = rPlantGen.TransRelBegin(currentstates.first);
00324     titg_end = rPlantGen.TransRelEnd(currentstates.first);
00325     tith = rSpecGen.TransRelBegin(currentstates.second);
00326     tith_end = rSpecGen.TransRelEnd(currentstates.second);
00327 
00328 #ifdef FAUDES_DEBUG_FUNCTION
00329     // print all transitions of current states
00330     FD_DF("SupConParallel: transitions from current states:");
00331     for (;titg != titg_end; ++titg) { 
00332       FD_DF("SupConParallel: g: " << rPlantGen.SStr(titg->X1) << "-" << rPlantGen.EStr(titg->Ev) 
00333          << "-" << rPlantGen.SStr(titg->X2));
00334     }
00335     for (;tith != tith_end; ++tith) {
00336       FD_DF("SupConParallel: h: " << rSpecGen.SStr(tith->X1) << "-" << rSpecGen.EStr(tith->Ev) 
00337           << "-" << rSpecGen.SStr(tith->X2));
00338     }
00339     titg = rPlantGen.TransRelBegin(currentstates.first);
00340     tith = rSpecGen.TransRelBegin(currentstates.second);
00341 #endif                                                                      
00342 
00343     // process all h transitions while there could be matching g transitions
00344     while ((tith != tith_end) && (titg != titg_end)) {
00345       FD_DF("SupconParallel: current g-transition: " << rPlantGen.TStr(*titg) );
00346       FD_DF("SupconParallel: actual h-transition: " << rSpecGen.TStr(*tith));
00347       // increment titg and titg, case A: execute common events
00348       if (titg->Ev == tith->Ev) {
00349   FD_DF("SupconParallel: executing common event "  << rPlantGen.EStr(titg->Ev));
00350   newstates = std::make_pair(titg->X2, tith->X2);
00351   rcmapit = rReverseCompositionMap.find(newstates);
00352   // if state is new: add to todo list and result
00353   if (rcmapit == rReverseCompositionMap.end()) {
00354     todo.push(newstates);
00355     // if marked 
00356     if (rPlantGen.ExistsMarkedState(newstates.first) && 
00357     rSpecGen.ExistsMarkedState(newstates.second)) {
00358       tmpstate = rResGen.InsMarkedState();
00359       FD_DF("SupconParallel: NEW MSTATE: (" << rPlantGen.SStr(newstates.first) << "|"
00360          << rSpecGen.SStr(newstates.second) << ") -> " << tmpstate);
00361     }
00362     // if not maked 
00363     else {
00364       tmpstate = rResGen.InsState();
00365       FD_DF("SupconParallel: NEW STATE: (" << rPlantGen.SStr(newstates.first) << "|" 
00366                << rSpecGen.SStr(newstates.second) << ") -> " << tmpstate);
00367     }
00368     rReverseCompositionMap[newstates] = tmpstate;
00369     FD_DF("SupconParallel: todo push: (" << rPlantGen.SStr(newstates.first)
00370        << "|" << rSpecGen.SStr(newstates.second) << ") -> " << tmpstate);
00371   }
00372   // if state already exists
00373   else {
00374     tmpstate = rcmapit->second;
00375   }
00376   // if successor state is not critical add transition and increment titg and tith
00377   if (! critical.Exists(tmpstate)) {
00378     FD_DF("SupconParallel: ADDING TRANSITION " 
00379        << rPlantGen.SStr(rReverseCompositionMap[currentstates]) << "-" << rPlantGen.EStr(titg->Ev) 
00380        << "-" << rPlantGen.SStr(tmpstate));
00381     rResGen.SetTransition(rReverseCompositionMap[currentstates], titg->Ev, tmpstate);
00382     FD_DF("SupconParallel: incrementing g and h transrel");
00383     ++titg;
00384     ++tith;
00385   }
00386   // if successor state is critical and event is uncontrollable then delete current state 
00387   else if (!rCAlph.Exists(titg->Ev)) {
00388     FD_DF("SupconParallel: successor " << rSpecGen.SStr(tmpstate) 
00389            << "in critical and common event " << rSpecGen.EStr(titg->Ev) 
00390            << " uncontrollable:");
00391     FD_DF("SupconParallel: critical insert" << rPlantGen.SStr(tmpstate));
00392     critical.Insert(tmpstate);
00393 #ifdef FAUDES_CHECKED
00394     // do not end while loops here for detecting all h transitions 
00395     // not in g
00396     FD_DF("SupconParallel: incrementing g and h transrel (FAUDES_CHECKED)");
00397     ++titg;
00398     ++tith;
00399 #else
00400     // exit all loops
00401     titg = titg_end;
00402     tith = tith_end;
00403 #endif
00404         }
00405         // else if successor state in critical and event controllable increment titg and tith
00406         else {
00407     FD_DF("SupconParallel: incrementing g and h transrel");
00408           ++titg;
00409           ++tith;
00410         }
00411       } // end: if processing common event 
00412       // increment titg and titg, case B: process g event that is not enebled for h
00413       else if (titg->Ev < tith->Ev) {
00414   FD_DF("SupconParallel: asynchronous execution of event " 
00415      << rPlantGen.EStr(titg->Ev) << " in g while " << rSpecGen.EStr(tith->Ev) << " in h");
00416   // if uncontrollable transition leaves specification
00417   // delete state from res and put into criticalset
00418   if (!rCAlph.Exists(titg->Ev)) {
00419     FD_DF("SupconParallel: asynchronous event " << rPlantGen.EStr(titg->Ev) 
00420        << " in g is uncontrollable");
00421     tmpstate = rReverseCompositionMap[currentstates]; 
00422     FD_DF("SupconParallel: critical insert" << rPlantGen.SStr(tmpstate));
00423     critical.Insert(tmpstate);
00424     // exit all loops
00425     titg = titg_end;
00426     tith = tith_end;
00427     break;
00428   }
00429   FD_DF("SupconParallel: incrementing g transrel");
00430   ++titg;
00431       } 
00432       // increment titg and titg, case C: process h event that is not enabled for g
00433       else {
00434   //#ifdef FAUDES_CHECKED
00435   // FD_WARN("SupconParallel:  transition " << rSpecGen.TStr(*tith) << " in specification h not found in g");
00436   //#endif
00437   FD_DF("SupconParallel: incrementing h transrel");
00438   ++tith;
00439       }
00440     } // end while incrementing tith and titg 
00441     // increment titg and titg, case D: process leftover events of g
00442     while (titg != titg_end) {
00443       FD_DF("SupconParallel: asynchronous execution of event " 
00444          << rPlantGen.EStr(titg->Ev) << " in g at end of h");
00445       FD_DF("SupconParallel: actual g-transition: " << rPlantGen.SStr(titg->X1) 
00446          << "-" << rPlantGen.EStr(titg->Ev) << "-" << rPlantGen.SStr(titg->X2));
00447       FD_DF("SupconParallel: actual h-transition: end");
00448       // if uncontrollable transition leaves specification
00449       if (!rCAlph.Exists(titg->Ev)) {
00450   tmpstate = rReverseCompositionMap[currentstates];
00451   FD_DF("SupconParallel: asynchron executed uncontrollable end "
00452            << "event " << rPlantGen.EStr(titg->Ev) << " leaves specification:");
00453   FD_DF("SupconParallel: critical insert" << rPlantGen.SStr(tmpstate));
00454   critical.Insert(tmpstate);
00455   // exit this loop 
00456   break;
00457       }
00458       FD_DF("SupconParallel: incrementing g transrel");
00459       ++titg;
00460     }
00461     //#ifdef FAUDES_CHECKED
00462     // increment titg and titg, case E: process leftover events of h
00463     //while (txoith != tith_end) {
00464     //  FD_WARN("SupconParallel:  transition " << rSpecGen.TStr(*tith)  << " in specification h not found in g");
00465     //  FD_DF("SupconParallel: incrementing h transrel");
00466     //  ++tith;
00467     //}
00468     //#endif
00469   } // while todo
00470   FD_DF("SupconParallel: deleting critical states...");
00471   StateSet::Iterator sit;
00472   for(sit = critical.Begin(); sit!= critical.End(); ++sit)
00473      rResGen.DelState(*sit); 
00474   //rResGen.DelStates(critical);
00475 }
00476 
00477 
00478 
00479 // SupConNBUnchecked(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, rResGen)
00480 void SupConNBUnchecked(
00481   const vGenerator& rPlantGen,
00482   const EventSet& rCAlph,  
00483   const vGenerator& rSpecGen,
00484   std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, 
00485   vGenerator& rResGen) 
00486 {
00487   FD_DF("SupConNB(" << &rPlantGen << "," << &rSpecGen << ")");
00488 
00489   // PREPARE RESULT:  
00490   vGenerator* pResGen = &rResGen;
00491   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00492     pResGen= rResGen.New();
00493   }
00494   pResGen->Clear();
00495   pResGen->Name(CollapsString("SupConNB(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"));
00496   pResGen->InjectAlphabet(rPlantGen.Alphabet());
00497 
00498   // controllable events
00499   FD_DF("SupConNB: controllable events: "   << rCAlph.ToString());
00500 
00501   // ALGORITHM:
00502   SupconParallel(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, *pResGen);
00503 
00504   // make resulting generator trim until it's fully controllable
00505   while (1) {
00506     if (pResGen->Empty()) {
00507       break;
00508     }
00509     Idx state_num = pResGen->Size();
00510     bool supcon = SupConUnchecked(rPlantGen, rCAlph, *pResGen);
00511     bool trim = pResGen->Trim();
00512     if (supcon && trim && (pResGen->Size() == state_num)) {
00513       break;
00514     }
00515   }
00516 
00517   // convenience state names
00518   if (rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && rResGen.StateNamesEnabled()) 
00519     SetComposedStateNames(rPlantGen, rSpecGen, rReverseCompositionMap, *pResGen);
00520   else
00521     pResGen->ClearStateNames();
00522 
00523   // copy result
00524   if(pResGen != &rResGen) {
00525     pResGen->Move(rResGen);
00526     delete pResGen;
00527   }
00528 
00529 }
00530 
00531 // ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen)
00532 void ControlProblemConsistencyCheck(
00533   const vGenerator& rPlantGen,
00534   const EventSet& rCAlph, 
00535   const vGenerator& rSpecGen) 
00536 {
00537 
00538   // alphabets must match
00539   if ( rPlantGen.Alphabet() != rSpecGen.Alphabet()) {
00540     EventSet only_in_plant = rPlantGen.Alphabet() - rSpecGen.Alphabet();
00541     EventSet only_in_spec = rSpecGen.Alphabet() - rPlantGen.Alphabet();
00542     only_in_plant.Name("Only_In_Plant");
00543     only_in_spec.Name("Only_In_Specification");
00544     std::stringstream errstr;
00545     errstr << "Alphabets of generators do not match.";
00546     if(!only_in_plant.Empty())
00547       errstr << " " << only_in_plant.ToString() << ".";
00548     if(!only_in_spec.Empty())
00549       errstr << " " << only_in_spec.ToString() << ".";
00550     throw Exception("SupCon/SupConNB", errstr.str(), 100);
00551   }
00552   
00553   // TODO: add test for rCAlph <= Alphabet
00554 
00555   // TODO: check symboltables to match
00556 
00557   // plant and spec must be deterministic
00558   bool plant_det = rPlantGen.IsDeterministic();
00559   bool spec_det = rSpecGen.IsDeterministic();
00560 
00561   if ((plant_det == false) && (spec_det == true)) {
00562     std::stringstream errstr;
00563     errstr << "Plant generator must be deterministic, "
00564       << "but is nondeterministic";
00565     throw Exception("ControllableConsistencyCheck", errstr.str(), 201);
00566   }
00567   else if ((plant_det == true) && (spec_det == false)) {
00568     std::stringstream errstr;
00569     errstr << "Spec generator must be deterministic, "
00570        << "but is nondeterministic";
00571     throw Exception("ControllableConsistencyCheck", errstr.str(), 203);
00572   }
00573   else if ((plant_det == false) && (spec_det == false)) {
00574     std::stringstream errstr;
00575     errstr << "Plant and spec generator must be deterministic, "
00576        << "but both are nondeterministic";
00577     throw Exception("ControllableConsistencyCheck", errstr.str(), 204);
00578   }
00579 }
00580 
00581 
00582 /*
00583 ****************************************
00584 * SUPCON: WRAPPER / USER FUNCTIONS     *
00585 ****************************************
00586 */
00587 
00588 
00589 // IsControllable(rPlantGen, rCAlph, rSupCandGen)
00590 bool IsControllable(
00591   const vGenerator& rPlantGen, 
00592   const EventSet& rCAlph, 
00593   const vGenerator& rSupCandGen) 
00594 {
00595   FD_DF("IsControllable(" << &rSupCandGen << "," << &rPlantGen << ")");
00596 
00597   // HELPERS:
00598   FD_DF("IsControllable: controllable events: " << rCAlph.ToString());
00599   // critical set
00600   StateSet critical;
00601 
00602   // CONSISTENCY CHECKS:
00603   ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSupCandGen);
00604 
00605   // ALGORITHM:
00606   return IsControllableUnchecked(rPlantGen, rCAlph, rSupCandGen, critical);
00607 }
00608 
00609 
00610 // IsControllable(rPlantGen, rCAlph, rSupCandGen, critical)
00611 bool IsControllable(
00612   const vGenerator& rPlantGen, 
00613   const EventSet& rCAlph, 
00614   const vGenerator& rSupCandGen, 
00615   StateSet& rCriticalStates) 
00616 {
00617   FD_DF("IsControllable(" << &rSupCandGen << "," << &rPlantGen << ")");
00618 
00619   // CONSISTENCY CHECKS:
00620   ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSupCandGen);
00621 
00622   // ALGORITHM:
00623   return IsControllableUnchecked(rPlantGen, rCAlph, rSupCandGen, rCriticalStates);
00624 }
00625 
00626 
00627 // SupConNB(rPlantGen, rCAlph, rSpecGen, rResGen)
00628 void SupConNB(
00629   const vGenerator& rPlantGen, 
00630   const EventSet& rCAlph, 
00631   const vGenerator& rSpecGen, 
00632   vGenerator& rResGen) 
00633 {
00634 
00635   // CONSISTENCY CHECK:
00636   ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen);
00637 
00638   // HELPERS:
00639   std::map< std::pair<Idx,Idx>, Idx> rcmap;
00640 
00641   // ALGORITHM:
00642   SupConNBUnchecked(rPlantGen, rCAlph, rSpecGen, rcmap, rResGen);
00643 }
00644 
00645 
00646 
00647 
00648 // SupConNBNonDet(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, 
00649 //     pDetPlantGen, pDetSpecGen, rResGen)
00650 void SupConNBNonDet(
00651   const vGenerator& rPlantGen, 
00652   const EventSet& rCAlph,
00653   const vGenerator& rSpecGen,
00654   std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap,
00655   Generator rDetPlantGen, 
00656   Generator rDetSpecGen, 
00657   std::map<Idx,StateSet>& rPowerStatesPlant, 
00658   std::map<Idx,StateSet>& rPowerStatesSpec,
00659   bool& rDetPlantBool, 
00660   bool& rDetSpecBool, 
00661   vGenerator& rResGen) 
00662 {
00663   FD_DF("SupConNBNonDet(" << &rPlantGen << "," << &rSpecGen << ")");
00664 
00665   // alphabets must match
00666   if (rPlantGen.Alphabet() != rSpecGen.Alphabet()) {
00667     throw Exception("SupConNBNonDet", "Alphabets of generators don't match", 100);
00668   }
00669 
00670   // PREPARE RESULT:
00671   vGenerator* pResGen = &rResGen;
00672   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00673     pResGen= rResGen.New();
00674   }
00675   pResGen->Clear();
00676   pResGen->Name(CollapsString("SupConNBNonDet(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"));
00677   pResGen->InjectAlphabet(rPlantGen.Alphabet());
00678   
00679   // HELPERS:
00680   rPowerStatesPlant.clear();
00681   rPowerStatesSpec.clear();
00682 
00683   // controllable events
00684   FD_DF("SupConNB: controllable events: " << rCAlph.ToString());
00685 
00686   // pointers to actual generators
00687   vGenerator* plantp;
00688   vGenerator* specp;
00689 
00690   // plant and spec determinism
00691   rDetPlantBool = rPlantGen.IsDeterministic();
00692   rDetSpecBool = rSpecGen.IsDeterministic();
00693   
00694   // create deterministic generators and set pointers to the actual ones
00695   plantp = const_cast<vGenerator*>(&rPlantGen);
00696   specp = const_cast<vGenerator*>(&rSpecGen);
00697   if (rDetPlantBool == false) {
00698       Deterministic(rPlantGen, rPowerStatesPlant, rDetPlantGen);    
00699       plantp = &rDetPlantGen;
00700   }
00701   if (rDetSpecBool == false) {
00702       Deterministic(rSpecGen, rPowerStatesSpec, rDetSpecGen);
00703       specp = &rDetSpecGen;
00704   }
00705   
00706   // ALGORITHM:
00707 
00708   // compute supervisor
00709   SupconParallel(*plantp, rCAlph, *specp, rReverseCompositionMap, *pResGen);
00710 
00711   // make resulting generator trim until it's fully controllable
00712   while (! (SupConUnchecked(*plantp, rCAlph, *pResGen) && pResGen->Trim()));
00713 
00714   // copy result
00715   if(pResGen != &rResGen) {
00716     pResGen->Move(rResGen);
00717     delete pResGen;
00718   }
00719 }
00720 
00721 // SupCon(rPlantGen, rCAlph, rSpecGen, rResGen)
00722 void SupCon(
00723   const vGenerator& rPlantGen, 
00724   const EventSet& rCAlph,
00725   const vGenerator& rSpecGen, 
00726   vGenerator& rResGen) 
00727 {
00728   // HELPERS:
00729   std::map< std::pair<Idx,Idx>, Idx> rcmap;
00730 
00731   // ALGORITHM:
00732   SupCon(rPlantGen, rCAlph, rSpecGen, rcmap, rResGen);
00733 }
00734 
00735 
00736 // SupCon(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, rResGen)
00737 void SupCon(
00738   const vGenerator& rPlantGen, 
00739   const EventSet& rCAlph,
00740   const vGenerator& rSpecGen,
00741   std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, 
00742   vGenerator& rResGen) 
00743 {
00744   FD_DF("SupCon(" << &rPlantGen << "," << &rSpecGen << ")");
00745 
00746   // PREPARE RESULT:
00747   
00748 
00749   // prepare result
00750   vGenerator* pResGen = &rResGen;
00751   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00752     pResGen= rResGen.New();
00753   }
00754   pResGen->Clear();
00755   pResGen->Name(CollapsString("SupCon(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"));
00756   pResGen->InjectAlphabet(rPlantGen.Alphabet());
00757   
00758   // HELPERS:
00759   FD_DF("SupCon: controllable events: " << rCAlph.ToString());
00760 
00761   // CONSISTENCY CHECK:
00762   ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen);
00763 
00764   // ALGORITHM:
00765 
00766   // parallel composition
00767   SupconParallel(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, *pResGen);
00768   // make resulting generator controllable
00769   SupConUnchecked(rPlantGen, rCAlph, *pResGen);
00770 
00771   // convenience state names
00772   if (rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && rResGen.StateNamesEnabled()) 
00773     SetComposedStateNames(rPlantGen, rSpecGen, rReverseCompositionMap, *pResGen);
00774   else
00775     pResGen->ClearStateNames();
00776 
00777   // copy result
00778   if(pResGen != &rResGen) {
00779     pResGen->Move(rResGen);
00780     delete pResGen;
00781   }
00782 }
00783 
00784 
00785 // TraverseUncontrollableBackwards(rCAlph, rtransrel, critical, current)
00786 void TraverseUncontrollableBackwards(
00787   const EventSet& rCAlph, 
00788   TransSetX2EvX1& rtransrel, 
00789   StateSet& rCriticalStates, 
00790   Idx current) {
00791   FD_DF("TraverseUncontrollableBackwards: " << rCriticalStates.Str(current));
00792 
00793   // HELPERS:
00794   std::stack<Idx> todo;
00795   TransSetX2EvX1::Iterator rtit = rtransrel.BeginByX2(current);
00796   TransSetX2EvX1::Iterator rtit_end = rtransrel.EndByX2(current);
00797 
00798   // ALGORITHM:
00799   rCriticalStates.Insert(current);
00800   todo.push(current);
00801   FD_DF("TraverseUncontrollableBackwards: current rCriticalStates set: " 
00802      << rCriticalStates.ToString());
00803   // process todo stack
00804   while (! todo.empty()) {
00805     // get top state from todo stack
00806     current = todo.top(); todo.pop();
00807     // iteration over all transitions with x2 == current
00808     rtit_end = rtransrel.EndByX2(current);
00809     rtit = rtransrel.BeginByX2(current);
00810     for (; rtit != rtit_end; ++rtit) {
00811       // if uncontrollable event and predecessor state not already critical
00812       if ((!rCAlph.Exists(rtit->Ev)) && (! rCriticalStates.Exists(rtit->X1))) {
00813         FD_DF("TraverseUncontrollableBackwards: todo push " << rCriticalStates.Str(rtit->X1));
00814   todo.push(rtit->X1);
00815   FD_DF("TraverseUncontrollableBackwards: critical insert: " << rCriticalStates.Str(rtit->X1));
00816   rCriticalStates.Insert(rtit->X1);
00817       }
00818     }
00819   } // end while todo
00820 }
00821 
00822 
00823 // controllability test for cGenerator plant
00824 bool IsControllable(
00825   const cGenerator& rPlantGen, 
00826   const vGenerator& rSupCandGen)
00827 {
00828   return IsControllable(rPlantGen, rPlantGen.ControllableEvents(), rSupCandGen);
00829 }
00830 
00831 
00832 // supcon for cGenerators:
00833 // uses and maintains controllablity from plant 
00834 void SupConNB(
00835   const cGenerator& rPlantGen, 
00836   const vGenerator& rSpecGen, 
00837   vGenerator& rResGen) {
00838 
00839   // prepare result
00840   vGenerator* pResGen = &rResGen;
00841   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00842     pResGen= rResGen.New();
00843   }
00844 
00845   // execute 
00846   SupConNB(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,*pResGen);
00847 
00848   // copy all attributes of input alphabet
00849   pResGen->EventAttributes(rPlantGen.Alphabet());
00850 
00851   // copy result
00852   if(pResGen != &rResGen) {
00853     pResGen->Move(rResGen);
00854     delete pResGen;
00855   }
00856 
00857 }
00858 
00859 // supcon for cGenerators
00860 // uses and maintains controllablity from plant 
00861 void SupCon(
00862   const cGenerator& rPlantGen, 
00863   const vGenerator& rSpecGen, 
00864   vGenerator& rResGen) {
00865 
00866   // prepare result
00867   vGenerator* pResGen = &rResGen;
00868   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00869     pResGen= rResGen.New();
00870   }
00871 
00872   // execute
00873   SupCon(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,*pResGen);
00874 
00875   // copy all attributes of input alphabet
00876   pResGen->EventAttributes(rPlantGen.Alphabet());
00877 
00878   // copy result
00879   if(pResGen != &rResGen) {
00880     pResGen->Move(rResGen);
00881     delete pResGen;
00882   }
00883 
00884 }
00885 
00886 } // name space 

libFAUDES 2.16b --- 2010-9-8 --- c++ source docu by doxygen 1.6.3