| |
libFAUDES
Sections
Index
|
op_observercomputation.cppGo to the documentation of this file.00001 /** @file op_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 Furthermore, an algorithm for computing natural observers without changing event labels as 00012 presented in 00013 Lei Feng; Wonham, W.M., "On the Computation of Natural Observers in Discrete-Event Systems," 00014 Decision and Control, 2006 45th IEEE Conference on , vol., no., pp.428-433, 13-15 Dec. 2006 00015 is implemented. 00016 */ 00017 00018 /* FAU Discrete Event Systems Library (libfaudes) 00019 00020 Copyright (C) 2006 Bernd Opitz 00021 Exclusive copyright is granted to Klaus Schmidt 00022 00023 This library is free software; you can redistribute it and/or 00024 modify it under the terms of the GNU Lesser General Public 00025 License as published by the Free Software Foundation; either 00026 version 2.1 of the License, or (at your option) any later version. 00027 00028 This library is distributed in the hope that it will be useful, 00029 but WITHOUT ANY WARRANTY; without even the implied warranty of 00030 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00031 Lesser General Public License for more details. 00032 00033 You should have received a copy of the GNU Lesser General Public 00034 License along with this library; if not, write to the Free Software 00035 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 00036 00037 #include "op_observercomputation.h" 00038 00039 using namespace std; 00040 00041 namespace faudes{ 00042 00043 00044 // calculateDynamicSystemClosedObs(rGen, rHighAlph, rGenDyn) 00045 void calculateDynamicSystemClosedObs(const vGenerator& rGen, EventSet& rHighAlph, vGenerator& rGenDyn) 00046 { 00047 OP_DF("calculateDynamicSystemClosedObs(" << rGen.Name() << "," << rHighAlph.Name() << "," << rGenDyn.Name() << ")"); 00048 // transition relation sorted in reverse order for backwards reachability 00049 TransSetX2EvX1 tset_X2EvX1; 00050 rGen.TransRel(tset_X2EvX1); 00051 00052 // prepare generator rGenDyn 00053 rGenDyn.ClearTransRel(); 00054 rGenDyn.InjectAlphabet(rHighAlph); // all high-level events are contained in the alphabet of rGenDyn 00055 rGenDyn.InjectStates(rGen.States() ); // the dynamic system has all states of rGen 00056 00057 // helpers 00058 EventSet::Iterator eIt = rGenDyn.AlphabetBegin(); 00059 EventSet::Iterator eItEnd = rGenDyn.AlphabetEnd(); 00060 00061 TransSetX2EvX1::Iterator tItByX2Ev; 00062 TransSetX2EvX1::Iterator tItByX2EvEnd; 00063 StateSet reach; 00064 // map from exit states (Idx) to high-level event (Idx) and reachable entry state (Idx) 00065 map<Idx,vector<pair<Idx,Idx> > > exitStateToEventState; 00066 StateSet::Iterator sIt; 00067 StateSet::Iterator sItEnd; 00068 TransSet::Iterator tIt; 00069 TransSet::Iterator tItEnd; 00070 map<Idx,StateSet> entryStateToLocalReach; 00071 map<Idx,vector<pair<Idx,Idx> > >::iterator esIt; 00072 map<Idx,vector<pair<Idx,Idx> > >::iterator esItEnd; 00073 // algorithm for computing the dynamic system 00074 // loop over all states of original generator 00075 StateSet::Iterator stateSetIt = rGen.StatesBegin(); 00076 StateSet::Iterator stateSetItEnd = rGen.StatesEnd(); 00077 // flag that indicates if the current state is an entry state 00078 bool isEntryState = false; 00079 for( ; stateSetIt != stateSetItEnd; ++stateSetIt) { 00080 OP_DF("calculateDynamicSystemClosedObs: loop over all states; current state: " << rGen.StateName(*stateSetIt) 00081 << " [" << *stateSetIt << "]"); 00082 // check if current state (*stateSetIt) is an entry-state (a backward transition with 00083 // a high-level event exists. If yes, the locally reachable states (reach) are stored in 00084 // the entryStateToLocalReach map 00085 isEntryState = false; 00086 tItByX2Ev=tset_X2EvX1.BeginByX2(*stateSetIt); 00087 tItByX2EvEnd=tset_X2EvX1.EndByX2(*stateSetIt); 00088 for(; tItByX2Ev != tItByX2EvEnd; ++tItByX2Ev) 00089 { 00090 OP_DF("calculateDynamicSystemClosedObs: checking transition : " << rGen.TStr(*tItByX2Ev)); 00091 if(rHighAlph.Exists(tItByX2Ev->Ev)){ 00092 isEntryState = true; 00093 OP_DF("calculateDynamicSystemClosedObs: current state is an entry-state"); 00094 // insert the exit state and the high-level event with the reachable entry state into the exitStates set 00095 esIt = exitStateToEventState.find(tItByX2Ev->X1); 00096 if(esIt == exitStateToEventState.end() ){ 00097 exitStateToEventState[tItByX2Ev->X1] = vector<pair<Idx,Idx> >(); 00098 } 00099 exitStateToEventState[tItByX2Ev->X1].push_back(make_pair(tItByX2Ev->Ev,tItByX2Ev->X2) ); 00100 } 00101 } 00102 if(isEntryState == true){ 00103 // compute locally reachable states for current entry state and insert it into entryStateToLocalReach 00104 reach.Clear(); 00105 LocalAccessibleReach(rGen, rHighAlph, *stateSetIt, reach); 00106 OP_DF("calculateDynamicSystemClosedObs: states in local reach: \n " << reach.ToString() ); 00107 entryStateToLocalReach[*stateSetIt]=reach; 00108 } 00109 } 00110 // after this loop we have the set of exit states in exitStates and a map from entry states to their 00111 // locally reachable state set entryStateToLocalReach 00112 00113 // create the transition structure of the dynamic system 00114 esIt = exitStateToEventState.begin(); 00115 esItEnd = exitStateToEventState.end(); 00116 vector<pair <Idx,Idx> >::iterator vIt; 00117 vector<pair <Idx,Idx> >::iterator vItEnd; 00118 // To construct the dynamic system, each local state has to be connected to all states in 00119 // the local accessible reach of entry states that can be reached via a high-level event. 00120 // We compute the local backward reach of each exit state and find the corresponding entry states in 00121 // the map exitStateToEventState 00122 StateSet exitStateBackwardReach; 00123 StateSet::Iterator brIt, brItEnd; 00124 map<Idx,StateSet>::const_iterator enIt; 00125 for(; esIt != esItEnd; ++esIt) 00126 { 00127 // compute the locally backwards reachable states 00128 exitStateBackwardReach.Clear(); 00129 LocalCoaccessibleReach(tset_X2EvX1, rHighAlph, esIt->first, exitStateBackwardReach); 00130 00131 vIt = esIt->second.begin(); 00132 vItEnd = esIt->second.end(); 00133 brItEnd = exitStateBackwardReach.End(); 00134 // loop over all pairs (Ev,X2) of current exit state and insert transitions from all states in the 00135 // backwards reach 00136 for( ; vIt != vItEnd; ++vIt) 00137 { 00138 brIt = exitStateBackwardReach.Begin(); 00139 // go over all backwards reachable states 00140 for( ; brIt != brItEnd; brIt++){ 00141 // find the set of reachable states from exit state 00142 enIt = entryStateToLocalReach.find(vIt->second); 00143 sIt = enIt->second.Begin(); 00144 sItEnd = enIt->second.End(); 00145 // go over all reachable states from the entry states 00146 for( ; sIt != sItEnd; sIt++){ 00147 rGenDyn.SetTransition(*brIt,vIt->first,*sIt); 00148 OP_DF("calculateDynamicSystemClosedObs: Transition added to resulting generator: " << 00149 rGenDyn.TStr(Transition(*brIt,vIt->first,*sIt))); 00150 } 00151 } 00152 } 00153 } 00154 OP_DF("calculateDynamicSystemClosedObs: leaving function"); 00155 } 00156 00157 // calculateDynamicSystemObs(rGen, rHighAlph, rGenDyn) 00158 void calculateDynamicSystemObs(const vGenerator& rGen, EventSet& rHighAlph, vGenerator& rGenDyn) 00159 { 00160 OP_DF("calculateDynamicSystemObs(" << rGen.Name() << "," << rHighAlph.Name() << "," << rGenDyn.Name() << ")"); 00161 // prepare generator rGenDyn 00162 // locally reachable states 00163 StateSet reach; 00164 StateSet::Iterator stIt, stEndIt; 00165 // label for transitions to marked states in the dynamic system 00166 std::string eventname = ( rGenDyn.EventSymbolTablep())->UniqueSymbol("obsLabel"); 00167 Idx obsLabel = (rGenDyn.EventSymbolTablep())->InsEntry(eventname); 00168 rGenDyn.InsEvent(obsLabel); 00169 // algorithm for computing the dynamic system 00170 // loop over all states of original generator 00171 StateSet::Iterator stateSetIt = rGen.StatesBegin(); 00172 StateSet::Iterator stateSetItEnd = rGen.StatesEnd(); 00173 for( ; stateSetIt != stateSetItEnd; ++stateSetIt) { 00174 OP_DF("calculateDynamicSystemObs: loop over all states; current state: " << rGen.StateName(*stateSetIt) 00175 << " [" << *stateSetIt << "]"); 00176 // compute locally reachable states for current state 00177 reach.Clear(); 00178 LocalAccessibleReach(rGen, rHighAlph, *stateSetIt, reach); 00179 OP_DF("calculateDynamicSystemObs: states in local reach: \n " << reach.ToString() ); 00180 stIt = reach.Begin(); 00181 stEndIt = reach.End(); 00182 for( ; stIt != stEndIt; stIt++){ 00183 if(rGen.ExistsMarkedState(*stIt) ){ 00184 rGenDyn.SetTransition(*stateSetIt,obsLabel,*stIt); 00185 OP_DF("calculateDynamicSystemObs: Transition added to resulting generator: " << 00186 rGenDyn.TStr(Transition(*stateSetIt,obsLabel,*stIt))); 00187 } 00188 } 00189 } 00190 OP_DF("calculateDynamicSystemObs: leaving function"); 00191 } 00192 00193 // calculateDynamicSystemMSA(rGen, rHighAlph, rGenDyn) 00194 void calculateDynamicSystemMSA(const vGenerator& rGen, EventSet& rHighAlph, vGenerator& rGenDyn) 00195 { 00196 OP_DF("calculateDynamicSystemMSA(" << rGen.Name() << "," << rHighAlph.Name() << "," << rGenDyn.Name() << ")"); 00197 // transition relation sorted in reverse order for backwards reachability 00198 TransSetX2EvX1 tset_X2EvX1; 00199 rGen.TransRel(tset_X2EvX1); 00200 00201 // prepare generator rGenDyn 00202 // set of states already investigated 00203 StateSet doneStates, goodStates; 00204 TransSet::Iterator tIt; 00205 TransSet::Iterator tEndIt; 00206 // label for transitions for msa-accepting states in the dynamic system 00207 std::string eventname = ( rGenDyn.EventSymbolTablep())->UniqueSymbol("msaLabel"); 00208 Idx msaLabel = (rGenDyn.EventSymbolTablep())->InsEntry(eventname); 00209 rGenDyn.InsEvent(msaLabel); 00210 // algorithm for computing the dynamic system 00211 // loop over all states of original generator 00212 StateSet::Iterator stateSetIt = rGen.StatesBegin(); 00213 StateSet::Iterator stateSetItEnd = rGen.StatesEnd(); 00214 // flag that indicates if the current state is an entry state 00215 for( ; stateSetIt != stateSetItEnd; ++stateSetIt) { 00216 // if the state is known to be good (msa holds), it does not have to be considered again 00217 if(goodStates.Exists(*stateSetIt) ) 00218 continue; 00219 00220 OP_DF("calculateDynamicSystemMSA: loop over all states; current state: " << rGen.StateName(*stateSetIt) 00221 << " [" << *stateSetIt << "]"); 00222 doneStates.Clear(); 00223 bool msaHolds = recursiveCheckMSAForward(rGen, rHighAlph, *stateSetIt, doneStates); 00224 // if all forward transitions lead to marked states, all states that have been reached are states where msa holds 00225 if(msaHolds == true){ 00226 goodStates.SetUnion(doneStates); 00227 continue; 00228 } 00229 doneStates.Clear(); 00230 msaHolds = recursiveCheckMSABackward(rGen, tset_X2EvX1, rHighAlph, *stateSetIt, doneStates); 00231 // if all backward transitions lead to marked states, all states that have been reached are states where msa holds 00232 if(msaHolds == true){ 00233 goodStates.SetUnion(doneStates); 00234 continue; 00235 } 00236 // otherwise, msa is violated for the current state. Then, msa-transitions are introduced to all states 00237 // reachable via a high-level event 00238 else{ 00239 tIt = rGenDyn.TransRelBegin(*stateSetIt); 00240 tEndIt = rGenDyn.TransRelEnd(*stateSetIt); 00241 for( ; tIt != tEndIt; tIt++){ 00242 rGenDyn.SetTransition(*stateSetIt,msaLabel,tIt->X2); 00243 OP_DF("calculateDynamicSystemObs: Transition added to resulting generator: " << 00244 rGenDyn.TStr(Transition(*stateSetIt,msaLabel,tIt->X2))); 00245 } 00246 } 00247 } 00248 OP_DF("calculateDynamicSystemMSA: leaving function"); 00249 } 00250 00251 bool recursiveCheckMSAForward(const vGenerator& rGen, const EventSet& rHighAlph, Idx currentState, StateSet& rDoneStates){ 00252 // if the current state is marked, no violation of MSA occurs 00253 rDoneStates.Insert(currentState); 00254 if(rGen.ExistsMarkedState(currentState) ){ 00255 return true; 00256 } 00257 TransSet::Iterator tIt, tEndIt; 00258 tIt = rGen.TransRelBegin(currentState); 00259 tEndIt = rGen.TransRelEnd(currentState); 00260 for( ; tIt != tEndIt; tIt++){ 00261 if(rHighAlph.Exists( tIt->Ev) ){ 00262 return false; 00263 } 00264 else if(rDoneStates.Exists( tIt->X2) ) 00265 continue; 00266 else{ 00267 bool msaHolds = recursiveCheckMSAForward(rGen, rHighAlph, tIt->X2, rDoneStates); 00268 if(msaHolds == false) 00269 return false; 00270 } 00271 } 00272 return true; 00273 00274 } 00275 00276 00277 bool recursiveCheckMSABackward(const vGenerator& rGen, const TransSetX2EvX1& rRevTransSet, const EventSet& rHighAlph, Idx currentState, StateSet& rDoneStates){ 00278 // if the current state is marked, no violation of MSA occurs 00279 rDoneStates.Insert(currentState); 00280 if(rGen.ExistsMarkedState(currentState) ){ 00281 return true; 00282 } 00283 TransSetX2EvX1::Iterator tIt, tEndIt; 00284 tIt = rRevTransSet.BeginByX2(currentState); 00285 tEndIt = rRevTransSet.EndByX2(currentState); 00286 for( ; tIt != tEndIt; tIt++){ 00287 if(rHighAlph.Exists( tIt->Ev) ){ 00288 return false; 00289 } 00290 else if(rDoneStates.Exists( tIt->X1) ) 00291 continue; 00292 else{ 00293 bool msaHolds = recursiveCheckMSABackward(rGen, rRevTransSet, rHighAlph, tIt->X1, rDoneStates); 00294 if(msaHolds == false) 00295 return false; 00296 } 00297 } 00298 return true; 00299 } 00300 00301 //calculateDynamicSystemLCC(rGen, rControllableEvents, rHighAlph, rGenDyn) 00302 void calculateDynamicSystemLCC(const vGenerator& rGen, const EventSet& rControllableEvents, const EventSet& rHighAlph, vGenerator& rGenDyn){ 00303 OP_DF("calculateDynamicSystemLCC(" << rGen.Name() << "," << rControllableEvents.Name() << "," << rHighAlph.Name() << "," << rGenDyn.Name() << ")"); 00304 // transition relation sorted in reverse order for backwards reachability 00305 TransSetX2EvX1 tset_X2EvX1; 00306 rGen.TransRel(tset_X2EvX1); 00307 00308 // prepare generator rGenDyn 00309 TransSet::Iterator tIt; 00310 TransSet::Iterator tEndIt; 00311 // labels for transitions for states with uncontrollable successor strings in the dynamic system 00312 // eventLCCLabel maps the original event to the LCCLabel in the dynamic system 00313 EventSet::Iterator eIt, eEndIt; 00314 map<Idx, Idx> eventLCCLabel; 00315 eIt = rHighAlph.Begin(); 00316 eEndIt = rHighAlph.End(); 00317 for( ; eIt != eEndIt; eIt++){ 00318 if(!rControllableEvents.Exists(*eIt) ){ 00319 std::string eventname = ( rGenDyn.EventSymbolTablep())->UniqueSymbol(SymbolTable::GlobalEventSymbolTablep()->Symbol(*eIt) + "LCCLabel"); 00320 eventLCCLabel[*eIt] = (rGenDyn.EventSymbolTablep())->InsEntry(eventname); 00321 rGenDyn.InsEvent(eventLCCLabel[*eIt] ); 00322 } 00323 } 00324 // map from exit states (Idx) to uncontrollable high-level events (Idx) 00325 map<Idx,vector<Idx> > exitStateToEvents; 00326 map<Idx,vector<Idx> >::const_iterator esIt, esEndIt; 00327 // algorithm for computing the dynamic system 00328 // loop over all states of original generator 00329 StateSet::Iterator sIt = rGen.StatesBegin(); 00330 StateSet::Iterator sEndIt = rGen.StatesEnd(); 00331 for( ; sIt != sEndIt; ++sIt) { 00332 OP_DF("calculateDynamicSystemLCC: loop over all states; current state: " << rGen.StateName(*sIt) 00333 << " [" << *sIt << "]"); 00334 // check if current state (*stateSetIt) is an exit-state (a forward transition with 00335 // a high-level event exists. If yes, the outgoing high-level events are stored 00336 tIt = rGen.TransRelBegin(*sIt); 00337 tEndIt = rGen.TransRelEnd(*sIt); 00338 for(; tIt != tEndIt; ++tIt) 00339 { 00340 OP_DF("calculateDynamicSystemLCC: checking transition : " << rGen.TStr(*tIt)); 00341 // if the event is an uncontrollable high-level event, it is inserted for the current exit state 00342 if(rHighAlph.Exists(tIt->Ev) && !rControllableEvents.Exists(tIt->Ev) ){ 00343 OP_DF("calculateDynamicSystemLCC: current state is an exit-state"); 00344 // insert the exit state and the high-level event into the exitStates set 00345 esIt = exitStateToEvents.find(*sIt); 00346 if(esIt == exitStateToEvents.end() ){ 00347 exitStateToEvents[*sIt] = vector<Idx>(); 00348 } 00349 exitStateToEvents[*sIt].push_back(tIt->Ev); 00350 } 00351 } 00352 } 00353 // after this loop, we have the set of exit states with their outgoing uncontrollable high-level events. 00354 // Now we compute the backwards reachable state via uncontrollable strings to determine all states where lcc holds 00355 esIt = exitStateToEvents.begin(); 00356 esEndIt = exitStateToEvents.end(); 00357 vector<Idx>::const_iterator vIt, vEndIt; 00358 // set of states already investigated 00359 StateSet doneStates; 00360 for( ; esIt != esEndIt; esIt++){ 00361 doneStates.Clear(); 00362 recursiveCheckLCC(tset_X2EvX1, rControllableEvents, rHighAlph, esIt->first, doneStates); 00363 // add the uncontrollable transition labels to all states found in the backward reachability 00364 // transitions are introduced to all states that are reachable via strings including one high-level event 00365 vIt = esIt->second.begin(); 00366 vEndIt = esIt->second.end(); 00367 // loop over all uncontrollable high-level events in the current exit state 00368 for( ; vIt != vEndIt; vIt++){ 00369 sIt = doneStates.Begin(); 00370 sEndIt = doneStates.End(); 00371 // loop over all backward reachable states 00372 for( ; sIt != sEndIt; sIt++){ 00373 TransSet::Iterator dsIt, dsEndIt; 00374 dsIt = rGenDyn.TransRelBegin(*sIt); 00375 dsEndIt = rGenDyn.TransRelEnd(*sIt); 00376 // loop over all states reachable via strings with one high-level event (these states are already encoded 00377 // in rGenDyn if calculateDynamicSystemClosedObs is called before calculateDynamicSystemLCC) 00378 for( ; dsIt != dsEndIt; dsIt++){ 00379 rGenDyn.SetTransition(*sIt, eventLCCLabel[*vIt], dsIt->X2); 00380 } 00381 } 00382 } 00383 } 00384 } 00385 00386 void recursiveCheckLCC(const TransSetX2EvX1& rRevTransSet, const EventSet& rControllableEvents, const EventSet& rHighAlph, Idx currentState, StateSet& rDoneStates){ 00387 // insert the current state into the backward reachable states via uncontrollable strings 00388 rDoneStates.Insert(currentState); 00389 // helpers 00390 TransSetX2EvX1::Iterator tIt, tEndIt; 00391 tIt = rRevTransSet.BeginByX2(currentState); 00392 tEndIt = rRevTransSet.EndByX2(currentState); 00393 // loop over all outgoing transitions in the current state 00394 for( ; tIt != tEndIt; tIt++){ 00395 // if the transition is a high-level transition, we stop the backward reachability 00396 if(rHighAlph.Exists(tIt->Ev) ){ 00397 // if the transition is uncontrollable, an uncontrollable string has been found -> LCC is fulfilled 00398 continue; 00399 } 00400 // if the event is an uncontrollable low-level event, we go backward along uncontrollable transitions 00401 else{ 00402 if(!rControllableEvents.Exists(tIt->Ev) && !rDoneStates.Exists(tIt->X1) ){ 00403 recursiveCheckLCC(rRevTransSet,rControllableEvents,rHighAlph,tIt->X1,rDoneStates); 00404 } 00405 } 00406 } 00407 // the end of the loop is reached, if no more uncontrollable event has been found from the current state 00408 } 00409 00410 00411 // calcClosedObserver(rGen,rHighAlph) 00412 Idx calcClosedObserver(const vGenerator& rGen, EventSet& rHighAlph){ 00413 // helpers 00414 Generator dynGen; 00415 map<Idx,Idx> mapStateToPartition; 00416 vector<Idx> newPartitions; 00417 EventSet origAlph; 00418 Generator genPart; 00419 while(origAlph != rHighAlph){ 00420 origAlph = rHighAlph; 00421 dynGen.Clear(); 00422 // compute the dynamic system for the given generator and high-level alphabet 00423 calculateDynamicSystemClosedObs(rGen, rHighAlph, dynGen); 00424 // compute the quasi conqruence 00425 mapStateToPartition.clear(); 00426 newPartitions.clear(); 00427 genPart.Clear(); 00428 calcBisimulation(dynGen, mapStateToPartition, genPart, newPartitions); 00429 // Extend the high-level alphabet according to the algorithm of Lei 00430 ExtendHighAlphabet(rGen, rHighAlph, mapStateToPartition); 00431 } 00432 return genPart.Size(); 00433 } 00434 00435 // calcNaturalObserver(rGen,rHighAlph) 00436 Idx calcNaturalObserver(const vGenerator& rGen, EventSet& rHighAlph){ 00437 // helpers 00438 Generator dynGen; 00439 map<Idx,Idx> mapStateToPartition; 00440 vector<Idx> newPartitions; 00441 EventSet origAlph; 00442 Generator genPart; 00443 while(origAlph != rHighAlph){ 00444 origAlph = rHighAlph; 00445 dynGen.Clear(); 00446 // compute the dynamic system for the given generator and high-level alphabet 00447 calculateDynamicSystemClosedObs(rGen, rHighAlph, dynGen); 00448 calculateDynamicSystemObs(rGen, rHighAlph, dynGen); 00449 // compute the quasi conqruence 00450 mapStateToPartition.clear(); 00451 newPartitions.clear(); 00452 genPart.Clear(); 00453 calcBisimulation(dynGen, mapStateToPartition, genPart, newPartitions); 00454 // Extend the high-level alphabet according to the algorithm of Lei 00455 ExtendHighAlphabet(rGen, rHighAlph, mapStateToPartition); 00456 } 00457 return genPart.Size(); 00458 } 00459 00460 // calcNaturalObserverLCC(rGen,rHighAlph) 00461 Idx calcNaturalObserverLCC(const vGenerator& rGen, const EventSet& rControllableEvents, EventSet& rHighAlph){ 00462 // helpers 00463 Generator dynGen; 00464 map<Idx,Idx> mapStateToPartition; 00465 vector<Idx> newPartitions; 00466 EventSet origAlph; 00467 Generator genPart; 00468 while(origAlph != rHighAlph){ 00469 origAlph = rHighAlph; 00470 dynGen.Clear(); 00471 // compute the dynamic system for the given generator and high-level alphabet 00472 calculateDynamicSystemClosedObs(rGen, rHighAlph, dynGen); 00473 calculateDynamicSystemLCC(rGen, rControllableEvents, rHighAlph, dynGen); 00474 calculateDynamicSystemObs(rGen, rHighAlph, dynGen); 00475 // compute the quasi conqruence 00476 mapStateToPartition.clear(); 00477 newPartitions.clear(); 00478 genPart.Clear(); 00479 calcBisimulation(dynGen, mapStateToPartition, genPart, newPartitions); 00480 // Extend the high-level alphabet according to the algorithm of Lei 00481 ExtendHighAlphabet(rGen, rHighAlph, mapStateToPartition); 00482 } 00483 return genPart.Size(); 00484 } 00485 00486 // calcMSAObserver(rGen,rHighAlph) 00487 Idx calcMSAObserver(const vGenerator& rGen, EventSet& rHighAlph){ 00488 // helpers 00489 Generator dynGen; 00490 map<Idx,Idx> mapStateToPartition; 00491 vector<Idx> newPartitions; 00492 EventSet origAlph; 00493 Generator genPart; 00494 while(origAlph != rHighAlph){ 00495 origAlph = rHighAlph; 00496 dynGen.Clear(); 00497 // compute the dynamic system for the given generator and high-level alphabet 00498 calculateDynamicSystemClosedObs(rGen, rHighAlph, dynGen); 00499 calculateDynamicSystemMSA(rGen, rHighAlph, dynGen); 00500 // compute the quasi conqruence 00501 mapStateToPartition.clear(); 00502 newPartitions.clear(); 00503 genPart.Clear(); 00504 calcBisimulation(dynGen, mapStateToPartition, genPart, newPartitions); 00505 // Extend the high-level alphabet according to the algorithm of Lei 00506 ExtendHighAlphabet(rGen, rHighAlph, mapStateToPartition); 00507 } 00508 return genPart.Size(); 00509 } 00510 00511 // calcMSAObserverLCC(rGen,rHighAlph) 00512 Idx calcMSAObserverLCC(const vGenerator& rGen, const EventSet& rControllableEvents, EventSet& rHighAlph){ 00513 // helpers 00514 Generator dynGen; 00515 map<Idx,Idx> mapStateToPartition; 00516 vector<Idx> newPartitions; 00517 EventSet origAlph; 00518 Generator genPart; 00519 while(origAlph != rHighAlph){ 00520 origAlph = rHighAlph; 00521 dynGen.Clear(); 00522 // compute the dynamic system for the given generator and high-level alphabet 00523 calculateDynamicSystemClosedObs(rGen, rHighAlph, dynGen); 00524 calculateDynamicSystemLCC(rGen, rControllableEvents, rHighAlph, dynGen); 00525 calculateDynamicSystemMSA(rGen, rHighAlph, dynGen); 00526 // compute the quasi conqruence 00527 mapStateToPartition.clear(); 00528 newPartitions.clear(); 00529 genPart.Clear(); 00530 calcBisimulation(dynGen, mapStateToPartition, genPart, newPartitions); 00531 // Extend the high-level alphabet according to the algorithm of Lei 00532 ExtendHighAlphabet(rGen, rHighAlph, mapStateToPartition); 00533 } 00534 return genPart.Size(); 00535 } 00536 00537 // ExtendHighAlphabet(rGen,rHighAlph,rMapStateToPartition) 00538 void ExtendHighAlphabet(const vGenerator& rGen, EventSet& rHighAlph, map<Idx,Idx>& rMapStateToPartition){ 00539 00540 OP_DF("relabel(" << rGenRelabel.Name() << "," << rControllableEvents.Name() << "," << rHighAlph.Name() << ", rNewPartition, rMapStateToPartition, rMapChangedTransReverse, rMapChangedTrans, rMapRelabeledEvents)"); 00541 00542 // helpers 00543 map<Idx,Idx>::const_iterator spIt, spEndIt; 00544 spIt = rMapStateToPartition.begin(); 00545 spEndIt = rMapStateToPartition.end(); 00546 // Determine map from Partition to states from the rMapStateToPartition 00547 map<Idx,StateSet> partitionToStateMap; 00548 map<Idx,StateSet>::iterator fIt, fEndIt; 00549 for( ; spIt != spEndIt; spIt++){ 00550 fIt = partitionToStateMap.find(spIt->second); 00551 if(fIt == partitionToStateMap.end() ){ 00552 partitionToStateMap[spIt->second] = StateSet(); 00553 } 00554 partitionToStateMap[spIt->second].Insert(spIt->first); 00555 00556 } 00557 // Go through all cosets 00558 fIt = partitionToStateMap.begin(); 00559 fEndIt = partitionToStateMap.end(); 00560 for( ; fIt != fEndIt; fIt++){ 00561 // Current Coset 00562 Idx currentCoset = fIt->first; 00563 // Examine all states of the current coset 00564 StateSet::Iterator stIt, stEndIt; 00565 stIt = fIt->second.Begin(); 00566 stEndIt = fIt->second.End(); 00567 // map from event to exit states and goal cosets 00568 map<Idx,pair<StateSet,IndexSet> > eventStatesMap; 00569 // local events that lead to a different coset 00570 EventSet localViolatingEvents; 00571 // local events that appear inside the current coset 00572 EventSet localEvents; 00573 for( ; stIt != stEndIt; stIt++){ 00574 TransSet::Iterator tIt, tEndIt; 00575 tIt = rGen.TransRelBegin(*stIt); 00576 tEndIt = rGen.TransRelEnd(*stIt); 00577 for( ; tIt != tEndIt; tIt++){ 00578 // local event 00579 if(!rHighAlph.Exists(tIt->Ev) ){ 00580 // unobservable transition to other coset 00581 if(rMapStateToPartition[tIt->X2] != currentCoset){ 00582 localViolatingEvents.Insert(tIt->Ev); 00583 localEvents.Erase(tIt->Ev); 00584 } 00585 else{ 00586 if(!localViolatingEvents.Exists(tIt->Ev) ) 00587 localEvents.Insert(tIt->Ev); 00588 } 00589 } 00590 // high-level event 00591 else{ 00592 eventStatesMap[tIt->Ev].first.Insert(*stIt); 00593 eventStatesMap[tIt->Ev].second.Insert(rMapStateToPartition[tIt->X2]); 00594 } 00595 } 00596 } 00597 // All outgoing transitions for the current coset are determined. Now, the localViolatingEvents are added 00598 // to the high-level alphabet, and the remaining nondeterministic transitions are found 00599 rHighAlph = rHighAlph + localViolatingEvents; 00600 map<Idx,pair<StateSet,IndexSet> >::const_iterator seIt, seEndIt; 00601 seIt = eventStatesMap.begin(); 00602 seEndIt = eventStatesMap.end(); 00603 // vector for the nondeterministic exit states 00604 vector<pair<StateSet, Idx> > nondeterministicStates; 00605 for( ; seIt != seEndIt; seIt ++){ 00606 // if there is more than one goal coset, the current event introduces nondeterminism 00607 if(seIt->second.second.Size() > 1){ 00608 nondeterministicStates.push_back(make_pair(StateSet(),0) ); 00609 nondeterministicStates.back().first = seIt->second.first; 00610 nondeterministicStates.back().second = seIt->first; 00611 } 00612 } 00613 // Now, all combinations with nondeterministic exit states have to be checked 00614 rHighAlph = rHighAlph + localEvents; 00615 EventSet::Iterator eIt, eEndIt; 00616 eIt = localEvents.Begin(); 00617 eEndIt = localEvents.End(); 00618 // check which local events can be removed from the high-level alphabet 00619 for( ; eIt != eEndIt; eIt++){ 00620 rHighAlph.Erase(*eIt); 00621 // go through all states of the current coset and check if rHighAlph splits the coset 00622 stIt = fIt->second.Begin(); 00623 for( ; stIt != stEndIt; stIt++){ 00624 // if the rHighAlph does not split the coset, the current event cannot be removed 00625 if(!CheckSplit(rGen, rHighAlph, nondeterministicStates, *stIt) ){ 00626 rHighAlph.Insert(*eIt); 00627 break; 00628 } 00629 } 00630 } 00631 } 00632 } 00633 00634 00635 // CheckSplit(rGen,rSplitAlphabet,rNondeterministicStates,entryState) 00636 bool CheckSplit(const Generator& rGen, const EventSet& rSplitAlphabet, const vector<pair<StateSet, Idx> >& rNondeterministicStates, Idx entryState){ 00637 StateSet accessibleReach; 00638 // compute the local accessible reach for the current entry state 00639 LocalAccessibleReach(rGen, rSplitAlphabet, entryState, accessibleReach); 00640 // check if for any of the nondeterministic state sets, more than one state appears in the local accessible reach 00641 vector<pair<StateSet, Idx> >::const_iterator vsIt, vsEndIt; 00642 vsIt = rNondeterministicStates.begin(); 00643 vsEndIt = rNondeterministicStates.end(); 00644 bool split = true; 00645 for( ; vsIt != vsEndIt; vsIt++){ 00646 StateSet nondetExit = vsIt->first * accessibleReach; 00647 StateSet::Iterator stIt, stEndIt; 00648 stIt = nondetExit.Begin(); 00649 stEndIt = nondetExit.End(); 00650 StateSet nondetReach; 00651 // collect the goal states of the nondeterministic exit states 00652 for( ; stIt != stEndIt; stIt++){ 00653 nondetReach.Insert(rGen.TransRelBegin(*stIt, vsIt->second)->X2); 00654 } 00655 if( nondetReach.Size() > 1){ 00656 split = false; 00657 break; 00658 } 00659 } 00660 return split; 00661 } 00662 00663 // ================================================================================== 00664 // Functions for the computation of the high-level alphabet with relabeling 00665 // ================================================================================== 00666 00667 00668 // calcAbstAlphClosed(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents) 00669 void calcAbstAlphClosed(cGenerator& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) { 00670 OP_DF("calcAbstAlphClosed(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)"); 00671 // The controllable events are separated from the cGenerator. All functions that are successively 00672 // called, are defined for vGenerators 00673 EventSet cntrevs = rGenObs.ControllableEvents(); 00674 calcAbstAlphClosed(rGenObs, cntrevs , rHighAlph, rNewHighAlph, rMapRelabeledEvents); 00675 // the controllable events that have been changed by the called function are set in the cGenerator cGenObs 00676 rGenObs.SetControllable(cntrevs); 00677 } 00678 00679 // calcAbstAlphClosed(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents) 00680 void calcAbstAlphClosed(vGenerator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) { 00681 OP_DF("calcAbstAlphClosed(" << rGenObs.Name() << "," << "rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)"); 00682 // The function called next returns a relabeled generator and a map of relabeled transitions 00683 map<Transition,Idx> changedtrans; 00684 calcAbstAlphClosed(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans); 00685 // for later use, the relabeled transitions are converted into relabeled events 00686 // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty 00687 map<Transition,Idx>::iterator rtEndIt = changedtrans.end(); 00688 map<Transition,Idx>::iterator rtIt = changedtrans.begin(); 00689 for(; rtIt != rtEndIt; rtIt++){ 00690 if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){// if the event does not exist, yet, a nex element in the map is created 00691 rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>(); 00692 if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist 00693 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second); 00694 } 00695 else { // a new label is inserted into the map 00696 if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist 00697 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second); 00698 } 00699 } 00700 } 00701 00702 // calcAbstAlphClosed(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans) 00703 void calcAbstAlphClosed(vGenerator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans) 00704 { 00705 OP_DF("calcAbstAlphClosed(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)"); 00706 // Initialization of variables 00707 rNewHighAlph = rHighAlph; 00708 rMapChangedTrans.clear(); 00709 Generator genDyn(rGenObs); 00710 map<Transition,Transition> mapChangedTransReverse; 00711 vector<Idx> newPartitions; 00712 map<Idx,Idx> mapStateToPartition; 00713 map<Idx, EventSet> mapRelabeledEvents; 00714 bool done=false; 00715 #ifdef DF_PLOT 00716 Idx iterationCount=1; 00717 string name; 00718 #endif 00719 // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition. 00720 // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs 00721 // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition. 00722 while(done==false) 00723 { 00724 // compute the dynamic system for the given generator and high-level alphabet 00725 calculateDynamicSystemClosedObs(rGenObs, rNewHighAlph, genDyn); 00726 #ifdef DF_PLOT 00727 name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToString(iterationCount)); 00728 genDyn.DotWrite(name); 00729 #endif 00730 00731 Generator genPart; 00732 mapStateToPartition.clear(); 00733 newPartitions.clear(); 00734 00735 // compute coarsest quasi-congruence on the dynamic system 00736 calcBisimulation(genDyn, mapStateToPartition, genPart, newPartitions); 00737 #ifdef DF_PLOT 00738 name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToString(iterationCount)); 00739 genPart.DotWrite(name); 00740 ++iterationCount; 00741 #endif 00742 00743 // check if quotient automaton is deterministic and free of unobservable events 00744 // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly 00745 done=relabel(rGenObs, rControllableEvents, rNewHighAlph, newPartitions, mapStateToPartition, mapChangedTransReverse, rMapChangedTrans, mapRelabeledEvents); 00746 } 00747 } 00748 00749 00750 // calcAbstAlphObs(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents) 00751 void calcAbstAlphObs(cGenerator& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) { 00752 OP_DF("calcAbstAlphObs(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)"); 00753 // The controllable events are separated from the cGenerator. All functions that are successively 00754 // called, are defined for vGenerators 00755 EventSet cntrevs = rGenObs.ControllableEvents(); 00756 calcAbstAlphObs(rGenObs, cntrevs , rHighAlph, rNewHighAlph, rMapRelabeledEvents); 00757 // the controllable events that have been changed by the called function are set in the cGenerator cGenObs 00758 rGenObs.SetControllable(cntrevs); 00759 } 00760 00761 // calcAbstAlphObs(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents) 00762 void calcAbstAlphObs(vGenerator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) { 00763 OP_DF("calcAbstAlphObs(" << rGenObs.Name() << "," << "rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)"); 00764 // The function called next returns a relabeled generator and a map of relabeled transitions 00765 map<Transition,Idx> changedtrans; 00766 calcAbstAlphObs(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans); 00767 // for later use, the relabeled transitions are converted into relabeled events 00768 // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty 00769 map<Transition,Idx>::iterator rtEndIt = changedtrans.end(); 00770 map<Transition,Idx>::iterator rtIt = changedtrans.begin(); 00771 for(; rtIt != rtEndIt; rtIt++){ 00772 if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){// if the event does not exist, yet, a nex element in the map is created 00773 rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>(); 00774 if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist 00775 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second); 00776 } 00777 else { // a new label is inserted into the map 00778 if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist 00779 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second); 00780 } 00781 } 00782 } 00783 00784 // calcAbstAlphObs(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans) 00785 void calcAbstAlphObs(vGenerator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans) 00786 { 00787 OP_DF("calcAbstAlphObs(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)"); 00788 // Initialization of variables 00789 rNewHighAlph = rHighAlph; 00790 rMapChangedTrans.clear(); 00791 Generator genDyn(rGenObs); 00792 map<Transition,Transition> mapChangedTransReverse; 00793 vector<Idx> newPartitions; 00794 map<Idx,Idx> mapStateToPartition; 00795 map<Idx, EventSet> mapRelabeledEvents; 00796 bool done=false; 00797 #ifdef DF_PLOT 00798 Idx iterationCount=1; 00799 string name; 00800 #endif 00801 // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition. 00802 // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs 00803 // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition. 00804 while(done==false) 00805 { 00806 // compute the dynamic system for the given generator and high-level alphabet 00807 calculateDynamicSystemClosedObs(rGenObs, rNewHighAlph, genDyn); 00808 calculateDynamicSystemObs(rGenObs, rNewHighAlph, genDyn); 00809 #ifdef DF_PLOT 00810 name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToString(iterationCount)); 00811 genDyn.DotWrite(name); 00812 #endif 00813 00814 Generator genPart; 00815 mapStateToPartition.clear(); 00816 newPartitions.clear(); 00817 00818 // compute coarsest quasi-congruence on the dynamic system 00819 calcBisimulation(genDyn, mapStateToPartition, genPart, newPartitions); 00820 #ifdef DF_PLOT 00821 name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToString(iterationCount)); 00822 genPart.DotWrite(name); 00823 ++iterationCount; 00824 #endif 00825 00826 // check if quotient automaton is deterministic and free of unobservable events 00827 // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly 00828 done=relabel(rGenObs, rControllableEvents, rNewHighAlph, newPartitions, mapStateToPartition, mapChangedTransReverse, rMapChangedTrans, mapRelabeledEvents); 00829 } 00830 } 00831 00832 00833 // calcAbstAlphMSA(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents) 00834 void calcAbstAlphMSA(cGenerator& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) { 00835 OP_DF("calcAbstAlphMSA(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)"); 00836 // The controllable events are separated from the cGenerator. All functions that are successively 00837 // called, are defined for vGenerators 00838 EventSet cntrevs = rGenObs.ControllableEvents(); 00839 calcAbstAlphMSA(rGenObs, cntrevs , rHighAlph, rNewHighAlph, rMapRelabeledEvents); 00840 // the controllable events that have been changed by the called function are set in the cGenerator cGenObs 00841 rGenObs.SetControllable(cntrevs); 00842 } 00843 00844 // calcAbstAlphMSA(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents) 00845 void calcAbstAlphMSA(vGenerator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) { 00846 OP_DF("calcAbstAlphMSA(" << rGenObs.Name() << "," << "rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)"); 00847 // The function called next returns a relabeled generator and a map of relabeled transitions 00848 map<Transition,Idx> changedtrans; 00849 calcAbstAlphMSA(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans); 00850 // for later use, the relabeled transitions are converted into relabeled events 00851 // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty 00852 map<Transition,Idx>::iterator rtEndIt = changedtrans.end(); 00853 map<Transition,Idx>::iterator rtIt = changedtrans.begin(); 00854 for(; rtIt != rtEndIt; rtIt++){ 00855 if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){// if the event does not exist, yet, a nex element in the map is created 00856 rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>(); 00857 if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist 00858 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second); 00859 } 00860 else { // a new label is inserted into the map 00861 if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist 00862 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second); 00863 } 00864 } 00865 } 00866 00867 // calcAbstAlphMSA(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans) 00868 void calcAbstAlphMSA(vGenerator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans) 00869 { 00870 OP_DF("calcAbstAlphMSA(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)"); 00871 // Initialization of variables 00872 rNewHighAlph = rHighAlph; 00873 rMapChangedTrans.clear(); 00874 Generator genDyn(rGenObs); 00875 map<Transition,Transition> mapChangedTransReverse; 00876 vector<Idx> newPartitions; 00877 map<Idx,Idx> mapStateToPartition; 00878 map<Idx, EventSet> mapRelabeledEvents; 00879 bool done=false; 00880 #ifdef DF_PLOT 00881 Idx iterationCount=1; 00882 string name; 00883 #endif 00884 // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition. 00885 // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs 00886 // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition. 00887 while(done==false) 00888 { 00889 // compute the dynamic system for the given generator and high-level alphabet 00890 calculateDynamicSystemClosedObs(rGenObs, rNewHighAlph, genDyn); 00891 calculateDynamicSystemMSA(rGenObs, rNewHighAlph, genDyn); 00892 #ifdef DF_PLOT 00893 name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToString(iterationCount)); 00894 genDyn.DotWrite(name); 00895 #endif 00896 00897 Generator genPart; 00898 mapStateToPartition.clear(); 00899 newPartitions.clear(); 00900 00901 // compute coarsest quasi-congruence on the dynamic system 00902 calcBisimulation(genDyn, mapStateToPartition, genPart, newPartitions); 00903 #ifdef DF_PLOT 00904 name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToString(iterationCount)); 00905 genPart.DotWrite(name); 00906 ++iterationCount; 00907 #endif 00908 00909 // check if quotient automaton is deterministic and free of unobservable events 00910 // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly 00911 done=relabel(rGenObs, rControllableEvents, rNewHighAlph, newPartitions, mapStateToPartition, mapChangedTransReverse, rMapChangedTrans, mapRelabeledEvents); 00912 } 00913 } 00914 00915 00916 // // calcAbstAlphObsOCC(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents) 00917 // void calcAbstAlphObsOCC(cGenerator& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents){ 00918 // OP_DF("calcAbstAlphObsOCC(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)"); 00919 // // The controllable events are separated from the cGenerator. All functions that are successively 00920 // // called, are defined for vGenerators 00921 // map<Transition,Idx> changedtrans; 00922 // EventSet rControllableEvents = rGenObs.ControllableEvents(); 00923 // // The function called next returns a relabeled generator and a map of relabeled transitions 00924 // calcAbstAlphObsOCC(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans); 00925 // // for later use, the relabeled transitions are converted into relabeled events 00926 // // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty 00927 // map<Transition,Idx>::iterator rtEndIt = changedtrans.end(); 00928 // map<Transition,Idx>::iterator rtIt = changedtrans.begin(); 00929 // for(; rtIt != rtEndIt; rtIt++){ 00930 // if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){ 00931 // rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>(); 00932 // if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist 00933 // rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second); 00934 // } else { 00935 // if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist 00936 // rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second); 00937 // } 00938 // } 00939 // // the controllable events that have been changed by the called function are set in the cGenerator cGenObs 00940 // rGenObs.SetControllable(rControllableEvents); 00941 // } 00942 00943 // // calcAbstAlphObsOCC(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans) 00944 // void calcAbstAlphObsOCC(vGenerator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans) 00945 // { 00946 // OP_DF("calcAbstAlphObsOCC(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)"); 00947 // // Initialization of variables 00948 // rNewHighAlph = rHighAlph; 00949 // rMapChangedTrans.clear(); 00950 // Generator genDyn(rGenObs); 00951 // map<Transition,Transition> mapChangedTransReverse; 00952 // vector<Idx> newPartitions; 00953 // map<Idx,Idx> mapStateToPartition; 00954 // map<Idx, EventSet> mapRelabeledEvents; 00955 // bool done=false; 00956 // #ifdef DF_PLOT 00957 // Idx iterationCount=1; 00958 // string name; 00959 // #endif 00960 // // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition 00961 // // and output control consistency (OCC). 00962 // // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs 00963 // // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition and OCC. 00964 // while(done==false) 00965 // { 00966 // // compute dynamic system for Lm-observer and OCC on rGenObs 00967 // calculateDynamicSystemObsOCC(rGenObs, rControllableEvents, rNewHighAlph, genDyn); 00968 // #ifdef DF_PLOT 00969 // name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToString(iterationCount)); 00970 // genDyn.DotWrite(name); 00971 // #endif 00972 // 00973 // Generator genPart; 00974 // mapStateToPartition.clear(); 00975 // newPartitions.clear(); 00976 // // compute coarsest quasi-congruence on the dynamic system 00977 // calcBisimulation(genDyn, mapStateToPartition, genPart, newPartitions); 00978 // #ifdef DF_PLOT 00979 // name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToString(iterationCount)); 00980 // genPart.DotWrite(name); 00981 // ++iterationCount; 00982 // #endif 00983 // 00984 // // check if quotient automaton is deterministic and free of unobservable events 00985 // // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly 00986 // done=relabel(rGenObs, rControllableEvents, rNewHighAlph, newPartitions, mapStateToPartition, mapChangedTransReverse, rMapChangedTrans, mapRelabeledEvents); 00987 // } 00988 // } 00989 /* 00990 // calculateDynamicSystemObsOCC(rGen, rControllableEvents, rHighAlph, rGenDyn) 00991 void calculateDynamicSystemObsOCC(const vGenerator& rGen, EventSet& rControllableEvents, EventSet& rHighAlph, vGenerator& rGenDyn){ 00992 OP_DF("calculateDynamicSystemObsOCC(" << rGen.Name() << "," << rControllableEvents.Name() << "," << rHighAlph.Name() << "," << rGenDyn.Name() << ")"); 00993 // transition relation sorted in reverse order for backwards reachability 00994 TransSetX2EvX1 tset_X2EvX1; 00995 rGen.TransRel(tset_X2EvX1); 00996 00997 // prepare generator rGenDyn 00998 rGenDyn.ClearTransRel(); 00999 rGenDyn.InjectAlphabet(rHighAlph); // all high-level events are contained in the alphabet of rGenDyn 01000 // labels for transitions to marked states and for controllable paths 01001 std::string eventname = ( rGenDyn.EventSymbolTablep())->UniqueSymbol("cLabel_1"); 01002 Idx cLabel = (rGenDyn.EventSymbolTablep())->InsEntry(eventname); 01003 eventname = ( rGenDyn.EventSymbolTablep())->UniqueSymbol("mLabel_1"); 01004 Idx mLabel = (rGenDyn.EventSymbolTablep())->InsEntry(eventname); 01005 rGenDyn.InsEvent(cLabel); 01006 rGenDyn.InsEvent(mLabel); 01007 rGenDyn.InjectInitStates(rGen.InitStates() ); 01008 rGenDyn.InjectStates(rGen.States() ); 01009 rGenDyn.InjectMarkedStates(rGen.MarkedStates() ); 01010 01011 // maps for the construction of the dynamic system 01012 map<Idx, map<Idx, bool> > exitLocalStatesMap; // map from each exit state to locally backward reachable states and a boolean that is false if there exists an uncontrollable path to the exit state 01013 map<Idx, StateSet> entryLocalStatesMap; // map from entry states to locally forward reachable states 01014 StateSet::Iterator stIt, stEndIt; 01015 stIt = rGen.StatesBegin(); 01016 stEndIt = rGen.StatesEnd(); 01017 TransSet::Iterator tsIt, tsEndIt; 01018 bool isExitState; 01019 // go through all states of the original generator 01020 for(; stIt != stEndIt; stIt++){ 01021 OP_DF("calculateDynamicSystemObsOCC: loop over all states; current state: " << rGen.StateName(*stIt) 01022 << " [" << *stIt << "]"); 01023 // determine the marked states that are locally reachable from the current state and insert 01024 // transitions labeled with mLabel in rGenDyn 01025 forwardReachabilityObs(rGen, rHighAlph, *stIt, mLabel, rGenDyn); 01026 // if the current state is an exit state, carry out the backward reachability to determine 01027 // which states can be reached on a controllable/uncontrollable path -> store in exitLocalStatesMap 01028 // in this case, also determine the corresponding entry states and compute their locally reachable states 01029 // for the entryLocalStatesMap 01030 tsIt = rGen.TransRelBegin(*stIt); 01031 tsEndIt = rGen.TransRelEnd(*stIt); 01032 isExitState = false; 01033 for( ; tsIt != tsEndIt; tsIt++){ 01034 if(rHighAlph.Exists(tsIt->Ev) ){ 01035 OP_DF("calculateDynamicSystemObsOCC: current state is an exit-state"); 01036 isExitState = true; 01037 // if the local reach for the connected entry state has not been computed, yet, insert it in the 01038 // entryLocalStatesMap 01039 if( entryLocalStatesMap.find(tsIt->X2) == entryLocalStatesMap.end() ){ 01040 entryLocalStatesMap[tsIt->X2] = StateSet(); 01041 LocalAccessibleReach(rGen,rHighAlph, tsIt->X2, entryLocalStatesMap[tsIt->X2]); 01042 } 01043 } 01044 } 01045 // if the current state is an exit state, compute the backward local reach with the controllability properties of the 01046 // paths to locally backward reachable states 01047 if(isExitState == true){ 01048 StateSet doneStates; 01049 exitLocalStatesMap[*stIt][*stIt] = false; // the exit state is reachable from the exit state via an uncontrollable path 01050 doneStates.Insert(*stIt); 01051 backwardReachabilityObsOCC(tset_X2EvX1, rControllableEvents, rHighAlph, *stIt, *stIt, false, exitLocalStatesMap, doneStates); 01052 01053 } 01054 01055 } 01056 // the generator rGenDyn is constructed by connecting all exit and entry states with their local state sets 01057 map<Idx, map<Idx, bool> >::const_iterator elIt, elEndIt; 01058 elIt = exitLocalStatesMap.begin(); 01059 elEndIt = exitLocalStatesMap.end(); 01060 map<Idx,bool>::const_iterator lcIt, lcEndIt; 01061 StateSet::Iterator exIt, exEndIt; 01062 map<Idx,StateSet>::const_iterator enIt; 01063 01064 for( ; elIt != elEndIt; elIt++){ 01065 lcEndIt = elIt->second.end(); 01066 // go over all entry states reachable from the current exit state (via all feasible high-level events) 01067 tsIt = rGen.TransRel().Begin(elIt->first); 01068 tsEndIt = rGen.TransRel().End(elIt->first); 01069 for( ; tsIt != tsEndIt; tsIt++){ 01070 OP_DF("calculateDynamicSystemObsOCC: insert transitions for the high-level event" << rGen.EventName(tsIt->Ev) << "[" << tsIt->Ev << "]"); 01071 if(rHighAlph.Exists(tsIt->Ev) ){ 01072 bool controllable = rControllableEvents.Exists(tsIt->Ev); 01073 enIt = entryLocalStatesMap.find(tsIt->X2); 01074 stEndIt = enIt->second.End(); 01075 // iterate over all locally backward reachable states from current exit state 01076 for(lcIt = elIt->second.begin(); lcIt != lcEndIt; lcIt ++){ 01077 // iterate over all locally forward reachable states from current entry state 01078 for( stIt = enIt->second.Begin(); stIt != stEndIt; stIt++){ 01079 OP_DF("calculateDynamicSystemObsOCC: Transition added to resulting generator: " << 01080 rGenDyn.TStr(Transition(lcIt->first,tsIt->Ev,*stIt))); 01081 01082 rGenDyn.SetTransition(lcIt->first,tsIt->Ev,*stIt); // insert a transition for each local state combination 01083 if( controllable || lcIt->second ){ // insert an clabel transition if the local path is controllable or the high-level event is controllable 01084 OP_DF("calculateDynamicSystemObsOCC: cLabel-Transition added to resulting generator: " << 01085 rGenDyn.TStr(Transition(lcIt->first,cLabel,*stIt))); 01086 01087 rGenDyn.SetTransition(lcIt->first,cLabel,*stIt); 01088 } 01089 } 01090 } 01091 } 01092 } 01093 } 01094 } 01095 01096 // forwardReachabilityObs(rGen, rHighAlph, lowState, mLabel, rGenDyn) 01097 void forwardReachabilityObs(const vGenerator& rGen, const EventSet& rHighAlph, Idx lowState, Idx mLabel, vGenerator& rGenDyn) { 01098 OP_DF("forwardReachabilityObs(" << rGen.Name() << "," << rHighAlph.Name() << "," << lowState << "," << rGenDyn.EventName(mLabel) << "," << rGenDyn.Name() << ")"); 01099 // helpers: 01100 // iterators 01101 TransSet::Iterator tIt; 01102 TransSet::Iterator tEndIt; 01103 // todo list 01104 std::stack<Idx> todo; 01105 01106 // algorithm: the locally reachable states from lowState are evaluated. If a reachable state is marked, 01107 // a transition with mLabel is inserted from lowState to that state is inserted in rGenDyn. 01108 todo.push(lowState); 01109 StateSet doneStates; 01110 // if lowState is marked itself, the dynamic system contains a selfloop with the mlabel 01111 if(rGen.MarkedStates().Exists(lowState) ){ 01112 OP_DF("forwardReachabilityObs: Transition with mLabel added to resulting generator: " << 01113 rGenDyn.TStr(Transition(lowState,mLabel,lowState))); 01114 rGenDyn.SetTransition(lowState, mLabel, lowState); 01115 } 01116 01117 doneStates.Insert(lowState); 01118 // the local reachability is evaluated until no new state is found 01119 while (! todo.empty()) { 01120 const Idx current = todo.top(); 01121 todo.pop(); 01122 tIt = rGen.TransRelBegin(current); 01123 tEndIt = rGen.TransRelEnd(current); 01124 for (; tIt != tEndIt; ++tIt) { 01125 // if the current transition is labeled with a high level event, it is skipped 01126 if (rHighAlph.Exists(tIt->Ev)) { 01127 continue; 01128 } 01129 // if the successor state has not been found, yst (not in doneStates) 01130 else if (! doneStates.Exists(tIt->X2)) { 01131 todo.push(tIt->X2); 01132 if(rGen.MarkedStates().Exists(tIt->X2) ){ 01133 OP_DF("forwardReachabilityObs: Transition with mLabel added to resulting generator: " << 01134 rGenDyn.TStr(Transition(lowState,mLabel,tIt->X2))); 01135 rGenDyn.SetTransition(lowState, mLabel, tIt->X2); 01136 } 01137 doneStates.Insert(tIt->X2); 01138 } 01139 } 01140 } 01141 }*/ 01142 01143 // backwardReachabilityObsOCC(rTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, currentState, controllablePath, rExitLocalStatesMap, rDoneStates) 01144 void backwardReachabilityObsOCC(const TransSetX2EvX1& rTransSetX2EvX1, const EventSet& rControllableEvents, const EventSet& rHighAlph, Idx exitState, Idx currentState, bool controllablePath, map<Idx, map<Idx, bool> >& rExitLocalStatesMap, StateSet& rDoneStates){ 01145 OP_DF("backwardReachabilityObsOCC(rTransSetX2EvX1," << rControllableEvents.Name() << "," << rHighAlph.Name() << "," << exitState << "," << currentState << "," << controllablePath << ",rExitLocalStatesMap, rDoneStates)"); 01146 // 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 01147 // the controllability properties of the state do not change on the current path 01148 01149 // helpers 01150 TransSetX2EvX1::Iterator tsIt, tsEndIt; 01151 tsIt = rTransSetX2EvX1.BeginByX2(currentState); 01152 tsEndIt = rTransSetX2EvX1.EndByX2(currentState); 01153 bool currentControllablePath; 01154 // we iterate over all backward transitions of the currentState to establish backward reachability 01155 for( ;tsIt != tsEndIt; tsIt++){ 01156 // 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 01157 if( !rHighAlph.Exists(tsIt->Ev) && tsIt->X1 != exitState){ 01158 // if the state has not been visited, yet, the controllability of the current path are set in the rExitLocalStatesMap 01159 if( !rDoneStates.Exists(tsIt->X1) ){ 01160 rDoneStates.Insert(tsIt->X1); 01161 // the path is controllable if the current transition has a controllable event or the path was already controllable 01162 currentControllablePath = rControllableEvents.Exists(tsIt->Ev) || controllablePath; 01163 rExitLocalStatesMap[exitState][tsIt->X1] = currentControllablePath; 01164 // as the state has not been visited, yet, it is subject to a new backward reachability 01165 backwardReachabilityObsOCC(rTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, tsIt->X1, currentControllablePath, rExitLocalStatesMap, rDoneStates); 01166 } 01167 else{ // for an existing state, the controllability value can change from uncontrollable to controllable (if 01168 // a new controllable path has been found). It is important to note, that the OCC condition implies that 01169 // if there is one controllable path, then the the state is flagged controllable except for the case of the 01170 // given exitState that is always uncontrollable 01171 currentControllablePath = rControllableEvents.Exists(tsIt->Ev) || controllablePath; 01172 if(rExitLocalStatesMap[exitState][tsIt->X1] != currentControllablePath && currentControllablePath == true){ 01173 rExitLocalStatesMap[exitState][tsIt->X1] = true; 01174 // as the controllabiity attribute of the current state changed it is subject to a new backward reachability 01175 backwardReachabilityObsOCC(rTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, tsIt->X1, true, rExitLocalStatesMap, rDoneStates); 01176 } 01177 } 01178 } 01179 } 01180 } 01181 01182 // calcAbstAlphObsLCC(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents) 01183 void calcAbstAlphObsLCC(cGenerator& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents){ 01184 OP_DF("calcAbstAlphObsLCC(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)"); 01185 // The controllable events are separated from the cGenerator. All functions that are successively 01186 // called, are defined for vGenerators 01187 map<Transition,Idx> changedtrans; 01188 EventSet rControllableEvents = rGenObs.ControllableEvents(); 01189 // The function called next returns a relabeled generator and a map of relabeled transitions 01190 calcAbstAlphObsLCC(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans); 01191 // for later use, the relabeled transitions are converted into relabeled events 01192 // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty 01193 map<Transition,Idx>::iterator rtEndIt = changedtrans.end(); 01194 map<Transition,Idx>::iterator rtIt = changedtrans.begin(); 01195 for(; rtIt != rtEndIt; rtIt++){ 01196 if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){ 01197 rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>(); 01198 if(rGenObs.Alphabet().Exists(rtIt->second) ) 01199 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second); 01200 } else { 01201 if(rGenObs.Alphabet().Exists(rtIt->second) ) 01202 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second); 01203 } 01204 } 01205 // the controllable events that have been changed by the called function are set in the cGenerator cGenObs 01206 rGenObs.SetControllable(rControllableEvents); 01207 } 01208 01209 // calcAbstAlphObsLCC(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans) 01210 void calcAbstAlphObsLCC(vGenerator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans) 01211 { 01212 OP_DF("calcAbstAlphObsLCC(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)"); 01213 // Initialization of variables 01214 rNewHighAlph = rHighAlph; 01215 rMapChangedTrans.clear(); 01216 Generator genDyn(rGenObs); 01217 map<Transition,Transition> mapChangedTransReverse; 01218 vector<Idx> newPartitions; 01219 map<Idx,Idx> mapStateToPartition; 01220 map<Idx, EventSet> mapRelabeledEvents; 01221 bool done=false; 01222 #ifdef DF_PLOT 01223 Idx iterationCount=1; 01224 string name; 01225 #endif 01226 // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition 01227 // and local control consistency (LCC). 01228 // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs 01229 // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition and LCC. 01230 while(done==false) 01231 { 01232 // compute the dynamic system for the given generator and high-level alphabet 01233 calculateDynamicSystemClosedObs(rGenObs, rNewHighAlph, genDyn); 01234 calculateDynamicSystemLCC(rGenObs, rControllableEvents, rNewHighAlph, genDyn); 01235 calculateDynamicSystemObs(rGenObs, rNewHighAlph, genDyn); 01236 #ifdef DF_PLOT 01237 name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToString(iterationCount)); 01238 genDyn.DotWrite(name); 01239 #endif 01240 01241 Generator genPart; 01242 mapStateToPartition.clear(); 01243 newPartitions.clear(); 01244 // compute coarsest quasi-congruence on the dynamic system 01245 calcBisimulation(genDyn, mapStateToPartition, genPart, newPartitions); 01246 #ifdef DF_PLOT 01247 name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToString(iterationCount)); 01248 genPart.DotWrite(name); 01249 ++iterationCount; 01250 #endif 01251 01252 // check if quotient automaton is deterministic and free of unobservable events 01253 // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly 01254 done=relabel(rGenObs, rControllableEvents, rNewHighAlph, newPartitions, mapStateToPartition, mapChangedTransReverse, rMapChangedTrans, mapRelabeledEvents); 01255 } 01256 } 01257 01258 01259 // calcAbstAlphMSALCC(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents) 01260 void calcAbstAlphMSALCC(cGenerator& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents){ 01261 OP_DF("calcAbstAlphMSALCC(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)"); 01262 // The controllable events are separated from the cGenerator. All functions that are successively 01263 // called, are defined for vGenerators 01264 map<Transition,Idx> changedtrans; 01265 EventSet rControllableEvents = rGenObs.ControllableEvents(); 01266 // The function called next returns a relabeled generator and a map of relabeled transitions 01267 calcAbstAlphMSALCC(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans); 01268 // for later use, the relabeled transitions are converted into relabeled events 01269 // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty 01270 map<Transition,Idx>::iterator rtEndIt = changedtrans.end(); 01271 map<Transition,Idx>::iterator rtIt = changedtrans.begin(); 01272 for(; rtIt != rtEndIt; rtIt++){ 01273 if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){ 01274 rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>(); 01275 if(rGenObs.Alphabet().Exists(rtIt->second) ) 01276 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second); 01277 } else { 01278 if(rGenObs.Alphabet().Exists(rtIt->second) ) 01279 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second); 01280 } 01281 } 01282 // the controllable events that have been changed by the called function are set in the cGenerator cGenObs 01283 rGenObs.SetControllable(rControllableEvents); 01284 } 01285 01286 // calcAbstAlphMSALCC(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans) 01287 void calcAbstAlphMSALCC(vGenerator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans) 01288 { 01289 OP_DF("calcAbstAlphMSALCC(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)"); 01290 // Initialization of variables 01291 rNewHighAlph = rHighAlph; 01292 rMapChangedTrans.clear(); 01293 Generator genDyn(rGenObs); 01294 map<Transition,Transition> mapChangedTransReverse; 01295 vector<Idx> newPartitions; 01296 map<Idx,Idx> mapStateToPartition; 01297 map<Idx, EventSet> mapRelabeledEvents; 01298 bool done=false; 01299 #ifdef DF_PLOT 01300 Idx iterationCount=1; 01301 string name; 01302 #endif 01303 // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition 01304 // and local control consistency (LCC). 01305 // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs 01306 // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition and LCC. 01307 while(done==false) 01308 { 01309 // compute the dynamic system for the given generator and high-level alphabet 01310 calculateDynamicSystemClosedObs(rGenObs, rNewHighAlph, genDyn); 01311 calculateDynamicSystemLCC(rGenObs, rControllableEvents, rNewHighAlph, genDyn); 01312 calculateDynamicSystemMSA(rGenObs, rNewHighAlph, genDyn); 01313 #ifdef DF_PLOT 01314 name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToString(iterationCount)); 01315 genDyn.DotWrite(name); 01316 #endif 01317 01318 Generator genPart; 01319 mapStateToPartition.clear(); 01320 newPartitions.clear(); 01321 // compute coarsest quasi-congruence on the dynamic system 01322 calcBisimulation(genDyn, mapStateToPartition, genPart, newPartitions); 01323 #ifdef DF_PLOT 01324 name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToString(iterationCount)); 01325 genPart.DotWrite(name); 01326 ++iterationCount; 01327 #endif 01328 01329 // check if quotient automaton is deterministic and free of unobservable events 01330 // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly 01331 done=relabel(rGenObs, rControllableEvents, rNewHighAlph, newPartitions, mapStateToPartition, mapChangedTransReverse, rMapChangedTrans, mapRelabeledEvents); 01332 } 01333 } 01334 01335 /* 01336 // calculateDynamicSystemObsLCC(rGen, rControllableEvents, rHighAlph, rGenDyn) 01337 void calculateDynamicSystemObsLCC(const vGenerator& rGen, EventSet& rControllableEvents, EventSet& rHighAlph, vGenerator& rGenDyn){ 01338 OP_DF("calculateDynamicSystemObsLCC(" << rGen.Name() << "," << rControllableEvents.Name() << "," << rHighAlph.Name() << "," << rGenDyn.Name() << ")"); 01339 // transition relation sorted in reverse order for backwards reachability 01340 TransSetX2EvX1 tset_X2EvX1; 01341 rGen.TransRel(tset_X2EvX1); 01342 01343 // prepare generator rGenDyn 01344 rGenDyn.ClearTransRel(); 01345 rGenDyn.InjectAlphabet(rHighAlph); 01346 std::string eventname = ( rGenDyn.EventSymbolTablep())->UniqueSymbol("ucLabel_1"); 01347 Idx ucLabel = (rGenDyn.EventSymbolTablep())->InsEntry(eventname); 01348 eventname = ( rGenDyn.EventSymbolTablep())->UniqueSymbol("mLabel_1"); 01349 Idx mLabel = (rGenDyn.EventSymbolTablep())->InsEntry(eventname); 01350 rGenDyn.InsEvent(ucLabel); 01351 rGenDyn.InsEvent(mLabel); 01352 rGenDyn.InjectInitStates(rGen.InitStates() ); 01353 rGenDyn.InjectStates(rGen.States() ); 01354 rGenDyn.InjectMarkedStates(rGen.MarkedStates() ); 01355 01356 // maps for the construction of the dynamic system 01357 map<Idx, map<Idx, bool> > exitLocalStatesMap; // map from each exit state to locally backward reachable states and a boolean that is false if there exists an uncontrollable path to the exit state 01358 map<Idx, StateSet> entryLocalStatesMap; // map from entry states to locally forward reachable states 01359 StateSet::Iterator stIt, stEndIt; 01360 stIt = rGen.StatesBegin(); 01361 stEndIt = rGen.StatesEnd(); 01362 TransSet::Iterator tsIt, tsEndIt; 01363 bool isExitState; 01364 // go through all states of the original generator 01365 for(; stIt != stEndIt; stIt++){ 01366 OP_DF("calculateDynamicSystemObsLCC: loop over all states; current state: " << rGen.StateName(*stIt) 01367 << " [" << *stIt << "]"); 01368 // determine the marked states that are locally reachable from the current state and insert 01369 // transitions labeled with mLabel in rGenDyn 01370 forwardReachabilityObs(rGen, rHighAlph, *stIt, mLabel, rGenDyn); 01371 // if the current state is an exit state, carry out the backward reachability to determine 01372 // which states can be reached on a controllable/uncontrollable path -> store in exitLocalStatesMap 01373 // in this case, also determine the corresponding entry states and compute their locally reachable states 01374 // for the entryLocalStatesMap 01375 tsIt = rGen.TransRelBegin(*stIt); 01376 tsEndIt = rGen.TransRelEnd(*stIt); 01377 isExitState = false; 01378 for( ; tsIt != tsEndIt; tsIt++){ 01379 if(rHighAlph.Exists(tsIt->Ev) ){ 01380 OP_DF("calculateDynamicSystemObsLCC: current state is an exit-state"); 01381 isExitState = true; 01382 // if the local reach for the connected entry state has not been computed, yet, insert it in the 01383 // entryLocalStatesMap 01384 if( entryLocalStatesMap.find(tsIt->X2) == entryLocalStatesMap.end() ){ 01385 entryLocalStatesMap[tsIt->X2] = StateSet(); 01386 LocalAccessibleReach(rGen,rHighAlph, tsIt->X2, entryLocalStatesMap[tsIt->X2]); 01387 } 01388 } 01389 } 01390 // if the current state is an exit state, compute the backward local reach with the controllability properties of the 01391 // paths to locally backward reachable states 01392 if(isExitState == true){ 01393 StateSet doneStates; 01394 exitLocalStatesMap[*stIt][*stIt] = false; // the exit state is reachable from the exit state via an uncontrollable path 01395 doneStates.Insert(*stIt); 01396 backwardReachabilityObsLCC(tset_X2EvX1, rControllableEvents, rHighAlph, *stIt, *stIt, false, exitLocalStatesMap, doneStates); 01397 01398 } 01399 01400 } 01401 // the generator rGenDyn is constructed by connecting all exit and entry states with their local state sets 01402 map<Idx, map<Idx, bool> >::const_iterator elIt, elEndIt; 01403 elIt = exitLocalStatesMap.begin(); 01404 elEndIt = exitLocalStatesMap.end(); 01405 map<Idx,bool>::const_iterator lcIt, lcEndIt; 01406 StateSet::Iterator exIt, exEndIt; 01407 map<Idx,StateSet>::const_iterator enIt; 01408 01409 for( ; elIt != elEndIt; elIt++){ 01410 lcEndIt = elIt->second.end(); 01411 // go over all entry states reachable from the current exit state (via all feasible high-level events) 01412 tsIt = rGen.TransRel().Begin(elIt->first); 01413 tsEndIt = rGen.TransRel().End(elIt->first); 01414 for( ; tsIt != tsEndIt; tsIt++){ 01415 OP_DF("calculateDynamicSystemObsLCC: insert transitions for the high-level event" << rGen.EventName(tsIt->Ev) << "[" << tsIt->Ev << "]"); 01416 if(rHighAlph.Exists(tsIt->Ev) ){ 01417 bool controllable = rControllableEvents.Exists(tsIt->Ev); 01418 enIt = entryLocalStatesMap.find(tsIt->X2); 01419 stEndIt = enIt->second.End(); 01420 // iterate over all locally backward reachable states from current exit state 01421 for(lcIt = elIt->second.begin(); lcIt != lcEndIt; lcIt ++){ 01422 // iterate over all locally forward reachable states from current entry state 01423 for( stIt = enIt->second.Begin(); stIt != stEndIt; stIt++){ 01424 OP_DF("calculateDynamicSystemObsLCC: Transition added to resulting generator: " << 01425 rGenDyn.TStr(Transition(lcIt->first,tsIt->Ev,*stIt))); 01426 01427 rGenDyn.SetTransition(lcIt->first,tsIt->Ev,*stIt); // insert a transition for each local state combination 01428 if( !(controllable || lcIt->second) ){ // insert an uclabel transition if the local path is uncontrollable 01429 OP_DF("calculateDynamicSystemObsLCC: cLabel-Transition added to resulting generator: " << 01430 rGenDyn.TStr(Transition(lcIt->first,ucLabel,*stIt))); 01431 01432 rGenDyn.SetTransition(lcIt->first,ucLabel,*stIt); 01433 } 01434 } 01435 } 01436 } 01437 } 01438 } 01439 } 01440 01441 // backwardReachabilityObsLCC(crTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, currentState, controllablePath, rExitLocalStatesMap, rDoneStates) 01442 void backwardReachabilityObsLCC(const TransSetX2EvX1& rTransSetX2EvX1, const EventSet& rControllableEvents, const EventSet& rHighAlph, Idx exitState, Idx currentState, bool controllablePath, map<Idx, map<Idx, bool> >& rExitLocalStatesMap, StateSet& rDoneStates){ 01443 OP_DF("backwardReachabilityObsOCC(rTransSetX2EvX1," << rControllableEvents.Name() << "," << rHighAlph.Name() << "," << exitState << "," << currentState << "," << controllablePath << ",rExitLocalStatesMap, rDoneStates)"); 01444 // 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 01445 // the controllability properties of the state do not change on the current path 01446 01447 // helpers 01448 TransSetX2EvX1::Iterator tsIt, tsEndIt; 01449 tsIt = rTransSetX2EvX1.BeginByX2(currentState); 01450 tsEndIt = rTransSetX2EvX1.EndByX2(currentState); 01451 bool currentControllablePath; 01452 // we iterate over all backward transitions of the currentState to establish backward reachability 01453 for( ;tsIt != tsEndIt; tsIt++){ 01454 // 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 01455 if( !rHighAlph.Exists(tsIt->Ev) && tsIt->X1 != exitState){ 01456 // if the state has not been visited, yet, the controllability of the current path are set in the rExitLocalStatesMap 01457 if( !rDoneStates.Exists(tsIt->X1) ){ 01458 rDoneStates.Insert(tsIt->X1); 01459 // the path is uncontrollable if the current transition has an uncontrollable event or the path was already uncontrollable 01460 currentControllablePath = rControllableEvents.Exists(tsIt->Ev) || controllablePath; 01461 rExitLocalStatesMap[exitState][tsIt->X1] = currentControllablePath; 01462 // as the state has not been visited, yet, it is subject to a new backward reachability 01463 backwardReachabilityObsLCC(rTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, tsIt->X1, currentControllablePath, rExitLocalStatesMap, rDoneStates); 01464 } 01465 else{ // for an existing state, the controllability value can change from controllable to uncontrollable (if 01466 // a new uncontrollable path has been found). It is important to note, that the LCC condition implies that 01467 // if there is one uncontrollable path, then the state is flagged uncontrollable except for the case of the 01468 // given exitState that is always uncontrollable 01469 currentControllablePath = rControllableEvents.Exists(tsIt->Ev) || controllablePath; 01470 if(rExitLocalStatesMap[exitState][tsIt->X1] != currentControllablePath && currentControllablePath == false){ 01471 rExitLocalStatesMap[exitState][tsIt->X1] = currentControllablePath; 01472 // as the controllabiity attribute of the current state changed it is subject to a new backward reachability 01473 backwardReachabilityObsLCC(rTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, tsIt->X1, false, rExitLocalStatesMap, rDoneStates); 01474 } 01475 } 01476 } 01477 } 01478 }*/ 01479 01480 // relabel(rGenRelabel, rControllableEvents, rHighAlph, rNewPartitions, rMapStateToPartition, rMapChangedTransReverse, rMapChangedTrans, rMapRelabeledEvents) 01481 bool relabel(vGenerator& rGenRelabel, EventSet& rControllableEvents, EventSet& rHighAlph, vector<Idx>& rNewPartitions, map<Idx,Idx>& rMapStateToPartition, map<Transition,Transition>& rMapChangedTransReverse, map<Transition,Idx>& rMapChangedTrans, map<Idx, EventSet>& rMapRelabeledEvents) 01482 { 01483 01484 OP_DF("relabel(" << rGenRelabel.Name() << "," << rControllableEvents.Name() << "," << rHighAlph.Name() << ", rNewPartition, rMapStateToPartition, rMapChangedTransReverse, rMapChangedTrans, rMapRelabeledEvents)"); 01485 01486 // helpers 01487 01488 // keep track of how transitions between cosets have been relabeled 01489 // first Idx: coset from where transition starts, second Idx: high-level event, 01490 // third Idx: other coset, where transition ends, forth Idx: new high-level event 01491 map<Idx, map<Idx, map<Idx, Idx> > > mapRelabel; 01492 01493 // set of low-level events, that have not been relabeled 01494 set<Idx> notRelabeledLowEvents; 01495 // transition relation of the original version of rGenRelabel 01496 const TransSet& transSet = rGenRelabel.TransRel(); 01497 TransSet::Iterator tIt = transSet.Begin(); 01498 TransSet::Iterator tItEnd = transSet.End(); 01499 // vector that contains pairs of original and changed transitions 01500 vector<pair<TransSet::Iterator,Transition> > editTransSet; 01501 // prepare data structure for keeping track of how transitions were relabeled 01502 vector<Idx>::iterator newPartIt = rNewPartitions.begin(); 01503 vector<Idx>::iterator newPartItEnd = rNewPartitions.end(); 01504 for(; newPartIt != newPartItEnd; ++newPartIt) 01505 mapRelabel[*newPartIt]=map<Idx, map <Idx, Idx> >(); 01506 01507 // algorithm: The relabeling according to the state partition as computed by the bisimulation algorithm is 01508 // performed. A high-level transitions is relebaled with a new event, if a transition with the same event leads 01509 // from the same coset to a different coset (non-determinism in the projected automaton). A low-level transition 01510 // is relabeled if it connects different cosets (corresponds to unobservable transition betweeen cosets). The 01511 // also has build-in procedures to take care that as few new event labels as possible are introduced. 01512 01513 // iteration over all transitions of rGenRelabel 01514 for(; tIt != tItEnd; ++tIt) 01515 { 01516 OP_DF("relabel: current transition: " << rGenRelabel.TStr(*tIt) ); 01517 Idx indexX1Partition=rMapStateToPartition[tIt->X1]; 01518 OP_DF("relabel: X1 belongs to coset with index " << indexX1Partition); 01519 Idx indexX2Partition=rMapStateToPartition[tIt->X2]; 01520 OP_DF("relabel: X2 belongs to coset with index " << indexX2Partition); 01521 01522 //check if current transition is labeled with a high-level-event 01523 if(rHighAlph.Exists(tIt->Ev)) 01524 { 01525 OP_DF("relabel: Event is high-level event"); 01526 // In the first case, there exists no entry for this transition in mapRelabel. Hence, this is the 01527 // first occurence of tIt->Ev leaving the coset of tIt->X1 found in the iteration. 01528 // Thus, there is no need to relabel this event. Store transition in mapRelabel 01529 if(mapRelabel[indexX1Partition].find(tIt->Ev) == mapRelabel[indexX1Partition].end()) 01530 { 01531 mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition]=tIt->Ev; 01532 OP_DF("relabel: First occurence of the current event leaving the current X1-coset"); 01533 } 01534 // Otherwise, there exists an entry for the current event leaving the current X1-coset. It has to be 01535 // verified if the transition goes to the same coset as the previously found transitions or not. 01536 else 01537 { 01538 // check if a transition with the same event has already been found that enters the same X2-coset. If 01539 // yes, the same label as for this transition is chosen. If not, a new label is introduced. 01540 if(mapRelabel[indexX1Partition][tIt->Ev].find(indexX2Partition) != mapRelabel[indexX1Partition][tIt->Ev].end()) 01541 { 01542 if(mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition] != tIt->Ev) 01543 { 01544 OP_DF("relabel: the same event leading to the same X2-coset has already been relabeld before. The current transition is relabeld correspondingly"); 01545 pair<TransSet::Iterator,Transition> newPair; 01546 newPair.first=tIt; 01547 newPair.second = Transition(tIt->X1,mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition],tIt->X2); 01548 editTransSet.push_back(newPair); 01549 } 01550 else //nothing to be done 01551 OP_DF("relabel: There already exists a high-level transition from the current X1-coset to the same X2-coset and the current transition ist labeled with the same event. No relabeling necessary"); 01552 } 01553 // there are entries of tIt->Ev, but no one leads to the same X2-coset. 01554 // Check if new labels created before can be reused. If not, create a new one 01555 // and eliminate the non-determinism by relebeling the current transition tIt with this event 01556 else 01557 { 01558 bool createNewLabel = false; 01559 // check if the event already has been relabeled for some other transition 01560 if(rMapRelabeledEvents.find(tIt->Ev) != rMapRelabeledEvents.end()) 01561 { 01562 EventSet::Iterator lsIt = rMapRelabeledEvents[tIt->Ev].Begin(); 01563 EventSet::Iterator lsItEnd = rMapRelabeledEvents[tIt->Ev].End(); 01564 for(; lsIt != lsItEnd; ++lsIt) 01565 { 01566 createNewLabel = false; 01567 map<Idx,Idx>::iterator mapIt = mapRelabel[indexX1Partition][tIt->Ev].begin(); 01568 map<Idx,Idx>::iterator mapItEnd = mapRelabel[indexX1Partition][tIt->Ev].end(); 01569 for(; mapIt != mapItEnd; ++mapIt) 01570 { 01571 // if the currently investigated label has already been used in 01572 // the current coset for a transition to another coset, relabeling is necessary 01573 if(mapIt->second == *lsIt) 01574 { 01575 createNewLabel = true; 01576 break; 01577 } 01578 } 01579 // use an old label if possible 01580 if(createNewLabel == false) 01581 { 01582 pair<TransSet::Iterator,Transition> newPair; 01583 newPair.first=tIt; 01584 newPair.second = Transition(tIt->X1,*lsIt,tIt->X2); 01585 editTransSet.push_back(newPair); 01586 OP_DF("relabel: An event was found that can be reused: " << rGenRelabel.EventName(*lsIt)); 01587 break; 01588 } 01589 } 01590 } 01591 // if no useable labels are available, a new label has to be introduced 01592 else 01593 { 01594 createNewLabel = true; 01595 } 01596 // no label could be found that can be reused 01597 if(createNewLabel == true) 01598 { 01599 // create a new label and relabel the current transition with it 01600 std::string eventName = ( rGenRelabel.EventSymbolTablep())->UniqueSymbol(rGenRelabel.EventSymbolTablep()->Symbol(tIt->Ev) + "newHLevent_1"); 01601 Idx newLabel = (rGenRelabel.EventSymbolTablep())->InsEntry(eventName); 01602 01603 rGenRelabel.InsEvent(eventName); 01604 // if the original is controllable, the attribute of the new event is also controllable 01605 if(rControllableEvents.Exists(tIt->Ev)){ 01606 rControllableEvents.Insert(newLabel); 01607 } 01608 OP_DF("relabel: No event that can be reused could be found. The new event " << rGenRelabel.EventName(newLabel) << " was created"); 01609 rHighAlph.Insert(newLabel); 01610 //create the new transition and remember that the old one has to be replaced with the new one 01611 pair<TransSet::Iterator,Transition> newPair; 01612 newPair.first=tIt; 01613 newPair.second = Transition(tIt->X1,newLabel,tIt->X2); 01614 editTransSet.push_back(newPair); 01615 rMapRelabeledEvents[tIt->Ev].Insert(newLabel); 01616 } 01617 } 01618 } 01619 } 01620 // the current transition is labeled with a low-level event 01621 else 01622 { 01623 OP_DF("relabel: Event is low-level event"); 01624 // potential relabeling is only necessary if the low-level transition leaves its coset 01625 if(indexX1Partition != indexX2Partition) 01626 { 01627 // transition connects two cosets and it is the first occurrence of the event. 01628 // Create a new event and relabel the transition with it 01629 if(rMapRelabeledEvents.find(tIt->Ev) == rMapRelabeledEvents.end()) 01630 { 01631 std::string eventName = ( rGenRelabel.EventSymbolTablep())->UniqueSymbol(rGenRelabel.EventSymbolTablep()->Symbol(tIt->Ev) + "newHLevent_1"); 01632 Idx newLabel = (rGenRelabel.EventSymbolTablep())->InsEntry(eventName); 01633 rGenRelabel.InsEvent(eventName); 01634 // insert the new event in the high-level alphabet and set its controllability property 01635 rHighAlph.Insert(newLabel); 01636 if(rControllableEvents.Exists(tIt->Ev)){ 01637 rControllableEvents.Insert(newLabel); 01638 } 01639 OP_DF("relabel: First occurence of current low-level event " << rGenRelabel.EventName(tIt->Ev) 01640 << " between cosets. The new event " << rGenRelabel.EventName(newLabel) << " was created"); 01641 mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition]=newLabel; 01642 rMapRelabeledEvents[tIt->Ev].Insert(newLabel); 01643 pair<TransSet::Iterator,Transition> newPair; 01644 newPair.first=tIt; 01645 newPair.second = Transition(tIt->X1,newLabel,tIt->X2); 01646 editTransSet.push_back(newPair); 01647 } 01648 // there are entries of tIt->Ev, but no one leads to the same X2-coset. 01649 // Check if new labels created before can be reused. If not, create a new one 01650 // and eliminate the non-determinism by relebeling the current transition tIt with this event 01651 else 01652 { 01653 EventSet::Iterator lsIt = rMapRelabeledEvents[tIt->Ev].Begin(); 01654 EventSet::Iterator lsItEnd = rMapRelabeledEvents[tIt->Ev].End(); 01655 bool createNewLabel = true; 01656 for(; lsIt != lsItEnd; ++lsIt) 01657 { 01658 bool labelFound = false; 01659 // check if the event already has been relabeled for some other transition 01660 if(mapRelabel.find(indexX1Partition) == mapRelabel.end()) 01661 { 01662 // if the currently investigated label has already been used in 01663 // the current coset for a transition to another coset, relabeling is necessary 01664 labelFound = true; 01665 } 01666 else 01667 { 01668 // label lsIt can be reused as this is the first low-level transition leaving the X1-coset 01669 if(mapRelabel[indexX1Partition].find(tIt->Ev) == mapRelabel[indexX1Partition].end()) 01670 { 01671 labelFound = true; 01672 } 01673 else 01674 { 01675 // a transition with the same original event tIt->Ev leaving the X1-coset has been found before 01676 // and it entered a different X2-coset. Check if one of them was relabeled with lsIt. If yes, then lsIt can 01677 // not be reused and the next event has to be examined. If no, lsIt can be reused 01678 if(mapRelabel[indexX1Partition][tIt->Ev].find(indexX2Partition) == mapRelabel[indexX1Partition][tIt->Ev].end()) 01679 { 01680 map<Idx,Idx>::iterator mapIt=mapRelabel[indexX1Partition][tIt->Ev].begin(); 01681 map<Idx,Idx>::iterator mapItEnd=mapRelabel[indexX1Partition][tIt->Ev].end(); 01682 labelFound = true; 01683 for(; mapIt != mapItEnd; ++ mapIt) 01684 { 01685 if(mapIt->second== *lsIt) 01686 { 01687 labelFound = false; 01688 break; 01689 } 01690 } 01691 } 01692 // a transition with the same original event tIt-Ev leaving the X1-coset has been found before 01693 // and it entered the same X2-coset. Reuse the corresponding label 01694 else 01695 { 01696 pair<TransSet::Iterator,Transition> newPair; 01697 newPair.first=tIt; 01698 newPair.second = Transition(tIt->X1,mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition],tIt->X2); 01699 editTransSet.push_back(newPair); 01700 OP_DF("relabel: A transition to same X2-coset has already been found and relabeled before; the current transition is also labeled with " << rGenRelabel.EventName(mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition])); 01701 createNewLabel = false; 01702 break; 01703 } 01704 } 01705 } 01706 // reuse existing event 01707 if(labelFound == true) 01708 { 01709 pair<TransSet::Iterator,Transition> newPair; 01710 newPair.first=tIt; 01711 newPair.second = Transition(tIt->X1,*lsIt,tIt->X2); 01712 editTransSet.push_back(newPair); 01713 OP_DF("relabele: Low level event " << rGenRelabel.EventName(tIt->Ev) << " is relabeled with " << rGenRelabel.EventName(*lsIt) << " which can be reused"); 01714 mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition]=*lsIt; 01715 createNewLabel = false; 01716 break; 01717 } 01718 } //end for 01719 // a new label has to be created and the corresponding transition is inserted 01720 if(createNewLabel == true) 01721 { 01722 std::string eventName = ( rGenRelabel.EventSymbolTablep())->UniqueSymbol(rGenRelabel.EventSymbolTablep()->Symbol(tIt->Ev) + "newHLevent_1"); //?? 01723 Idx newLabel = (rGenRelabel.EventSymbolTablep())->InsEntry(eventName); 01724 rGenRelabel.InsEvent(eventName); 01725 // insert the new event in the high-level alphabet and set its controllability property 01726 rHighAlph.Insert(newLabel); 01727 if(rControllableEvents.Exists(tIt->Ev) ){ 01728 rControllableEvents.Insert(newLabel); 01729 } 01730 OP_DF("relabel: No label could be reused, and the new event " << rGenRelabel.EventName(newLabel) << " was created"); 01731 mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition]=newLabel; 01732 pair<TransSet::Iterator,Transition> newPair; 01733 newPair.first=tIt; 01734 newPair.second = Transition(tIt->X1,newLabel,tIt->X2); 01735 editTransSet.push_back(newPair); 01736 rMapRelabeledEvents[tIt->Ev].Insert(newLabel); 01737 } 01738 } 01739 } 01740 // the low-level event does not have to be relabeled 01741 else //indexX1Partition==indexX2Partition 01742 { 01743 notRelabeledLowEvents.insert(tIt->Ev); 01744 } 01745 } 01746 } 01747 01748 01749 // It is possible that events need not be relabeled. For example, if all occurrences of a low-level event have to 01750 // be relabeled and added to the high-level alphabet, it is possible to just add the original low-level event 01751 // to the high-level alphabet without any relabeling. Note that this information is only available after all 01752 // transitions have been evaluated. 01753 vector<pair<TransSet::Iterator,Transition> >::iterator etSetIt = editTransSet.begin(); 01754 vector<pair<TransSet::Iterator,Transition> >::iterator etSetItEnd = editTransSet.end(); 01755 set<Idx> insertHighEvents; 01756 set<Idx> deleteHighEvents; 01757 bool quotAuotTrue=true; 01758 01759 OP_DF("relabel: Trying to avoid unnecessariy new labels"); 01760 // All relabeled transitions are checked 01761 for(etSetIt = editTransSet.begin(); etSetIt != editTransSet.end(); ++etSetIt) 01762 { 01763 Idx oldEvent = etSetIt->first->Ev; 01764 Idx newEvent = etSetIt->second.Ev; 01765 OP_DF("relabel: Checking transition X1=" << rGenRelabel.StateName(etSetIt->first->X1)<< " ["<<etSetIt->first->X1 01766 << "] Ev=" << rGenRelabel.EventName(oldEvent) << " X2=" << rGenRelabel.StateName(etSetIt->first->X2) 01767 << " [" << etSetIt->first->X2 << "] which shall be relabeled with event " << rGenRelabel.EventName(newEvent)); 01768 // check if the original event is a low-level event and if there is an event left that has not been relabeled. If all events are relabeled, then at least one label can be replaced by the original event label. 01769 if(notRelabeledLowEvents.find(oldEvent) == notRelabeledLowEvents.end() && !rHighAlph.Exists(oldEvent)) 01770 { 01771 OP_DF("relabel: There is no low-level event " << rGenRelabel.EventName(oldEvent) << " left"); 01772 insertHighEvents.insert(oldEvent); 01773 // if a low-level event has been relabeled, the automaton under investigation is not the desired quotient automaton, yet. 01774 quotAuotTrue=false; 01775 // if newEvent is the first new event created for relabeling oldEvent, the relabeling is discarded 01776 if(rMapRelabeledEvents[oldEvent].Find(newEvent) == rMapRelabeledEvents[oldEvent].Begin()) 01777 { 01778 OP_DF("relabel: Transition will not be relabeled"); 01779 // if newEvent is the only event created for relabeling oldEvent, delete newEvent from rGenRelabel 01780 if(rMapRelabeledEvents[oldEvent].Find(newEvent)==(--(rMapRelabeledEvents[oldEvent].End()))) 01781 { 01782 OP_DF("relabel: newEvent is the first and last event in rMapRelabeledEvents[oldEvent]"); 01783 deleteHighEvents.insert(newEvent); 01784 } 01785 // delete pair<original Transition, new Transition> 01786 vector<pair<TransSet::Iterator,Transition> >::iterator helpIt = etSetIt; 01787 helpIt--; 01788 editTransSet.erase(etSetIt); 01789 etSetIt = helpIt; 01790 } 01791 else 01792 { 01793 // find predecessor of newEvent in map rMapRelabeledEvents[oldEvent] and use that event for relabeling 01794 Idx newLabel = *(--(rMapRelabeledEvents[oldEvent].Find(newEvent))); 01795 etSetIt->second.Ev = newLabel; 01796 // delete newEvent from rGenRelabel if it is no longer needed 01797 if(rMapRelabeledEvents[oldEvent].Find(newEvent)==(--(rMapRelabeledEvents[oldEvent].End()))) 01798 { 01799 deleteHighEvents.insert(newEvent); 01800 } 01801 } 01802 } 01803 } 01804 // update the rMapRelabeledEvents with the changes 01805 // as the relabeling of oldEvent is discarded, it is removed from the map of relebeled events and 01806 // reinserted into the map of not relabeled events 01807 01808 // mofidy alphabet of rGenRelabel and the abstraction alphabet by inserting the new high-level events and deleting the not needed new event labels. 01809 set<Idx>::iterator setIt = insertHighEvents.begin(); 01810 set<Idx>::iterator setItEnd = insertHighEvents.end(); 01811 for(; setIt!= setItEnd; ++ setIt) 01812 { 01813 rHighAlph.Insert(*setIt); 01814 } 01815 setIt = deleteHighEvents.begin(); 01816 setItEnd = deleteHighEvents.end(); 01817 for(; setIt != setItEnd; ++setIt) 01818 { 01819 rGenRelabel.DelEvent(*setIt); 01820 rHighAlph.Erase(*setIt); 01821 rControllableEvents.Erase(*setIt); // controllable event is erased if it does not exist anymore. Schmidt 10/07 01822 } 01823 01824 rControllableEvents = rControllableEvents * rGenRelabel.Alphabet(); // Schmidt 10/07 01825 // check if quotient automaton is deterministic and free of unobservable transitions, i.e., no transitions are relabeled and no low-level events are declared as high-level events 01826 if(editTransSet.empty()&& quotAuotTrue== true) 01827 { 01828 OP_DF("relabel: Leaving function relabel with true"); 01829 return true; 01830 } 01831 01832 // delete original trnasitions and create relabeled transitions in rGenRelabel 01833 etSetIt = editTransSet.begin(); 01834 etSetItEnd = editTransSet.end(); 01835 for(; etSetIt != etSetItEnd; ++etSetIt) 01836 { 01837 map<Transition,Transition>::iterator mrIt; 01838 mrIt=rMapChangedTransReverse.find(*(etSetIt->first)); 01839 // if the current relabeled transition has already been relabeled in a previous step of the observer algorithm, the original transition is found in the rMapChangedTransReverse map. 01840 if(mrIt!=rMapChangedTransReverse.end()) 01841 { 01842 Transition originalTrans = mrIt->second; 01843 (rMapChangedTrans.find(originalTrans))->second = (etSetIt->second).Ev; 01844 rMapChangedTransReverse.erase(mrIt); 01845 rMapChangedTransReverse[etSetIt->second]=originalTrans; 01846 OP_DF("relabel: The transition X1= " << rGenRelabel.SStr((etSetIt->first)->X1) << " Ev=" << rGenRelabel.EStr((etSetIt->first)->Ev) << " X2= " << rGenRelabel.SStr((etSetIt->first)->X2) << " has already been relabeled in a former iteration step. The original transition was " << rGenRelabel.SStr(originalTrans.X1) << " Ev=" << rGenRelabel.EStr(originalTrans.Ev) << " X2= " << rGenRelabel.SStr(originalTrans.X2) << "; the new label is " << rGenRelabel.EStr((etSetIt->second).Ev)); 01847 } 01848 // the current relabeled transition is simply inserted in the rMapChangedTrans map with its original transition if it is the first relabeling. 01849 else 01850 { 01851 rMapChangedTransReverse[etSetIt->second]=*(etSetIt->first); 01852 rMapChangedTrans[*(etSetIt->first)]=(etSetIt->second).Ev; 01853 OP_DF("relabel: First relabeling of transition X1=" << rGenRelabel.SStr((etSetIt->first)->X1) 01854 << " Ev=" << rGenRelabel.EStr((etSetIt->first)->Ev) << " X2= " << rGenRelabel.SStr((etSetIt->first)->X2) << " new label is " << rGenRelabel.EStr((etSetIt->second).Ev)); 01855 } 01856 // The old transition is removed and the new transition is inserted into rGenRelabel 01857 rGenRelabel.ClrTransition(etSetIt->first); 01858 rGenRelabel.SetTransition(etSetIt->second); 01859 } 01860 01861 OP_DF("relabel: leaving function with false"); 01862 return false; 01863 } 01864 01865 // insertRelabeledEvents(rGenPlant, rMapRelabeledEvents, rNewEvents) 01866 void insertRelabeledEvents(cGenerator& rGenPlant, const map<Idx,set<Idx> >& rMapRelabeledEvents, cEventSet& rNewEvents) { 01867 map<Idx,set<Idx> >::const_iterator reEndIt = rMapRelabeledEvents.end(); 01868 TransSet::Iterator tsEndIt = rGenPlant.TransRelEnd(); 01869 TransSet::Iterator tsIt = rGenPlant.TransRelBegin(); 01870 // check all transitions of rGenPlant 01871 for(; tsIt != tsEndIt; tsIt++){ 01872 map<Idx,set<Idx> >::const_iterator reIt = rMapRelabeledEvents.find(tsIt->Ev); 01873 if(reIt == reEndIt) continue; 01874 AttributeCFlags attr = rGenPlant.EventAttribute(tsIt->Ev); 01875 set<Idx>::const_iterator rsEndIt = reIt->second.end(); 01876 set<Idx>::const_iterator rsIt = reIt->second.begin(); 01877 // if a transition with an event that gets new labels has been found, parallel transitions 01878 // with the new events are added to rGenPlant 01879 for(; rsIt != rsEndIt; rsIt++){ 01880 rGenPlant.InsEvent(*rsIt,attr); 01881 rNewEvents.Insert(*rsIt,attr); 01882 rGenPlant.SetTransition(tsIt->X1,*rsIt,tsIt->X2); 01883 } 01884 } 01885 } 01886 01887 // insertRelabeledEvents(rGenPlant, rMapRelabeledEvents, rNewEvents) 01888 // tm: alternative, smart on attributes 01889 void insertRelabeledEvents(Generator& rGenPlant, const map<Idx,set<Idx> >& rMapRelabeledEvents, EventSet& rNewEvents) { 01890 map<Idx,set<Idx> >::const_iterator reEndIt = rMapRelabeledEvents.end(); 01891 TransSet::Iterator tsEndIt = rGenPlant.TransRelEnd(); 01892 TransSet::Iterator tsIt = rGenPlant.TransRelBegin(); 01893 // check all transitions of rGenPlant 01894 for(; tsIt != tsEndIt; tsIt++){ 01895 map<Idx,set<Idx> >::const_iterator reIt = rMapRelabeledEvents.find(tsIt->Ev); 01896 if(reIt == reEndIt) continue; 01897 AttributeVoid* attrp = rGenPlant.EventAttribute(tsIt->Ev).Copy(); 01898 set<Idx>::const_iterator rsEndIt = reIt->second.end(); 01899 set<Idx>::const_iterator rsIt = reIt->second.begin(); 01900 // if a transition with an event that gets new labels has been found, parallel transitions 01901 // with the new events are added to rGenPlant 01902 for(; rsIt != rsEndIt; rsIt++){ 01903 rGenPlant.InsEvent(*rsIt); 01904 rGenPlant.EventAttribute(*rsIt,*attrp); 01905 rNewEvents.Insert(*rsIt); 01906 rNewEvents.Attribute(*rsIt,*attrp); 01907 rGenPlant.SetTransition(tsIt->X1,*rsIt,tsIt->X2); 01908 // should also copy transition attribute 01909 } 01910 delete attrp; 01911 } 01912 } 01913 01914 // insertRelabeledEvents(rGenPlant, rMapRelabeledEvents) 01915 void insertRelabeledEvents(cGenerator& rGenPlant, const map<Idx,set<Idx> >& rMapRelabeledEvents) { 01916 cEventSet dummy; 01917 insertRelabeledEvents(rGenPlant,rMapRelabeledEvents,dummy); 01918 } 01919 01920 // insertRelabeledEvents(rGenPlant, rMapRelabeledEvents) 01921 void insertRelabeledEvents(Generator& rGenPlant, const map<Idx,set<Idx> >& rMapRelabeledEvents) { 01922 EventSet dummy; 01923 insertRelabeledEvents(rGenPlant,rMapRelabeledEvents,dummy); 01924 } 01925 01926 01927 01928 01929 /** 01930 * Rti convenience wrapper 01931 */ 01932 void calcAbstAlphObs( 01933 cGenerator& rGenObs, 01934 EventSet& rHighAlph, 01935 EventSet& rNewHighAlph, 01936 EventRelabelMap& rMapRelabeledEvents) 01937 { 01938 calcAbstAlphObs(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents.STLMap()); 01939 } 01940 01941 01942 /** 01943 * Rti convenience wrapper 01944 */ 01945 void insertRelabeledEvents(Generator& rGenPlant, const EventRelabelMap& rMapRelabeledEvents, EventSet& rNewEvents) { 01946 insertRelabeledEvents(rGenPlant, rMapRelabeledEvents.STLMap(), rNewEvents); 01947 } 01948 01949 /** 01950 * Rti convenience wrapper 01951 */ 01952 void insertRelabeledEvents(Generator& rGenPlant, const EventRelabelMap& rMapRelabeledEvents) { 01953 insertRelabeledEvents(rGenPlant, rMapRelabeledEvents.STLMap()); 01954 } 01955 01956 }// namespace 01957 |
libFAUDES 2.14g --- 2009-12-3 --- c++ source docu by doxygen 1.5.6