pd_alg_cc.cpp
Go to the documentation of this file.
1 /** @file pd_alg_cc.cpp Top-level functions*/
2 
3 
4 /* Pushdown plugin for FAU Discrete Event Systems Library (libfaudes)
5 
6  Copyright (C) 2013 Stefan Jacobi, Sven Schneider, Anne-Kathrin Hess
7 
8 */
9 
10 #include "pd_alg_cc.h"
11 
12 namespace faudes {
13 
14 
15 /* *************************
16  * Transient
17  * *************************/
19 
20  TransSet::Iterator transit;
21  StateSet rStates;
22  //iterate over all transitions
23  for(transit = pd.TransRelBegin(); transit != pd.TransRelEnd(); transit++){
24 
25  //add start state of lambda read transition to set
26  if(pd.IsEventLambda(transit->Ev)){
27  rStates.Insert(transit->X1);
28  }
29  }
30 
31  return rStates;
32 }
33 
34 /* *************************
35  * Rnce
36  * *************************/
38 
39  StateSet transientStates = Transient(pd);
40  StateSet ucEars;
42  StateSet::Iterator stateit;
43  EventSet::Iterator eventit;
44  Idx oldState;
45 
46  //iterate over all states
47  for(stateit = pd.StatesBegin(); stateit != pd.StatesEnd(); stateit++){
48 
49  //get the merge attribute, which must must be either an ear or a heads
50  const MergeStateSplit* mss = dynamic_cast<const MergeStateSplit*>(pd.Merge(*stateit));
51  if(mss == NULL){
52  std::stringstream errstr;
53  errstr << "State in Rnce was neither head nor ear, check correctness of Merge attribute" << std::endl;
54  throw Exception("Rnce", errstr.str(), 1001);
55  }
56 
57  //only look at ears
58  if(mss->IsHead()){
59  continue;
60  }
61 
62  //only look at transient ears
63  if(transientStates.Exists(*stateit)){
64  continue;
65  }
66 
67  //check the current state for each uncontrollable event
68  for(eventit = uc.Begin(); eventit != uc.End(); eventit++){
69 
70  //only look at states whose corresponding dfa state allows this
71  //uncontrollable event
72  oldState = pd.DfaState(*stateit);
73  if(!s.ExistsTransition(oldState,*eventit)){
74  continue;
75  }
76 
77  //only look at states that do not allow the uncontrollable event to happen
78  if(pd.ExistsTransition(*stateit,*eventit)){
79  continue;
80  }
81 
82  //all these states are uncontrollable ears
83  ucEars.Insert(*stateit);
84  }
85  }
86  PushdownGenerator rPd = pd;
87  rPd.DelStates(ucEars);
88  return rPd;
89 }
90 
91 /* *************************
92  * Times
93  * *************************/
95 
96  //result generator
98 
99  //map to remember which states get merged into which
100  std::map<std::pair<Idx,Idx>, Idx > stateMap;
101 
102  StateSet::Iterator pdStateit, sStateit;
103  Idx newState;
104  std::vector<Idx> oldStatesVector;
105  //construct states as cartesian prodcut of both generators states
106  for(pdStateit = pd.StatesBegin(); pdStateit != pd.StatesEnd(); pdStateit++){
107  for(sStateit = s.StatesBegin(); sStateit != s.StatesEnd(); sStateit++){
108 
109  //add new state for each pair of states and save it in the map
110  newState = rPd.InsState();
111  stateMap.insert(std::make_pair(std::make_pair(*sStateit, *pdStateit), newState));
112 
113  //add information about parent states
114  oldStatesVector.clear();
115  oldStatesVector.push_back(*sStateit);
116  oldStatesVector.push_back(*pdStateit);
117  MergeStates oldStates = MergeStates(oldStatesVector);
118  rPd.SetMerge(newState,oldStates);
119  rPd.SetDfaState(newState,*sStateit);
120 
121  //if both states are init states, the new state is an init state as well
122  if(*pdStateit == pd.InitState() && *sStateit == s.InitState()){
123  rPd.SetInitState(newState);
124  }
125 
126  //if both states are final states, the new state is a final state as well
127  if(pd.ExistsMarkedState(*pdStateit) && s.ExistsMarkedState(*sStateit)){
128  rPd.SetMarkedState(newState);
129  }
130  }
131  }
132 
133  //stack symbols are the same as the pushdown generator's stack symbols
134  rPd.InsStackSymbols(pd.StackSymbols());
135 
136  //stack bottom is the same as the pushdown generator's stack bottom
138 
139  //the new event set is the intersection of both old event sets
140  IntersectEvents(s,pd,rPd);
141 
142  //add lambda event if there was a lambda event in the pushdown generator's event set
143  if(pd.Alphabet().Exists(FAUDES_PD_LAMBDA)){
145  }
146 
147  Idx newX1, newX2;
148  std::string sEvName, pdEvName;
149  //add transitions to rPd. Iterate over all pushdown generator transitions
150  TransSet::Iterator pdTransit, sTransit;
151  PopPushSet::const_iterator ppsit;
152  for(pdTransit = pd.TransRelBegin(); pdTransit != pd.TransRelEnd(); pdTransit++){
153 
154  //look at every pop push set of the transition
155  for(ppsit = pd.PopPushBegin(*pdTransit); ppsit != pd.PopPushEnd(*pdTransit); ppsit++){
156 
157  pdEvName = pd.EventName(pdTransit->Ev);
158  //for every no-read transition (q,lambda,w,w',q') of pd and every state p of s,
159  //add a transition ((p,q),lambda,w,w',(p,q'))
160  if(pdEvName.compare(FAUDES_PD_LAMBDA) == 0){
161  for(sStateit = s.StatesBegin(); sStateit != s.StatesEnd(); sStateit++){
162 
163  //find new states corresponding to (p,q), and (p,q')
164  newX1 = stateMap.find(std::make_pair(*sStateit, pdTransit->X1))->second;
165  newX2 = stateMap.find(std::make_pair(*sStateit, pdTransit->X2))->second;
166 
167  //add transition
168  rPd.SetTransition(newX1, rPd.EventIndex(FAUDES_PD_LAMBDA), newX2, ppsit->first, ppsit->second);
169  }
170  }
171  //for every read transition (q,a,w,w',q') of pd and every transition (p,a,p')
172  //of s, add a transition ((p,q),a,w,w',(p',q'))
173  else{
174 
175  //iterate over all system transitions
176  for(sTransit = s.TransRelBegin(); sTransit != s.TransRelEnd(); sTransit++){
177 
178  sEvName = s.EventName(sTransit->Ev);
179  //compare the transition events
180  if(pdEvName.compare(sEvName) == 0){
181 
182  //find new states corresponding to (p,q), and (p',q')
183  newX1 = stateMap.find(std::make_pair(sTransit->X1, pdTransit->X1))->second;
184  newX2 = stateMap.find(std::make_pair(sTransit->X2, pdTransit->X2))->second;
185 
186  //add transition
187  rPd.SetTransition(newX1, rPd.EventIndex(sEvName), newX2, ppsit->first, ppsit->second);
188  }
189  }
190  }
191  }
192  }
193  return rPd;
194 }
195 
196 
197 /* *************************
198  * IntersectEvents
199  * *************************/
201  EventSet::Iterator pdEventit, sEventit;
202  for(pdEventit = pd.AlphabetBegin(); pdEventit != pd.AlphabetEnd(); pdEventit++){
203  for(sEventit = s.AlphabetBegin(); sEventit != s.AlphabetEnd(); sEventit++){
204  if(*pdEventit == *sEventit){
205  //controllable and observable
206  if(pd.Controllable(*pdEventit) &&
207  s.Controllable(*sEventit) &&
208  pd.Observable(*pdEventit) &&
209  s.Observable(*sEventit))
210  {
211  rPd.InsControllableEvent(*pdEventit);
212  }
213  //controllable and not observable
214  else if(pd.Controllable(*pdEventit) &&
215  s.Controllable(*sEventit) &&
216  !pd.Observable(*pdEventit) &&
217  !s.Observable(*sEventit))
218  {
219  rPd.InsControllableEvent(*pdEventit);
220  rPd.ClrObservable(*pdEventit);
221  }
222  //not controllable, but observable
223  else if(!pd.Controllable(*pdEventit) &&
224  !s.Controllable(*sEventit) &&
225  pd.Observable(*pdEventit) &&
226  s.Observable(*sEventit))
227  {
228  rPd.InsEvent(*pdEventit);
229  }
230  //neither controllable nor observable
231  else if(!pd.Controllable(*pdEventit) &&
232  !s.Controllable(*sEventit) &&
233  !pd.Observable(*pdEventit) &&
234  !s.Observable(*sEventit))
235  {
236  rPd.InsUnobservableEvent(*pdEventit);
237  }
238  }
239  }
240  }
241 }
242 
243 /* *************************
244  * Split
245  * *************************/
247 
248  //copy the generator
249  PushdownGenerator rPd = pd;
250 
251  //insert lambda event in case it has not already been added
253 
254  //clear transition relation and states, because they will be replaced
255  rPd.ClearTransRel();
256  StateSet::Iterator stateit=rPd.StatesBegin();
257  while(stateit!=rPd.StatesEnd()){
258  rPd.DelState(*(stateit++)); // fixed: 2013-12-17
259  }
260 
261  //map ears and stack symbols to their heads for later reference
262  std::multimap<Idx,std::pair<Idx,Idx> > headEarMap;
263  //map ears and stack symbols to the states of the old generator for later reference.
264  //headMap<headIdx,oldIdx>, earMap<oldIdx,headIdx>
265  std::map<Idx,Idx> headMap, earMap;
266 
267  StackSymbolSet::Iterator ssit;
268  Idx newHead, newEar;
269  //insert new states as ears and heads
270  for(stateit = pd.StatesBegin(); stateit != pd.StatesEnd(); stateit++){
271 
272  //insert a head for each state in the old generator
273  newHead = rPd.InsState();
274  MergeStateSplit mss(*stateit);
275  rPd.SetMerge(newHead, mss);
276  rPd.SetDfaState(newHead,pd.DfaState(*stateit));
277 
278  //if the state was the initial state in the old generator, this head
279  //is an initial state as well
280  if(pd.ExistsInitState(*stateit)){
281  rPd.SetInitState(newHead);
282  }
283 
284  //save head in map
285  headMap.insert(std::make_pair(*stateit,newHead));
286 
287  //insert an ear for each state in the old generator and each stack symbol
288  //except lambda
289  for(ssit = rPd.StackSymbolsBegin(); ssit != rPd.StackSymbolsEnd(); ssit++){
290  if(!rPd.IsStackSymbolLambda(*ssit)){
291  newEar = rPd.InsState();
292  MergeStateSplit mss(*stateit, *ssit);
293  rPd.SetMerge(newEar, mss);
294  rPd.SetDfaState(newEar,pd.DfaState(*stateit));
295 
296  //if the state was a final state in the old generator, this ears
297  //is a final state as well
298  if(pd.ExistsMarkedState(*stateit)){
299  rPd.SetMarkedState(newEar);
300  }
301 
302  //save ear in map
303  earMap.insert(std::make_pair(newEar, *stateit));
304  //save pair of head and ear in map
305  headEarMap.insert(std::make_pair(newHead,std::make_pair(newEar,*ssit)));
306 
307  }
308  }
309  }
310 
311  TransSet::Iterator transit;
312  PopPushSet::const_iterator popPushit;
313  std::multimap<Idx,std::pair<Idx,Idx> >::iterator headEarit;
314  std::vector<Idx> ssvector;
315  Idx head, ear, startState, endState, event;
316  Idx stackSymbol;
317  //insert transitions
318  //iterate over all ears
319  for(headEarit = headEarMap.begin(); headEarit != headEarMap.end(); headEarit++){
320 
321  //insert transition from head to ear
322  head = headEarit->first;
323  ear = headEarit->second.first;
324  stackSymbol = headEarit->second.second;
325 
326  ssvector.clear();
327  ssvector.push_back(stackSymbol);
328 
329  rPd.SetTransition(head, rPd.EventIndex(FAUDES_PD_LAMBDA), ear, ssvector, ssvector);
330 
331  //connect ears to heads
332  for(transit = pd.TransRelBegin(); transit != pd.TransRelEnd(); transit++){
333  for(popPushit = pd.PopPushBegin(*transit); popPushit != pd.PopPushEnd(*transit); popPushit++){
334 
335  //determine if this ear is associated with the transitions start state and
336  //determine if the ear has the same stack symbol as the transition's
337  //pop symbol (the pop vector is supposed to contain only one stack symbol).
338  //if both are true:
339  if(earMap.find(ear)->second == transit->X1 && stackSymbol == *popPushit->first.begin()){
340 
341  //look up the head associated with the transition's end state
342  endState = headMap.find(transit->X2)->second;
343  startState = ear;
344  event = rPd.EventIndex(pd.EventName(transit->Ev));
345 
346  //insert transition from ear to head
347  rPd.SetTransition(startState, event, endState, popPushit->first, popPushit->second);
348  }
349  }
350  }
351  }
352  return rPd;
353 }
354 
355 /* *************************
356  * Nonblock
357  * *************************/
358 void PushdownNonblock(const PushdownGenerator& pd, PushdownGenerator& res, bool print){
359 
360  //make DFA-coaccessible
361 
362  PushdownGenerator rPd = pd;
363  rPd.Coaccessible();
364 
365  //restrict pd to read, pop and push rules
366  if(print){
367  rPd = Rpp(rPd);
368  std::cout << "*******************" << std::endl;
369  std::cout << "Nonblock rpp" << std::endl;
370  std::cout << "*******************" << std::endl;
371  rPd.Write();
372  }
373  else{
374  rPd = Rpp(rPd);
375  }
376 
377 
378  //remove useless transitions created by rpp
379  rPd = RemoveUselessTransitions(rPd);
380 
381 
382  //remove double acceptance
383  if(print){
384  rPd = Nda(rPd);
385  std::cout << "*******************" << std::endl;
386  std::cout << "Nonblock nda" << std::endl;
387  std::cout << "*******************" << std::endl;
388  rPd.Write();
389  }
390  else{
391  rPd = Nda(rPd);
392  }
393 
394  rPd.Accessible();
395  rPd.Coaccessible();
396  rPd = TrimStackSymbols(rPd);
397 
398  //convert to grammar
399  Grammar gr;
400  if(print){
401  gr = Sp2Lr2(rPd);
402  std::cout << "*******************" << std::endl;
403  std::cout << "Nonblock sp2lr" << std::endl;
404  std::cout << "*******************" << std::endl;
405  std::cout << gr.GrammarProductions().size() << std::endl;
406  std::cout << gr.Str() << std::endl;
407  }
408  else{
409  gr = Sp2Lr2(rPd);
410  }
411 
412  //remove nonproductive productions
413  gr = Rnpp(gr);
414 
415  //remove unreachable productions
416  if(print){
417  gr = Rup(gr);
418  std::cout << "*******************" << std::endl;
419  std::cout << "Nonblock rup" << std::endl;
420  std::cout << "*******************" << std::endl;
421  std::cout << gr.GrammarProductions().size() << std::endl;
422  std::cout << gr.Str() << std::endl;
423  }
424  else{
425  gr = Rup(gr);
426  }
427 
428  //augment grammar
429  //create temporary automaton to create a new event for the augment terminal
430  //and a new stack symbol for the augment nonterminal
431  PushdownGenerator tempPd = rPd;
432  //get fresh terminal
433  Idx freshEventIdx;
434  std::string freshEventName = "augSymbol";
435  std::stringstream currentTry;
436  currentTry << freshEventName;
437  bool freshFound = false;
438  int tries = 0;
439  //try to get an unused event name to create a new terminal from
440  while(!freshFound){
441  if(tempPd.ExistsEvent(currentTry.str())){
442  currentTry.clear();
443  currentTry << freshEventName << tries;
444  tries++;
445  continue;
446  }
447  freshFound = true;
448  freshEventIdx = tempPd.InsEvent(currentTry.str());
449 
450  }
451  //create fresh terminal
452  Terminal t(freshEventIdx);
453 
454 
455  std::vector<Idx> v;
456  //no need for this stack symbol to be unique, because no nonterminal should contain 0
457  Idx stackSymbolIdx = tempPd.InsStackSymbol(StackSymbol("augSymbol"));
458  v.push_back(stackSymbolIdx);
459  Nonterminal nt(0,v);
460 
461  Grammar augGr = Aug(gr, nt, t);
462 
463  //construct the goto generator for the augmented grammar
464  GotoGenerator gotoGen;
465  if(print){
466  gotoGen = Lrm(augGr,1);
467  std::cout << "*******************" << std::endl;
468  std::cout << "Nonblock lrm" << std::endl;
469  std::cout << "*******************" << std::endl;
470  gotoGen.Write();
471  }
472  else{
473  gotoGen = Lrm(augGr,1);
474  }
475 
476  //construct a parser for the grammar
477  Lr1Parser parser;
478  if(print){
479  parser = Lrp(gr, augGr, gotoGen, 1, t);
480  std::cout << "*******************" << std::endl;
481  std::cout << "Nonblock lrp" << std::endl;
482  std::cout << "*******************" << std::endl;
483  std::cout <<parser.Str() << std::endl;
484  }
485  else{
486  parser = Lrp(gr, augGr, gotoGen, 1, t);
487  }
488 
489  //convert parser to pushdown generator
490  if(print){
491  rPd = Gp2Pp(gotoGen, parser);
492  std::cout << "*******************" << std::endl;
493  std::cout << "Nonblock gp2pp" << std::endl;
494  std::cout << "*******************" << std::endl;
495  rPd.Write();
496  }
497  else{
498  rPd = Gp2Pp(gotoGen, parser);
499  }
500 
501  //remove augmentation
502  if(print){
503  rPd = Dim(rPd, t);
504  std::cout << "*******************" << std::endl;
505  std::cout << "Nonblock dim" << std::endl;
506  std::cout << "*******************" << std::endl;
507  rPd.Write();
508  }
509  else{
510  rPd = Dim(rPd, t);
511  }
512 
513  //make the pushdown generator accessible
514  if(print){
515  rPd.Accessible();
516  std::cout << "*******************" << std::endl;
517  std::cout << "Nonblock accessible" << std::endl;
518  std::cout << "*******************" << std::endl;
519  rPd.Write();
520  }
521  else{
522  rPd.Accessible();
523  }
524 
525  //split transitions popping more than one stack symbol into more transitions
526  if(print){
527  rPd = Rep2(rPd);
528  std::cout << "*******************" << std::endl;
529  std::cout << "Nonblock rep2" << std::endl;
530  std::cout << "*******************" << std::endl;
531  rPd.Write();
532  }
533  else{
534  rPd = Rep2(rPd);
535  }
536 
537  //remove transitions popping lambda
538  if(print){
539  rPd = Rep0(rPd);
540  std::cout << "*******************" << std::endl;
541  std::cout << "Nonblock rep0" << std::endl;
542  std::cout << "*******************" << std::endl;
543  rPd.Write();
544  }
545  else{
546  rPd = Rep0(rPd);
547  }
548 
549 
550  //remove useless transitions created by rep0
551 
552  if(print){
553  rPd = RemoveUselessTransitions(rPd);
554  std::cout << "*******************" << std::endl;
555  std::cout << "Nonblock removeUselessTransitions" << std::endl;
556  std::cout << "*******************" << std::endl;
557  rPd.Write();
558  }
559  else{
560  rPd = RemoveUselessTransitions(rPd);
561  }
562 
563 
564  //set correct flags for controllability and observability
565  CorrectEvents(pd, rPd);
566 
567  res = rPd;
568 }
569 
570 /* *************************
571  * CorrectEvents
572  * *************************/
574 
575  EventSet::Iterator correctevit, evit;
576  for(evit = pd.AlphabetBegin(); evit != pd.AlphabetEnd(); evit++){
577  for(correctevit = correctPd.AlphabetBegin(); correctevit != correctPd.AlphabetEnd(); correctevit++){
578  if(*evit == *correctevit){
579  //controllable
580  if(correctPd.Controllable(*correctevit)){
581  pd.SetControllable(*evit);
582  }
583  //uncontrollable
584  else{
585  pd.ClrControllable(*evit);
586  }
587 
588  //observable
589  if(correctPd.Observable(*correctevit)){
590  pd.SetObservable(*evit);
591  }
592  //uncontrollable
593  else{
594  pd.ClrObservable(*evit);
595  }
596  }
597  }
598  }
599 }
600 
601 /* *************************
602  * Ts
603  * *************************/
604 bool Ts(const PushdownGenerator& pd, Idx state){
605 
606  //bool to return
607  bool reachable = false;
608 
609  //take copy of the generator
610  PushdownGenerator tempPd = pd;
611 
612  //delete all final states and set state as new final state
613  tempPd.ClearMarkedStates();
614  tempPd.InsMarkedState(state);
615 
616  //make DFA-accessible to speed up nonblock
617  tempPd.Accessible();
618  tempPd = TrimStackSymbols(tempPd);
619 
620  //make the generator nonblocking
621 
622  /*uint stateCount = tempPd.Size();
623  uint transCount = tempPd.TransRelSize();
624  std::cout << "states: " << stateCount << ", transitions: " << transCount << std::endl;
625  timeval start, finish, result;
626  gettimeofday(&start,0);*/
627 
628  PushdownGenerator temp;
629  PushdownNonblock(tempPd, temp);
630  tempPd = temp;
631 
632  /*gettimeofday(&finish,0);
633  timeval_subtract(&result, &finish, &start);
634  float secstate = (float)result.tv_sec/(float)stateCount;
635  float sectrans = (float)result.tv_sec/(float)transCount;
636  std::cout << "time taken: " << result.tv_sec << "." << result.tv_usec << " sec, " << secstate << " sec/state, " << sectrans << " sec/transition" << std::endl;*/
637 
638  //if the generator still has final states, the original state was reachable
639  if(tempPd.MarkedStatesSize() > 0){
640  reachable = true;
641  }
642  return reachable;
643 }
644 
645 /* *************************
646  * Te
647  * *************************/
648 bool Te(const PushdownGenerator& pd, const Transition& trans, const std::vector<Idx>& pop, const std::vector<Idx>& push){
649 
650  //bool to return
651  bool reachable = false;
652 
653  //take copy of the generator
654  PushdownGenerator tempPd = pd;
655 
656  //remove the transition (q,x,w,w',q') from the generator
657  tempPd.ClrTransition(trans,pop,push);
658 
659  //delete all final states and set state as new final state
660  tempPd.ClearMarkedStates();
661  Idx newState = tempPd.InsMarkedState();
662 
663  //insert transition (q,lambda,w,w,q'')
664  tempPd.SetTransition(trans.X1,tempPd.EventIndex(FAUDES_PD_LAMBDA),newState,pop,pop);
665 
666  //make DFA-accessible to speed up nonblock
667  tempPd.Accessible();
668  tempPd = TrimStackSymbols(tempPd);
669 
670 
671 
672  //make the generator nonblocking
673 
674  /*uint stateCount = tempPd.Size();
675  uint transCount = tempPd.TransRelSize();
676  std::cout << "states: " << stateCount << ", transitions: " << transCount << std::endl;
677  timeval start, finish, result;
678  gettimeofday(&start,0);*/
679 
680  PushdownGenerator temp;
681  PushdownNonblock(tempPd, temp);
682  tempPd = temp;
683 
684  /*gettimeofday(&finish,0);
685  timeval_subtract(&result, &finish, &start);
686  float secstate = (float)result.tv_sec/(float)stateCount;
687  float sectrans = (float)result.tv_sec/(float)transCount;
688  std::cout << "time taken: " << result.tv_sec << "." << result.tv_usec << " sec, " << secstate << " sec/state, " << sectrans << " sec/transition" << std::endl;*/
689 
690  //if the generator still has final states, the original state was reachable
691  if(tempPd.MarkedStatesSize() > 0){
692  reachable = true;
693  }
694  return reachable;
695 
696 }
697 
698 // /* *************************
699 // * Ruls
700 // * *************************/
701 // PushdownGenerator Ruls(const PushdownGenerator& pd){
702 //
703 // //generator to return
704 // PushdownGenerator rPd = pd;
705 //
706 // //make DFA-Coaccessible to remove (hopefully a lot of) useless ears
707 // rPd.Coaccessible();
708 //
709 // PushdownGenerator tempPd = rPd;
710 //
711 // StateSet earsToDelete;
712 // StateSet::Iterator stateit;
713 // //iterate over all states of the generator and delete certain ears
714 // for(stateit = tempPd.StatesBegin(); stateit != tempPd.StatesEnd(); stateit++){
715 //
716 // //try to convert merge attribute of the state to MergeStateSplit
717 // const MergeStateSplit* mss = dynamic_cast<const MergeStateSplit*>(tempPd.Merge(*stateit));
718 // if(mss == NULL){
719 // std::stringstream errstr;
720 // errstr << "State in Ruls was neither head nor ear, check correctness of Merge attribute" << std::endl;
721 // throw Exception("Ruls", errstr.str(), 1001);
722 // }
723 //
724 // //only look at ears
725 // if(mss->IsHead()){
726 // continue;
727 // }
728 //
729 // //do not delete ears that are at the start of a transition
730 // if(tempPd.ExistsTransition(*stateit)){
731 // continue;
732 // }
733 //
734 // //do not delete final ears that are reachable
735 // if(tempPd.ExistsMarkedState(*stateit)){
736 // std::cout << "*** testing state " << *stateit << std::endl;
737 // if(Ts(tempPd, *stateit)){
738 // std::cout << "*** ... reachable" << std::endl;
739 // continue;
740 // }
741 // else{
742 // std::cout << "*** ... not reachable" << std::endl;
743 // }
744 // }
745 //
746 // //schedule all other ears for deletion
747 // earsToDelete.Insert(*stateit);
748 // }
749 //
750 // //delete ears
751 // rPd.DelStates(earsToDelete);
752 //
753 // return rPd;
754 // }
755 
756 /* *************************
757  * Ruls1
758  * *************************/
759 bool Ruls1(Idx state, const PushdownGenerator& pd){
760 
761  //try to convert merge attribute of the state to MergeStateSplit
762  const MergeStateSplit* mss = dynamic_cast<const MergeStateSplit*>(pd.Merge(state));
763  if(mss == NULL){
764  std::stringstream errstr;
765  errstr << "State in Ruls was neither head nor ear, check correctness of Merge attribute" << std::endl;
766  throw Exception("Ruls", errstr.str(), 1001);
767  }
768 
769  //only look at ears
770  if(mss->IsHead()){
771  return false;
772  }
773 
774  //do not delete ears that are at the start of a transition
775  if(pd.ExistsTransition(state)){
776  return false;
777  }
778 
779  //do not delete final ears that are reachable
780  if(pd.ExistsMarkedState(state)){
781 
782  if(Ts(pd, state)){
783  return false;
784  }
785  else{
786  return true;
787  }
788  }
789  //should never reach this
790  return false;
791 }
792 
793 /* *************************
794  * Ruls
795  * *************************/
797 
798  //generator to return
799  PushdownGenerator rPd = pd;
800 
801  //make DFA-Coaccessible to remove (hopefully a lot of) useless ears
802  rPd.Coaccessible();
803 
804  StateSet statesToKeep;
805  StateSet::Iterator stateit=rPd.StatesBegin();
806 
807  //keep checking states until all the generator's states are checked
808  while(stateit!=rPd.StatesEnd()){
809  //test for usefulness
810  if (Ruls1(*stateit,rPd)){
811  //delete state if not useful
812  rPd.DelState(*(stateit++)); // fixed: 2013-12-17
813  }else
814  stateit++;
815  }
816 
817  return rPd;
818 }
819 
820 /* *************************
821  * PushdownAccessible
822  * *************************/
824 
825  PushdownGenerator rPd = pd;
826 
827  //make DFA-accessible
828  rPd.Accessible();
829  //std::cout << "********* AC, after Accessible" << std::endl;
830  //remove now-useless stack symbols
831  rPd = TrimStackSymbols(rPd);
832  //std::cout << "********* AC, after TrimStackSymbols" << std::endl;
833  //rPd.Write();
834 
835  //rPd.Write();
836 
837  //iterate over all states to test DPA-accessibility
838  StateSet states = rPd.States();
839  StateSet::Iterator stateit=states.Begin();
840  while(stateit != states.End()){
841  //disregard the start state
842  if(rPd.ExistsInitState(*stateit)){
843  stateit++;
844  continue;
845  }
846  //test state for reachability
847  if(!Ts(rPd, *stateit)){
848  rPd.DelState(*(stateit++));
849  }else (stateit++);
850  }
851 
852  //iterate over the remaining transitions to test DPA-accessibility
853  PushdownGenerator tempPd = rPd;
854  TransSet::Iterator transit;
855  PopPushSet::const_iterator ppit;
856  for(transit = tempPd.TransRelBegin(); transit != tempPd.TransRelEnd(); transit++){
857  for(ppit = tempPd.PopPushBegin(*transit); ppit != tempPd.PopPushEnd(*transit); ppit++){
858 
859  //test transition for reachability
860  if(!Te(rPd, *transit, ppit->first, ppit->second)){
861  rPd.ClrTransition(*transit, ppit->first, ppit->second);
862  }
863  }
864  }
865 
866  res = rPd;
867 }
868 
869 /* *************************
870  * Ccs
871  * *************************/
872 PushdownGenerator Ccs(const PushdownGenerator& contr, const System& plant){
873 
874  //generator to return
875  PushdownGenerator rPd;
876 
877  //create product generator
878 
879  rPd = Times(plant,contr);
880 
881  //trim the generator
882  PushdownGenerator temp;
883  PushdownAccessible(rPd,temp);
884  rPd = temp;
885 
886  //remove useless stack symbols
887  rPd = TrimStackSymbols(rPd);
888 
889  //split states into heads and ears
890  rPd = Split(rPd);
891 
892  //remove useless states
893  rPd = Ruls(rPd);
894  //save number of states
895  uint numberOfStates = rPd.Size();
896 
897  //remove noncontrollable ears
898  rPd = Rnce(rPd, plant);
899 
900  //if states were removed
901  if(numberOfStates != rPd.Size()){
902  PushdownGenerator res;
903  PushdownNonblock(rPd, res, true);
904  return res;
905  }
906 
907  //else return the input because no modification was required in the first place
908  return contr;
909 }
910 
911 /* *************************
912  * Ccl
913  * *************************/
914 PushdownGenerator Ccl(const PushdownGenerator& contr, const System& plant, Idx iteration){
915 
916  //generator to return
917  PushdownGenerator rPd;
918 
919  //create controller candidate
920  //create controller candidate
921  rPd = Ccs(contr, plant);
922 
923  //termination condition: no states were removed
924  if(rPd.Size() == contr.Size()){
925  return contr;
926  }
927  //else reiterate
928  rPd = Ccl(rPd, plant, iteration + 1);
929 
930  return rPd;
931 }
932 
933 /* *************************
934  * PushdownConstructController
935  * *************************/
937 
938  //product of specification and plant
939  PushdownGenerator rPd = Times(plant, spec);
940 
941  //make nonblocking
942  PushdownGenerator temp;
943  PushdownNonblock(rPd,temp);
944  rPd = temp;
945 
946  //construct controller
947  rPd = Ccl(rPd, plant, 1);
948 
949  res = rPd;
950 }
951 
952 
953 /* *************************
954  * timeval_subtract
955  * *************************/
956 int timeval_subtract (timeval* result, timeval* x, timeval* y){
957  /* Perform the carry for the later subtraction by updating y. */
958  if (x->tv_usec < y->tv_usec) {
959  int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
960  y->tv_usec -= 1000000 * nsec;
961  y->tv_sec += nsec;
962  }
963  if (x->tv_usec - y->tv_usec > 1000000) {
964  int nsec = (x->tv_usec - y->tv_usec) / 1000000;
965  y->tv_usec += 1000000 * nsec;
966  y->tv_sec -= nsec;
967  }
968 
969  /* Compute the time remaining to wait.
970  tv_usec is certainly positive. */
971  result->tv_sec = x->tv_sec - y->tv_sec;
972  result->tv_usec = x->tv_usec - y->tv_usec;
973 
974  /* Return 1 if result is negative. */
975  return x->tv_sec < y->tv_sec;
976 }
977 
978 } // namespace faudes
979 

libFAUDES 2.24g --- 2014.09.15 --- c++ api documentaion by doxygen