| |
libFAUDES
Sections
Index
|
op_obserververification.cppGo to the documentation of this file.00001 /** @file op_obserververification.cpp 00002 00003 Methods to verify the obsrver condition for natural projections. 00004 The observer condition is, e.g., defined in 00005 K. C. Wong and W. M. Wonham, “Hierarchical control of discrete-event 00006 systems,” Discrete Event Dynamic Systems: Theory and Applications, 1996. 00007 In addition, methods to verify output control consistency (OCC) and 00008 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 #include "op_obserververification.h" 00032 00033 00034 using namespace std; 00035 00036 namespace faudes { 00037 00038 bool IsObs(const Generator& rLowGen, const EventSet& rHighAlph){ 00039 OP_DF("IsObs(" << rLowGen.Name() << "," << rHighAlph.Name() << ")"); 00040 // Initialization of variables 00041 EventSet newHighAlph = rHighAlph; 00042 EventSet controllableEvents; 00043 map<Transition,Idx> mapChangedTrans; 00044 Generator genDyn(rLowGen); 00045 map<Transition,Transition> mapChangedTransReverse; 00046 vector<Idx> newPartitions; 00047 map<Idx,Idx> mapStateToPartition; 00048 map<Idx, EventSet> mapRelabeledEvents; 00049 // One step of the observer algorithm: A dynamic system is computed that fulfills the one-step observer condition. 00050 // if the result is equal to the original generator, then the natural projection on the high-level alphabet fulfills the observer property 00051 calculateDynamicSystemClosedObs(rLowGen, newHighAlph, genDyn); 00052 calculateDynamicSystemObs(rLowGen, newHighAlph, genDyn); 00053 Generator genPart; 00054 // compute coarsest quasi-congruence on the dynamic system 00055 calcBisimulation(genDyn, mapStateToPartition, genPart, newPartitions); 00056 // Extend the high-level alphabet according to the algorithm of Lei 00057 ExtendHighAlphabet(rLowGen, newHighAlph, mapStateToPartition); 00058 // return the result of the event extension 00059 return newHighAlph == rHighAlph; 00060 00061 } 00062 00063 bool IsOCC(const cGenerator& rLowGen, const EventSet& rHighAlph){ 00064 OP_DF("IsOCC(" << rLowGen.Name() << "," << rHighAlph.Name() << ")"); 00065 EventSet controllableEvents = rLowGen.ControllableEvents(); 00066 // call the function that implements the algorithm 00067 return IsOCC(rLowGen, controllableEvents, rHighAlph); 00068 } 00069 00070 bool IsOCC(const Generator& rLowGen, const EventSet& rControllableEvents, const EventSet& rHighAlph){ 00071 OP_DF("IsOCC(" << rLowGen.Name() << "," << rHighAlph.Name() << ")"); 00072 //helpers: 00073 StateSet::Iterator stIt, stEndIt; 00074 stIt = rLowGen.StatesBegin(); 00075 stEndIt = rLowGen.StatesEnd(); 00076 TransSet::Iterator tIt, tEndIt; 00077 // iteration over all states of rLowGen. If there is an uncontrollable feasible high-level event, backward reachability is conducted to determine if OCC holds. 00078 for( ; stIt != stEndIt; stIt++){ 00079 tIt = rLowGen.TransRelBegin(*stIt); 00080 tEndIt = rLowGen.TransRelEnd(*stIt); 00081 for( ; tIt != tEndIt; tIt++){ 00082 if(rHighAlph.Exists(tIt->Ev) && !rControllableEvents.Exists(tIt->Ev) ){ 00083 // check if all local backward paths are uncontrollable 00084 bool uncontrollable = backwardVerificationOCC(rLowGen, rControllableEvents, rHighAlph, *stIt); 00085 // if not all paths are uncontrollable, OCC is violated 00086 if(uncontrollable == false) 00087 return false; 00088 // otherwise, go to the next state 00089 else 00090 break; 00091 } 00092 } 00093 } 00094 return true; 00095 } 00096 00097 bool backwardVerificationOCC(const Generator& rLowGen, const EventSet& rControllableEvents, const EventSet& rHighAlph, Idx currentState){ 00098 OP_DF("backwardVerificationOCC(" << rLowGen.Name() << "," << rControllableEvents.Name() << "," << rHighAlph.Name() << "," << currentState << ")"); 00099 // reverse transition relation 00100 TransSetX2EvX1 tset_X2EvX1; 00101 rLowGen.TransRel(tset_X2EvX1); 00102 TransSetX2EvX1::Iterator tsIt, tsEndIt; 00103 // todo list 00104 std::stack<Idx> todo; 00105 // algorithm: the locally backwards reachable states from current staet are 00106 // evaluated. If a controllable event is found, OCC is violated. 00107 StateSet doneStates; 00108 doneStates.Insert(currentState); 00109 todo.push(currentState); 00110 // the local reachability is evaluated until no new state is found 00111 while( !todo.empty() ){ 00112 const Idx current = todo.top(); 00113 todo.pop(); 00114 tsIt = tset_X2EvX1.BeginByX2(current); 00115 tsEndIt = tset_X2EvX1.EndByX2(current); 00116 for(; tsIt != tsEndIt; tsIt++){ 00117 // if the current transition is labeled with a high-level evnet 00118 // it is skipped 00119 if(rHighAlph.Exists(tsIt->Ev) ) 00120 continue; 00121 // if the current transition is controllable, OCC is violated 00122 else if( rControllableEvents.Exists(tsIt->Ev) ) 00123 return false; 00124 else if( !doneStates.Exists(tsIt->X1) ){ 00125 todo.push(tsIt->X1); 00126 doneStates.Insert(tsIt->X1); 00127 } 00128 } 00129 } 00130 return true; 00131 } 00132 00133 00134 bool IsLCC(const cGenerator& rLowGen, const EventSet& rHighAlph){ 00135 OP_DF("IsLCC(" << rLowGen.Name() << "," << rHighAlph.Name() << ")"); 00136 EventSet controllableEvents = rLowGen.ControllableEvents(); 00137 // call the function that implements the algorithm 00138 return IsLCC(rLowGen, controllableEvents, rHighAlph); 00139 } 00140 00141 bool IsLCC(const Generator& rLowGen, const EventSet& rControllableEvents, const EventSet& rHighAlph){ 00142 OP_DF("IsLCC(" << rLowGen.Name() << "," << rHighAlph.Name() << ")"); 00143 // reverse transition relation 00144 TransSetX2EvX1 tset_X2EvX1; 00145 rLowGen.TransRel(tset_X2EvX1); 00146 //helpers: 00147 StateSet::Iterator stIt, stEndIt; 00148 stIt = rLowGen.StatesBegin(); 00149 stEndIt = rLowGen.StatesEnd(); 00150 TransSet::Iterator tIt, tEndIt; 00151 StateSet doneStates; 00152 map<Idx, bool> localStatesMap; 00153 map<Idx, bool>::const_iterator lsIt, lsEndIt; 00154 // iteration over all states of rLowGen. If there is an uncontrollable feasible high-level event, backward reachability is conducted to determine if LCC holds. 00155 for( ; stIt != stEndIt; stIt++){ 00156 tIt = rLowGen.TransRelBegin(*stIt); 00157 tEndIt = rLowGen.TransRelEnd(*stIt); 00158 for( ; tIt != tEndIt; tIt++){ 00159 if(rHighAlph.Exists(tIt->Ev) && !rControllableEvents.Exists(tIt->Ev) ){ 00160 doneStates.Clear(); 00161 localStatesMap.clear(); 00162 localStatesMap[*stIt] = false; 00163 doneStates.Insert(*stIt); 00164 // check if for all backward reachable states, a local uncontrollable backward paths exists 00165 backwardVerificationLCC(tset_X2EvX1, rControllableEvents, rHighAlph, *stIt, *stIt, false, localStatesMap, doneStates); 00166 // if for some state, all paths are controllable, LCC is violated 00167 lsIt = localStatesMap.begin(); 00168 lsEndIt = localStatesMap.end(); 00169 for( ; lsIt != lsEndIt; lsIt++){ 00170 // if there is a state with only controllable paths, LCC is violated 00171 if(lsIt->second == true) 00172 return false; 00173 } 00174 // the evaluation for the current state is finished 00175 break; 00176 } 00177 } 00178 } 00179 return true; 00180 } 00181 00182 00183 void backwardVerificationLCC(const TransSetX2EvX1& rTransSetX2EvX1, const EventSet& rControllableEvents, const EventSet& rHighAlph, Idx exitState, Idx currentState, bool controllablePath, map<Idx, bool>& rLocalStatesMap, StateSet& rDoneStates){ 00184 OP_DF("backwardVerificationLCC(rTransSetX2EvX1," << rControllableEvents.Name() << "," << rHighAlph.Name() << "," << exitState << "," << currentState << "," << controllablePath << ",rExitLocalStatesMap, rDoneStates)"); 00185 // go along all backward transitions. Discard the goal state if it is reached via a high-level event or if it is in the rDoneStates and 00186 // the controllability properties of the state do not change on the current path 00187 00188 // helpers 00189 TransSetX2EvX1::Iterator tsIt, tsEndIt; 00190 tsIt = rTransSetX2EvX1.BeginByX2(currentState); 00191 tsEndIt = rTransSetX2EvX1.EndByX2(currentState); 00192 bool currentControllablePath; 00193 // we iterate over all backward transitions of the currentState to establish backward reachability 00194 for( ;tsIt != tsEndIt; tsIt++){ 00195 // states reachable via a high-level event are not in the local backward reach and the controllability property of the current exitState does not change 00196 if( !rHighAlph.Exists(tsIt->Ev) && tsIt->X1 != exitState){ 00197 // if the state has not been visited, yet, the controllability of the current path are set in the rExitLocalStatesMap 00198 if( !rDoneStates.Exists(tsIt->X1) ){ 00199 rDoneStates.Insert(tsIt->X1); 00200 // the path is uncontrollable if the current transition has an uncontrollable event or the path was already uncontrollable 00201 currentControllablePath = rControllableEvents.Exists(tsIt->Ev) || controllablePath; 00202 rLocalStatesMap[tsIt->X1] = currentControllablePath; 00203 // as the state has not been visited, yet, it is subject to a new backward reachability 00204 backwardVerificationLCC(rTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, tsIt->X1, currentControllablePath, rLocalStatesMap, rDoneStates); 00205 } 00206 else{ // for an existing state, the controllability value can change from controllable to uncontrollable (if 00207 // a new uncontrollable path has been found). It is important to note, that the LCC condition implies that 00208 // if there is one uncontrollable path, then the state is flagged uncontrollable except for the case of the 00209 // given exitState that is always uncontrollable 00210 currentControllablePath = rControllableEvents.Exists(tsIt->Ev) || controllablePath; 00211 if(rLocalStatesMap[tsIt->X1] != currentControllablePath && currentControllablePath == false){ 00212 rLocalStatesMap[tsIt->X1] = false; 00213 // as the controllabiity attribute of the current state changed it is subject to a new backward reachability 00214 backwardVerificationLCC(rTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, tsIt->X1, false, rLocalStatesMap, rDoneStates); 00215 } 00216 } 00217 } 00218 } 00219 } 00220 00221 00222 00223 /** 00224 * Rti convenience wrapper 00225 */ 00226 void IsObs(const cGenerator& rLowGen, const EventSet& rHighAlph, bool rRes) { 00227 rRes=IsObs(rLowGen,rHighAlph); 00228 } 00229 00230 /** 00231 * Rti convenience wrapper 00232 */ 00233 void IsLCC(const cGenerator& rLowGen, const EventSet& rHighAlph, bool rRes) { 00234 rRes=IsLCC(rLowGen,rHighAlph); 00235 } 00236 00237 00238 00239 }// namespace faudes |
libFAUDES 2.14g --- 2009-12-3 --- c++ source docu by doxygen 1.5.6