pd_alg_cc.cpp

Go to the documentation of this file.
00001 /** @file pd_alg_cc.cpp  Top-level functions*/
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_cc.h"
00011 
00012 namespace faudes {
00013 
00014   
00015 /* *************************
00016  * Transient
00017  * *************************/
00018 StateSet Transient(const PushdownGenerator& pd){
00019   
00020   TransSet::Iterator transit;
00021   StateSet rStates;
00022   //iterate over all transitions
00023   for(transit = pd.TransRelBegin(); transit != pd.TransRelEnd(); transit++){
00024     
00025     //add start state of lambda read transition to set
00026     if(pd.IsEventLambda(transit->Ev)){
00027       rStates.Insert(transit->X1);
00028     }
00029   }
00030   
00031   return rStates;  
00032 }
00033 
00034 /* *************************
00035  * Rnce
00036  * *************************/
00037 PushdownGenerator Rnce(const PushdownGenerator& pd, const System& s){
00038   
00039   StateSet transientStates = Transient(pd);
00040   StateSet ucEars;
00041   EventSet uc = pd.UncontrollableEvents();
00042   StateSet::Iterator stateit;
00043   EventSet::Iterator eventit;
00044   Idx oldState;
00045   
00046   //iterate over all states
00047   for(stateit = pd.StatesBegin(); stateit != pd.StatesEnd(); stateit++){
00048     
00049     //get the merge attribute, which must must be either an ear or a heads
00050     const MergeStateSplit* mss = dynamic_cast<const MergeStateSplit*>(pd.Merge(*stateit));
00051     if(mss == NULL){
00052       std::stringstream errstr;
00053       errstr << "State in Rnce was neither head nor ear, check correctness of Merge attribute" << std::endl;
00054       throw Exception("Rnce", errstr.str(), 1001);
00055     }
00056     
00057     //only look at ears
00058     if(mss->IsHead()){
00059       continue;
00060     }
00061     
00062     //only look at transient ears
00063     if(transientStates.Exists(*stateit)){
00064       continue;
00065     }
00066     
00067     //check the current state for each uncontrollable event
00068     for(eventit = uc.Begin(); eventit != uc.End(); eventit++){
00069       
00070       //only look at states whose corresponding dfa state allows this 
00071       //uncontrollable event
00072       oldState = pd.DfaState(*stateit);
00073       if(!s.ExistsTransition(oldState,*eventit)){
00074         continue;
00075       }
00076             
00077       //only look at states that do not allow the uncontrollable event to happen
00078       if(pd.ExistsTransition(*stateit,*eventit)){
00079         continue;
00080       }
00081       
00082       //all these states are uncontrollable ears
00083       ucEars.Insert(*stateit);
00084     }
00085   } 
00086   PushdownGenerator rPd = pd;
00087   rPd.DelStates(ucEars);
00088   return rPd;
00089 }
00090 
00091 /* *************************
00092  * Times
00093  * *************************/
00094 PushdownGenerator Times(const System& s, const PushdownGenerator& pd){
00095   
00096   //result generator
00097   PushdownGenerator rPd;
00098   
00099   //map to remember which states get merged into which
00100   std::map<std::pair<Idx,Idx>, Idx > stateMap;
00101   
00102   StateSet::Iterator pdStateit, sStateit;
00103   Idx newState;
00104   std::vector<Idx> oldStatesVector;
00105   //construct states as cartesian prodcut of both generators states
00106   for(pdStateit = pd.StatesBegin(); pdStateit != pd.StatesEnd(); pdStateit++){
00107     for(sStateit = s.StatesBegin(); sStateit != s.StatesEnd(); sStateit++){
00108       
00109       //add new state for each pair of states and save it in the map
00110       newState = rPd.InsState();
00111       stateMap.insert(std::make_pair(std::make_pair(*sStateit, *pdStateit), newState));
00112       
00113       //add information about parent states
00114       oldStatesVector.clear();
00115       oldStatesVector.push_back(*sStateit);
00116       oldStatesVector.push_back(*pdStateit);
00117       MergeStates oldStates = MergeStates(oldStatesVector);
00118       rPd.SetMerge(newState,oldStates);
00119       rPd.SetDfaState(newState,*sStateit);
00120       
00121       //if both states are init states, the new state is an init state as well
00122       if(*pdStateit == pd.InitState() && *sStateit == s.InitState()){
00123         rPd.SetInitState(newState);
00124       }
00125       
00126       //if both states are final states, the new state is a final state as well
00127       if(pd.ExistsMarkedState(*pdStateit) && s.ExistsMarkedState(*sStateit)){
00128         rPd.SetMarkedState(newState);
00129       }
00130     } 
00131   }
00132 
00133   //stack symbols are the same as the pushdown generator's stack symbols
00134   rPd.InsStackSymbols(pd.StackSymbols());
00135 
00136   //stack bottom is the same as the pushdown generator's stack bottom
00137   rPd.SetStackBottom(pd.StackSymbolObj(pd.StackBottom()));
00138   
00139   //the new event set is the intersection of both old event sets
00140   IntersectEvents(s,pd,rPd);
00141 
00142   //add lambda event if there was a lambda event in the pushdown generator's event set
00143   if(pd.Alphabet().Exists(FAUDES_PD_LAMBDA)){
00144     rPd.InsEvent(FAUDES_PD_LAMBDA);
00145   }
00146   
00147   Idx newX1, newX2;
00148   std::string sEvName, pdEvName;
00149   //add transitions to rPd. Iterate over all pushdown generator transitions
00150   TransSet::Iterator pdTransit, sTransit;
00151   PopPushSet::const_iterator ppsit;
00152   for(pdTransit = pd.TransRelBegin(); pdTransit != pd.TransRelEnd(); pdTransit++){
00153     
00154     //look at every pop push set of the transition
00155     for(ppsit = pd.PopPushBegin(*pdTransit); ppsit != pd.PopPushEnd(*pdTransit); ppsit++){
00156       
00157       pdEvName = pd.EventName(pdTransit->Ev);
00158       //for every no-read transition (q,lambda,w,w',q') of pd and every state p of s,
00159       //add a transition ((p,q),lambda,w,w',(p,q'))
00160       if(pdEvName.compare(FAUDES_PD_LAMBDA) == 0){
00161         for(sStateit = s.StatesBegin(); sStateit != s.StatesEnd(); sStateit++){
00162           
00163           //find new states corresponding to (p,q), and (p,q')
00164           newX1 = stateMap.find(std::make_pair(*sStateit, pdTransit->X1))->second;
00165           newX2 = stateMap.find(std::make_pair(*sStateit, pdTransit->X2))->second;
00166           
00167           //add transition
00168           rPd.SetTransition(newX1, rPd.EventIndex(FAUDES_PD_LAMBDA), newX2, ppsit->first, ppsit->second);
00169         }
00170       }
00171       //for every read transition (q,a,w,w',q') of pd and every transition (p,a,p')
00172       //of s, add a transition ((p,q),a,w,w',(p',q'))
00173       else{
00174         
00175         //iterate over all system transitions
00176         for(sTransit = s.TransRelBegin(); sTransit != s.TransRelEnd(); sTransit++){
00177           
00178           sEvName = s.EventName(sTransit->Ev);
00179           //compare the transition events
00180           if(pdEvName.compare(sEvName) == 0){
00181             
00182             //find new states corresponding to (p,q), and (p',q')
00183             newX1 = stateMap.find(std::make_pair(sTransit->X1, pdTransit->X1))->second;
00184             newX2 = stateMap.find(std::make_pair(sTransit->X2, pdTransit->X2))->second;
00185             
00186             //add transition
00187             rPd.SetTransition(newX1, rPd.EventIndex(sEvName), newX2, ppsit->first, ppsit->second);
00188           }
00189         }
00190       }
00191     }
00192   }
00193   return rPd;
00194 }
00195 
00196 
00197 /* *************************
00198  * IntersectEvents
00199  * *************************/
00200 void IntersectEvents(const System& s, const PushdownGenerator& pd, PushdownGenerator& rPd){
00201   EventSet::Iterator pdEventit, sEventit;
00202   for(pdEventit = pd.AlphabetBegin(); pdEventit != pd.AlphabetEnd(); pdEventit++){
00203     for(sEventit = s.AlphabetBegin(); sEventit != s.AlphabetEnd(); sEventit++){
00204       if(*pdEventit == *sEventit){
00205         //controllable and observable
00206         if(pd.Controllable(*pdEventit) && 
00207           s.Controllable(*sEventit) && 
00208           pd.Observable(*pdEventit) &&
00209           s.Observable(*sEventit))
00210         {
00211           rPd.InsControllableEvent(*pdEventit);
00212         }
00213         //controllable and not observable
00214         else if(pd.Controllable(*pdEventit) &&
00215           s.Controllable(*sEventit) &&
00216           !pd.Observable(*pdEventit) &&
00217           !s.Observable(*sEventit))
00218         {
00219           rPd.InsControllableEvent(*pdEventit);
00220           rPd.ClrObservable(*pdEventit);
00221         }
00222         //not controllable, but observable
00223         else if(!pd.Controllable(*pdEventit) &&
00224           !s.Controllable(*sEventit) &&
00225           pd.Observable(*pdEventit) &&
00226           s.Observable(*sEventit))
00227         {
00228           rPd.InsEvent(*pdEventit);
00229         }
00230         //neither controllable nor observable
00231         else if(!pd.Controllable(*pdEventit) &&
00232           !s.Controllable(*sEventit) &&
00233           !pd.Observable(*pdEventit) &&
00234           !s.Observable(*sEventit))
00235         {
00236           rPd.InsUnobservableEvent(*pdEventit);
00237         }
00238       }
00239     }
00240   }
00241 }
00242 
00243 /* *************************
00244  * Split
00245  * *************************/
00246 PushdownGenerator Split(const PushdownGenerator& pd){
00247   
00248   //copy the generator
00249   PushdownGenerator rPd = pd;
00250   
00251   //insert lambda event in case it has not already been added
00252   rPd.InsEvent(FAUDES_PD_LAMBDA);
00253   
00254   //clear transition relation and states, because they will be replaced
00255   rPd.ClearTransRel();
00256   StateSet::Iterator stateit=rPd.StatesBegin();
00257   while(stateit!=rPd.StatesEnd()){
00258     rPd.DelState(*(stateit++)); // fixed: 2013-12-17
00259   }
00260     
00261   //map ears and stack symbols to their heads for later reference
00262   std::multimap<Idx,std::pair<Idx,Idx> > headEarMap;
00263   //map ears and stack symbols to the states of the old generator for later reference.
00264   //headMap<headIdx,oldIdx>, earMap<oldIdx,headIdx>
00265   std::map<Idx,Idx> headMap, earMap;
00266   
00267   StackSymbolSet::Iterator ssit;
00268   Idx newHead, newEar;
00269   //insert new states as ears and heads
00270   for(stateit = pd.StatesBegin(); stateit != pd.StatesEnd(); stateit++){
00271     
00272     //insert a head for each state in the old generator
00273     newHead = rPd.InsState();
00274     MergeStateSplit mss(*stateit);
00275     rPd.SetMerge(newHead, mss);
00276     rPd.SetDfaState(newHead,pd.DfaState(*stateit));
00277     
00278     //if the state was the initial state in the old generator, this head
00279     //is an initial state as well
00280     if(pd.ExistsInitState(*stateit)){
00281       rPd.SetInitState(newHead);
00282     }
00283     
00284     //save head in map
00285     headMap.insert(std::make_pair(*stateit,newHead));
00286         
00287     //insert an ear for each state in the old generator and each stack symbol
00288     //except lambda
00289     for(ssit = rPd.StackSymbolsBegin(); ssit != rPd.StackSymbolsEnd(); ssit++){
00290       if(!rPd.IsStackSymbolLambda(*ssit)){
00291         newEar = rPd.InsState();
00292         MergeStateSplit mss(*stateit, *ssit);
00293         rPd.SetMerge(newEar, mss);
00294         rPd.SetDfaState(newEar,pd.DfaState(*stateit));
00295         
00296         //if the state was a final state in the old generator, this ears
00297         //is a final state as well
00298         if(pd.ExistsMarkedState(*stateit)){
00299           rPd.SetMarkedState(newEar);
00300         }
00301         
00302         //save ear in map
00303         earMap.insert(std::make_pair(newEar, *stateit));
00304         //save pair of head and ear in map
00305         headEarMap.insert(std::make_pair(newHead,std::make_pair(newEar,*ssit)));
00306         
00307       }
00308     }
00309   }
00310   
00311   TransSet::Iterator transit;
00312   PopPushSet::const_iterator popPushit;
00313   std::multimap<Idx,std::pair<Idx,Idx> >::iterator headEarit;
00314   std::vector<Idx> ssvector;
00315   Idx head, ear, startState, endState, event;
00316   Idx stackSymbol;
00317   //insert transitions
00318   //iterate over all ears
00319   for(headEarit = headEarMap.begin(); headEarit != headEarMap.end(); headEarit++){
00320     
00321     //insert transition from head to ear
00322     head = headEarit->first;
00323     ear = headEarit->second.first;
00324     stackSymbol = headEarit->second.second;
00325     
00326     ssvector.clear();
00327     ssvector.push_back(stackSymbol);
00328     
00329     rPd.SetTransition(head, rPd.EventIndex(FAUDES_PD_LAMBDA), ear, ssvector, ssvector);
00330     
00331     //connect ears to heads
00332     for(transit = pd.TransRelBegin(); transit != pd.TransRelEnd(); transit++){
00333       for(popPushit = pd.PopPushBegin(*transit); popPushit != pd.PopPushEnd(*transit); popPushit++){
00334         
00335         //determine if this ear is associated with the transitions start state and
00336         //determine if the ear has the same stack symbol as the transition's
00337         //pop symbol (the pop vector is supposed to contain only one stack symbol).
00338         //if both are true:
00339         if(earMap.find(ear)->second == transit->X1 && stackSymbol == *popPushit->first.begin()){
00340           
00341           //look up the head associated with the transition's end state
00342           endState = headMap.find(transit->X2)->second;
00343           startState = ear;
00344           event = rPd.EventIndex(pd.EventName(transit->Ev));
00345           
00346           //insert transition from ear to head
00347           rPd.SetTransition(startState, event, endState, popPushit->first, popPushit->second);
00348         }
00349       }
00350     } 
00351   }
00352   return rPd;
00353 }
00354 
00355 /* *************************
00356  * Nonblock
00357  * *************************/
00358 void PushdownNonblock(const PushdownGenerator& pd, PushdownGenerator& res, bool print){
00359   
00360   //make DFA-coaccessible
00361 
00362   PushdownGenerator rPd = pd;
00363   rPd.Coaccessible();
00364    
00365   //restrict pd to read, pop and push rules
00366   if(print){
00367     rPd = Rpp(rPd);
00368     std::cout << "*******************" << std::endl;
00369     std::cout << "Nonblock rpp" << std::endl;
00370     std::cout << "*******************" << std::endl;
00371     rPd.Write();
00372   }
00373   else{
00374     rPd = Rpp(rPd);
00375   }
00376   
00377   
00378   //remove useless transitions created by rpp
00379   rPd = RemoveUselessTransitions(rPd);
00380  
00381   
00382   //remove double acceptance
00383   if(print){
00384     rPd = Nda(rPd);
00385     std::cout << "*******************" << std::endl;
00386     std::cout << "Nonblock nda" << std::endl;
00387     std::cout << "*******************" << std::endl;
00388     rPd.Write();
00389   }
00390   else{
00391     rPd = Nda(rPd);
00392   }
00393   
00394   rPd.Accessible();
00395   rPd.Coaccessible();
00396   rPd = TrimStackSymbols(rPd);
00397   
00398   //convert to grammar
00399   Grammar gr;
00400   if(print){
00401     gr = Sp2Lr2(rPd);
00402     std::cout << "*******************" << std::endl;
00403     std::cout << "Nonblock sp2lr" << std::endl;
00404     std::cout << "*******************" << std::endl;
00405     std::cout << gr.GrammarProductions().size() << std::endl;
00406     std::cout << gr.Str() << std::endl;
00407   }
00408   else{
00409     gr = Sp2Lr2(rPd);
00410   }
00411   
00412   //remove nonproductive productions
00413   gr = Rnpp(gr);
00414     
00415   //remove unreachable productions
00416   if(print){
00417     gr = Rup(gr);
00418     std::cout << "*******************" << std::endl;
00419     std::cout << "Nonblock rup" << std::endl;
00420     std::cout << "*******************" << std::endl;
00421     std::cout << gr.GrammarProductions().size() << std::endl;
00422     std::cout << gr.Str() << std::endl;
00423   }
00424   else{
00425     gr = Rup(gr);
00426   }
00427   
00428   //augment grammar 
00429   //create temporary automaton to create a new event for the augment terminal
00430   //and a new stack symbol for the augment nonterminal
00431   PushdownGenerator tempPd = rPd;
00432   //get fresh terminal
00433   Idx freshEventIdx;
00434   std::string freshEventName = "augSymbol";
00435   std::stringstream currentTry;
00436   currentTry << freshEventName;
00437   bool freshFound = false;
00438   int tries = 0;
00439   //try to get an unused event name to create a new terminal from
00440   while(!freshFound){
00441     if(tempPd.ExistsEvent(currentTry.str())){
00442       currentTry.clear();
00443       currentTry << freshEventName << tries;
00444       tries++;
00445       continue;
00446     }
00447     freshFound = true;
00448     freshEventIdx = tempPd.InsEvent(currentTry.str());
00449     
00450   }
00451   //create fresh terminal 
00452   Terminal t(freshEventIdx);  
00453  
00454 
00455   std::vector<Idx> v;
00456   //no need for this stack symbol to be unique, because no nonterminal should contain 0
00457   Idx stackSymbolIdx = tempPd.InsStackSymbol(StackSymbol("augSymbol"));
00458   v.push_back(stackSymbolIdx);
00459   Nonterminal nt(0,v);
00460   
00461   Grammar augGr = Aug(gr, nt, t);
00462   
00463   //construct the goto generator for the augmented grammar
00464   GotoGenerator gotoGen;
00465   if(print){
00466     gotoGen = Lrm(augGr,1);
00467     std::cout << "*******************" << std::endl;
00468     std::cout << "Nonblock lrm" << std::endl;
00469     std::cout << "*******************" << std::endl;
00470     gotoGen.Write();
00471   }
00472   else{
00473     gotoGen = Lrm(augGr,1);
00474   }
00475   
00476   //construct a parser for the grammar
00477   Lr1Parser parser;
00478   if(print){
00479     parser = Lrp(gr, augGr, gotoGen, 1, t);
00480     std::cout << "*******************" << std::endl;
00481     std::cout << "Nonblock lrp" << std::endl;
00482     std::cout << "*******************" << std::endl;
00483     std::cout <<parser.Str() << std::endl;
00484   }
00485   else{
00486     parser = Lrp(gr, augGr, gotoGen, 1, t);
00487   }
00488   
00489   //convert parser to pushdown generator
00490   if(print){
00491     rPd = Gp2Pp(gotoGen, parser);
00492     std::cout << "*******************" << std::endl;
00493     std::cout << "Nonblock gp2pp" << std::endl;
00494     std::cout << "*******************" << std::endl;
00495     rPd.Write();
00496   }
00497   else{
00498     rPd = Gp2Pp(gotoGen, parser);
00499   }
00500   
00501   //remove augmentation
00502   if(print){
00503     rPd = Dim(rPd, t);
00504     std::cout << "*******************" << std::endl;
00505     std::cout << "Nonblock dim" << std::endl;
00506     std::cout << "*******************" << std::endl;
00507     rPd.Write();
00508   }
00509   else{
00510     rPd = Dim(rPd, t);
00511   }
00512   
00513   //make the pushdown generator accessible
00514   if(print){
00515     rPd.Accessible();
00516     std::cout << "*******************" << std::endl;
00517     std::cout << "Nonblock accessible" << std::endl;
00518     std::cout << "*******************" << std::endl;
00519     rPd.Write();
00520   }
00521   else{
00522     rPd.Accessible();
00523   }
00524   
00525   //split transitions popping more than one stack symbol into more transitions
00526   if(print){
00527     rPd = Rep2(rPd);
00528     std::cout << "*******************" << std::endl;
00529     std::cout << "Nonblock rep2" << std::endl;
00530     std::cout << "*******************" << std::endl;
00531     rPd.Write();
00532   }
00533   else{
00534     rPd = Rep2(rPd);
00535   }
00536   
00537   //remove transitions popping lambda
00538   if(print){
00539     rPd = Rep0(rPd);
00540     std::cout << "*******************" << std::endl;
00541     std::cout << "Nonblock rep0" << std::endl;
00542     std::cout << "*******************" << std::endl;
00543     rPd.Write();
00544   }
00545   else{
00546     rPd = Rep0(rPd);
00547   }
00548   
00549   
00550   //remove useless transitions created by rep0
00551 
00552   if(print){
00553     rPd = RemoveUselessTransitions(rPd);
00554     std::cout << "*******************" << std::endl;
00555     std::cout << "Nonblock removeUselessTransitions" << std::endl;
00556     std::cout << "*******************" << std::endl;
00557     rPd.Write();
00558   }
00559   else{
00560     rPd = RemoveUselessTransitions(rPd);
00561   }
00562   
00563   
00564   //set correct flags for controllability and observability
00565   CorrectEvents(pd, rPd);
00566   
00567   res = rPd;
00568 }
00569 
00570 /* *************************
00571  * CorrectEvents
00572  * *************************/
00573 void CorrectEvents(const PushdownGenerator& correctPd, PushdownGenerator& pd){
00574   
00575   EventSet::Iterator correctevit, evit;
00576   for(evit = pd.AlphabetBegin(); evit != pd.AlphabetEnd(); evit++){
00577     for(correctevit = correctPd.AlphabetBegin(); correctevit != correctPd.AlphabetEnd(); correctevit++){
00578       if(*evit == *correctevit){
00579         //controllable 
00580         if(correctPd.Controllable(*correctevit)){
00581           pd.SetControllable(*evit);
00582         }
00583         //uncontrollable 
00584         else{
00585           pd.ClrControllable(*evit);
00586         }
00587         
00588         //observable 
00589         if(correctPd.Observable(*correctevit)){
00590           pd.SetObservable(*evit);
00591         }
00592         //uncontrollable 
00593         else{
00594           pd.ClrObservable(*evit);
00595         }
00596       }
00597     }
00598   }
00599 }
00600 
00601 /* *************************
00602  * Ts
00603  * *************************/
00604 bool Ts(const PushdownGenerator& pd, Idx state){
00605   
00606   //bool to return
00607   bool reachable = false;
00608   
00609   //take copy of the generator
00610   PushdownGenerator tempPd = pd;
00611   
00612   //delete all final states and set state as new final state
00613   tempPd.ClearMarkedStates();
00614   tempPd.InsMarkedState(state);
00615   
00616   //make DFA-accessible to speed up nonblock
00617   tempPd.Accessible();
00618   tempPd = TrimStackSymbols(tempPd);
00619 
00620   //make the generator nonblocking
00621   
00622   /*uint stateCount = tempPd.Size();
00623   uint transCount = tempPd.TransRelSize();
00624   std::cout << "states: " << stateCount << ", transitions: " << transCount << std::endl;
00625   timeval start, finish, result;
00626   gettimeofday(&start,0);*/
00627   
00628   PushdownGenerator temp;
00629   PushdownNonblock(tempPd, temp);
00630   tempPd = temp;
00631   
00632   /*gettimeofday(&finish,0);
00633   timeval_subtract(&result, &finish, &start);
00634   float secstate = (float)result.tv_sec/(float)stateCount;
00635   float sectrans = (float)result.tv_sec/(float)transCount;
00636   std::cout << "time taken: "  << result.tv_sec << "." << result.tv_usec << " sec, " <<  secstate << " sec/state, " << sectrans << " sec/transition" <<  std::endl;*/
00637   
00638   //if the generator still has final states, the original state was reachable
00639   if(tempPd.MarkedStatesSize() > 0){
00640     reachable = true;
00641   }
00642   return reachable;
00643 }
00644 
00645 /* *************************
00646  * Te
00647  * *************************/
00648 bool Te(const PushdownGenerator& pd, const Transition& trans, const std::vector<Idx>& pop, const std::vector<Idx>& push){
00649   
00650   //bool to return
00651   bool reachable = false;
00652   
00653   //take copy of the generator
00654   PushdownGenerator tempPd = pd;
00655   
00656   //remove the transition (q,x,w,w',q') from the generator
00657   tempPd.ClrTransition(trans,pop,push);
00658   
00659   //delete all final states and set state as new final state
00660   tempPd.ClearMarkedStates();
00661   Idx newState = tempPd.InsMarkedState();
00662   
00663   //insert transition (q,lambda,w,w,q'')
00664   tempPd.SetTransition(trans.X1,tempPd.EventIndex(FAUDES_PD_LAMBDA),newState,pop,pop);
00665 
00666   //make DFA-accessible to speed up nonblock
00667   tempPd.Accessible();
00668   tempPd = TrimStackSymbols(tempPd);
00669 
00670   
00671   
00672   //make the generator nonblocking
00673   
00674   /*uint stateCount = tempPd.Size();
00675   uint transCount = tempPd.TransRelSize();
00676   std::cout << "states: " << stateCount << ", transitions: " << transCount << std::endl;
00677   timeval start, finish, result;
00678   gettimeofday(&start,0);*/
00679   
00680   PushdownGenerator temp;
00681   PushdownNonblock(tempPd, temp);
00682   tempPd = temp;
00683   
00684   /*gettimeofday(&finish,0);
00685   timeval_subtract(&result, &finish, &start);
00686   float secstate = (float)result.tv_sec/(float)stateCount;
00687   float sectrans = (float)result.tv_sec/(float)transCount;
00688   std::cout << "time taken: "  << result.tv_sec << "." << result.tv_usec << " sec, " <<  secstate << " sec/state, " << sectrans << " sec/transition" <<  std::endl;*/
00689   
00690   //if the generator still has final states, the original state was reachable
00691   if(tempPd.MarkedStatesSize() > 0){
00692     reachable = true;
00693   }
00694   return reachable;
00695   
00696 }
00697 
00698 // /* *************************
00699 //  * Ruls
00700 //  * *************************/
00701 // PushdownGenerator Ruls(const PushdownGenerator& pd){
00702 //   
00703 //   //generator to return
00704 //   PushdownGenerator rPd = pd;
00705 //   
00706 //   //make DFA-Coaccessible to remove (hopefully a lot of) useless ears
00707 //   rPd.Coaccessible();
00708 //   
00709 //   PushdownGenerator tempPd = rPd;
00710 //   
00711 //   StateSet earsToDelete;
00712 //   StateSet::Iterator stateit;
00713 //   //iterate over all states of the generator and delete certain ears
00714 //   for(stateit = tempPd.StatesBegin(); stateit != tempPd.StatesEnd(); stateit++){
00715 //     
00716 //     //try to convert merge attribute of the state to MergeStateSplit
00717 //     const MergeStateSplit* mss = dynamic_cast<const MergeStateSplit*>(tempPd.Merge(*stateit));
00718 //     if(mss == NULL){
00719 //       std::stringstream errstr;
00720 //       errstr << "State in Ruls was neither head nor ear, check correctness of Merge attribute" << std::endl;
00721 //       throw Exception("Ruls", errstr.str(), 1001);
00722 //     }
00723 //     
00724 //     //only look at ears
00725 //     if(mss->IsHead()){
00726 //       continue;
00727 //     }
00728 //     
00729 //     //do not delete ears that are at the start of a transition
00730 //     if(tempPd.ExistsTransition(*stateit)){
00731 //       continue;
00732 //     }
00733 //     
00734 //     //do not delete final ears that are reachable
00735 //     if(tempPd.ExistsMarkedState(*stateit)){
00736 //       std::cout << "*** testing state " << *stateit << std::endl;
00737 //       if(Ts(tempPd, *stateit)){
00738 //         std::cout << "*** ... reachable" << std::endl;
00739 //         continue;
00740 //       }
00741 //       else{
00742 //           std::cout << "*** ... not reachable" << std::endl;
00743 //       }
00744 //     }
00745 //     
00746 //     //schedule all other ears for deletion
00747 //     earsToDelete.Insert(*stateit);
00748 //   }
00749 //   
00750 //   //delete ears
00751 //   rPd.DelStates(earsToDelete);
00752 //   
00753 //   return rPd;
00754 // }
00755 
00756 /* *************************
00757  * Ruls1
00758  * *************************/
00759 bool Ruls1(Idx state, const PushdownGenerator& pd){
00760   
00761   //try to convert merge attribute of the state to MergeStateSplit
00762     const MergeStateSplit* mss = dynamic_cast<const MergeStateSplit*>(pd.Merge(state));
00763     if(mss == NULL){
00764       std::stringstream errstr;
00765       errstr << "State in Ruls was neither head nor ear, check correctness of Merge attribute" << std::endl;
00766       throw Exception("Ruls", errstr.str(), 1001);
00767     }
00768     
00769     //only look at ears
00770     if(mss->IsHead()){
00771       return false;
00772     }
00773     
00774     //do not delete ears that are at the start of a transition
00775     if(pd.ExistsTransition(state)){
00776       return false;
00777     }
00778     
00779     //do not delete final ears that are reachable
00780     if(pd.ExistsMarkedState(state)){
00781 
00782       if(Ts(pd, state)){
00783         return false;
00784       }
00785       else{
00786         return true;
00787       }
00788     }
00789     //should never reach this
00790     return false;
00791 }
00792 
00793 /* *************************
00794  * Ruls
00795  * *************************/
00796 PushdownGenerator Ruls(const PushdownGenerator& pd){
00797   
00798   //generator to return
00799   PushdownGenerator rPd = pd;
00800   
00801   //make DFA-Coaccessible to remove (hopefully a lot of) useless ears
00802   rPd.Coaccessible();
00803     
00804   StateSet statesToKeep;
00805   StateSet::Iterator stateit=rPd.StatesBegin();
00806   
00807   //keep checking states until all the generator's states are checked
00808   while(stateit!=rPd.StatesEnd()){
00809     //test for usefulness
00810     if (Ruls1(*stateit,rPd)){
00811       //delete state if not useful
00812       rPd.DelState(*(stateit++)); // fixed: 2013-12-17
00813     }else
00814     stateit++;
00815   }
00816   
00817   return rPd;
00818 }
00819 
00820 /* *************************
00821  * PushdownAccessible
00822  * *************************/
00823 void PushdownAccessible(const PushdownGenerator& pd, PushdownGenerator& res){
00824  
00825   PushdownGenerator rPd = pd;
00826   
00827   //make DFA-accessible
00828   rPd.Accessible();
00829   //std::cout << "********* AC, after Accessible" << std::endl;
00830   //remove now-useless stack symbols
00831   rPd = TrimStackSymbols(rPd);
00832   //std::cout << "********* AC, after TrimStackSymbols" << std::endl;
00833   //rPd.Write();
00834   
00835   //rPd.Write();
00836   
00837   //iterate over all states to test DPA-accessibility
00838   StateSet states = rPd.States();
00839   StateSet::Iterator stateit=states.Begin();
00840   while(stateit != states.End()){    
00841     //disregard the start state
00842     if(rPd.ExistsInitState(*stateit)){
00843       stateit++;
00844       continue;
00845     }
00846     //test state for reachability
00847     if(!Ts(rPd, *stateit)){
00848       rPd.DelState(*(stateit++));
00849     }else (stateit++);
00850   }
00851   
00852   //iterate over the remaining transitions to test DPA-accessibility
00853   PushdownGenerator tempPd = rPd;
00854   TransSet::Iterator transit;
00855   PopPushSet::const_iterator ppit;
00856   for(transit = tempPd.TransRelBegin(); transit != tempPd.TransRelEnd(); transit++){
00857     for(ppit = tempPd.PopPushBegin(*transit); ppit != tempPd.PopPushEnd(*transit); ppit++){
00858 
00859       //test transition for reachability
00860       if(!Te(rPd, *transit, ppit->first, ppit->second)){
00861         rPd.ClrTransition(*transit, ppit->first, ppit->second);
00862       }
00863     }
00864   }
00865   
00866   res = rPd;
00867 }
00868 
00869 /* *************************
00870  * Ccs
00871  * *************************/
00872 PushdownGenerator Ccs(const PushdownGenerator& contr, const System& plant){
00873   
00874   //generator to return
00875   PushdownGenerator rPd;
00876 
00877   //create product generator
00878   
00879   rPd = Times(plant,contr);
00880 
00881   //trim the generator
00882   PushdownGenerator temp;
00883   PushdownAccessible(rPd,temp);
00884   rPd = temp;
00885   
00886   //remove useless stack symbols
00887   rPd = TrimStackSymbols(rPd);
00888   
00889   //split states into heads and ears
00890   rPd = Split(rPd);
00891   
00892   //remove useless states
00893   rPd = Ruls(rPd);
00894   //save number of states
00895   uint numberOfStates = rPd.Size();
00896 
00897   //remove noncontrollable ears
00898   rPd = Rnce(rPd, plant);
00899   
00900   //if states were removed
00901   if(numberOfStates != rPd.Size()){
00902     PushdownGenerator res;
00903     PushdownNonblock(rPd, res, true);
00904     return res;
00905   }
00906   
00907   //else  return the input because no modification was required in the first place
00908   return contr;
00909 }
00910 
00911 /* *************************
00912  * Ccl
00913  * *************************/
00914 PushdownGenerator Ccl(const PushdownGenerator& contr, const System& plant, Idx iteration){
00915   
00916   //generator to return
00917   PushdownGenerator rPd;
00918   
00919   //create controller candidate
00920   //create controller candidate
00921   rPd = Ccs(contr, plant);
00922   
00923   //termination condition: no states were removed
00924   if(rPd.Size() == contr.Size()){
00925     return contr;
00926   }
00927   //else reiterate
00928   rPd = Ccl(rPd, plant, iteration + 1);
00929   
00930   return rPd;
00931 }
00932 
00933 /* *************************
00934  * PushdownConstructController
00935  * *************************/
00936 void PushdownConstructController(const PushdownGenerator& spec, const System& plant, PushdownGenerator& res){
00937   
00938   //product of specification and plant
00939   PushdownGenerator rPd = Times(plant, spec);
00940   
00941   //make nonblocking
00942   PushdownGenerator temp;
00943   PushdownNonblock(rPd,temp);
00944   rPd = temp;
00945   
00946   //construct controller
00947   rPd = Ccl(rPd, plant, 1);
00948   
00949   res = rPd;
00950 }
00951 
00952 
00953 /* *************************
00954  * timeval_subtract
00955  * *************************/
00956 int timeval_subtract (timeval* result, timeval* x, timeval* y){
00957   /* Perform the carry for the later subtraction by updating y. */
00958   if (x->tv_usec < y->tv_usec) {
00959     int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
00960     y->tv_usec -= 1000000 * nsec;
00961     y->tv_sec += nsec;
00962   }
00963   if (x->tv_usec - y->tv_usec > 1000000) {
00964     int nsec = (x->tv_usec - y->tv_usec) / 1000000;
00965     y->tv_usec += 1000000 * nsec;
00966     y->tv_sec -= nsec;
00967   }
00968 
00969   /* Compute the time remaining to wait.
00970     tv_usec is certainly positive. */
00971   result->tv_sec = x->tv_sec - y->tv_sec;
00972   result->tv_usec = x->tv_usec - y->tv_usec;
00973 
00974   /* Return 1 if result is negative. */
00975   return x->tv_sec < y->tv_sec;
00976 }
00977   
00978 } // namespace faudes
00979 

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