mtc_observercomputation.cpp

Go to the documentation of this file.
00001 /** @file mtc_observercomputation.cpp
00002 
00003 Methods to compute natural projections that exhibit the obsrver property.
00004 The observer algorithm is elaborated in
00005 K. C. Wong and W. M. Wonham, "On the Computation of Observers in Discrete Event
00006 Systems," Discrete Event Dynamic Systems, vol. 14, no. 1, pp. 55-107, 2004. 
00007 In addition, methods to compute natural projections that exhibit
00008 output control consistency (OCC) and local control consistency (LCC) are provided. See for example
00009 K. Schmidt and C. Breindl, "On Maximal Permissiveness of Hierarchical and Modular Supervisory
00010 Control Approaches for Discrete Event Systems," Workshop on Discrete Event Systems, 2008. 
00011 */
00012 
00013 /* FAU Discrete Event Systems Library (libfaudes)
00014 
00015    Copyright (C) 2006  Bernd Opitz
00016    Exclusive copyright is granted to Klaus Schmidt
00017 
00018    This library is free software; you can redistribute it and/or
00019    modify it under the terms of the GNU Lesser General Public
00020    License as published by the Free Software Foundation; either
00021    version 2.1 of the License, or (at your option) any later version.
00022 
00023    This library is distributed in the hope that it will be useful,
00024    but WITHOUT ANY WARRANTY; without even the implied warranty of
00025    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00026    Lesser General Public License for more details.
00027 
00028    You should have received a copy of the GNU Lesser General Public
00029    License along with this library; if not, write to the Free Software
00030    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00031 
00032 #include "mtc_observercomputation.h"
00033 #include "cfl_localgen.h"
00034 
00035 using  namespace std;
00036 namespace faudes{
00037 
00038 
00039 // calcNaturalObserver(rGen,rHighAlph)
00040 Idx calcNaturalObserver(const MtcSystem& rGen, EventSet& rHighAlph){
00041     // helpers
00042     Generator dynGen;
00043     map<Idx,Idx> mapStateToPartition;
00044     vector<Idx> newPartitions;
00045     EventSet origAlph;
00046     Generator genPart;
00047     while(origAlph != rHighAlph){
00048         origAlph  = rHighAlph;
00049         // compute the dynamic system for the given generator and high-level alphabet
00050         calculateDynamicSystemObs(rGen, rHighAlph, dynGen);
00051         // compute the quasi conqruence 
00052         mapStateToPartition.clear();
00053         newPartitions.clear();
00054         genPart.Clear();
00055         calcBisimulation(dynGen, mapStateToPartition, genPart, newPartitions);
00056         // Extend the high-level alphabet according to the algorithm of Lei
00057         ExtendHighAlphabet(rGen, rHighAlph, mapStateToPartition);
00058     }
00059     return genPart.Size();
00060 }
00061 
00062 // calcAbstAlphObs(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
00063 void calcAbstAlphObs(MtcSystem& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > &  rMapRelabeledEvents) {
00064   OP_DF("calcAbstAlphObs(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
00065   // The controllable events are separated from the System. All functions that are successively 
00066   // called, are defined for Generators
00067   EventSet cntrevs = rGenObs.ControllableEvents();
00068   calcAbstAlphObs(rGenObs, cntrevs , rHighAlph, rNewHighAlph, rMapRelabeledEvents);
00069   // the controllable events that have been changed by the called function are set in the System cGenObs
00070   rGenObs.SetControllable(cntrevs);
00071 }
00072 
00073 // calcAbstAlphObs(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
00074 void calcAbstAlphObs(MtcSystem& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > &  rMapRelabeledEvents) {
00075   OP_DF("calcAbstAlphObs(" << rGenObs.Name() << "," << "rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
00076   // The function called next returns a relabeled generator and a map of relabeled transitions
00077   map<Transition,Idx>  changedtrans;
00078   calcAbstAlphObs(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans);
00079   // for later use, the relabeled transitions are converted into relabeled events 
00080   // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty
00081   map<Transition,Idx>::iterator rtEndIt = changedtrans.end();
00082   map<Transition,Idx>::iterator rtIt =  changedtrans.begin();
00083   for(; rtIt != rtEndIt; rtIt++){
00084     if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){// if the event does not exist, yet, a nex element in the map is created
00085       rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>();
00086       if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist 
00087         rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
00088     } 
00089     else {  // a new label is inserted into the map
00090       if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist    
00091         rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
00092     }
00093   }
00094 }
00095 
00096 // calcAbstAlphObs(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans)
00097 void calcAbstAlphObs(MtcSystem& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans)
00098 { 
00099   OP_DF("calcAbstAlphObs(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)");
00100   // Initialization of variables
00101   rNewHighAlph = rHighAlph;
00102   rMapChangedTrans.clear();
00103   Generator genDyn(rGenObs);
00104   map<Transition,Transition> mapChangedTransReverse;
00105   vector<Idx> newPartitions;
00106   map<Idx,Idx> mapStateToPartition;
00107   map<Idx, EventSet> mapRelabeledEvents;
00108   bool done=false;
00109   #ifdef DF_PLOT
00110     Idx iterationCount=1;
00111     string name;
00112   #endif
00113   // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition. 
00114   // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs
00115   // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition. 
00116   while(done==false)
00117   {
00118     // compute dynamic system for Lm-observer on rGenObs
00119     calculateDynamicSystemObs(rGenObs, rNewHighAlph, genDyn);
00120     #ifdef DF_PLOT
00121     name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToStringInteger(iterationCount));
00122     genDyn.DotWrite(name);
00123     #endif
00124   
00125     Generator genPart;
00126     mapStateToPartition.clear();
00127     newPartitions.clear();
00128   
00129     // compute coarsest quasi-congruence on the dynamic system
00130     calcBisimulation(genDyn, mapStateToPartition, genPart, newPartitions);
00131     #ifdef DF_PLOT
00132     name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToStringInteger(iterationCount));
00133     genPart.DotWrite(name);
00134     ++iterationCount;
00135     #endif
00136   
00137     // check if quotient automaton is deterministic and free of unobservable events
00138     // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly
00139     done=relabel(rGenObs, rControllableEvents, rNewHighAlph, newPartitions, mapStateToPartition, mapChangedTransReverse,  rMapChangedTrans, mapRelabeledEvents);
00140   }
00141 }
00142 
00143 // calculateDynamicSystemObs(rGen, rHighAlph, rGenDyn)
00144 void calculateDynamicSystemObs(const MtcSystem& rGen, EventSet& rHighAlph, Generator& rGenDyn)
00145 {
00146   OP_DF("calculateDynamicSystemObs(" << rGen.Name() << "," << rHighAlph.Name() << "," << rGenDyn.Name() << ")");
00147   // transition relation sorted in reverse order for backwards reachability
00148   TransSetX2EvX1 tset_X2EvX1;
00149   rGen.TransRel(tset_X2EvX1);
00150   
00151   // prepare generator rGenDyn
00152   rGenDyn.ClearTransRel();
00153   rGenDyn.InjectAlphabet(rHighAlph); // all high-level events are contained in the alphabet of rGenDyn
00154   
00155   // helpers
00156   EventSet::Iterator eIt = rGenDyn.AlphabetBegin();
00157   EventSet::Iterator eItEnd = rGenDyn.AlphabetEnd();
00158   
00159   TransSetX2EvX1::Iterator tItByX2Ev;
00160   TransSetX2EvX1::Iterator tItByX2EvEnd;
00161   StateSet reach;
00162   StateSet::Iterator sIt;
00163   StateSet::Iterator sItEnd;
00164   TransSet::Iterator tIt;
00165   TransSet::Iterator tItEnd;
00166   map<Idx,StateSet> entryStateToLocalReach;
00167   set<Idx>::iterator esIt, esItEnd;
00168   // map that maps a state (first Idx) to a reachable entry state (second Idx) via a high-level event (third Idx)
00169   map<Idx,vector<pair<Idx,Idx> > > stateToEntryState;
00170   map<Idx,vector<pair<Idx,Idx> > >::iterator stesIt;
00171   map<Idx,vector<pair<Idx,Idx> > >::iterator stesItEnd;
00172   
00173   // generate the color labels for the dynamic system
00174   ColorSet allColors = rGen.Colors();
00175   ColorSet::Iterator csIt, csEndIt;
00176   csIt = allColors.Begin();
00177   csEndIt = allColors.End();
00178   std::string colorLabel;
00179   // maps a unique color index to the index of the associated transition label in teh dynamic system
00180   map<Idx,Idx> colorEventMap; 
00181   for(; csIt != csEndIt; csIt++){
00182     colorLabel = ( rGenDyn.EventSymbolTablep())->UniqueSymbol("colorLabel" + rGen.ColorName(*csIt) + "_1");
00183     colorEventMap[*csIt] = (rGenDyn.EventSymbolTablep())->InsEntry(colorLabel); 
00184   }
00185   
00186   // algorithm for computing the dynamic system
00187   
00188   // loop over all states of original generator
00189   StateSet::Iterator stateSetIt = rGen.StatesBegin();
00190   StateSet::Iterator stateSetItEnd = rGen.StatesEnd();
00191   for( ; stateSetIt != stateSetItEnd; ++stateSetIt) {
00192     OP_DF("calculateDynamicSystemObs: loop over all states; current state: " << rGen.StateName(*stateSetIt) 
00193     << " [" << *stateSetIt << "]");
00194     
00195     // compute locally reachable states for current state
00196     reach.Clear();
00197     LocalAccessibleReach(rGen, rHighAlph, *stateSetIt, reach);
00198     OP_DF("calculateDynamicSystemObs: states in local reach: \n " << reach.ToString() );
00199     
00200     // check if current state (*stateSetIt) is an entry-state (a backward transition with
00201     // a high-level event exists. If yes, the locally reachable states (reach) are stored in
00202     // the entryStateToLocalReach map
00203     tItByX2Ev=tset_X2EvX1.BeginByX2(*stateSetIt); 
00204     tItByX2EvEnd=tset_X2EvX1.EndByX2(*stateSetIt); 
00205     for(; tItByX2Ev != tItByX2EvEnd; ++tItByX2Ev)
00206     {
00207       OP_DF("calculateDynamicSystemObs: checking transition : " << rGen.TStr(*tItByX2Ev));
00208       if(rHighAlph.Exists(tItByX2Ev->Ev)){
00209           OP_DF("calculateDynamicSystemObs: current state is an entry-state");
00210           // map entry-state to its locally reachable states
00211           entryStateToLocalReach[*stateSetIt]=reach;
00212           break;
00213       }
00214     }
00215     vector<pair<Idx,Idx> > emptyVector;
00216     stateToEntryState[*stateSetIt]=emptyVector;
00217     // loop over all states in the local reach of current state to determine which marked states
00218     // are locally reachable and to determine which high-level events can occur after local strings
00219     sIt=reach.Begin();
00220     sItEnd=reach.End();
00221     Idx colorEvent;
00222     for( ; sIt != sItEnd; ++sIt) 
00223     {
00224       // check if state sIt is marked; if yes, create an m-transition (mLabel) between current state and sIt
00225       const ColorSet& stateColors = rGen.Colors(*sIt);
00226       csIt = stateColors.Begin();
00227       csEndIt = stateColors.End();
00228       for( ; csIt != csEndIt; csIt++){
00229           OP_DF("calculateDynamicSystemObs: marked state " << rGen.SStr(*sIt) 
00230           <<  " is locally reachable from current state");
00231       colorEvent = colorEventMap[*csIt];
00232           rGenDyn.InsEvent(colorEvent ); // ??
00233           rGenDyn.InsState(*stateSetIt); // ??
00234           rGenDyn.InsState(*sIt); //??
00235           rGenDyn.SetTransition(*stateSetIt, colorEvent, *sIt);
00236       }
00237       // loop over all transitions of current state sIt to determine if high-level events are possible
00238       tIt    = rGen.TransRelBegin(*sIt);
00239       tItEnd = rGen.TransRelEnd(*sIt);
00240       for(; tIt != tItEnd; ++tIt)
00241       {
00242           OP_DF("calculateDynamicSystemObs: Loop over all states in reach; checking transition: " 
00243             << rGen.TStr(*tIt));
00244           if(rHighAlph.Exists(tIt->Ev))
00245           {
00246             OP_DF("calculateDynamicSystemObs: state " << rGen.SStr(tIt->X2) << 
00247             " is an entry state and can be reached from current state" << rGen.SStr(*stateSetIt) << " by event " << rGen.EventName(tIt->Ev));
00248             pair<Idx,Idx> newPair;
00249             newPair.first=tIt->X2;
00250             newPair.second=tIt->Ev;
00251             // store the reachable entry state and the corresponding high-level event
00252             stateToEntryState[*stateSetIt].push_back(newPair);
00253           }
00254       }
00255     }
00256   }
00257   
00258   // create the transition structure of the dynamic system
00259   stesIt    = stateToEntryState.begin();
00260   stesItEnd = stateToEntryState.end();
00261   vector<pair <Idx,Idx> >* pPairs;
00262   vector<pair <Idx,Idx> >::iterator vIt;
00263   vector<pair <Idx,Idx> >::iterator vItEnd;
00264   // To construct the dynamic system, each local state has to be connected to all states in
00265   // the local accessible reach of entry states that can be reached via a high-level event.
00266   // This information is contained in the stateToEntryState map combined with the entryStateToLocalReach map.
00267   // iteration over all entries (X1) of map stateToEntryState
00268   for(; stesIt != stesItEnd; ++stesIt)
00269   {
00270       pPairs=&(stesIt->second);
00271       vIt    = (*pPairs).begin();
00272       vItEnd = (*pPairs).end();
00273       // loop over all pairs (Ev,X2) of current entry
00274       for( ; vIt != vItEnd; ++vIt)
00275       {
00276         // check if transition already exists
00277         if(!((rGenDyn.TransRel()).Exists(stesIt->first,vIt->second,vIt->first))) 
00278         {
00279             // find local reach of entry state X2 
00280             StateSet* pLocalReach = &((entryStateToLocalReach.find(vIt->first))->second);
00281           
00282             // Add a Ev-transition from X1 to every state in the local reach of X2     
00283             StateSet::Iterator lrsIt    = pLocalReach->Begin();
00284             StateSet::Iterator lrsItEnd = pLocalReach->End();
00285             for(; lrsIt != lrsItEnd; ++lrsIt)
00286             {
00287               rGenDyn.InsEvent(vIt->second); // ??
00288               rGenDyn.InsState(stesIt->first); // ??
00289               rGenDyn.InsState(*lrsIt); //??
00290               rGenDyn.SetTransition(stesIt->first,vIt->second,*lrsIt);
00291               OP_DF("calculateDynamicSystemObs: Transition added to resulting generator: " << 
00292                 rGenDyn.TStr(Transition(stesIt->first,vIt->second,*lrsIt))); 
00293             }
00294         }
00295       }
00296   }
00297   OP_DF("calculateDynamicSystemObs: leaving function");
00298 }
00299  
00300 }

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