op_observercomputation.cpp

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

libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen