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

libFAUDES 2.18b --- 2010-12-17 --- c++ source docu by doxygen 1.6.3