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