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     std::stringstream errstr;
00543     errstr << "Alphabets of generators do not match. Only in plant: " 
00544        << only_in_plant.ToString() << ". Only in spec: "
00545        << only_in_spec.ToString() << ".";
00546     throw Exception("SupCon/SupConNB", errstr.str(), 100);
00547   }
00548   
00549   // TODO: add test for rCAlph <= Alphabet
00550 
00551   // TODO: check symboltables to match
00552 
00553   // plant and spec must be deterministic
00554   bool plant_det = rPlantGen.IsDeterministic();
00555   bool spec_det = rSpecGen.IsDeterministic();
00556 
00557   if ((plant_det == false) && (spec_det == true)) {
00558     std::stringstream errstr;
00559     errstr << "Plant generator must be deterministic, "
00560       << "but is nondeterministic";
00561     throw Exception("ControllableConsistencyCheck", errstr.str(), 201);
00562   }
00563   else if ((plant_det == true) && (spec_det == false)) {
00564     std::stringstream errstr;
00565     errstr << "Spec generator must be deterministic, "
00566        << "but is nondeterministic";
00567     throw Exception("ControllableConsistencyCheck", errstr.str(), 203);
00568   }
00569   else if ((plant_det == false) && (spec_det == false)) {
00570     std::stringstream errstr;
00571     errstr << "Plant and spec generator must be deterministic, "
00572        << "but both are nondeterministic";
00573     throw Exception("ControllableConsistencyCheck", errstr.str(), 204);
00574   }
00575 }
00576 
00577 
00578 /*
00579 ****************************************
00580 * SUPCON: WRAPPER / USER FUNCTIONS     *
00581 ****************************************
00582 */
00583 
00584 
00585 // IsControllable(rPlantGen, rCAlph, rSupCandGen)
00586 bool IsControllable(
00587   const vGenerator& rPlantGen, 
00588   const EventSet& rCAlph, 
00589   const vGenerator& rSupCandGen) 
00590 {
00591   FD_DF("IsControllable(" << &rSupCandGen << "," << &rPlantGen << ")");
00592 
00593   // HELPERS:
00594   FD_DF("IsControllable: controllable events: " << rCAlph.ToString());
00595   // critical set
00596   StateSet critical;
00597 
00598   // CONSISTENCY CHECKS:
00599   ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSupCandGen);
00600 
00601   // ALGORITHM:
00602   return IsControllableUnchecked(rPlantGen, rCAlph, rSupCandGen, critical);
00603 }
00604 
00605 
00606 // IsControllable(rPlantGen, rCAlph, rSupCandGen, critical)
00607 bool IsControllable(
00608   const vGenerator& rPlantGen, 
00609   const EventSet& rCAlph, 
00610   const vGenerator& rSupCandGen, 
00611   StateSet& rCriticalStates) 
00612 {
00613   FD_DF("IsControllable(" << &rSupCandGen << "," << &rPlantGen << ")");
00614 
00615   // CONSISTENCY CHECKS:
00616   ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSupCandGen);
00617 
00618   // ALGORITHM:
00619   return IsControllableUnchecked(rPlantGen, rCAlph, rSupCandGen, rCriticalStates);
00620 }
00621 
00622 // IsControllable
00623 void IsControllable(
00624   const vGenerator& rPlantGen, 
00625   const EventSet&  rCAlph,
00626   const vGenerator& rSupCandGen, 
00627   bool& rRes) 
00628 {
00629   rRes=IsControllable(rPlantGen, rCAlph, rSupCandGen);
00630 }
00631 
00632 
00633 
00634 // SupConNB(rPlantGen, rCAlph, rSpecGen, rResGen)
00635 void SupConNB(
00636   const vGenerator& rPlantGen, 
00637   const EventSet& rCAlph, 
00638   const vGenerator& rSpecGen, 
00639   vGenerator& rResGen) 
00640 {
00641 
00642   // CONSISTENCY CHECK:
00643   ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen);
00644 
00645   // HELPERS:
00646   std::map< std::pair<Idx,Idx>, Idx> rcmap;
00647 
00648   // ALGORITHM:
00649   SupConNBUnchecked(rPlantGen, rCAlph, rSpecGen, rcmap, rResGen);
00650 }
00651 
00652 
00653 
00654 
00655 // SupConNBNonDet(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, 
00656 //     pDetPlantGen, pDetSpecGen, rResGen)
00657 void SupConNBNonDet(
00658   const vGenerator& rPlantGen, 
00659   const EventSet& rCAlph,
00660   const vGenerator& rSpecGen,
00661   std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap,
00662   Generator rDetPlantGen, 
00663   Generator rDetSpecGen, 
00664   std::map<Idx,StateSet>& rPowerStatesPlant, 
00665   std::map<Idx,StateSet>& rPowerStatesSpec,
00666   bool& rDetPlantBool, 
00667   bool& rDetSpecBool, 
00668   vGenerator& rResGen) 
00669 {
00670   FD_DF("SupConNBNonDet(" << &rPlantGen << "," << &rSpecGen << ")");
00671 
00672   // alphabets must match
00673   if (rPlantGen.Alphabet() != rSpecGen.Alphabet()) {
00674     throw Exception("SupConNBNonDet", "Alphabets of generators don't match", 100);
00675   }
00676 
00677   // PREPARE RESULT:
00678   vGenerator* pResGen = &rResGen;
00679   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00680     pResGen= rResGen.New();
00681   }
00682   pResGen->Clear();
00683   pResGen->Name(CollapsString("SupConNBNonDet(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"));
00684   pResGen->InjectAlphabet(rPlantGen.Alphabet());
00685   
00686   // HELPERS:
00687   rPowerStatesPlant.clear();
00688   rPowerStatesSpec.clear();
00689 
00690   // controllable events
00691   FD_DF("SupConNB: controllable events: " << rCAlph.ToString());
00692 
00693   // pointers to actual generators
00694   vGenerator* plantp;
00695   vGenerator* specp;
00696 
00697   // plant and spec determinism
00698   rDetPlantBool = rPlantGen.IsDeterministic();
00699   rDetSpecBool = rSpecGen.IsDeterministic();
00700   
00701   // create deterministic generators and set pointers to the actual ones
00702   plantp = const_cast<vGenerator*>(&rPlantGen);
00703   specp = const_cast<vGenerator*>(&rSpecGen);
00704   if (rDetPlantBool == false) {
00705       Deterministic(rPlantGen, rPowerStatesPlant, rDetPlantGen);    
00706       plantp = &rDetPlantGen;
00707   }
00708   if (rDetSpecBool == false) {
00709       Deterministic(rSpecGen, rPowerStatesSpec, rDetSpecGen);
00710       specp = &rDetSpecGen;
00711   }
00712   
00713   // ALGORITHM:
00714 
00715   // compute supervisor
00716   SupconParallel(*plantp, rCAlph, *specp, rReverseCompositionMap, *pResGen);
00717 
00718   // make resulting generator trim until it's fully controllable
00719   while (! (SupConUnchecked(*plantp, rCAlph, *pResGen) && pResGen->Trim()));
00720 
00721   // copy result
00722   if(pResGen != &rResGen) {
00723     pResGen->Move(rResGen);
00724     delete pResGen;
00725   }
00726 }
00727 
00728 // SupCon(rPlantGen, rCAlph, rSpecGen, rResGen)
00729 void SupCon(
00730   const vGenerator& rPlantGen, 
00731   const EventSet& rCAlph,
00732   const vGenerator& rSpecGen, 
00733   vGenerator& rResGen) 
00734 {
00735   // HELPERS:
00736   std::map< std::pair<Idx,Idx>, Idx> rcmap;
00737 
00738   // ALGORITHM:
00739   SupCon(rPlantGen, rCAlph, rSpecGen, rcmap, rResGen);
00740 }
00741 
00742 
00743 // SupCon(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, rResGen)
00744 void SupCon(
00745   const vGenerator& rPlantGen, 
00746   const EventSet& rCAlph,
00747   const vGenerator& rSpecGen,
00748   std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, 
00749   vGenerator& rResGen) 
00750 {
00751   FD_DF("SupCon(" << &rPlantGen << "," << &rSpecGen << ")");
00752 
00753   // PREPARE RESULT:
00754   
00755 
00756   // prepare result
00757   vGenerator* pResGen = &rResGen;
00758   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00759     pResGen= rResGen.New();
00760   }
00761   pResGen->Clear();
00762   pResGen->Name(CollapsString("SupCon(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"));
00763   pResGen->InjectAlphabet(rPlantGen.Alphabet());
00764   
00765   // HELPERS:
00766   FD_DF("SupCon: controllable events: " << rCAlph.ToString());
00767 
00768   // CONSISTENCY CHECK:
00769   ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen);
00770 
00771   // ALGORITHM:
00772 
00773   // parallel composition
00774   SupconParallel(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, *pResGen);
00775   // make resulting generator controllable
00776   SupConUnchecked(rPlantGen, rCAlph, *pResGen);
00777 
00778   // copy result
00779   if(pResGen != &rResGen) {
00780     pResGen->Move(rResGen);
00781     delete pResGen;
00782   }
00783 }
00784 
00785 
00786 // TraverseUncontrollableBackwards(rCAlph, rtransrel, critical, current)
00787 void TraverseUncontrollableBackwards(
00788   const EventSet& rCAlph, 
00789   TransSetX2EvX1& rtransrel, 
00790   StateSet& rCriticalStates, 
00791   Idx current) {
00792   FD_DF("TraverseUncontrollableBackwards: " << rCriticalStates.Str(current));
00793 
00794   // HELPERS:
00795   std::stack<Idx> todo;
00796   TransSetX2EvX1::Iterator rtit = rtransrel.BeginByX2(current);
00797   TransSetX2EvX1::Iterator rtit_end = rtransrel.EndByX2(current);
00798 
00799   // ALGORITHM:
00800   rCriticalStates.Insert(current);
00801   todo.push(current);
00802   FD_DF("TraverseUncontrollableBackwards: current rCriticalStates set: " 
00803      << rCriticalStates.ToString());
00804   // process todo stack
00805   while (! todo.empty()) {
00806     // get top state from todo stack
00807     current = todo.top(); todo.pop();
00808     // iteration over all transitions with x2 == current
00809     rtit_end = rtransrel.EndByX2(current);
00810     rtit = rtransrel.BeginByX2(current);
00811     for (; rtit != rtit_end; ++rtit) {
00812       // if uncontrollable event and predecessor state not already critical
00813       if ((!rCAlph.Exists(rtit->Ev)) && (! rCriticalStates.Exists(rtit->X1))) {
00814         FD_DF("TraverseUncontrollableBackwards: todo push " << rCriticalStates.Str(rtit->X1));
00815   todo.push(rtit->X1);
00816   FD_DF("TraverseUncontrollableBackwards: critical insert: " << rCriticalStates.Str(rtit->X1));
00817   rCriticalStates.Insert(rtit->X1);
00818       }
00819     }
00820   } // end while todo
00821 }
00822 
00823 // controllability test for cGenerator plant
00824 bool cIsControllable(
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 cSupConNB(
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 cSupCon(
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.14g --- 2009-12-3 --- c++ source docu by doxygen 1.5.6