mtc_observercomputation.cppGo 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 |