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

libFAUDES 2.22s --- 2013.10.07 --- c++ source docu by doxygen