|
libFAUDES
Sections
Index
|
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 00034 namespace faudes{ 00035 00036 00037 // calcNaturalObserver(rGen,rHighAlph) 00038 Idx calcNaturalObserver(const mtcGenerator& 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(mtcGenerator& 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 cGenerator. All functions that are successively 00064 // called, are defined for vGenerators 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 cGenerator cGenObs 00068 rGenObs.SetControllable(cntrevs); 00069 } 00070 00071 // calcAbstAlphObs(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents) 00072 void calcAbstAlphObs(mtcGenerator& 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(mtcGenerator& 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 mtcGenerator& rGen, EventSet& rHighAlph, vGenerator& 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.18b --- 2010-12-17 --- c++ source docu by doxygen 1.6.3