pd_alg_opt.cpp

Go to the documentation of this file.
00001 /** @file pd_alg_opt.cpp  functions for optimizations*/
00002 
00003 
00004 /* Pushdown plugin for FAU Discrete Event Systems Library (libfaudes)
00005 
00006    Copyright (C) 2013  Stefan Jacobi, Sven Schneider, Anne-Kathrin Hess
00007 
00008 */
00009 
00010 #include "pd_alg_opt.h"
00011 
00012 namespace faudes {
00013 
00014 /* *************************
00015  * TrimStackSymbols
00016  * *************************/
00017 PushdownGenerator TrimStackSymbols(const PushdownGenerator& pd){
00018   
00019   //copy the generator
00020   PushdownGenerator rPd = pd;
00021   
00022   StackSymbolSet usedSymbols;
00023   TransSet::Iterator transit;
00024   PopPushSet::const_iterator ppit;
00025   std::vector<Idx>::const_iterator ssit;
00026   std::vector<Idx> pop, push;
00027   //iterate over all transitions to get all used stack symbols
00028   for(transit = pd.TransRelBegin(); transit != pd.TransRelEnd(); transit++){
00029     for(ppit = pd.PopPushBegin(*transit); ppit != pd.PopPushEnd(*transit); ppit++){
00030       
00031       //extract pop and push
00032       pop = ppit->first;
00033       push = ppit->second;
00034       
00035       //extract stack symbols
00036       for(ssit = pop.begin(); ssit != pop.end(); ssit++){
00037         usedSymbols.Insert(*ssit);
00038       }
00039       //extract stack symbols
00040       for(ssit = push.begin(); ssit != push.end(); ssit++){
00041         usedSymbols.Insert(*ssit);
00042       }
00043     }
00044   }
00045   
00046   //delete all stack symbols except for the used ones
00047   StackSymbolSet::Iterator currentssit;
00048   for(currentssit = pd.StackSymbolsBegin(); currentssit != pd.StackSymbolsEnd(); currentssit++){
00049     
00050     //stack symbol is not used and is not lambda
00051     if(!usedSymbols.Exists(*currentssit) && !pd.IsStackSymbolLambda(*currentssit)){
00052       rPd.DelStackSymbol(*currentssit);
00053     }
00054   }
00055   
00056   return rPd;
00057 }
00058 
00059 /* *************************
00060  * RemoveUselessTransitions
00061  * *************************/
00062 PushdownGenerator RemoveUselessTransitions(const PushdownGenerator& pd){
00063   
00064   //generator to return
00065   PushdownGenerator rPd = pd;
00066   
00067   TransSet::Iterator transOutit, transInit;
00068   PopPushSet::const_iterator ppOutit, ppInit;
00069   //iterate over all transitions (q, a, uv, w, q')
00070   for(transOutit = pd.TransRelBegin(); transOutit != pd.TransRelEnd(); transOutit++){
00071     
00072     //get all possible stack tops for state q
00073     Idx q = transOutit->X1;
00074     StackSymbolSet possibleStackTops = GetPossibleStackTops(pd, StateSet(), q);
00075     
00076     //iterate over pop-push-sets
00077     for(ppOutit = pd.PopPushBegin(*transOutit); ppOutit != pd.PopPushEnd(*transOutit); ppOutit++){
00078       
00079       //get the symbol v that gets popped from the stack first
00080       Idx popSymbol = ppOutit->first.back();
00081       
00082       //if the current pop symbol is not a possible stack top, delete the current 
00083       //transition
00084       if(!possibleStackTops.Exists(popSymbol) && !pd.IsStackSymbolLambda(popSymbol)){
00085         rPd.ClrTransition(*transOutit, ppOutit->first, ppOutit->second);
00086       }
00087     }
00088   }
00089   
00090   //remove transition (p, lambda, u, u, q) that contribute nothing ("lambda read");
00091   
00092   //save generator for iterating
00093   PushdownGenerator tempPd = rPd;
00094   //save X2-sorted transition set for iterating
00095   TTransSet<TransSort::X2EvX1> transitionsByX2;
00096   rPd.TransRel().ReSort(transitionsByX2);
00097   //iterate over all transitions (p, lambda, u, u, q)
00098   for(transInit = tempPd.TransRelBegin(); transInit != tempPd.TransRelEnd(); transInit++){
00099     
00100     //the event must be lambda
00101     if(!rPd.IsEventLambda(transInit->Ev)){
00102       continue;
00103     }
00104     
00105     
00106     //iterate over pop push pairs
00107     for(ppInit = tempPd.PopPushBegin(*transInit); ppInit != tempPd.PopPushEnd(*transInit); ppInit++){
00108       
00109       //pop must equal push
00110       if(ppInit->first.size() != 1 || ppInit->first != ppInit->second){
00111         continue;
00112       }
00113       
00114       //get the target state q and stack symbol u
00115       Idx q = transInit->X2;
00116       Idx u = ppInit->first.front();
00117       
00118       //find all transitions (q, a, u, v, r) originating at q with pop u
00119       for(transOutit = tempPd.TransRelBegin(q); transOutit != tempPd.TransRelEnd(q); transOutit++){
00120         
00121         //the event must be lambda
00122 //         if(!rPd.IsEventLambda(transOutit->Ev)){
00123 //           continue;
00124 //         }
00125         
00126         //iterate over pop push pairs
00127         for(ppOutit = tempPd.PopPushBegin(*transOutit); ppOutit != tempPd.PopPushEnd(*transOutit); ppOutit++){
00128           
00129           //test for u pop 
00130           if(ppOutit->first.size() == 1 && ppOutit->first.front() == u){
00131             
00132             //delete transition (p, lambda, u, u, q)
00133             rPd.ClrTransition(*transInit, ppInit->first, ppInit->second);
00134             
00135             //insert transition (p, a, u, v, r)
00136             rPd.SetTransition(transInit->X1, transOutit->Ev, transOutit->X2, ppOutit->first, ppOutit->second);
00137           }
00138         }
00139       }
00140     }
00141   }
00142   
00143   //there might be unreachable states and transitions left, so make the generator //accessible
00144   rPd.Accessible();
00145   
00146   return rPd;
00147 }
00148 
00149 /* *************************
00150  * GetPossibleStackTops
00151  * *************************/
00152 StackSymbolSet GetPossibleStackTops(const PushdownGenerator& pd, const StateSet& examinedStates, Idx q){
00153   
00154   StackSymbolSet possibleStackTops;
00155   
00156   //if the current state has already been examined, it will contribute nothing new
00157   if(examinedStates.Exists(q)){
00158     return possibleStackTops;
00159   }
00160   
00161   //mark the current state as examined
00162   StateSet currentExaminedStates = examinedStates;
00163   currentExaminedStates.Insert(q);
00164   
00165   //if the current state is an init state, it will contribute at least the stack bottom
00166   if(pd.ExistsInitState(q)){
00167     possibleStackTops.Insert(pd.StackBottom());
00168   }
00169   
00170   //sort transitions by end state
00171   TTransSet<TransSort::X2EvX1> transByX2;
00172   pd.TransRel().ReSort(transByX2);
00173  
00174   TTransSet<TransSort::X2EvX1>::Iterator transit;
00175   PopPushSet::const_iterator ppit;
00176   //iterate over all transitions (p, b, u, w'v', q) going into q and collect all
00177   //stack symbols w'
00178   for(transit = transByX2.BeginByX2(q); transit != transByX2.EndByX2(q); transit++){
00179     for(ppit = pd.PopPushBegin(*transit); ppit != pd.PopPushEnd(*transit); ppit++){
00180       
00181       //get the symbol w' that gets pushed onto the stack last
00182       Idx pushSymbol = ppit->second.front();
00183       
00184       //if w' and u are lambda, get the transition's predecessor state stack tops
00185       if(pd.IsStackSymbolLambda(pushSymbol) && pd.IsStackSymbolLambda(ppit->first.front())){
00186         StackSymbolSet predStackTops = GetPossibleStackTops(pd, currentExaminedStates, transit->X1);
00187         possibleStackTops.SetUnion(predStackTops);
00188       }
00189       //if only w' is lambda, every stack symbol can be a predecessor, because it might
00190       //be under the stack top, about which nothing is known
00191       else if(pd.IsStackSymbolLambda(pushSymbol)){
00192         possibleStackTops.SetUnion(pd.StackSymbols());
00193         possibleStackTops.Erase(pd.StackSymbolIndex(FAUDES_PD_LAMBDA));
00194         break;
00195       }
00196       //if w' is not lambda, add w' to the possible stack tops
00197       else{
00198         possibleStackTops.Insert(pushSymbol);
00199       }
00200     }
00201   }
00202   
00203   return possibleStackTops;  
00204 }
00205   
00206 } // namespace faudes
00207 

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