pd_alg_cc.cppGo 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 |