pd_alg_sub.cpp
Go to the documentation of this file.
1 /** @file pd_alg_nb_sub_a.cpp Blockfree and Accessible subfunctions */
2 
3 
4 /* Pushdown plugin for FAU Discrete Event Systems Library (libfaudes)
5 
6  Copyright (C) 2013/14 Ramon Barakat, Stefan Jacobi, Sven Schneider, Anne-Kathrin Hess
7 
8 */
9 
10 #include "pd_alg_sub.h"
11 
12 namespace faudes {
13 
14 
15 
16 /* *************************
17  * AnnotatePdStates
18  * *************************/
19 PushdownGenerator AnnotatePdStates(const std::string word, const PushdownGenerator& pd){
20 
21  //take a copy of the old generator
23 
24  //annotate states of the new generator
25  StateSet::Iterator its;
26  for(its = pd.StatesBegin(); its != pd.StatesEnd(); its++){
28  rPd.SetMerge(*its,msa);
29  }
30  return rPd;
31 }
32 
33 /* *************************
34  * RenameStackSymbold
35  * *************************/
36 PushdownGenerator RenameStackSymbold(const std::string word, const PushdownGenerator& pd){
37 
38  //the annotation string
39  std::string annotation = word + "-";
40 
41  //take a copy of the old generator
43 
44  //rename every stack symbol and delete the old one
45  StackSymbolSet::Iterator it;
46  for(it = pd.StackSymbolsBegin(); it != pd.StackSymbolsEnd(); it++){
47  //don't rename lambda
48  if(!pd.IsStackSymbolLambda(*it)){
49  rPd.InsStackSymbol(annotation + pd.StackSymbolName(*it));
50  rPd.DelStackSymbol(pd.StackSymbolName(*it));
51  }
52  }
53  //rename stack bottom
54  rPd.SetStackBottom(annotation + pd.StackSymbolName(pd.StackBottom()));
55 
56  //iterate over transitions and replace stack symbols in push and pop with
57  //the renamed versions
59  std::vector<Idx> oldPush, oldPop, push, pop;
60  std::vector<Idx>::const_iterator pushit, popit;
61  PopPushSet popPush;
62  PopPushSet::const_iterator ppit;
63 
64  //take copy of transitions to iterate over
65  //copying is necessary because transitions will get deleted
66  //iterating over the original TransSet can lead to undefined behaviour
67  TransSet transRel = rPd.TransRel();
68  for(tit = transRel.Begin(); tit != transRel.End(); tit++){
69 
70  //iterate over pop/push pairs
71  popPush = rPd.PopPush(*tit);
72  for(ppit = popPush.begin(); ppit != popPush.end(); ppit++){
73 
74  //rename pop stack symbols
75  oldPop = ppit->first;
76  for(popit = oldPop.begin(); popit != oldPop.end(); popit++){
77  //dont rename lambda
78  if(pd.IsStackSymbolLambda(*popit)){
79  pop.push_back(*popit);
80  }
81  else{
82  pop.push_back(rPd.StackSymbolIndex(annotation + rPd.StackSymbolName(*popit)));
83  }
84  }
85 
86  //rename push stack symbols
87  oldPush = ppit->second;
88  for(pushit = oldPush.begin(); pushit != oldPush.end(); pushit++){
89  //dont rename lambda
90  if(pd.IsStackSymbolLambda(*pushit)){
91  push.push_back(*pushit);
92  }
93  else{
94  push.push_back(rPd.StackSymbolIndex(annotation + rPd.StackSymbolName(*pushit)));
95  }
96  }
97 
98  //create new transitions
99  rPd.SetTransition(*tit, pop, push);
100  pop.clear();
101  push.clear();
102 
103  //and delete the old one
104  rPd.ClrTransition(*tit, oldPop, oldPush);
105  }
106  }
107  return rPd;
108 }
109 
110 /* *************************
111  * Nda
112  * *************************/
114  FUNCTION(__FUNCTION__); //scope log
115  FD_DF("Nda(" << &pd << ")");
116 
117  PushdownGenerator rPd = pd;
118 
119  //states and transition relation will be rebuilt, so delete the existing ones
120  rPd.ClearTransRel();
121  rPd.ClearStates();
122 
123  StateSet::Iterator stateit;
124  Idx newStateAct, newStatePas;
125  std::string active = "active";
126  std::string passive = "passive";
127  std::map<Idx,std::pair<Idx,Idx> > stateMap;
128  //for insert an active and a passive state for each state of the old generator
129  for(stateit = pd.StatesBegin(); stateit != pd.StatesEnd(); stateit++){
130 
131  //active state
132  newStateAct = rPd.InsState();
133  MergeStateAnnotation mssAct(*stateit,active);
134  rPd.SetMerge(newStateAct,mssAct);
135 
136  //if the old state was a final state, the active state is final as well
137  if(pd.ExistsMarkedState(*stateit)){
138  rPd.SetMarkedState(newStateAct);
139  }
140 
141  //if the old state was the starting state, the active state is a starting state
142  //as well
143  if(pd.ExistsInitState(*stateit)){
144  rPd.SetInitState(newStateAct);
145  }
146 
147  //passive state
148  newStatePas = rPd.InsState();
149  MergeStateAnnotation mssPas(*stateit,passive);
150  rPd.SetMerge(newStatePas,mssPas);
151 
152  //save relation between old state and new states for later reference
153  stateMap.insert(std::make_pair(*stateit,std::make_pair(newStateAct,newStatePas)));
154  }
155 
156  TransSet::Iterator transit;
157  PopPushSet::const_iterator ppit;
158  std::vector<Idx> pop, push;
159  Idx startState, endState, oldStartState, oldEndState, oldEvent;
160  //insert transitions
161  for(transit = pd.TransRelBegin(); transit != pd.TransRelEnd(); transit++){
162  for(ppit = pd.PopPushBegin(*transit); ppit != pd.PopPushEnd(*transit); ppit++){
163 
164  //for convenience
165  pop = ppit->first;
166  push = ppit->second;
167  oldStartState = transit->X1;
168  oldEndState = transit->X2;
169  oldEvent = transit->Ev;
170 
171  //for any reading transition
172  if(!pd.IsEventLambda(oldEvent)){
173 
174  //connect active state to active state
175  startState = stateMap.find(oldStartState)->second.first;
176  endState = stateMap.find(oldEndState)->second.first;
177  rPd.SetTransition(startState,oldEvent,endState,pop,push);
178 
179  //connect passive state to active state
180  startState = stateMap.find(oldStartState)->second.second;
181  rPd.SetTransition(startState,oldEvent,endState,pop,push);
182  }
183  else{
184 
185  //for any pushing and popping transition
186  if(push.size() == 2 || pd.IsStackSymbolLambda(push.front())){
187 
188  //connect passive state to passive state
189  startState = stateMap.find(oldStartState)->second.second;
190  endState = stateMap.find(oldEndState)->second.second;
191  rPd.SetTransition(startState,oldEvent,endState,pop,push);
192 
193  //if the old start state was marked, connect active state to passive state
194  if(pd.ExistsMarkedState(oldStartState)){
195  startState = stateMap.find(oldStartState)->second.first;
196  rPd.SetTransition(startState,oldEvent,endState,pop,push);
197  }
198 
199  //else connect active state to active state
200  else{
201  startState = stateMap.find(oldStartState)->second.first;
202  endState = stateMap.find(oldEndState)->second.first;
203  rPd.SetTransition(startState,oldEvent,endState,pop,push);
204  }
205  }
206 
207  //should never get here
208  else{
209  std::stringstream errstr;
210  errstr << "While executing Nda(): Found transition which is neither read nor pop nor push, which is not allowed" << std::endl;
211  throw Exception("Nda", errstr.str(), 1001);
212  }
213  }
214  }
215  }
216 
217  return rPd;
218 }
219 
220 /* *************************
221  * ReachableStateMap
222  * *************************/
223 void ReachableStateMap(const PushdownGenerator& rPd, std::map<Idx,StateSet>& rMap){
224 
225  StateSet reachableStates;
226  std::stack<Idx> todo;
227  StateSet::Iterator stateit;
228  TransSet::Iterator transit;
229  std::map<Idx,StateSet>::iterator mapit;
230 
231  rMap.clear();
232 
233  //for all states
234  for(stateit = rPd.StatesBegin(); stateit != rPd.StatesEnd(); ++stateit)
235  if(*stateit == rPd.InitState()){
236  //after trim, all states should be reachable from init state
237  rMap[*stateit] = rPd.States();
238  }else{
239  //calculate reachable states (transitive closure)
240  reachableStates.Clear();
241  todo.push(*stateit);
242 
243  while(!todo.empty()){
244  //get next
245  Idx curr = todo.top();
246  todo.pop();
247  reachableStates.Insert(curr);
248 
249  //for all directly reachable states (neighbors)
250  for(transit = rPd.TransRelBegin(curr); transit != rPd.TransRelEnd(curr); ++ transit){
251  //if already regard, nothing todo
252  if(reachableStates.Exists(transit->X2))
253  continue;
254 
255  mapit = rMap.find(transit->X2);
256 
257  //if for the neighbor the reachable states are already calculated (= neighbor in map)
258  //all states reachable from neighbor are also reachable from the current one
259  if(mapit != rMap.end())
260  reachableStates.InsertSet(mapit->second);
261  else
262  todo.push(transit->X2);
263  }
264  }
265 
266  rMap[*stateit] = reachableStates;
267  }
268 }
269 
270 /* *************************
271  * TrimPushdownGenerator
272  * *************************/
273 bool PushdownTrim(PushdownGenerator& pd, const uint n, bool debug) {
274  DEBUG_PRINTF(debug,"**** Trim **** ","");
275 
276  if(pd.InitStatesEmpty() || pd.MarkedStatesEmpty()){
277  //remember stack bottom
278  StackSymbol sb = pd.StackSymbolObj(pd.StackBottom());
279 
280  //clear states, transitions and stacksymbols (except stack bottom)
281  pd.ClearStates();
282  pd.ClearTransRel();
283  pd.DelStackSymbols(pd.StackSymbols());
284 
285  //reset stackbottom
286  pd.SetStackBottom(sb);
287  return false;
288  }
289 
290  if(n == 0)
291  //trim generator
292  return pd.vGenerator::Trim();
293 
294  PushdownGenerator rPd(pd);
295 
296  //remove all transitions and just add possible ones
297  rPd.ClearTransRel();
298 
299  StackSymbolSet usedStackSymbols;
300  std::vector<Idx>::const_iterator ssit;
301  TransSet::Iterator transIt;
302  PopPushSet::iterator ppIt;
303  std::vector<Idx> transPop, transPush, newStack, tmpStack, initStack, currStack;
304 
305  //stack bottom always used
306  usedStackSymbols.Insert(rPd.StackBottom());
307 
308  // initialize todo stack
309  //pairs (state,stack) represent a state with the current stack (in size of n)
310  std::stack<std::pair<Idx,std::vector<Idx> > > todo;
311 
312  // initialize done set
313  std::set<std::pair<Idx,std::vector<Idx> > > done;
314  std::set<std::pair<Idx,std::vector<Idx> > >::iterator doneit;
315  StateSet accStates,inaccStates;
316 
317  accStates.Insert(rPd.InitState());
318 
319  //create initial stack
320  initStack.push_back(rPd.StackBottom());
321 
322  //create start situation (init state with stack = [stackBottom])
323  std::pair<Idx,std::vector<Idx> > start = std::make_pair(rPd.InitState(), initStack);
324  todo.push(start);
325 
326  //start loop
327  while (!todo.empty()) {
328  //get last added
329  std::pair<Idx,std::vector<Idx> > curr = todo.top();
330  todo.pop();
331 
332  //get state
333  Idx currState = curr.first;
334  //get stack
335  currStack = curr.second;
336 
337  done.insert(curr);
338 
339  //for each transition from current
340  for (transIt = pd.TransRelBegin(currState);
341  transIt != pd.TransRelEnd(currState); ++transIt) {
342  for (ppIt = pd.PopPushBegin(*transIt); ppIt != pd.PopPushEnd(*transIt); ++ppIt) {
343  transPop = ppIt->first;
344  transPush = ppIt->second;
345 
346  // check if pop-condition is satisfied by the given stack
347  // The pop-condition is satisfied if the first k stack symbols correspond
348  // with pop ( for k <= n)
349  uint k = std::min(currStack.size(),transPop.size());
350  bool popPossible = std::equal(transPop.begin(),transPop.begin() +std::min(k,n),currStack.begin());
351 
352 
353  if (popPossible || pd.IsStackSymbolLambda(transPop.front())) {
354  DEBUG_PRINTF(debug," pop is possible","");
355 
356  //add transition to resulting generator
357  rPd.SetTransition(*transIt,transPop,transPush);
358  DEBUG_PRINTF(debug,"Trim_SetTransition",rPd);
359 
360 
361  //extract stack symbols
362  for(ssit = transPop.begin(); ssit != transPop.end(); ssit++){
363  usedStackSymbols.Insert(*ssit);
364  }
365  //extract stack symbols
366  for(ssit = transPush.begin(); ssit != transPush.end(); ssit++){
367  usedStackSymbols.Insert(*ssit);
368  }
369 
370  tmpStack.clear();
371  newStack.clear();
372 
373  //tmpStack = oldStack - pop or empty
374  if(currStack.size() > transPop.size())
375  tmpStack.insert(tmpStack.begin(),currStack.begin()+transPop.size(),currStack.end());
376 
377  //newStack = push[0 to n] if push != lambda
378  if(!pd.IsStackSymbolLambda(transPush.front()))
379  newStack.insert(newStack.begin(),transPush.begin(),std::min(transPush.begin()+n, transPush.end()));
380 
381  if(newStack.size() < n){
382  uint j = n - newStack.size();
383  //newStack = newStack + tmpStack[0 to j]
384  newStack.insert(newStack.end(),tmpStack.begin(),std::min(tmpStack.begin()+j,tmpStack.end()));
385  }
386 
387  //create new reachable situation (reached state with the new stack)
388  std::pair<Idx,std::vector<Idx> > newSituation = std::make_pair(transIt->X2, newStack);
389 
390  //if the new situation already exists, no need to check
391  if (done.find(newSituation) == done.end()) {
392  DEBUG_PRINTF(debug," find new situation","");
393  todo.push(newSituation);
394  //add accessible state
395  accStates.Insert(transIt->X2);
396  }
397  }
398  }
399  }
400  } //while
401 
402  //remove inaccessible states
403  inaccStates = rPd.States() - accStates;
404  rPd.DelStates(inaccStates);
405 
406  //delete all stack symbols except for the used ones
407  StackSymbolSet::Iterator currentssit;
408  for(currentssit = pd.StackSymbolsBegin(); currentssit != pd.StackSymbolsEnd(); currentssit++){
409  //stack symbol is not used and is not lambda
410  if(!usedStackSymbols.Exists(*currentssit) && !pd.IsStackSymbolLambda(*currentssit)){
411  rPd.DelStackSymbol(*currentssit);
412  }
413  }
414 
415  DEBUG_PRINTF(debug,"TrimEnd",rPd);
416 
417  pd=rPd;
418 
419  //trim generator
420  return pd.vGenerator::Trim();
421 }
422 
423 /* *************************
424  * SPDA
425  * *************************/
427  TransformationHistoryVec* pTransformHistory) {
428  FUNCTION(__FUNCTION__); //scope log
429  FD_DF("A SPDA(" << &pd << ")");
430 
431  //remember changes during this iteration
432  std::vector<std::pair<Idx,MergeTransition> > changes; //XXX:NEW
433 
434  //take a copy of the old generator
436 
437  //annotate states of the new generator
438  StateSet::Iterator stateit;
439  for (stateit = pd.StatesBegin(); stateit != pd.StatesEnd(); stateit++) {
440  MergeStateAnnotation msa = MergeStateAnnotation(*stateit, "old");
441  rPd.SetMerge(*stateit, msa);
442  }
443 
446 
447  //clear transition relation
448  rPd.ClearTransRel();
449 
450  std::multimap<Transition, std::pair<std::vector<Idx>, std::vector<Idx> > >
451  readSet, multiPushSet, popPushSet, unchangedSet, onlyStateChangeSet;
452  std::multimap<Transition, std::pair<std::vector<Idx>, std::vector<Idx> > >::iterator multimapit;
453  std::pair<Transition, std::pair<std::vector<Idx>, std::vector<Idx> > > transition;
454  std::pair<std::vector<Idx>, std::vector<Idx> > popPushPair;
455  std::vector<Idx> pop, push, pushEnd;
456  TransSet::Iterator transit;
457  PopPushSet::const_iterator ppit;
458 
459  //partition transitions of old generator into four sets
460  //because states have only been copied (and annotated), the state indices remain
461  //the same for both generators
462  for (transit = pd.TransRelBegin(); transit != pd.TransRelEnd(); transit++) {
463  for (ppit = pd.PopPushBegin(*transit); ppit != pd.PopPushEnd(*transit);
464  ppit++) {
465 
466  //get pop and push pair
467  pop = ppit->first;
468  push = ppit->second;
469 
470  //create transition and decide further down into which set it will be put
471  transition = std::make_pair(*transit, *ppit);
472 
473  //first set contains all transitions whose event is not lambda and pop does not
474  //equal push
475  //(i. e., are of the form (p,a,x,y,q) with x != y)
476  if (!pd.IsEventLambda(transit->Ev) && pop != push) {
477  readSet.insert(transition);
478  }
479 
480  //all other sets do not read anything (they have lambda events)
481  else if (pd.IsEventLambda(transit->Ev)) {
482 
483  //filter out all push transitions (p,lambda,x,yx,q), they will not need to be changed
484  if (push.size() == 2 && push.back() == pop.front()) {
485  unchangedSet.insert(transition);
486  continue;
487  }
488 
489  //XXX: NEW!
490  //onlyStateChangeSet contains all transitions that pop and push same stack symbols
491  //(i. e., are of the form (p,lambda,x,x,q) )
492  else if (pop == push && pop.size() == 1) {
493  onlyStateChangeSet.insert(transition);
494  continue;
495  }
496  //(i. e., are of the form (p,lambda,x,yzx,q) with z not empty)
497  else if (push.size() > 1) {
498  //multiPushSet contains all transitions that push more then one symbol
499  //(i. e., are of the form (p,lambda,x,yzx,q) with z not empty)
500  if (push.back() == pop.front()) {
501  multiPushSet.insert(transition);
502  }
503 
504  //popPushSet set contains all transitions that don't effectively pop
505  //(i. e., are of the form (p,lambda,x,yz,q) with a not empty, x != z)
506  else {
507  popPushSet.insert(transition);
508  }
509  }
510  //also put transitions without lambda push into popPushSet
511  //(i. e., are of the form (p,lambda,x,z,q) with z not empty and x != z)
512  else if (!pd.IsStackSymbolLambda(push.front())) {
513  popPushSet.insert(transition);
514  }
515 
516  //put transitions with lambda push into unchangedSet
517  else {
518  unchangedSet.insert(transition);
519  }
520  }
521  //put all remaining transitions into fourth set as well
522  else {
523  unchangedSet.insert(transition);
524  }
525  }
526  }
527 
528  //add lambda to events in case it has not already been added
529  Idx lambdaIdx = rPd.InsEvent(FAUDES_PD_LAMBDA);
530  Idx newState;
531 
532  //for every transition (p,a,x,y,q) in the readSet
533  for (multimapit = readSet.begin(); multimapit != readSet.end();
534  multimapit++) {
535 
536  //add new intermediate state and annotate it with (p,a,x,x,p)
537  newState = rPd.InsState();
538  pop = multimapit->second.first;
539  push = multimapit->second.first;
540  MergeTransition mt(multimapit->first.X1, multimapit->first.Ev,
541  multimapit->first.X1, pop, push);
542  rPd.SetMerge(newState, mt);
543 
544  //add transition to and from intermediate state
545  //(p,a,x,x,newstate)
546  rPd.SetTransition(multimapit->first.X1, multimapit->first.Ev, newState, pop, push);
547  //(newstate,lambda,x,y,q)
548  rPd.SetTransition(newState, lambdaIdx, multimapit->first.X2, pop, multimapit->second.second);
549 
550  //XXX:NEW
551  //if history is needed, add new State merged with old Transition to changes
552  if (pTransformHistory != NULL){
553  MergeTransition oldTrans = MergeTransition(multimapit->first,multimapit->second.first, multimapit->second.second);
554  changes.push_back(std::make_pair(newState,oldTrans));
555  }
556  }
557 
558  //for every transition (p,lambda,x,yax,q) with a not empty in the multiPushSet
559  for (multimapit = multiPushSet.begin(); multimapit != multiPushSet.end();
560  multimapit++) {
561 
562  //add new intermediate state and annotate it with (p,lambda,x,ax,p)
563  newState = rPd.InsState();
564  pop = multimapit->second.first;
565  push = std::vector<Idx>(
566  multimapit->second.second.end() - multimapit->second.first.size() - 1,
567  multimapit->second.second.end());
568  MergeTransition mt(multimapit->first.X1, multimapit->first.Ev,
569  multimapit->first.X1, pop, push);
570  rPd.SetMerge(newState, mt);
571 
572  //add transition to and from intermediate state
573  //(p,lambda,x,ax,newstate)
574  rPd.SetTransition(multimapit->first.X1, multimapit->first.Ev, newState, pop, push);
575  //(newstate,lambda,a,ya,q)
576  pop.clear();
577  pop.push_back(multimapit->second.second.at( multimapit->second.second.size()
578  - multimapit->second.first.size() - 1));
579  push = std::vector<Idx>(multimapit->second.second.begin(),
580  multimapit->second.second.end() - multimapit->second.first.size());
581  rPd.SetTransition(newState, lambdaIdx, multimapit->first.X2, pop, push);
582 
583  //XXX:NEW
584  //if history is needed, add new State merged with old Transition to changes
585  if (pTransformHistory != NULL){
586  MergeTransition oldTrans = MergeTransition(multimapit->first,multimapit->second.first, multimapit->second.second);
587  changes.push_back(std::make_pair(newState,oldTrans));
588  }
589  }
590 
591  //for every transition (p,lambda,x,yz,q) with z not empty and x != z in the popPushSet
592  for (multimapit = popPushSet.begin(); multimapit != popPushSet.end();
593  multimapit++) {
594 
595  //add new intermediate state and annotate it with (p,lambda,x,lambda,p)
596  newState = rPd.InsState();
597  pop = multimapit->second.first;
598  push.clear();
599  push.push_back(pd.StackSymbolIndex(FAUDES_PD_LAMBDA));
600  MergeTransition mt(multimapit->first.X1, multimapit->first.Ev,
601  multimapit->first.X1, pop, push);
602  rPd.SetMerge(newState, mt);
603 
604  //add transition to and from intermediate state
605  //(p,lambda,x,lambda,newstate)
606  rPd.SetTransition(multimapit->first.X1, lambdaIdx, newState, pop, push);
607  //(newstate,lambda,lambda,yz,q)
608  pop.clear();
609  pop.push_back(pd.StackSymbolIndex(FAUDES_PD_LAMBDA));
610  push = multimapit->second.second;
611  rPd.SetTransition(newState, lambdaIdx, multimapit->first.X2, pop, push);
612 
613  //XXX:NEW
614  //if history is needed, add new State merged with old Transition to changes
615  if (pTransformHistory != NULL){
616  MergeTransition oldTrans = MergeTransition(multimapit->first,multimapit->second.first, multimapit->second.second);
617  changes.push_back(std::make_pair(newState,oldTrans));
618  }
619  }
620 
621  //XXX:NEW!
622  /* ******************************************************************************************************** */
623 
624  if (!onlyStateChangeSet.empty()) {
625  //get new stack symbol
626  std::string newStackSym = rPd.UniqueStackSymbolName("x");
627  rPd.InsStackSymbol(newStackSym);
628 
629  //for every transition (p,lambda,x,x,q) in the set
630  for (multimapit = onlyStateChangeSet.begin();
631  multimapit != onlyStateChangeSet.end(); multimapit++) {
632 
633  //add new intermediate state and annotate it with (p,lambda,x,lambda,p)
634  newState = rPd.InsState();
635  pop = multimapit->second.first;
636  push = multimapit->second.second;
637 
638  //add new stack symbol at the beginning of the push vector
639  push.insert(push.begin(), rPd.StackSymbolIndex(newStackSym));
640 
641  MergeTransition mt(multimapit->first.X1, multimapit->first.Ev,
642  multimapit->first.X1, pop, push);
643  rPd.SetMerge(newState, mt);
644 
645  //add transition to and from intermediate state
646  //(p,lambda,x,yx,newstate) with y = newStackSym
647  rPd.SetTransition(multimapit->first.X1, lambdaIdx, newState, pop, push);
648 
649  pop.clear();
650  pop.push_back(rPd.StackSymbolIndex(newStackSym));
651  push.clear();
652  push.push_back(pd.StackSymbolIndex(FAUDES_PD_LAMBDA));
653 
654  //(newstate,lambda,newStackSym,lambda,q)
655  rPd.SetTransition(newState, lambdaIdx, multimapit->first.X2, pop, push);
656 
657  //if history is needed, add new State merged with old Transition to changes
658  if (pTransformHistory != NULL){
659  MergeTransition oldTrans = MergeTransition(multimapit->first,multimapit->second.first, multimapit->second.second);
660  changes.push_back(std::make_pair(newState,oldTrans));
661  }
662 
663  }
664  }
665 
666  /* ************************************************************************************************************ */
667 
668  //for every transitions in the unchangedSet
669  for (multimapit = unchangedSet.begin(); multimapit != unchangedSet.end();
670  multimapit++) {
671 
672  //read pop and push for convenience
673  pop = multimapit->second.first;
674  push = multimapit->second.second;
675 
676  //XXX: OLD
677  //if it is a read only transition in the form of (p,a,x,x,q), changed
678  //it to (p,a,lambda,lambda,q)
679  /*
680  if(!rPd.IsEventLambda(multimapit->first.Ev) && !pop.front().IsLambda() && pop == push ){
681  pop.clear();
682  pop.push_back(StackSymbol(FAUDES_PD_LAMBDA));
683  push.clear();
684  push.push_back(StackSymbol(FAUDES_PD_LAMBDA));
685  }
686  */
687  //insert the transition again
688  rPd.SetTransition(multimapit->first.X1, multimapit->first.Ev,
689  multimapit->first.X2, pop, push);
690  }
691 
692  //XXX:NEW
693  //if history is needed, add all changes to history
694  if (pTransformHistory != NULL)
695  pTransformHistory->push_back(changes);
696 
697 
698  //if lambda popping edges were added, they need to be removed first
699  if (popPushSet.size() != 0) {
700  rPd = RemoveLambdaPop(rPd);
701  }
702  //if changes were made, repeat recursively
703  if (popPushSet.size() + onlyStateChangeSet.size() + readSet.size()
704  + multiPushSet.size() != 0) {
705  //PushdownGeneratorTrim(rPd, FAUDES_PD_LOOKAHEAD);
706  rPd = SPDA(rPd, pTransformHistory);
707  }
708 
709 
710  return rPd;
711 
712 }
713 
714 
715 /* *************************
716  * RebuildFromSPDA
717  * *************************/
719  const TransformationHistoryVec& history) {
720  FUNCTION(__FUNCTION__); //scop log
721 
722  //copy
724 
725  TransformationHistoryVec::const_reverse_iterator historyit;
726  std::vector<std::pair<Idx,MergeTransition> > merges;
727  std::vector<std::pair<Idx,MergeTransition> >::iterator mergeit;
728  std::vector<Idx> pop,push;
729  std::vector<Idx>::iterator it;
730 
731  std::vector<Idx> t;
732  t.push_back(rPd.InsLambdaStackSymbol());
733 
734  //go through history backwards
735  for (historyit = history.rbegin(); historyit != history.rend();
736  ++historyit) {
737  //get merges
738  merges = *historyit;
739 
740  //recreate transition from merge (if possible)
741  for (mergeit = merges.begin(); mergeit != merges.end(); ++mergeit) {
742  //merge state
743  Idx state = mergeit->first;
744  //merge transition
745  MergeTransition mt = mergeit->second;
746 
747  //if merge state still exists
748  if (rPd.ExistsState(state)) {
749  //if states of transition still exists
750  if (rPd.ExistsState(mt.X1())
751  && rPd.ExistsState(mt.X2())) {
752 
753  pop = mt.Pop();
754  push = mt.Push();
755 
756  for(it = pop.begin(); it != pop.end(); ++it)
757  rPd.InsStackSymbol(rPd.StackSymbolName(*it));
758  for(it = push.begin(); it != push.end(); ++it)
759  rPd.InsStackSymbol(rPd.StackSymbolName(*it));
760 
761  //add transition
762  rPd.SetTransition(mt.X1(), mt.Ev(),
763  mt.X2(), mt.Pop(), mt.Push());
764  //delete merge state
765  rPd.DelState(state);
766  }
767  }
768  }
769  }
770 
771  return rPd;
772 }
773 
774 /* *************************
775  * RemainingPd
776  * *************************/
778  FUNCTION(__FUNCTION__); //scope log
779  bool debug = false; //debug RemainingPd?
780 
781  //take copy
782  PushdownGenerator rPd(pd);
783 
784  //remove all transition and add only remaining ones
785  rPd.ClearTransRel();
786 
787  std::set<GrammarProduction>::const_iterator proit;
788  TransSet::Iterator transit;
789  PopPushSet::const_iterator ppit;
790 
791  //check for all productions
792  for (proit = gr.GrammarProductionsBegin();
793  proit != gr.GrammarProductionsEnd(); ++proit) {
794  Nonterminal lhs = proit->Lhs();
795  GrammarSymbolVector rhs = proit->Rhs();
796 
797  // lhs = (qi,b) ( or (qi,b,qj) if lhs.mEndState != 0)
798  //if (lhs.EndState() == 0) {
799  TerminalPtr termPtr = std::dynamic_pointer_cast<Terminal>(
800  rhs.front());
801  if (termPtr) {
802  // first elem of rhs is either lambda or an event (both are terminals)
803  if (termPtr->IsLambda()) {
804  // rhs = lambda
805  if (lhs.EndState() == 0) {
806  // (q,b) -> lambda
807  // nothing to do
808  DEBUG_PRINTF(debug, "Find Tfinal P = " + (*proit).Str(),"");
809  } else {
810  // type (ii)
811  // (qi,b,qj) --> lambda
812  for (transit = pd.TransRelBegin(lhs.StartState());
813  transit != pd.TransRelEnd(lhs.StartState());
814  ++transit) {
815  for (ppit = pd.PopPushBegin(*transit);
816  ppit != pd.PopPushEnd(*transit); ++ppit) {
817  std::vector<Idx> pop = ppit->first;
818  std::vector<Idx> push = ppit->second;
819 
820  //pop transition (qi,lambda,b,lambda,qj) ==> (qi,b,qj) --> lambda
821  if (transit->X2 == lhs.EndState() // qj == qj
822  && pop.front() == lhs.OnStack().front() // b == b
823  && pd.IsStackSymbolLambda(push.front()) // push == lambda
824  && pd.IsEventLambda(transit->Ev)) { // event == lambda
825 
826  //add transition
827  rPd.SetTransition(*transit, pop, push); // add transition
828  DEBUG_PRINTF(debug, "Find T2 P = "+ (*proit).Str(), "");
829  }
830  }
831  }
832  }
833  } else {
834  // rhs = a(qj,b[,qt])
835 
836  // type (i)
837  // (qi,b[,qt]) --> a(qj,b[,qt])
838  for (transit = pd.TransRelBegin(lhs.StartState());
839  transit != pd.TransRelEnd(lhs.StartState());
840  ++transit) {
841  for (ppit = pd.PopPushBegin(*transit);
842  ppit != pd.PopPushEnd(*transit); ++ppit) {
843  std::vector<Idx> pop = ppit->first;
844  std::vector<Idx> push = ppit->second;
845 
846  NonterminalPtr nontermPtr =
847  std::dynamic_pointer_cast<Nonterminal>(rhs.back()); // ->(qj,b[,qt])
848 
849  // read Transition (qi,a,b,b,qj) ==> (qi,b[,qt]) --> a(qj,b[,qt])
850  if (nontermPtr) { // tmoor 2016-08: fix segfault
851  if(transit->X2 == nontermPtr->StartState() // qj == qj
852  && transit->Ev == termPtr->Event() // a == a
853  && pop.front() == lhs.OnStack().front() // b == b
854  && push.front() == lhs.OnStack().front()) {
855 
856  //add transition
857  rPd.SetTransition(*transit, pop, push); // add transition
858  DEBUG_PRINTF(debug, "Find T1 P = "+ (*proit).Str(), "");
859 
860  }} else {
861  FD_WARN("RemainingPd: Find not identifiable production" + (*proit).Str());
862  }
863  }
864  }
865  }
866  } else {
867  // first elem of rhs is a nonterminal
868 
869  NonterminalPtr nonterm1Ptr =
870  std::dynamic_pointer_cast<Nonterminal>(rhs.front());
871  if (nonterm1Ptr) {
872  if (rhs.size() == 1) {
873  // type (iii L)
874  // (qi,b) --> (qj,c)
875  for (transit = pd.TransRelBegin(lhs.StartState());
876  transit != pd.TransRelEnd(lhs.StartState());
877  ++transit) {
878  for (ppit = pd.PopPushBegin(*transit);
879  ppit != pd.PopPushEnd(*transit); ++ppit) {
880  std::vector<Idx> pop = ppit->first;
881  std::vector<Idx> push = ppit->second;
882 
883  // push Transition (qi,lambda,b,cb,qj) ==> (qi,b) --> (qj,c)
884  if (transit->X2 == nonterm1Ptr->StartState() // qj == qj
885  && pop.front() == lhs.OnStack().front() // b == b
886  // check push
887  && push.size() == 2 // push 2 elements c and b
888  && push.front()
889  == nonterm1Ptr->OnStack().front()// c == c
890  && push.back() == lhs.OnStack().front() // b == b
891  && pd.IsEventLambda(transit->Ev)) { // ev == lambda
892 
893  //add transition
894  rPd.SetTransition(*transit, pop, push); // add transition
895  DEBUG_PRINTF(debug, "Find T3L P = "+ (*proit).Str(), "");
896 
897  }
898  }
899  }
900  } else { //rhs.size() > 1
901  // type (iii R)
902  // (qi,b[,qt]) --> (qj,c,qs)(qs,b[,qt])
903  for (transit = pd.TransRelBegin(lhs.StartState());
904  transit != pd.TransRelEnd(lhs.StartState());
905  ++transit) {
906  for (ppit = pd.PopPushBegin(*transit);
907  ppit != pd.PopPushEnd(*transit); ++ppit) {
908  std::vector<Idx> pop = ppit->first;
909  std::vector<Idx> push = ppit->second;
910 
911  NonterminalPtr nonterm2Ptr =
912  std::dynamic_pointer_cast<Nonterminal>(
913  rhs.back()); // ->(qs,b[,qt])
914 
915  // push Transition (qi,lambda,b,cb,qj) ==> (qi,b[,qt]) --> (qj,c,qs)(qs,b[,qt])
916  if (nonterm2Ptr) {
917  if(transit->X2 == nonterm1Ptr->StartState() // qj == qj
918  && pop.front() == lhs.OnStack().front() // pop b == b
919  // check push
920  && push.size() == 2 // push 2 elements c and b
921  && push.front()
922  == nonterm1Ptr->OnStack().front() // c == c
923  && push.back()
924  == nonterm2Ptr->OnStack().front() // b == b
925  && pd.IsEventLambda(transit->Ev)) { // ev == lambda
926 
927  //add transition
928  rPd.SetTransition(*transit, pop, push); // add transition
929  DEBUG_PRINTF(debug, "Find T3R P = "+ (*proit).Str(), "");
930  }
931  } else {
932  //ERROR:
933  FD_WARN("RemainingPd: Find not identifiable production" + (*proit).Str());
934  }
935  }
936  }
937  }
938  }
939  }
940  } // foreach production
941 
942  return rPd;
943 }
944 
945 /* *************************
946  * RemoveLambdaPop
947  * *************************/
949  FUNCTION(__FUNCTION__); //scope log
950 
951  if(!pd.IsDeterministic()){
952  FD_WARN("RemoveLambdaPop: Generator is not deterministic ! Perhaps not all lambda popping transitions will remove.") // TODO
953  }
954 
955  //rename stack symbols and states
956  PushdownGenerator rPd (pd);
957 
958 
959  // XXX:is no longer needed
960  /*********************************************************************************
961  //remember important attributes of the generator before proceeding
962  StackSymbolSet oldStackSymbols = rPd.StackSymbols();
963  Idx oldInitState = rPd.InitState();
964  std::string oldStackBottom = rPd.StackSymbolName(rPd.StackBottom());
965 
966 
967  //clear old init state and create new init state which will be annotated with "new"
968  //and derived from pd.InitState() in a merge state annotation
969  rPd.ClrInitState(rPd.InitState());
970  Idx newInitState = rPd.InsState();
971  rPd.SetInitState(newInitState);
972  MergeStateAnnotation msa(pd.InitState(),"new");
973  rPd.SetMerge(newInitState, msa);
974 
975  //set new stack bottom
976  rPd.SetStackBottom("new-" + pd.StackSymbolName(pd.StackBottom()));
977 
978  //if the old initial state was marked, the new initial state is marked as well
979  if(pd.ExistsMarkedState(pd.InitState())){
980  rPd.InsMarkedState(rPd.InitState());
981  }
982 
983  //add transition that adds the old stack bottom symbol to the stack
984  //maybe lambda event needs to be inserted first
985  Idx lambdaIdx = rPd.InsEvent(FAUDES_PD_LAMBDA);
986  std::vector<StackSymbol> pop, push;
987  std::string newStackBottom = rPd.StackSymbolName(rPd.StackBottom());
988  //pop new stack bottom
989  pop.push_back(StackSymbol(newStackBottom));
990  //push new stack bottom and old stack bottom
991  push.push_back(StackSymbol(oldStackBottom));
992  push.push_back(StackSymbol(newStackBottom));
993  //add transition
994  rPd.SetTransition(newInitState, lambdaIdx, oldInitState, pop, push);
995 
996  // ********************************************************************/
997 
998  //iterate over all transitions
999  //take copy of transitions to iterate over
1000  //copying is necessary because transitions will get deleted
1001  //iterating over the original TransSet can lead to undefined behavior
1002  TransSet transRel = rPd.TransRel();
1003  TransSet::Iterator tit;
1004  StackSymbolSet::Iterator ssit;
1005  std::vector<Idx> examinedPop, examinedPush, newPop, newPush;
1006 
1007  for (tit = transRel.Begin(); tit != transRel.End(); tit++) {
1008 
1009  //look for lambda popping transitions (s1,ev,s2,lambda,w)
1010  //only need to look at the first pop/push pair, because only deterministic
1011  //generator are considered. the generator would be nondeterministic if there
1012  //was a transition in addition to a lambda popping one
1013  examinedPop = rPd.PopPush(*tit).begin()->first;
1014  examinedPush = rPd.PopPush(*tit).begin()->second;
1015  if (pd.IsStackSymbolLambda(examinedPop.front())) {
1016 
1017  //remove the transition
1018  rPd.ClrTransition(*tit, examinedPop, examinedPush);
1019 
1020  //add new transitions for every possible stack symbol u minus the just
1021  //inserted bottom and lambda so that it looks like (s1,ev,s2,u,uw) for
1022  for (ssit = rPd.StackSymbolsBegin(); ssit != rPd.StackSymbolsEnd();
1023  ssit++) {
1024  if (!rPd.IsStackSymbolLambda(*ssit)) {
1025  //fill pop with stack symbol
1026  newPop.clear();
1027  newPop.push_back(*ssit);
1028  //fill push with examinedPush plus stack symbol
1029  newPush.clear();
1030  newPush.insert(newPush.end(), examinedPush.begin(),
1031  examinedPush.end());
1032  newPush.push_back(*ssit);
1033  //add transition
1034  rPd.SetTransition(*tit, newPop, newPush);
1035  }
1036  }
1037  }
1038  }
1039 
1040  return rPd;
1041 }
1042 
1043 /* *************************
1044  * Sp2Lr
1045  * *************************/
1046 Grammar Sp2Lr(const PushdownGenerator& xrPd,uint n, bool ignorReducible,bool debug) {
1047  FUNCTION(__FUNCTION__); //scope log
1048  FD_DF("Sp2Lr(" << &xrPd << "," << n << ")");
1049 
1050  //Grammar to return
1051  Grammar rGr;
1052 
1053  StateSet::Iterator stateit1, stateit2;
1054  EventSet::Iterator eventit;
1055  TransSet::Iterator transit, transit2, transit3;
1056  StackSymbolSet::Iterator ssit;
1057  PopPushSet::const_iterator ppit, ppit2, ppit3;
1058  std::vector<Idx>::const_iterator popit, pushit;
1059  std::vector<Idx> ssVector, pop, push;
1060  std::map<Idx,StateSet> reachableStatesMap;
1061  GrammarSymbolVector rhs;
1062 
1063  //take a copy of pushdown generator
1064  PushdownGenerator tmpPd(xrPd);
1065 
1066  if(!ignorReducible){
1067  //Trim
1068  PushdownTrim(tmpPd,n);
1069  }
1070 
1071  //fill map
1072  ReachableStateMap(tmpPd,reachableStatesMap);
1073 
1074  //terminals equal the generator's events
1075  for (eventit = tmpPd.AlphabetBegin(); eventit != tmpPd.AlphabetEnd(); eventit++) {
1076  rGr.InsTerminal(Terminal(*eventit));
1077  }
1078  //Start Symbol (q0,$)
1079  ssVector.clear();
1080  ssVector.push_back(tmpPd.StackBottom());
1081  rGr.SetStartSymbol(Nonterminal(tmpPd.InitState(), ssVector));
1082 
1083  //create grammar productions:
1084 
1085  //for each final state qm and each stack symbol A
1086  //create (qm,A) -> lambda
1087  for (stateit1 = tmpPd.MarkedStatesBegin(); stateit1 != tmpPd.MarkedStatesEnd();
1088  stateit1++) {
1089  for (ssit = tmpPd.StackSymbolsBegin(); ssit != tmpPd.StackSymbolsEnd();
1090  ssit++) {
1091  if (!tmpPd.IsStackSymbolLambda(*ssit)) {
1092 
1093  //save used nonterminal
1094  ssVector.clear();
1095  ssVector.push_back(*ssit);
1096  Nonterminal nt(*stateit1, ssVector);
1097  rGr.InsNonterminal(nt);
1098 
1099  //insert a production ((qm,A) --> lambda)
1100  Terminal* t = new Terminal(tmpPd.EventIndex(FAUDES_PD_LAMBDA));
1101  GrammarSymbolPtr tPtr(t);
1103  v.push_back(tPtr);
1104  GrammarProduction gp(nt, v);
1105  rGr.InsGrammarProduction(gp);
1106 
1107  FD_DF("Sp2Lr: Inserting" + gp.Str())
1108  DEBUG_PRINTF(debug,"Sp2Lr: Inserting" + gp.Str(),"");
1109  }
1110  }
1111  }
1112 
1113  //For each pop-transition in form (qi,lambda,pop,lambda,qj)
1114  for (transit = tmpPd.TransRelBegin(); transit != tmpPd.TransRelEnd(); ++transit) {
1115  for (ppit = tmpPd.PopPushBegin(*transit); ppit != tmpPd.PopPushEnd(*transit); ppit++) {
1116  push = ppit->second;
1117 
1118  //pop transition (qi,lambda,pop,lambda,qj)
1119  if (tmpPd.IsStackSymbolLambda(push.front())) {
1120  Idx qi = transit->X1;
1121  Idx qj = transit->X2;
1122  pop = ppit->first;
1123 
1124  //ensure that event = lambda
1125  if(! tmpPd.IsEventLambda(transit->Ev)){
1126  std::stringstream errstr;
1127  errstr << "While executing Sp2Lr(): Found transition that push lambda but don't read lambda, "
1128  "so is neither read nor pop, which is not allowed" << std::endl;
1129  throw Exception("Sp2Lr", errstr.str(), 1001);
1130  }
1131 
1132  //save lhs nonterminal as reducible
1133  Nonterminal ntLhs(qi, pop, qj);
1134  rGr.InsNonterminal(ntLhs);
1135 
1136  //insert production (qi,pop,qj) --> lambda
1137  Terminal* t = new Terminal(transit->Ev);
1138  GrammarSymbolPtr tPtr(t);
1139  rhs.clear();
1140  rhs.push_back(tPtr);
1141  rGr.InsGrammarProduction(GrammarProduction(ntLhs, rhs));
1142 
1143  FD_DF("Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str())
1144  DEBUG_PRINTF(debug,"Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str(),"");
1145  }
1146  }
1147  }
1148 
1149  //generate reducible productions until no more productions can be generated
1150  uint oldSize = 0;
1151 
1152  do{
1153  //save old number of grammar productions
1154  oldSize = rGr.GrammarProductions().size();
1155 
1156  //try to generate new grammar productions for each transition
1157  for (transit = tmpPd.TransRelBegin(); transit != tmpPd.TransRelEnd(); transit++) {
1158  for (ppit = tmpPd.PopPushBegin(*transit); ppit != tmpPd.PopPushEnd(*transit); ppit++) {
1159 
1160  Idx qi = transit->X1;
1161  Idx qj = transit->X2;
1162  Idx a = transit->Ev;
1163  std::vector<Idx> b = ppit->first;
1164  push = ppit->second;
1165 
1166  //read transition (qi,a,b,b,qj)
1167  if (!tmpPd.IsEventLambda(transit->Ev)) {
1168 
1169  //ensure that pop = push
1170  if(b != push){
1171  std::stringstream errstr;
1172  errstr << "While executing Sp2Lr(): Found transition that pop != push but don't read lambda, so is neither read nor pop nor push, which is not allowed" << std::endl;
1173  throw Exception("Sp2Lr", errstr.str(), 1001);
1174  }
1175 
1176  //insert production (qi,b) --> a(qj,b)
1177  Nonterminal ntLhs(qi, b);
1178  Terminal* t = new Terminal(a);
1179  GrammarSymbolPtr tPtr(t);
1180  Nonterminal* ntRhs = new Nonterminal(qj, b);
1181  GrammarSymbolPtr ntRhsPtr(ntRhs);
1182 
1183  if(ignorReducible)
1184  rGr.InsNonterminal(*ntRhs);
1185 
1186  //... but only if (qj,b) is reducible
1187  if (rGr.Nonterminals().find(*ntRhs)
1188  != rGr.NonterminalsEnd()) {
1189 
1190  //save lhs nonterminal as reducible
1191  rGr.InsNonterminal(ntLhs);
1192 
1193  //insert production
1194  rhs.clear();
1195  rhs.push_back(tPtr);
1196  rhs.push_back(ntRhsPtr);
1197  rGr.InsGrammarProduction(GrammarProduction(ntLhs, rhs));
1198 
1199  FD_DF("Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str())
1200  DEBUG_PRINTF(debug,"Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str(),"");
1201 
1202  }
1203 
1204  //For all states qt that are reachable from qj
1205  StateSet reachFromTrg = reachableStatesMap.find(qj)->second;
1206  for (stateit1 = reachFromTrg.Begin(); stateit1 != reachFromTrg.End(); stateit1++) {
1207 
1208  Idx qt = *stateit1;
1209 
1210  //insert production (qi,b,qt) --> a (qj,b,qt)
1211  Nonterminal ntLhs(qi, b, qt);
1212  Nonterminal* ntRhs = new Nonterminal(qj, b, qt);
1213 
1214  if(ignorReducible)
1215  rGr.InsNonterminal(*ntRhs);
1216 
1217  //... but only if (qj,b,qt) is reducible
1218  if (rGr.Nonterminals().find(*ntRhs)
1219  != rGr.NonterminalsEnd()) {
1220  //save lhs nonterminal as ignorReducible
1221  rGr.InsNonterminal(ntLhs);
1222 
1223  //insert production
1224  GrammarSymbolPtr ntRhsPtr(ntRhs);
1225  rhs.clear();
1226  rhs.push_back(tPtr);
1227  rhs.push_back(ntRhsPtr);
1228  rGr.InsGrammarProduction(GrammarProduction(ntLhs, rhs));
1229 
1230  FD_DF("Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str())
1231  DEBUG_PRINTF(debug,"Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str(),"");
1232 
1233  }
1234  }
1235  } // end if read != lambda
1236  else {
1237 
1238  //pop transition (qi,lambda,b,lambda,qj)
1239  if (tmpPd.IsStackSymbolLambda(push.front())) {
1240  //already done
1241  }
1242 
1243  //push transition (qi,lambda,b,cb,qj)
1244  else if (push.size() == 2) {
1245 
1246  std::vector<Idx> c;
1247  c.push_back(push.front());
1248 
1249  //insert production (qi,b) --> (qj,c)
1250  Nonterminal ntLhs(qi, b);
1251  Nonterminal* ntRhs = new Nonterminal(qj, c);
1252  GrammarSymbolPtr ntRhsPtr(ntRhs);
1253 
1254  if(ignorReducible)
1255  rGr.InsNonterminal(*ntRhs);
1256 
1257  //... but only if (qj,c) is reducible
1258  if (rGr.Nonterminals().find(*ntRhs)
1259  != rGr.NonterminalsEnd()) {
1260 
1261  //save lhs nonterminal as ignorReducible
1262  rGr.InsNonterminal(ntLhs);
1263 
1264  //insert production
1265  rhs.clear();
1266  rhs.push_back(ntRhsPtr);
1267  rGr.InsGrammarProduction(GrammarProduction(ntLhs, rhs));
1268 
1269  FD_DF("Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str())
1270  DEBUG_PRINTF(debug,"Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str(),"");
1271  }
1272 
1273  //For all states qs that are reachable from qj
1274  StateSet reachFromTrg = reachableStatesMap.find(qj)->second;
1275  for (stateit1 = reachFromTrg.Begin(); stateit1 != reachFromTrg.End(); stateit1++) {
1276 
1277  Idx qs = *stateit1;
1278 
1279  //insert production (qi,b) --> (qj,c,qs)(qs,b)
1280  Nonterminal ntLhs(qi, b);
1281  Nonterminal* ntRhs1 = new Nonterminal(qj, c, qs);
1282  GrammarSymbolPtr ntRhs1Ptr(ntRhs1);
1283  Nonterminal* ntRhs2 = new Nonterminal(qs, b);
1284  GrammarSymbolPtr ntRhs2Ptr(ntRhs2);
1285 
1286  if(ignorReducible){
1287  rGr.InsNonterminal(*ntRhs1);
1288  rGr.InsNonterminal(*ntRhs2);
1289  }
1290 
1291  //... but only if (qj,c,qs) and (qs,b) are reducible
1292  if (rGr.Nonterminals().find(*ntRhs1) != rGr.NonterminalsEnd()
1293  && rGr.Nonterminals().find(*ntRhs2) != rGr.NonterminalsEnd()){
1294 
1295  //save lhs nonterminal as ignorReducible
1296  rGr.InsNonterminal(ntLhs);
1297 
1298  //insert production
1299  rhs.clear();
1300  rhs.push_back(ntRhs1Ptr);
1301  rhs.push_back(ntRhs2Ptr);
1302  rGr.InsGrammarProduction(GrammarProduction(ntLhs, rhs));
1303 
1304  FD_DF("Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str())
1305  DEBUG_PRINTF(debug,"Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str(),"");
1306  }
1307 
1308  //for each push transition (qs,_,c,lambda,qp)
1309  for (transit2 = tmpPd.TransRelBegin(qs); transit2 != tmpPd.TransRelEnd(qs); ++transit2) {
1310  for (ppit2 = tmpPd.PopPushBegin(*transit2); ppit2 != tmpPd.PopPushEnd(*transit2); ++ppit2) {
1311 
1312  if (tmpPd.IsStackSymbolLambda((ppit2->second).front()) && (ppit2->first).front() == push.front()) {
1313  //ey
1314  Idx qp = transit2->X2;
1315 
1316  //For all states qs' that are reachable from qs
1317  StateSet reachFromqs = reachableStatesMap.find(qs)->second;
1318  for (stateit2 = reachFromqs.Begin(); stateit2 != reachFromqs.End(); ++stateit2) { // reach from qp
1319  //for each transition (qs',_,B,lambda,qt)
1320  for (transit3 = tmpPd.TransRelBegin(*stateit2); transit3 != tmpPd.TransRelEnd(*stateit2);
1321  ++transit3) {
1322  //ex
1323  for (ppit3 = tmpPd.PopPushBegin(*transit3); ppit3 != tmpPd.PopPushEnd(*transit3);
1324  ++ppit3) {
1325  if (tmpPd.IsStackSymbolLambda((ppit3->second).front())
1326  && (ppit3->first).front() == push.back()) { //ex
1327 
1328  Idx qt = transit3->X2;
1329 
1330  //insert production (qi,b,qt) --> (qj,c,qp)(qp,b,qt)
1331  Nonterminal ntLhs(qi, b, qt);
1332  Nonterminal* ntRhs1 = new Nonterminal(qj,c,qp);
1333  GrammarSymbolPtr ntRhs1Ptr(ntRhs1);
1334  Nonterminal* ntRhs2 = new Nonterminal(qp,b,qt);
1335  GrammarSymbolPtr ntRhs2Ptr(ntRhs2);
1336 
1337  if(ignorReducible){
1338  rGr.InsNonterminal(*ntRhs1);
1339  rGr.InsNonterminal(*ntRhs2);
1340  }
1341 
1342  //... but only if (qj,c,qs) and (qs,b,qt) are reducible
1343  if (rGr.Nonterminals().find(*ntRhs1) != rGr.NonterminalsEnd()
1344  && rGr.Nonterminals().find(*ntRhs2) != rGr.NonterminalsEnd()) {
1345 
1346  //save lhs nonterminal as ignorReducible
1347  rGr.InsNonterminal(ntLhs);
1348 
1349  //insert production
1350  rhs.clear();
1351  rhs.push_back(ntRhs1Ptr);
1352  rhs.push_back(ntRhs2Ptr);
1353  rGr.InsGrammarProduction(GrammarProduction(ntLhs,rhs));
1354 
1355  FD_DF("Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str())
1356  DEBUG_PRINTF(debug,"Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str(),"");
1357  }
1358  }
1359  }
1360  }
1361  }
1362  }
1363  }
1364  }
1365  }
1366  }
1367  }
1368  }
1369  }
1370  if(ignorReducible)
1371  return rGr;
1372  } while (rGr.GrammarProductions().size() != oldSize);
1373 
1374  //return CFG
1375  return rGr;
1376 }
1377 
1378 /* *************************
1379  * Filter
1380  * *************************/
1381 std::set<Nonterminal> Filter(const std::set<Nonterminal>& symbolSet, const GrammarSymbolVector& w){
1382 
1383  //resulting set
1384  std::set<Nonterminal> rSet;
1385 
1386  GrammarSymbolVector::const_iterator wit;
1387  std::set<Nonterminal>::const_iterator ntit;
1388  //iterate over all symbols of the word
1389  for(wit = w.begin(); wit != w.end(); wit++){
1390  //test if current symbol is a nonterminal
1391  ConstNonterminalPtr nt = std::dynamic_pointer_cast<const Nonterminal>(*wit);
1392  if(nt){
1393 
1394  //look for the symbol in the nonterminal set
1395  ntit = symbolSet.find(*nt);
1396 
1397  //if the symbol was found, insert it into resulting set
1398  if(ntit != symbolSet.end()){
1399  rSet.insert(*ntit);
1400  }
1401  }
1402  }
1403  return rSet;
1404 }
1405 
1406 /* *************************
1407  * Rnpp1
1408  * *************************/
1409 std::set<Nonterminal> Rnpp1(const Grammar& gr, const std::set<Nonterminal>& ntSet){
1410 
1411  std::set<Nonterminal> rSet, filterSet;
1412  //copy resulting set from set of already eliminated nonterminals
1413  rSet = ntSet;
1414 
1415  std::set<GrammarProduction>::const_iterator pit;
1416  //iterate over all productions
1417 
1418  for(pit = gr.GrammarProductions().begin(); pit != gr.GrammarProductions().end(); pit++){
1419 
1420  filterSet = Filter(gr.Nonterminals(),pit->Rhs());
1421 
1422  //test if the nonterminals on the right hand side of the production are all in
1423  //the set of eliminable nonterminals (i. e., they are eliminable)
1424  //if so, then the nonterminal on the left hand side is eliminable as well
1425  if(std::includes(ntSet.begin(), ntSet.end(), filterSet.begin(), filterSet.end())){
1426  //insert left hand side into set of eliminable terminals
1427  rSet.insert(pit->Lhs());
1428  }
1429  }
1430  return rSet;
1431 }
1432 
1433 /* *************************
1434  * Rnppl
1435  * *************************/
1436 std::set<Nonterminal> Rnppl(const Grammar& gr, const std::set<Nonterminal>& ntSet){
1437 
1438  //get nonterminals that are eliminable in one step
1439  std::set<Nonterminal> rSet = Rnpp1(gr,ntSet);
1440  //look if that changed anything
1441  if(ntSet != rSet){
1442  //if any changes were detected, go on
1443  rSet = Rnppl(gr,rSet);
1444  }
1445  return rSet;
1446 }
1447 
1448 /* *************************
1449  * Rnpp
1450  * *************************/
1451 Grammar Rnpp(const Grammar& gr){
1452 
1453  //the grammar to be returned. keep the start symbol
1454  Grammar rGr(gr.StartSymbol());
1455 
1456  //compute removable nonterminals
1457  std::set<Nonterminal> removableNts = Rnppl(gr,std::set<Nonterminal>());
1458 
1459  std::set<GrammarProduction> productions;
1460  //if the start symbol is a removable nonterminal
1461 
1462  if(removableNts.find(gr.StartSymbol()) != removableNts.end()){
1463 
1464  std::set<GrammarProduction>::const_iterator gpit;
1465  //iterate over grammar productions A -> w
1466  for(gpit = gr.GrammarProductionsBegin(); gpit != gr.GrammarProductionsEnd(); gpit++){
1467 
1468  //convert A to GrammarSymbolPtr and put it togther with w into a vector
1469  Nonterminal* a = new Nonterminal(gpit->Lhs());
1470  NonterminalPtr aPtr(a);
1471  GrammarSymbolVector symbols(gpit->Rhs());
1472  symbols.push_back(aPtr);
1473 
1474  std::set<Nonterminal> filteredSet;
1475  //filter all nonterminals that are in A and w
1476  filteredSet = Filter(gr.Nonterminals(), symbols);
1477 
1478  //test if filteredSet is a subset of the removable nonterminals
1479  if(std::includes(removableNts.begin(), removableNts.end(), filteredSet.begin(), filteredSet.end())){
1480  productions.insert(*gpit);
1481  }
1482  }
1483  }
1484 
1485  //keep the terminals
1486  rGr.InsTerminals(gr.Terminals());
1487 
1488  //keep only removable nonterminals
1489  rGr.InsNonterminals(removableNts);
1490 
1491  //keep only the productions from above
1492  rGr.InsGrammarProductions(productions);
1493 
1494  return rGr;
1495 }
1496 
1497 /* *************************
1498  * Rup
1499  * *************************/
1500 Grammar Rup(const Grammar& gr){
1501 
1502  Grammar rGr;
1503 
1504  //copy terminals and start symbol from the old grammar
1505  rGr.InsTerminals(gr.Terminals());
1506  rGr.SetStartSymbol(gr.StartSymbol());
1507 
1508  std::set<GrammarProduction> todoProductions, reachableProductions;
1509  std::set<GrammarProduction>::const_iterator gpit;
1510  std::set<Nonterminal> usedNonterminals;
1511 
1512  //start with the start symbol, which is always used in a grammar
1513  usedNonterminals.insert(gr.StartSymbol());
1514 
1515  //get productions with start symbol as righthand side
1516  for(gpit = gr.GrammarProductionsBegin(); gpit != gr.GrammarProductionsEnd(); gpit++){
1517  if(gpit->Lhs() == gr.StartSymbol()){
1518  todoProductions.insert(*gpit);
1519  }
1520  }
1521 
1522  //look at all todo productions
1523  while(!todoProductions.empty()){
1524 
1525  //get the current todo production
1526  GrammarProduction currentGp(*todoProductions.begin());
1527  todoProductions.erase(currentGp);
1528 
1529  //since this production was reached, it is a reachable production
1530  reachableProductions.insert(currentGp);
1531 
1532  //insert all nonterminals of the current production into set of used nonterminals
1533  std::set<Nonterminal> filtered = Filter(gr.Nonterminals(),currentGp.Rhs());
1534  usedNonterminals.insert(filtered.begin(), filtered.end());
1535 
1536  //look at all productions
1537  for(gpit = gr.GrammarProductionsBegin(); gpit != gr.GrammarProductionsEnd(); gpit++){
1538  //if they have any of the used nonterminals on their lefthand side, insert them
1539  //into the todo productions
1540  if(usedNonterminals.find(gpit->Lhs()) != usedNonterminals.end()){
1541  todoProductions.insert(*gpit);
1542  }
1543  }
1544 
1545  //do not look at already reachable productions twice
1546  //this avoids infinite loops
1547  for(gpit = reachableProductions.begin(); gpit != reachableProductions.end(); gpit++){
1548  todoProductions.erase(*gpit);
1549  }
1550  }
1551 
1552  //insert all used nonterminals and all reachable productions
1553  rGr.InsNonterminals(usedNonterminals);
1554  rGr.InsGrammarProductions(reachableProductions);
1555 
1556  return rGr;
1557 }
1558 
1559 
1560 /* *************************
1561  * RemoveMultPop
1562  * *************************/
1564 
1565  //take a annotate copy of the old generator
1566  PushdownGenerator rPd = AnnotatePdStates("old",pd);
1567 
1568  //clear transition relation
1569  rPd.ClearTransRel();
1570 
1571  //lambda event
1572  Idx lambdaEv = rPd.InsEvent(FAUDES_PD_LAMBDA);
1573 
1574  //lambda stack symbol
1575  Idx lambdaSS = rPd.InsStackSymbol(FAUDES_PD_LAMBDA);
1576 
1577  StateSet::Iterator stateit;
1578  TransSet::Iterator transit;
1579  PopPushSet::const_iterator ppIt;
1580 
1581  Idx src,trg,lastState;
1582  std::vector<Idx> oldPop,oldPush,pop,push;
1583  std::vector<Idx>::iterator popit;
1584  //remember for each sub-vector of pop the new state
1585  std::map<std::vector<Idx>,Idx> popStateMap;
1586  std::map<std::vector<Idx>,Idx>::iterator mapit;
1587 
1588  //remove all multiple pop-transition
1589  //e.g. (p,a,x1x2...xN,w,q) =>
1590  //(p,lambda,x1,lambda,p1), (p1,lambda,x2,lambda,p2), ... , (pN-1,lambda,xN,xN,pN),(pN,a,xN,w,q)
1591  //note: by the previous call of there is no lambda pop
1592  for(stateit = pd.StatesBegin(); stateit != pd.StatesEnd(); ++stateit){
1593  popStateMap.clear();
1594  for (transit = pd.TransRelBegin(*stateit); transit != pd.TransRelEnd(*stateit); ++transit) {
1595  for (ppIt = pd.PopPushBegin(*transit); ppIt != pd.PopPushEnd(*transit); ++ppIt) {
1596  //get pop/push
1597  oldPop = ppIt->first;
1598  oldPush = ppIt->second;
1599 
1600  //ensure transition doesn't pop lambda
1601  if(pd.IsStackSymbolLambda(oldPop.front())){
1602  std::stringstream errstr;
1603  errstr << "While executing RemoveMultPop(): Found transition that pop lambda, which is not allowed !" << std::endl;
1604  throw Exception("RemoveMultPop", errstr.str(), 1001);
1605  }
1606 
1607  //lastState contains the src for the next iteration
1608  lastState = transit->X1;
1609  for (popit = oldPop.begin(); popit != oldPop.end(); ++popit) {
1610  std::vector<Idx> tmpPop(oldPop.begin(),popit+1);
1611  src = lastState;
1612 
1613  //check if derivation of sup-pop exists
1614  mapit = popStateMap.find(tmpPop);
1615  if(mapit != popStateMap.end()){
1616  trg = mapit->second;
1617  }else{
1618  //if not, create new state
1619  trg = rPd.InsState();
1620  popStateMap[tmpPop] = trg;
1621  }
1622 
1623  //get pop for new transition
1624  pop.clear();
1625  pop.push_back(*popit);
1626 
1627  //get push for new transition
1628  push.clear();
1629  if(std::distance(popit, oldPop.end() ) == 1)
1630  //if last element of pop, push it
1631  push.push_back(*popit);
1632  else
1633  //else push lambda
1634  push.push_back(lambdaSS);
1635 
1636  //add transition
1637  rPd.SetTransition(src, lambdaEv, trg, pop, push);
1638 
1639  //set new last state
1640  lastState = trg;
1641  }
1642 
1643  //create transition to original trg
1644  src = lastState;
1645  pop.clear();
1646  pop.push_back(oldPop.back());
1647 
1648  //add transition (pN,a,xN,w,q)
1649  rPd.SetTransition(src, transit->Ev, transit->X2, pop, oldPush);
1650  }
1651  }
1652  }
1653  return rPd;
1654 }
1655 
1656 /* *************************
1657  * InTransitionSize
1658  * *************************/
1660  uint count = 0;
1661 
1662  // alternative order X2-Ev-X1
1663  TransSetX2EvX1 transByX2;
1664  TransSetX2EvX1::Iterator titEnd,transit;
1665 
1666  // copy and re-order transrel
1667  rPd.TransRel().ReSort(transByX2);
1668 
1669  //Set the iterator to a variable, so it won't be recalculated every iteration.
1670  titEnd = transByX2.EndByX2(trg);
1671 
1672  //for each incoming transition
1673  for(transit = transByX2.BeginByX2(trg); transit != titEnd; ++transit){
1674  if(rPd.PopPush(*transit).empty())
1675  //if no pop-push pair, just add one
1676  count++;
1677  else
1678  //else each pop-push pair represent a different transition
1679  count += rPd.PopPush(*transit).size();
1680  }
1681 
1682  return count;
1683 }
1684 
1685 /* *************************
1686  * PossibleAdjacentMerges
1687  * *************************/
1688 std::set<std::pair <Transition,Transition> > PossibleAdjacentMerges (Idx q, const PushdownGenerator& pd){
1689 
1690  //result and temporary set
1691  std::set<std::pair <Transition,Transition> > res,tmp;
1692 
1693  // If no out edges, nothing to do
1694  if(!pd.ExistsTransition(q))
1695  return res;
1696 
1697  //Set the iterator to a variable, so it won't be recalculated every iteration.
1698  TransSet::Iterator transRel1Begin, transRel1End,transRel1it,
1699  transRel2Begin, transRel2End, transRel2it;
1700 
1701  //init iterators
1702  transRel1Begin = pd.TransRelBegin(q);
1703  transRel1End = pd.TransRelEnd(q);
1704 
1705  //for each transition from state q
1706  for(transRel1it = transRel1Begin; transRel1it != transRel1End ; ++transRel1it){
1707  Idx q2 = transRel1it->X2;
1708 
1709  //ignore self-loop
1710  if(q == q2)
1711  continue;
1712  //ignore leading to marked state
1713  if(pd.ExistsMarkedState(q2))
1714  continue;
1715  //ignore leading to init state
1716  if(q2 == pd.InitState())
1717  continue;
1718  //ignore, if no transitions from q2
1719  if(!pd.ExistsTransition(q2))
1720  continue;
1721  //ignore if current transition isn't the only transition that leads to q2
1722  if(InTransitionSize(q2,pd) != 1)
1723  continue;
1724 
1725  //Set the iterator to a variable, so it won't be recalculated every iteration.
1726  transRel2Begin = pd.TransRelBegin(q2);
1727  transRel2End = pd.TransRelEnd(q2);
1728  tmp.clear();
1729 
1730  bool canNotMerge = false;
1731  transRel2it = transRel2Begin;
1732  while((transRel2it != transRel2End) && !canNotMerge){
1733  //Transitions can not merge, if...
1734  canNotMerge = canNotMerge
1735  //...its a transition from a marked state to a not marked state
1736  || (pd.ExistsMarkedState(transRel2it->X1) && !pd.ExistsMarkedState(transRel2it->X2))
1737  //...selfe loop
1738  || (transRel2it->X1 == transRel2it->X2)
1739  //...the event are not lambda
1740  || (!pd.IsEventLambda(transRel1it->Ev) && !pd.IsEventLambda(transRel2it->Ev));
1741 
1742  //if almost one transition can not merge, clear all
1743  if(canNotMerge)
1744  tmp.clear();
1745  else
1746  tmp.insert(std::make_pair(*transRel1it,*transRel2it));
1747 
1748  ++transRel2it;
1749  }
1750 
1751  res.insert(tmp.begin(),tmp.end());
1752  }
1753 
1754  return res;
1755 
1756 }
1757 
1758 /* *************************
1759  * CombinedTransitions
1760  * *************************/
1761 bool CombinedTransitions(Idx q,PushdownGenerator& rPd, /*std::set<Idx>&*/ StateSet& next,/*std::set<Idx>&*/ StateSet& done){
1762  bool debug = false;
1763 
1764  std::multimap<Transition, std::pair<std::vector<Idx>, std::vector<Idx> > > toRmTrans;
1765  std::multimap<Transition, std::pair<std::vector<Idx>, std::vector<Idx> > >::iterator toRmTransit;
1766 
1767  std::pair<Transition, std::pair<std::vector<Idx>, std::vector<Idx> > > pdtransition;
1768  std::pair<std::vector<Idx>, std::vector<Idx> > pp;
1769  std::vector<Idx> pop1,push1, pop2, push2, newPop, newPush;
1770 
1771  Transition trans1,trans2;
1772  TransSet::Iterator tit,tit_end;
1773 
1774  std::set<std::pair <Transition,Transition> > pairs ;
1775  std::set<std::pair <Transition,Transition> >::iterator pairsIt;
1776  PopPushSet::const_iterator pp1it, pp2it;
1777 
1778  DEBUG_PRINTF(debug,"CombinedTransitions: Start combine edge for "+rPd.StateStr(q),"");
1779 
1780  //get all possible mergeable pairs
1781  pairs = PossibleAdjacentMerges(q,rPd);
1782  DEBUG_PRINTF(debug,"mup done "+rPd.StateStr(q),"");
1783 
1784  if(!pairs.empty()){
1785  bool merged = false;
1786 
1787  //try to combine edges
1788  for(pairsIt = pairs.begin(); pairsIt != pairs.end(); ++pairsIt){
1789  //get transitions
1790  trans1 = pairsIt->first;
1791  trans2 = pairsIt->second;
1792 
1793  DEBUG_PRINTF(debug,"CombinedTransitions: Try ("+trans1.Str()+"/"+trans2.Str()+")","");
1794 
1795  for(pp1it = rPd.PopPushBegin(trans1); pp1it != rPd.PopPushEnd(trans1); ++pp1it){
1796  for(pp2it = rPd.PopPushBegin(trans2); pp2it != rPd.PopPushEnd(trans2); ++pp2it){
1797  // pop/push of first transition
1798  pop1 = pp1it->first;
1799  push1 = pp1it->second;
1800 
1801  //pop/push of second transition
1802  std::vector<Idx> pop2 = pp2it->first;
1803  std::vector<Idx> push2 = pp2it->second;
1804 
1805  //check if push1 and pop2 match
1806  if(std::equal(push1.begin(),push1.begin() + std::min(push1.size(),pop2.size()) ,pop2.begin())){
1807  Idx ev = (rPd.IsEventLambda(trans1.Ev))? trans2.Ev : trans1.Ev;
1808  newPop.clear();
1809  newPush.clear();
1810 
1811  if(!rPd.IsStackSymbolLambda(pop1.front()))
1812  newPop = pop1;
1813 
1814  if(push1.size() <= pop2.size()){
1815  //newPop = pop1 :: (pop2\push1)
1816  newPop.insert(newPop.end(),pop2.begin()+ push1.size(), pop2.end());
1817  }
1818 
1819  if(newPop.size() == 1){
1820  if(!rPd.IsStackSymbolLambda(push2.front()))
1821  newPush = push2;
1822 
1823  if(pop2.size() <= push1.size())
1824  //newPush = push1\pop2
1825  newPush.insert(newPush.end(),push1.begin() + pop2.size(), push1.end());
1826 
1827  Idx lambda = rPd.InsStackSymbol(FAUDES_PD_LAMBDA);
1828  if(newPop.empty()) newPop.push_back(lambda);
1829  if(newPush.empty())newPush.push_back(lambda);
1830 
1831  //remember to remove old transitions
1832  pp = std::make_pair(pop1,push1);
1833  pdtransition = std::make_pair(trans1,pp);
1834  toRmTrans.insert(pdtransition);
1835 
1836  pp = std::make_pair(pop2,push2);
1837  pdtransition = std::make_pair(trans2,pp);
1838  toRmTrans.insert(pdtransition);
1839 
1840  // set new Transition
1841  rPd.SetTransition(trans1.X1,ev,trans2.X2,newPop,newPush);
1842 
1843  Transition nt = *rPd.FindTransition(trans1.X1,ev,trans2.X2);
1844 
1845  DEBUG_PRINTF(debug,
1846  "CombinedTransitions: Merge ("+ trans1.Str()+ " | "+ trans2.Str() + ") to "+ nt.Str() +"\n","");
1847 
1848  next.Insert(q);
1849  merged = true;
1850  }
1851  else
1852  DEBUG_PRINTF(debug,"CombinedTransitions: New Pop != 1","");
1853 
1854  }// pop-push incompatible
1855  else
1856  DEBUG_PRINTF(debug,"CombinedTransitions: Pop - Push incompatible","");
1857  }
1858  }
1859  }//for
1860 
1861  // remove merged transitions
1862  for(toRmTransit = toRmTrans.begin(); toRmTransit != toRmTrans.end(); ++toRmTransit)
1863  rPd.ClrTransition(toRmTransit->first,toRmTransit->second.first,toRmTransit->second.second);
1864 
1865  if(merged){
1866  return true;
1867  }
1868 
1869  }// pairs empty
1870  else
1871  DEBUG_PRINTF(debug,"CombinedTransitions: Pairs empty","");
1872 
1873  // if no transition merged together, get successor states
1874  StateSet succStates;
1875 
1876  tit = rPd.TransRelBegin(q);
1877  tit_end = rPd.TransRelEnd(q);
1878  for (; tit != tit_end; ++tit) {
1879  succStates.Insert(tit->X2);
1880  }
1881 
1882  next.InsertSet(succStates);
1883  done.Insert(q);
1884 
1885  return false;
1886 }
1887 
1888 /* *************************
1889  * MergeAdjacentTransitions
1890  * *************************/
1892 
1893  bool merged;
1894  StateSet todo, done,next;
1895  StateSet::Iterator it;
1896 
1897  //repeat until all possible transitions are merged together
1898  do{
1899 
1900  //clean sets
1901  todo.Clear();
1902  done.Clear();
1903 
1904  //start with init state
1905  todo.Insert(rPd.InitState());
1906 
1907  //initially no transition merged
1908  merged = false;
1909 
1910  //check if at least one merge is possible
1911  while(!todo.Empty()){
1912  next.Clear();
1913 
1914  for(it = todo.Begin(); it != todo.End(); ++it){
1915  merged = merged || CombinedTransitions(*it,rPd,next,done);
1916  }
1917 
1918  todo.Clear();
1919 
1920  todo = next - done;
1921  }
1922  }while(merged);
1923 }
1924 
1925 
1926 
1927 
1928 
1929 
1930 } // namespace faudes
1931 

libFAUDES 2.28c --- 2016.09.30 --- c++ api documentaion by doxygen