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