About
User Reference
C++ API
luafaudes
Developer
Links
libFAUDES online
libFAUDES

Sections

Index

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   
00034 namespace faudes{
00035 
00036 
00037 // calcNaturalObserver(rGen,rHighAlph)
00038 Idx calcNaturalObserver(const MtcSystem& rGen, EventSet& rHighAlph){
00039     // helpers
00040     Generator dynGen;
00041     map<Idx,Idx> mapStateToPartition;
00042     vector<Idx> newPartitions;
00043     EventSet origAlph;
00044     Generator genPart;
00045     while(origAlph != rHighAlph){
00046         origAlph  = rHighAlph;
00047         // compute the dynamic system for the given generator and high-level alphabet
00048         calculateDynamicSystemObs(rGen, rHighAlph, dynGen);
00049         // compute the quasi conqruence 
00050         mapStateToPartition.clear();
00051         newPartitions.clear();
00052         genPart.Clear();
00053         calcBisimulation(dynGen, mapStateToPartition, genPart, newPartitions);
00054         // Extend the high-level alphabet according to the algorithm of Lei
00055         ExtendHighAlphabet(rGen, rHighAlph, mapStateToPartition);
00056     }
00057     return genPart.Size();
00058 }
00059 
00060 // calcAbstAlphObs(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
00061 void calcAbstAlphObs(MtcSystem& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > &  rMapRelabeledEvents) {
00062   OP_DF("calcAbstAlphObs(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
00063   // The controllable events are separated from the System. All functions that are successively 
00064   // called, are defined for Generators
00065   EventSet cntrevs = rGenObs.ControllableEvents();
00066   calcAbstAlphObs(rGenObs, cntrevs , rHighAlph, rNewHighAlph, rMapRelabeledEvents);
00067   // the controllable events that have been changed by the called function are set in the System cGenObs
00068   rGenObs.SetControllable(cntrevs);
00069 }
00070 
00071 // calcAbstAlphObs(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
00072 void calcAbstAlphObs(MtcSystem& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > &  rMapRelabeledEvents) {
00073   OP_DF("calcAbstAlphObs(" << rGenObs.Name() << "," << "rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
00074   // The function called next returns a relabeled generator and a map of relabeled transitions
00075   map<Transition,Idx>  changedtrans;
00076   calcAbstAlphObs(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans);
00077   // for later use, the relabeled transitions are converted into relabeled events 
00078   // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty
00079   map<Transition,Idx>::iterator rtEndIt = changedtrans.end();
00080   map<Transition,Idx>::iterator rtIt =  changedtrans.begin();
00081   for(; rtIt != rtEndIt; rtIt++){
00082     if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){// if the event does not exist, yet, a nex element in the map is created
00083       rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>();
00084       if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist 
00085         rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
00086     } 
00087     else {  // a new label is inserted into the map
00088       if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist    
00089         rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
00090     }
00091   }
00092 }
00093 
00094 // calcAbstAlphObs(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans)
00095 void calcAbstAlphObs(MtcSystem& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans)
00096 { 
00097   OP_DF("calcAbstAlphObs(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)");
00098   // Initialization of variables
00099   rNewHighAlph = rHighAlph;
00100   rMapChangedTrans.clear();
00101   Generator genDyn(rGenObs);
00102   map<Transition,Transition> mapChangedTransReverse;
00103   vector<Idx> newPartitions;
00104   map<Idx,Idx> mapStateToPartition;
00105   map<Idx, EventSet> mapRelabeledEvents;
00106   bool done=false;
00107   #ifdef DF_PLOT
00108     Idx iterationCount=1;
00109     string name;
00110   #endif
00111   // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition. 
00112   // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs
00113   // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition. 
00114   while(done==false)
00115   {
00116     // compute dynamic system for Lm-observer on rGenObs
00117     calculateDynamicSystemObs(rGenObs, rNewHighAlph, genDyn);
00118     #ifdef DF_PLOT
00119     name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToStringInteger(iterationCount));
00120     genDyn.DotWrite(name);
00121     #endif
00122   
00123     Generator genPart;
00124     mapStateToPartition.clear();
00125     newPartitions.clear();
00126   
00127     // compute coarsest quasi-congruence on the dynamic system
00128     calcBisimulation(genDyn, mapStateToPartition, genPart, newPartitions);
00129     #ifdef DF_PLOT
00130     name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToStringInteger(iterationCount));
00131     genPart.DotWrite(name);
00132     ++iterationCount;
00133     #endif
00134   
00135     // check if quotient automaton is deterministic and free of unobservable events
00136     // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly
00137     done=relabel(rGenObs, rControllableEvents, rNewHighAlph, newPartitions, mapStateToPartition, mapChangedTransReverse,  rMapChangedTrans, mapRelabeledEvents);
00138   }
00139 }
00140 
00141 // calculateDynamicSystemObs(rGen, rHighAlph, rGenDyn)
00142 void calculateDynamicSystemObs(const MtcSystem& rGen, EventSet& rHighAlph, Generator& rGenDyn)
00143 {
00144   OP_DF("calculateDynamicSystemObs(" << rGen.Name() << "," << rHighAlph.Name() << "," << rGenDyn.Name() << ")");
00145   // transition relation sorted in reverse order for backwards reachability
00146   TransSetX2EvX1 tset_X2EvX1;
00147   rGen.TransRel(tset_X2EvX1);
00148   
00149   // prepare generator rGenDyn
00150   rGenDyn.ClearTransRel();
00151   rGenDyn.InjectAlphabet(rHighAlph); // all high-level events are contained in the alphabet of rGenDyn
00152   
00153   // helpers
00154   EventSet::Iterator eIt = rGenDyn.AlphabetBegin();
00155   EventSet::Iterator eItEnd = rGenDyn.AlphabetEnd();
00156   
00157   TransSetX2EvX1::Iterator tItByX2Ev;
00158   TransSetX2EvX1::Iterator tItByX2EvEnd;
00159   StateSet reach;
00160   StateSet::Iterator sIt;
00161   StateSet::Iterator sItEnd;
00162   TransSet::Iterator tIt;
00163   TransSet::Iterator tItEnd;
00164   map<Idx,StateSet> entryStateToLocalReach;
00165   set<Idx>::iterator esIt, esItEnd;
00166   // map that maps a state (first Idx) to a reachable entry state (second Idx) via a high-level event (third Idx)
00167   map<Idx,vector<pair<Idx,Idx> > > stateToEntryState;
00168   map<Idx,vector<pair<Idx,Idx> > >::iterator stesIt;
00169   map<Idx,vector<pair<Idx,Idx> > >::iterator stesItEnd;
00170   
00171   // generate the color labels for the dynamic system
00172   ColorSet allColors = rGen.Colors();
00173   ColorSet::Iterator csIt, csEndIt;
00174   csIt = allColors.Begin();
00175   csEndIt = allColors.End();
00176   std::string colorLabel;
00177   // maps a unique color index to the index of the associated transition label in teh dynamic system
00178   map<Idx,Idx> colorEventMap; 
00179   for(; csIt != csEndIt; csIt++){
00180     colorLabel = ( rGenDyn.EventSymbolTablep())->UniqueSymbol("colorLabel" + rGen.ColorName(*csIt) + "_1");
00181     colorEventMap[*csIt] = (rGenDyn.EventSymbolTablep())->InsEntry(colorLabel); 
00182   }
00183   
00184   // algorithm for computing the dynamic system
00185   
00186   // loop over all states of original generator
00187   StateSet::Iterator stateSetIt = rGen.StatesBegin();
00188   StateSet::Iterator stateSetItEnd = rGen.StatesEnd();
00189   for( ; stateSetIt != stateSetItEnd; ++stateSetIt) {
00190     OP_DF("calculateDynamicSystemObs: loop over all states; current state: " << rGen.StateName(*stateSetIt) 
00191     << " [" << *stateSetIt << "]");
00192     
00193     // compute locally reachable states for current state
00194     reach.Clear();
00195     LocalAccessibleReach(rGen, rHighAlph, *stateSetIt, reach);
00196     OP_DF("calculateDynamicSystemObs: states in local reach: \n " << reach.ToString() );
00197     
00198     // check if current state (*stateSetIt) is an entry-state (a backward transition with
00199     // a high-level event exists. If yes, the locally reachable states (reach) are stored in
00200     // the entryStateToLocalReach map
00201     tItByX2Ev=tset_X2EvX1.BeginByX2(*stateSetIt); 
00202     tItByX2EvEnd=tset_X2EvX1.EndByX2(*stateSetIt); 
00203     for(; tItByX2Ev != tItByX2EvEnd; ++tItByX2Ev)
00204     {
00205       OP_DF("calculateDynamicSystemObs: checking transition : " << rGen.TStr(*tItByX2Ev));
00206       if(rHighAlph.Exists(tItByX2Ev->Ev)){
00207           OP_DF("calculateDynamicSystemObs: current state is an entry-state");
00208           // map entry-state to its locally reachable states
00209           entryStateToLocalReach[*stateSetIt]=reach;
00210           break;
00211       }
00212     }
00213     vector<pair<Idx,Idx> > emptyVector;
00214     stateToEntryState[*stateSetIt]=emptyVector;
00215     // loop over all states in the local reach of current state to determine which marked states
00216     // are locally reachable and to determine which high-level events can occur after local strings
00217     sIt=reach.Begin();
00218     sItEnd=reach.End();
00219     Idx colorEvent;
00220     for( ; sIt != sItEnd; ++sIt) 
00221     {
00222       // check if state sIt is marked; if yes, create an m-transition (mLabel) between current state and sIt
00223       const ColorSet& stateColors = rGen.Colors(*sIt);
00224       csIt = stateColors.Begin();
00225       csEndIt = stateColors.End();
00226       for( ; csIt != csEndIt; csIt++){
00227           OP_DF("calculateDynamicSystemObs: marked state " << rGen.SStr(*sIt) 
00228           <<  " is locally reachable from current state");
00229       colorEvent = colorEventMap[*csIt];
00230           rGenDyn.InsEvent(colorEvent ); // ??
00231           rGenDyn.InsState(*stateSetIt); // ??
00232           rGenDyn.InsState(*sIt); //??
00233           rGenDyn.SetTransition(*stateSetIt, colorEvent, *sIt);
00234       }
00235       // loop over all transitions of current state sIt to determine if high-level events are possible
00236       tIt    = rGen.TransRelBegin(*sIt);
00237       tItEnd = rGen.TransRelEnd(*sIt);
00238       for(; tIt != tItEnd; ++tIt)
00239       {
00240           OP_DF("calculateDynamicSystemObs: Loop over all states in reach; checking transition: " 
00241             << rGen.TStr(*tIt));
00242           if(rHighAlph.Exists(tIt->Ev))
00243           {
00244             OP_DF("calculateDynamicSystemObs: state " << rGen.SStr(tIt->X2) << 
00245             " is an entry state and can be reached from current state" << rGen.SStr(*stateSetIt) << " by event " << rGen.EventName(tIt->Ev));
00246             pair<Idx,Idx> newPair;
00247             newPair.first=tIt->X2;
00248             newPair.second=tIt->Ev;
00249             // store the reachable entry state and the corresponding high-level event
00250             stateToEntryState[*stateSetIt].push_back(newPair);
00251           }
00252       }
00253     }
00254   }
00255   
00256   // create the transition structure of the dynamic system
00257   stesIt    = stateToEntryState.begin();
00258   stesItEnd = stateToEntryState.end();
00259   vector<pair <Idx,Idx> >* pPairs;
00260   vector<pair <Idx,Idx> >::iterator vIt;
00261   vector<pair <Idx,Idx> >::iterator vItEnd;
00262   // To construct the dynamic system, each local state has to be connected to all states in
00263   // the local accessible reach of entry states that can be reached via a high-level event.
00264   // This information is contained in the stateToEntryState map combined with the entryStateToLocalReach map.
00265   // iteration over all entries (X1) of map stateToEntryState
00266   for(; stesIt != stesItEnd; ++stesIt)
00267   {
00268       pPairs=&(stesIt->second);
00269       vIt    = (*pPairs).begin();
00270       vItEnd = (*pPairs).end();
00271       // loop over all pairs (Ev,X2) of current entry
00272       for( ; vIt != vItEnd; ++vIt)
00273       {
00274         // check if transition already exists
00275         if(!((rGenDyn.TransRel()).Exists(stesIt->first,vIt->second,vIt->first))) 
00276         {
00277             // find local reach of entry state X2 
00278             StateSet* pLocalReach = &((entryStateToLocalReach.find(vIt->first))->second);
00279           
00280             // Add a Ev-transition from X1 to every state in the local reach of X2     
00281             StateSet::Iterator lrsIt    = pLocalReach->Begin();
00282             StateSet::Iterator lrsItEnd = pLocalReach->End();
00283             for(; lrsIt != lrsItEnd; ++lrsIt)
00284             {
00285               rGenDyn.InsEvent(vIt->second); // ??
00286               rGenDyn.InsState(stesIt->first); // ??
00287               rGenDyn.InsState(*lrsIt); //??
00288               rGenDyn.SetTransition(stesIt->first,vIt->second,*lrsIt);
00289               OP_DF("calculateDynamicSystemObs: Transition added to resulting generator: " << 
00290                 rGenDyn.TStr(Transition(stesIt->first,vIt->second,*lrsIt))); 
00291             }
00292         }
00293       }
00294   }
00295   OP_DF("calculateDynamicSystemObs: leaving function");
00296 }
00297  
00298 }

libFAUDES 2.20d --- 2011.04.26 --- c++ source docu by doxygen