supcon.cpp

Go to the documentation of this file.
00001 
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 "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 (tith != 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.NewP();
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     rResGen = *pResGen;
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("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 
00623 
00624 // SupConNB(rPlantGen, rCAlph, rSpecGen, rResGen)
00625 void SupConNB(
00626   const vGenerator& rPlantGen, 
00627   const EventSet& rCAlph, 
00628   const vGenerator& rSpecGen, 
00629   vGenerator& rResGen) 
00630 {
00631 
00632   // CONSISTENCY CHECK:
00633   ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen);
00634 
00635   // HELPERS:
00636   std::map< std::pair<Idx,Idx>, Idx> rcmap;
00637 
00638   // ALGORITHM:
00639   SupConNBUnchecked(rPlantGen, rCAlph, rSpecGen, rcmap, rResGen);
00640 }
00641 
00642 
00643 
00644 
00645 // SupConNBNonDet(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, 
00646 //     pDetPlantGen, pDetSpecGen, rResGen)
00647 void SupConNBNonDet(
00648   const vGenerator& rPlantGen, 
00649   const EventSet& rCAlph,
00650   const vGenerator& rSpecGen,
00651   std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap,
00652   Generator rDetPlantGen, 
00653   Generator rDetSpecGen, 
00654   std::map<Idx,StateSet>& rPowerStatesPlant, 
00655   std::map<Idx,StateSet>& rPowerStatesSpec,
00656   bool& rDetPlantBool, 
00657   bool& rDetSpecBool, 
00658   vGenerator& rResGen) 
00659 {
00660   FD_DF("SupConNBNonDet(" << &rPlantGen << "," << &rSpecGen << ")");
00661 
00662   // alphabets must match
00663   if (rPlantGen.Alphabet() != rSpecGen.Alphabet()) {
00664     throw Exception("SupConNBNonDet", "Alphabets of generators don't match", 100);
00665   }
00666 
00667   // PREPARE RESULT:
00668   vGenerator* pResGen = &rResGen;
00669   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00670     pResGen= rResGen.NewP();
00671   }
00672   pResGen->Clear();
00673   pResGen->Name(CollapsString("SupConNBNonDet(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"));
00674   pResGen->InjectAlphabet(rPlantGen.Alphabet());
00675   
00676   // HELPERS:
00677   rPowerStatesPlant.clear();
00678   rPowerStatesSpec.clear();
00679 
00680   // controllable events
00681   FD_DF("SupConNB: controllable events: " << rCAlph.ToString());
00682 
00683   // pointers to actual generators
00684   vGenerator* plantp;
00685   vGenerator* specp;
00686 
00687   // plant and spec determinism
00688   rDetPlantBool = rPlantGen.IsDeterministic();
00689   rDetSpecBool = rSpecGen.IsDeterministic();
00690   
00691   // create deterministic generators and set pointers to the actual ones
00692   plantp = const_cast<vGenerator*>(&rPlantGen);
00693   specp = const_cast<vGenerator*>(&rSpecGen);
00694   if (rDetPlantBool == false) {
00695       Deterministic(rPlantGen, rPowerStatesPlant, rDetPlantGen);    
00696       plantp = &rDetPlantGen;
00697   }
00698   if (rDetSpecBool == false) {
00699       Deterministic(rSpecGen, rPowerStatesSpec, rDetSpecGen);
00700       specp = &rDetSpecGen;
00701   }
00702   
00703   // ALGORITHM:
00704 
00705   // compute supervisor
00706   SupconParallel(*plantp, rCAlph, *specp, rReverseCompositionMap, *pResGen);
00707 
00708   // make resulting generator trim until it's fully controllable
00709   while (! (SupConUnchecked(*plantp, rCAlph, *pResGen) && pResGen->Trim()));
00710 
00711   // copy result
00712   if(pResGen != &rResGen) {
00713     rResGen = *pResGen;
00714     delete pResGen;
00715   }
00716 }
00717 
00718 // SupCon(rPlantGen, rCAlph, rSpecGen, rResGen)
00719 void SupCon(
00720   const vGenerator& rPlantGen, 
00721   const EventSet& rCAlph,
00722   const vGenerator& rSpecGen, 
00723   vGenerator& rResGen) 
00724 {
00725   // HELPERS:
00726   std::map< std::pair<Idx,Idx>, Idx> rcmap;
00727 
00728   // ALGORITHM:
00729   SupCon(rPlantGen, rCAlph, rSpecGen, rcmap, rResGen);
00730 }
00731 
00732 
00733 // SupCon(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, rResGen)
00734 void SupCon(
00735   const vGenerator& rPlantGen, 
00736   const EventSet& rCAlph,
00737   const vGenerator& rSpecGen,
00738   std::map< std::pair<Idx,Idx>, Idx>& rReverseCompositionMap, 
00739   vGenerator& rResGen) 
00740 {
00741   FD_DF("SupCon(" << &rPlantGen << "," << &rSpecGen << ")");
00742 
00743   // PREPARE RESULT:
00744   
00745 
00746   // prepare result
00747   vGenerator* pResGen = &rResGen;
00748   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00749     pResGen= rResGen.NewP();
00750   }
00751   pResGen->Clear();
00752   pResGen->Name(CollapsString("SupCon(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"));
00753   pResGen->InjectAlphabet(rPlantGen.Alphabet());
00754   
00755   // HELPERS:
00756   FD_DF("SupCon: controllable events: " << rCAlph.ToString());
00757 
00758   // CONSISTENCY CHECK:
00759   ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen);
00760 
00761   // ALGORITHM:
00762 
00763   // parallel composition
00764   SupconParallel(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, *pResGen);
00765   // make resulting generator controllable
00766   SupConUnchecked(rPlantGen, rCAlph, *pResGen);
00767 
00768   // copy result
00769   if(pResGen != &rResGen) {
00770     rResGen = *pResGen;
00771     delete pResGen;
00772   }
00773 }
00774 
00775 
00776 // TraverseUncontrollableBackwards(rCAlph, rtransrel, critical, current)
00777 void TraverseUncontrollableBackwards(
00778   const EventSet& rCAlph, 
00779   TransSetX2EvX1& rtransrel, 
00780   StateSet& rCriticalStates, 
00781   Idx current) {
00782   FD_DF("TraverseUncontrollableBackwards: " << rCriticalStates.Str(current));
00783 
00784   // HELPERS:
00785   std::stack<Idx> todo;
00786   TransSetX2EvX1::Iterator rtit = rtransrel.BeginByX2(current);
00787   TransSetX2EvX1::Iterator rtit_end = rtransrel.EndByX2(current);
00788 
00789   // ALGORITHM:
00790   rCriticalStates.Insert(current);
00791   todo.push(current);
00792   FD_DF("TraverseUncontrollableBackwards: current rCriticalStates set: " 
00793      << rCriticalStates.ToString());
00794   // process todo stack
00795   while (! todo.empty()) {
00796     // get top state from todo stack
00797     current = todo.top(); todo.pop();
00798     // iteration over all transitions with x2 == current
00799     rtit_end = rtransrel.EndByX2(current);
00800     rtit = rtransrel.BeginByX2(current);
00801     for (; rtit != rtit_end; ++rtit) {
00802       // if uncontrollable event and predecessor state not already critical
00803       if ((!rCAlph.Exists(rtit->Ev)) && (! rCriticalStates.Exists(rtit->X1))) {
00804         FD_DF("TraverseUncontrollableBackwards: todo push " << rCriticalStates.Str(rtit->X1));
00805   todo.push(rtit->X1);
00806   FD_DF("TraverseUncontrollableBackwards: critical insert: " << rCriticalStates.Str(rtit->X1));
00807   rCriticalStates.Insert(rtit->X1);
00808       }
00809     }
00810   } // end while todo
00811 }
00812 
00813 } // name space 

Generated on Fri May 9 11:26:47 2008 for libFAUDES 2.09b by  doxygen 1.4.4