libFAUDES

Sections

Index

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

libFAUDES 2.14g --- 2009-12-3 --- c++ source docu by doxygen 1.5.6