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("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  return rPd;
710 }
711 
712 /* *************************
713  * RebuildFromSPDA
714  * *************************/
716  const TransformationHistoryVec& history) {
717  FUNCTION(__FUNCTION__); //scop log
718 
719  //copy
721 
722  TransformationHistoryVec::const_reverse_iterator historyit;
723  std::vector<std::pair<Idx,MergeTransition> > merges;
724  std::vector<std::pair<Idx,MergeTransition> >::iterator mergeit;
725  std::vector<Idx> pop,push;
726  std::vector<Idx>::iterator it;
727 
728  std::vector<Idx> t;
729  t.push_back(rPd.InsLambdaStackSymbol());
730 
731  //go through history backwards
732  for (historyit = history.rbegin(); historyit != history.rend();
733  ++historyit) {
734  //get merges
735  merges = *historyit;
736 
737  //recreate transition from merge (if possible)
738  for (mergeit = merges.begin(); mergeit != merges.end(); ++mergeit) {
739  //merge state
740  Idx state = mergeit->first;
741  //merge transition
742  MergeTransition mt = mergeit->second;
743 
744  //if merge state still exists
745  if (rPd.ExistsState(state)) {
746  //if states of transition still exists
747  if (rPd.ExistsState(mt.X1())
748  && rPd.ExistsState(mt.X2())) {
749 
750  pop = mt.Pop();
751  push = mt.Push();
752 
753  for(it = pop.begin(); it != pop.end(); ++it)
754  rPd.InsStackSymbol(rPd.StackSymbolName(*it));
755  for(it = push.begin(); it != push.end(); ++it)
756  rPd.InsStackSymbol(rPd.StackSymbolName(*it));
757 
758  //add transition
759  rPd.SetTransition(mt.X1(), mt.Ev(),
760  mt.X2(), mt.Pop(), mt.Push());
761  //delete merge state
762  rPd.DelState(state);
763  }
764  }
765  }
766  }
767 
768  return rPd;
769 }
770 
771 /* *************************
772  * RemainingPd
773  * *************************/
775  FUNCTION(__FUNCTION__); //scope log
776  bool debug = false; //debug RemainingPd?
777 
778  //take copy
779  PushdownGenerator rPd(pd);
780 
781  //remove all transition and add only remaining ones
782  rPd.ClearTransRel();
783 
784  std::set<GrammarProduction>::const_iterator proit;
785  TransSet::Iterator transit;
786  PopPushSet::const_iterator ppit;
787 
788  //check for all productions
789  for (proit = gr.GrammarProductionsBegin();
790  proit != gr.GrammarProductionsEnd(); ++proit) {
791  Nonterminal lhs = proit->Lhs();
792  GrammarSymbolVector rhs = proit->Rhs();
793 
794  // lhs = (qi,b) ( or (qi,b,qj) if lhs.mEndState != 0)
795  //if (lhs.EndState() == 0) {
796  TerminalPtr termPtr = std::tr1::dynamic_pointer_cast<Terminal>(
797  rhs.front());
798  if (termPtr != NULL) {
799  // first elem of rhs is either lambda or an event (both are terminals)
800  if (termPtr->IsLambda()) {
801  // rhs = lambda
802  if (lhs.EndState() == 0) {
803  // (q,b) -> lambda
804  // nothing to do
805  DEBUG_PRINTF(debug, "Find Tfinal P = " + (*proit).Str(),"");
806  } else {
807  // type (ii)
808  // (qi,b,qj) --> lambda
809  for (transit = pd.TransRelBegin(lhs.StartState());
810  transit != pd.TransRelEnd(lhs.StartState());
811  ++transit) {
812  for (ppit = pd.PopPushBegin(*transit);
813  ppit != pd.PopPushEnd(*transit); ++ppit) {
814  std::vector<Idx> pop = ppit->first;
815  std::vector<Idx> push = ppit->second;
816 
817  //pop transition (qi,lambda,b,lambda,qj) ==> (qi,b,qj) --> lambda
818  if (transit->X2 == lhs.EndState() // qj == qj
819  && pop.front() == lhs.OnStack().front() // b == b
820  && pd.IsStackSymbolLambda(push.front()) // push == lambda
821  && pd.IsEventLambda(transit->Ev)) { // event == lambda
822 
823  //add transition
824  rPd.SetTransition(*transit, pop, push); // add transition
825  DEBUG_PRINTF(debug, "Find T2 P = "+ (*proit).Str(), "");
826  }
827  }
828  }
829  }
830  } else {
831  // rhs = a(qj,b[,qt])
832 
833  // type (i)
834  // (qi,b[,qt]) --> a(qj,b[,qt])
835  for (transit = pd.TransRelBegin(lhs.StartState());
836  transit != pd.TransRelEnd(lhs.StartState());
837  ++transit) {
838  for (ppit = pd.PopPushBegin(*transit);
839  ppit != pd.PopPushEnd(*transit); ++ppit) {
840  std::vector<Idx> pop = ppit->first;
841  std::vector<Idx> push = ppit->second;
842 
843  NonterminalPtr nontermPtr =
844  std::tr1::dynamic_pointer_cast<Nonterminal>(rhs.back()); // ->(qj,b[,qt])
845 
846  // read Transition (qi,a,b,b,qj) ==> (qi,b[,qt]) --> a(qj,b[,qt])
847  if (nontermPtr != NULL
848  && transit->X2 == nontermPtr->StartState() // qj == qj
849  && transit->Ev == termPtr->Event() // a == a
850  && pop.front() == lhs.OnStack().front() // b == b
851  && push.front() == lhs.OnStack().front()) {
852 
853  //add transition
854  rPd.SetTransition(*transit, pop, push); // add transition
855  DEBUG_PRINTF(debug, "Find T1 P = "+ (*proit).Str(), "");
856 
857  } else if (nontermPtr == NULL) {
858  //ERROR:
859  FD_WARN("RemainingPd: Find not identifiable production" + (*proit).Str());
860  }
861  }
862  }
863  }
864  } else {
865  // first elem of rhs is a nonterminal
866 
867  NonterminalPtr nonterm1Ptr =
868  std::tr1::dynamic_pointer_cast<Nonterminal>(rhs.front());
869  if (nonterm1Ptr != NULL) {
870  if (rhs.size() == 1) {
871  // type (iii L)
872  // (qi,b) --> (qj,c)
873  for (transit = pd.TransRelBegin(lhs.StartState());
874  transit != pd.TransRelEnd(lhs.StartState());
875  ++transit) {
876  for (ppit = pd.PopPushBegin(*transit);
877  ppit != pd.PopPushEnd(*transit); ++ppit) {
878  std::vector<Idx> pop = ppit->first;
879  std::vector<Idx> push = ppit->second;
880 
881  // push Transition (qi,lambda,b,cb,qj) ==> (qi,b) --> (qj,c)
882  if (transit->X2 == nonterm1Ptr->StartState() // qj == qj
883  && pop.front() == lhs.OnStack().front() // b == b
884  // check push
885  && push.size() == 2 // push 2 elements c and b
886  && push.front()
887  == nonterm1Ptr->OnStack().front()// c == c
888  && push.back() == lhs.OnStack().front() // b == b
889  && pd.IsEventLambda(transit->Ev)) { // ev == lambda
890 
891  //add transition
892  rPd.SetTransition(*transit, pop, push); // add transition
893  DEBUG_PRINTF(debug, "Find T3L P = "+ (*proit).Str(), "");
894 
895  }
896  }
897  }
898  } else { //rhs.size() > 1
899  // type (iii R)
900  // (qi,b[,qt]) --> (qj,c,qs)(qs,b[,qt])
901  for (transit = pd.TransRelBegin(lhs.StartState());
902  transit != pd.TransRelEnd(lhs.StartState());
903  ++transit) {
904  for (ppit = pd.PopPushBegin(*transit);
905  ppit != pd.PopPushEnd(*transit); ++ppit) {
906  std::vector<Idx> pop = ppit->first;
907  std::vector<Idx> push = ppit->second;
908 
909  NonterminalPtr nonterm2Ptr =
910  std::tr1::dynamic_pointer_cast<Nonterminal>(
911  rhs.back()); // ->(qs,b[,qt])
912 
913  // push Transition (qi,lambda,b,cb,qj) ==> (qi,b[,qt]) --> (qj,c,qs)(qs,b[,qt])
914  if (nonterm2Ptr != NULL
915  && transit->X2 == nonterm1Ptr->StartState() // qj == qj
916  && pop.front() == lhs.OnStack().front() // pop b == b
917  // check push
918  && push.size() == 2 // push 2 elements c and b
919  && push.front()
920  == nonterm1Ptr->OnStack().front() // c == c
921  && push.back()
922  == nonterm2Ptr->OnStack().front() // b == b
923  && pd.IsEventLambda(transit->Ev)) { // ev == lambda
924 
925  //add transition
926  rPd.SetTransition(*transit, pop, push); // add transition
927  DEBUG_PRINTF(debug, "Find T3R P = "+ (*proit).Str(), "");
928  } else if (nonterm2Ptr == NULL) {
929  //ERROR:
930  FD_WARN("RemainingPd: Find not identifiable production" + (*proit).Str());
931  }
932  }
933  }
934  }
935  }
936  }
937  } // foreach production
938 
939  return rPd;
940 }
941 
942 /* *************************
943  * RemoveLambdaPop
944  * *************************/
946  FUNCTION(__FUNCTION__); //scope log
947 
948  if(!pd.IsDeterministic()){
949  FD_WARN("RemoveLambdaPop: Generator is not deterministic ! Perhaps not all lambda popping transitions will remove.") // TODO
950  }
951 
952  //rename stack symbols and states
953  PushdownGenerator rPd (pd);
954 
955 
956  // XXX:is no longer needed
957  /*********************************************************************************
958  //remember important attributes of the generator before proceeding
959  StackSymbolSet oldStackSymbols = rPd.StackSymbols();
960  Idx oldInitState = rPd.InitState();
961  std::string oldStackBottom = rPd.StackSymbolName(rPd.StackBottom());
962 
963 
964  //clear old init state and create new init state which will be annotated with "new"
965  //and derived from pd.InitState() in a merge state annotation
966  rPd.ClrInitState(rPd.InitState());
967  Idx newInitState = rPd.InsState();
968  rPd.SetInitState(newInitState);
969  MergeStateAnnotation msa(pd.InitState(),"new");
970  rPd.SetMerge(newInitState, msa);
971 
972  //set new stack bottom
973  rPd.SetStackBottom("new-" + pd.StackSymbolName(pd.StackBottom()));
974 
975  //if the old initial state was marked, the new initial state is marked as well
976  if(pd.ExistsMarkedState(pd.InitState())){
977  rPd.InsMarkedState(rPd.InitState());
978  }
979 
980  //add transition that adds the old stack bottom symbol to the stack
981  //maybe lambda event needs to be inserted first
982  Idx lambdaIdx = rPd.InsEvent(FAUDES_PD_LAMBDA);
983  std::vector<StackSymbol> pop, push;
984  std::string newStackBottom = rPd.StackSymbolName(rPd.StackBottom());
985  //pop new stack bottom
986  pop.push_back(StackSymbol(newStackBottom));
987  //push new stack bottom and old stack bottom
988  push.push_back(StackSymbol(oldStackBottom));
989  push.push_back(StackSymbol(newStackBottom));
990  //add transition
991  rPd.SetTransition(newInitState, lambdaIdx, oldInitState, pop, push);
992 
993  // ********************************************************************/
994 
995  //iterate over all transitions
996  //take copy of transitions to iterate over
997  //copying is necessary because transitions will get deleted
998  //iterating over the original TransSet can lead to undefined behavior
999  TransSet transRel = rPd.TransRel();
1000  TransSet::Iterator tit;
1001  StackSymbolSet::Iterator ssit;
1002  std::vector<Idx> examinedPop, examinedPush, newPop, newPush;
1003 
1004  for (tit = transRel.Begin(); tit != transRel.End(); tit++) {
1005 
1006  //look for lambda popping transitions (s1,ev,s2,lambda,w)
1007  //only need to look at the first pop/push pair, because only deterministic
1008  //generator are considered. the generator would be nondeterministic if there
1009  //was a transition in addition to a lambda popping one
1010  examinedPop = rPd.PopPush(*tit).begin()->first;
1011  examinedPush = rPd.PopPush(*tit).begin()->second;
1012  if (pd.IsStackSymbolLambda(examinedPop.front())) {
1013 
1014  //remove the transition
1015  rPd.ClrTransition(*tit, examinedPop, examinedPush);
1016 
1017  //add new transitions for every possible stack symbol u minus the just
1018  //inserted bottom and lambda so that it looks like (s1,ev,s2,u,uw) for
1019  for (ssit = rPd.StackSymbolsBegin(); ssit != rPd.StackSymbolsEnd();
1020  ssit++) {
1021  if (!rPd.IsStackSymbolLambda(*ssit)) {
1022  //fill pop with stack symbol
1023  newPop.clear();
1024  newPop.push_back(*ssit);
1025  //fill push with examinedPush plus stack symbol
1026  newPush.clear();
1027  newPush.insert(newPush.end(), examinedPush.begin(),
1028  examinedPush.end());
1029  newPush.push_back(*ssit);
1030  //add transition
1031  rPd.SetTransition(*tit, newPop, newPush);
1032  }
1033  }
1034  }
1035  }
1036 
1037  return rPd;
1038 }
1039 
1040 /* *************************
1041  * Sp2Lr
1042  * *************************/
1043 Grammar Sp2Lr(const PushdownGenerator& xrPd,uint n, bool ignorReducible,bool debug) {
1044  FUNCTION(__FUNCTION__); //scope log
1045  FD_DF("Sp2Lr(" << &xrPd << "," << n << ")");
1046 
1047  //Grammar to return
1048  Grammar rGr;
1049 
1050  StateSet::Iterator stateit1, stateit2;
1051  EventSet::Iterator eventit;
1052  TransSet::Iterator transit, transit2, transit3;
1053  StackSymbolSet::Iterator ssit;
1054  PopPushSet::const_iterator ppit, ppit2, ppit3;
1055  std::vector<Idx>::const_iterator popit, pushit;
1056  std::vector<Idx> ssVector, pop, push;
1057  std::map<Idx,StateSet> reachableStatesMap;
1058  GrammarSymbolVector rhs;
1059 
1060  //take a copy of pushdown generator
1061  PushdownGenerator tmpPd(xrPd);
1062 
1063  if(!ignorReducible){
1064  //Trim
1065  PushdownTrim(tmpPd,n);
1066  }
1067 
1068  //fill map
1069  ReachableStateMap(tmpPd,reachableStatesMap);
1070 
1071  //terminals equal the generator's events
1072  for (eventit = tmpPd.AlphabetBegin(); eventit != tmpPd.AlphabetEnd(); eventit++) {
1073  rGr.InsTerminal(Terminal(*eventit));
1074  }
1075  //Start Symbol (q0,$)
1076  ssVector.clear();
1077  ssVector.push_back(tmpPd.StackBottom());
1078  rGr.SetStartSymbol(Nonterminal(tmpPd.InitState(), ssVector));
1079 
1080  //create grammar productions:
1081 
1082  //for each final state qm and each stack symbol A
1083  //create (qm,A) -> lambda
1084  for (stateit1 = tmpPd.MarkedStatesBegin(); stateit1 != tmpPd.MarkedStatesEnd();
1085  stateit1++) {
1086  for (ssit = tmpPd.StackSymbolsBegin(); ssit != tmpPd.StackSymbolsEnd();
1087  ssit++) {
1088  if (!tmpPd.IsStackSymbolLambda(*ssit)) {
1089 
1090  //save used nonterminal
1091  ssVector.clear();
1092  ssVector.push_back(*ssit);
1093  Nonterminal nt(*stateit1, ssVector);
1094  rGr.InsNonterminal(nt);
1095 
1096  //insert a production ((qm,A) --> lambda)
1097  Terminal* t = new Terminal(tmpPd.EventIndex(FAUDES_PD_LAMBDA));
1098  GrammarSymbolPtr tPtr(t);
1100  v.push_back(tPtr);
1101  GrammarProduction gp(nt, v);
1102  rGr.InsGrammarProduction(gp);
1103 
1104  FD_DF("Sp2Lr: Inserting" + gp.Str())
1105  DEBUG_PRINTF(debug,"Sp2Lr: Inserting" + gp.Str(),"");
1106  }
1107  }
1108  }
1109 
1110  //For each pop-transition in form (qi,lambda,pop,lambda,qj)
1111  for (transit = tmpPd.TransRelBegin(); transit != tmpPd.TransRelEnd(); ++transit) {
1112  for (ppit = tmpPd.PopPushBegin(*transit); ppit != tmpPd.PopPushEnd(*transit); ppit++) {
1113  push = ppit->second;
1114 
1115  //pop transition (qi,lambda,pop,lambda,qj)
1116  if (tmpPd.IsStackSymbolLambda(push.front())) {
1117  Idx qi = transit->X1;
1118  Idx qj = transit->X2;
1119  pop = ppit->first;
1120 
1121  //ensure that event = lambda
1122  if(! tmpPd.IsEventLambda(transit->Ev)){
1123  std::stringstream errstr;
1124  errstr << "While executing Sp2Lr(): Found transition that push lambda but don't read lambda, "
1125  "so is neither read nor pop, which is not allowed" << std::endl;
1126  throw Exception("Sp2Lr", errstr.str(), 1001);
1127  }
1128 
1129  //save lhs nonterminal as reducible
1130  Nonterminal ntLhs(qi, pop, qj);
1131  rGr.InsNonterminal(ntLhs);
1132 
1133  //insert production (qi,pop,qj) --> lambda
1134  Terminal* t = new Terminal(transit->Ev);
1135  GrammarSymbolPtr tPtr(t);
1136  rhs.clear();
1137  rhs.push_back(tPtr);
1138  rGr.InsGrammarProduction(GrammarProduction(ntLhs, rhs));
1139 
1140  FD_DF("Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str())
1141  DEBUG_PRINTF(debug,"Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str(),"");
1142  }
1143  }
1144  }
1145 
1146  //generate reducible productions until no more productions can be generated
1147  uint oldSize = 0;
1148 
1149  do{
1150  //save old number of grammar productions
1151  oldSize = rGr.GrammarProductions().size();
1152 
1153  //try to generate new grammar productions for each transition
1154  for (transit = tmpPd.TransRelBegin(); transit != tmpPd.TransRelEnd(); transit++) {
1155  for (ppit = tmpPd.PopPushBegin(*transit); ppit != tmpPd.PopPushEnd(*transit); ppit++) {
1156 
1157  Idx qi = transit->X1;
1158  Idx qj = transit->X2;
1159  Idx a = transit->Ev;
1160  std::vector<Idx> b = ppit->first;
1161  push = ppit->second;
1162 
1163  //read transition (qi,a,b,b,qj)
1164  if (!tmpPd.IsEventLambda(transit->Ev)) {
1165 
1166  //ensure that pop = push
1167  if(b != push){
1168  std::stringstream errstr;
1169  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;
1170  throw Exception("Sp2Lr", errstr.str(), 1001);
1171  }
1172 
1173  //insert production (qi,b) --> a(qj,b)
1174  Nonterminal ntLhs(qi, b);
1175  Terminal* t = new Terminal(a);
1176  GrammarSymbolPtr tPtr(t);
1177  Nonterminal* ntRhs = new Nonterminal(qj, b);
1178  GrammarSymbolPtr ntRhsPtr(ntRhs);
1179 
1180  if(ignorReducible)
1181  rGr.InsNonterminal(*ntRhs);
1182 
1183  //... but only if (qj,b) is reducible
1184  if (rGr.Nonterminals().find(*ntRhs)
1185  != rGr.NonterminalsEnd()) {
1186 
1187  //save lhs nonterminal as reducible
1188  rGr.InsNonterminal(ntLhs);
1189 
1190  //insert production
1191  rhs.clear();
1192  rhs.push_back(tPtr);
1193  rhs.push_back(ntRhsPtr);
1194  rGr.InsGrammarProduction(GrammarProduction(ntLhs, rhs));
1195 
1196  FD_DF("Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str())
1197  DEBUG_PRINTF(debug,"Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str(),"");
1198 
1199  }
1200 
1201  //For all states qt that are reachable from qj
1202  StateSet reachFromTrg = reachableStatesMap.find(qj)->second;
1203  for (stateit1 = reachFromTrg.Begin(); stateit1 != reachFromTrg.End(); stateit1++) {
1204 
1205  Idx qt = *stateit1;
1206 
1207  //insert production (qi,b,qt) --> a (qj,b,qt)
1208  Nonterminal ntLhs(qi, b, qt);
1209  Nonterminal* ntRhs = new Nonterminal(qj, b, qt);
1210 
1211  if(ignorReducible)
1212  rGr.InsNonterminal(*ntRhs);
1213 
1214  //... but only if (qj,b,qt) is reducible
1215  if (rGr.Nonterminals().find(*ntRhs)
1216  != rGr.NonterminalsEnd()) {
1217  //save lhs nonterminal as ignorReducible
1218  rGr.InsNonterminal(ntLhs);
1219 
1220  //insert production
1221  GrammarSymbolPtr ntRhsPtr(ntRhs);
1222  rhs.clear();
1223  rhs.push_back(tPtr);
1224  rhs.push_back(ntRhsPtr);
1225  rGr.InsGrammarProduction(GrammarProduction(ntLhs, rhs));
1226 
1227  FD_DF("Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str())
1228  DEBUG_PRINTF(debug,"Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str(),"");
1229 
1230  }
1231  }
1232  } // end if read != lambda
1233  else {
1234 
1235  //pop transition (qi,lambda,b,lambda,qj)
1236  if (tmpPd.IsStackSymbolLambda(push.front())) {
1237  //already done
1238  }
1239 
1240  //push transition (qi,lambda,b,cb,qj)
1241  else if (push.size() == 2) {
1242 
1243  std::vector<Idx> c;
1244  c.push_back(push.front());
1245 
1246  //insert production (qi,b) --> (qj,c)
1247  Nonterminal ntLhs(qi, b);
1248  Nonterminal* ntRhs = new Nonterminal(qj, c);
1249  GrammarSymbolPtr ntRhsPtr(ntRhs);
1250 
1251  if(ignorReducible)
1252  rGr.InsNonterminal(*ntRhs);
1253 
1254  //... but only if (qj,c) is reducible
1255  if (rGr.Nonterminals().find(*ntRhs)
1256  != rGr.NonterminalsEnd()) {
1257 
1258  //save lhs nonterminal as ignorReducible
1259  rGr.InsNonterminal(ntLhs);
1260 
1261  //insert production
1262  rhs.clear();
1263  rhs.push_back(ntRhsPtr);
1264  rGr.InsGrammarProduction(GrammarProduction(ntLhs, rhs));
1265 
1266  FD_DF("Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str())
1267  DEBUG_PRINTF(debug,"Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str(),"");
1268  }
1269 
1270  //For all states qs that are reachable from qj
1271  StateSet reachFromTrg = reachableStatesMap.find(qj)->second;
1272  for (stateit1 = reachFromTrg.Begin(); stateit1 != reachFromTrg.End(); stateit1++) {
1273 
1274  Idx qs = *stateit1;
1275 
1276  //insert production (qi,b) --> (qj,c,qs)(qs,b)
1277  Nonterminal ntLhs(qi, b);
1278  Nonterminal* ntRhs1 = new Nonterminal(qj, c, qs);
1279  GrammarSymbolPtr ntRhs1Ptr(ntRhs1);
1280  Nonterminal* ntRhs2 = new Nonterminal(qs, b);
1281  GrammarSymbolPtr ntRhs2Ptr(ntRhs2);
1282 
1283  if(ignorReducible){
1284  rGr.InsNonterminal(*ntRhs1);
1285  rGr.InsNonterminal(*ntRhs2);
1286  }
1287 
1288  //... but only if (qj,c,qs) and (qs,b) are reducible
1289  if (rGr.Nonterminals().find(*ntRhs1) != rGr.NonterminalsEnd()
1290  && rGr.Nonterminals().find(*ntRhs2) != rGr.NonterminalsEnd()){
1291 
1292  //save lhs nonterminal as ignorReducible
1293  rGr.InsNonterminal(ntLhs);
1294 
1295  //insert production
1296  rhs.clear();
1297  rhs.push_back(ntRhs1Ptr);
1298  rhs.push_back(ntRhs2Ptr);
1299  rGr.InsGrammarProduction(GrammarProduction(ntLhs, rhs));
1300 
1301  FD_DF("Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str())
1302  DEBUG_PRINTF(debug,"Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str(),"");
1303  }
1304 
1305  //for each push transition (qs,_,c,lambda,qp)
1306  for (transit2 = tmpPd.TransRelBegin(qs); transit2 != tmpPd.TransRelEnd(qs); ++transit2) {
1307  for (ppit2 = tmpPd.PopPushBegin(*transit2); ppit2 != tmpPd.PopPushEnd(*transit2); ++ppit2) {
1308 
1309  if (tmpPd.IsStackSymbolLambda((ppit2->second).front()) && (ppit2->first).front() == push.front()) {
1310  //ey
1311  Idx qp = transit2->X2;
1312 
1313  //For all states qs' that are reachable from qs
1314  StateSet reachFromqs = reachableStatesMap.find(qs)->second;
1315  for (stateit2 = reachFromqs.Begin(); stateit2 != reachFromqs.End(); ++stateit2) { // reach from qp
1316  //for each transition (qs',_,B,lambda,qt)
1317  for (transit3 = tmpPd.TransRelBegin(*stateit2); transit3 != tmpPd.TransRelEnd(*stateit2);
1318  ++transit3) {
1319  //ex
1320  for (ppit3 = tmpPd.PopPushBegin(*transit3); ppit3 != tmpPd.PopPushEnd(*transit3);
1321  ++ppit3) {
1322  if (tmpPd.IsStackSymbolLambda((ppit3->second).front())
1323  && (ppit3->first).front() == push.back()) { //ex
1324 
1325  Idx qt = transit3->X2;
1326 
1327  //insert production (qi,b,qt) --> (qj,c,qp)(qp,b,qt)
1328  Nonterminal ntLhs(qi, b, qt);
1329  Nonterminal* ntRhs1 = new Nonterminal(qj,c,qp);
1330  GrammarSymbolPtr ntRhs1Ptr(ntRhs1);
1331  Nonterminal* ntRhs2 = new Nonterminal(qp,b,qt);
1332  GrammarSymbolPtr ntRhs2Ptr(ntRhs2);
1333 
1334  if(ignorReducible){
1335  rGr.InsNonterminal(*ntRhs1);
1336  rGr.InsNonterminal(*ntRhs2);
1337  }
1338 
1339  //... but only if (qj,c,qs) and (qs,b,qt) are reducible
1340  if (rGr.Nonterminals().find(*ntRhs1) != rGr.NonterminalsEnd()
1341  && rGr.Nonterminals().find(*ntRhs2) != rGr.NonterminalsEnd()) {
1342 
1343  //save lhs nonterminal as ignorReducible
1344  rGr.InsNonterminal(ntLhs);
1345 
1346  //insert production
1347  rhs.clear();
1348  rhs.push_back(ntRhs1Ptr);
1349  rhs.push_back(ntRhs2Ptr);
1350  rGr.InsGrammarProduction(GrammarProduction(ntLhs,rhs));
1351 
1352  FD_DF("Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str())
1353  DEBUG_PRINTF(debug,"Sp2Lr: Inserting" + GrammarProduction(ntLhs,rhs).Str(),"");
1354  }
1355  }
1356  }
1357  }
1358  }
1359  }
1360  }
1361  }
1362  }
1363  }
1364  }
1365  }
1366  }
1367  if(ignorReducible)
1368  return rGr;
1369  } while (rGr.GrammarProductions().size() != oldSize);
1370 
1371  //return CFG
1372  return rGr;
1373 }
1374 
1375 /* *************************
1376  * Filter
1377  * *************************/
1378 std::set<Nonterminal> Filter(const std::set<Nonterminal>& symbolSet, const GrammarSymbolVector& w){
1379 
1380  //resulting set
1381  std::set<Nonterminal> rSet;
1382 
1383  GrammarSymbolVector::const_iterator wit;
1384  std::set<Nonterminal>::const_iterator ntit;
1385  //iterate over all symbols of the word
1386  for(wit = w.begin(); wit != w.end(); wit++){
1387  //test if current symbol is a nonterminal
1388  ConstNonterminalPtr nt = std::tr1::dynamic_pointer_cast<const Nonterminal>(*wit);
1389  if(nt != NULL){
1390 
1391  //look for the symbol in the nonterminal set
1392  ntit = symbolSet.find(*nt);
1393 
1394  //if the symbol was found, insert it into resulting set
1395  if(ntit != symbolSet.end()){
1396  rSet.insert(*ntit);
1397  }
1398  }
1399  }
1400  return rSet;
1401 }
1402 
1403 /* *************************
1404  * Rnpp1
1405  * *************************/
1406 std::set<Nonterminal> Rnpp1(const Grammar& gr, const std::set<Nonterminal>& ntSet){
1407 
1408  std::set<Nonterminal> rSet, filterSet;
1409  //copy resulting set from set of already eliminated nonterminals
1410  rSet = ntSet;
1411 
1412  std::set<GrammarProduction>::const_iterator pit;
1413  //iterate over all productions
1414 
1415  for(pit = gr.GrammarProductions().begin(); pit != gr.GrammarProductions().end(); pit++){
1416 
1417  filterSet = Filter(gr.Nonterminals(),pit->Rhs());
1418 
1419  //test if the nonterminals on the right hand side of the production are all in
1420  //the set of eliminable nonterminals (i. e., they are eliminable)
1421  //if so, then the nonterminal on the left hand side is eliminable as well
1422  if(std::includes(ntSet.begin(), ntSet.end(), filterSet.begin(), filterSet.end())){
1423  //insert left hand side into set of eliminable terminals
1424  rSet.insert(pit->Lhs());
1425  }
1426  }
1427  return rSet;
1428 }
1429 
1430 /* *************************
1431  * Rnppl
1432  * *************************/
1433 std::set<Nonterminal> Rnppl(const Grammar& gr, const std::set<Nonterminal>& ntSet){
1434 
1435  //get nonterminals that are eliminable in one step
1436  std::set<Nonterminal> rSet = Rnpp1(gr,ntSet);
1437  //look if that changed anything
1438  if(ntSet != rSet){
1439  //if any changes were detected, go on
1440  rSet = Rnppl(gr,rSet);
1441  }
1442  return rSet;
1443 }
1444 
1445 /* *************************
1446  * Rnpp
1447  * *************************/
1448 Grammar Rnpp(const Grammar& gr){
1449 
1450  //the grammar to be returned. keep the start symbol
1451  Grammar rGr(gr.StartSymbol());
1452 
1453  //compute removable nonterminals
1454  std::set<Nonterminal> removableNts = Rnppl(gr,std::set<Nonterminal>());
1455 
1456  std::set<GrammarProduction> productions;
1457  //if the start symbol is a removable nonterminal
1458 
1459  if(removableNts.find(gr.StartSymbol()) != removableNts.end()){
1460 
1461  std::set<GrammarProduction>::const_iterator gpit;
1462  //iterate over grammar productions A -> w
1463  for(gpit = gr.GrammarProductionsBegin(); gpit != gr.GrammarProductionsEnd(); gpit++){
1464 
1465  //convert A to GrammarSymbolPtr and put it togther with w into a vector
1466  Nonterminal* a = new Nonterminal(gpit->Lhs());
1467  NonterminalPtr aPtr(a);
1468  GrammarSymbolVector symbols(gpit->Rhs());
1469  symbols.push_back(aPtr);
1470 
1471  std::set<Nonterminal> filteredSet;
1472  //filter all nonterminals that are in A and w
1473  filteredSet = Filter(gr.Nonterminals(), symbols);
1474 
1475  //test if filteredSet is a subset of the removable nonterminals
1476  if(std::includes(removableNts.begin(), removableNts.end(), filteredSet.begin(), filteredSet.end())){
1477  productions.insert(*gpit);
1478  }
1479  }
1480  }
1481 
1482  //keep the terminals
1483  rGr.InsTerminals(gr.Terminals());
1484 
1485  //keep only removable nonterminals
1486  rGr.InsNonterminals(removableNts);
1487 
1488  //keep only the productions from above
1489  rGr.InsGrammarProductions(productions);
1490 
1491  return rGr;
1492 }
1493 
1494 /* *************************
1495  * Rup
1496  * *************************/
1497 Grammar Rup(const Grammar& gr){
1498 
1499  Grammar rGr;
1500 
1501  //copy terminals and start symbol from the old grammar
1502  rGr.InsTerminals(gr.Terminals());
1503  rGr.SetStartSymbol(gr.StartSymbol());
1504 
1505  std::set<GrammarProduction> todoProductions, reachableProductions;
1506  std::set<GrammarProduction>::const_iterator gpit;
1507  std::set<Nonterminal> usedNonterminals;
1508 
1509  //start with the start symbol, which is always used in a grammar
1510  usedNonterminals.insert(gr.StartSymbol());
1511 
1512  //get productions with start symbol as righthand side
1513  for(gpit = gr.GrammarProductionsBegin(); gpit != gr.GrammarProductionsEnd(); gpit++){
1514  if(gpit->Lhs() == gr.StartSymbol()){
1515  todoProductions.insert(*gpit);
1516  }
1517  }
1518 
1519  //look at all todo productions
1520  while(!todoProductions.empty()){
1521 
1522  //get the current todo production
1523  GrammarProduction currentGp(*todoProductions.begin());
1524  todoProductions.erase(currentGp);
1525 
1526  //since this production was reached, it is a reachable production
1527  reachableProductions.insert(currentGp);
1528 
1529  //insert all nonterminals of the current production into set of used nonterminals
1530  std::set<Nonterminal> filtered = Filter(gr.Nonterminals(),currentGp.Rhs());
1531  usedNonterminals.insert(filtered.begin(), filtered.end());
1532 
1533  //look at all productions
1534  for(gpit = gr.GrammarProductionsBegin(); gpit != gr.GrammarProductionsEnd(); gpit++){
1535  //if they have any of the used nonterminals on their lefthand side, insert them
1536  //into the todo productions
1537  if(usedNonterminals.find(gpit->Lhs()) != usedNonterminals.end()){
1538  todoProductions.insert(*gpit);
1539  }
1540  }
1541 
1542  //do not look at already reachable productions twice
1543  //this avoids infinite loops
1544  for(gpit = reachableProductions.begin(); gpit != reachableProductions.end(); gpit++){
1545  todoProductions.erase(*gpit);
1546  }
1547  }
1548 
1549  //insert all used nonterminals and all reachable productions
1550  rGr.InsNonterminals(usedNonterminals);
1551  rGr.InsGrammarProductions(reachableProductions);
1552 
1553  return rGr;
1554 }
1555 
1556 
1557 /* *************************
1558  * RemoveMultPop
1559  * *************************/
1561 
1562  //take a annotate copy of the old generator
1563  PushdownGenerator rPd = AnnotatePdStates("old",pd);
1564 
1565  //clear transition relation
1566  rPd.ClearTransRel();
1567 
1568  //lambda event
1569  Idx lambdaEv = rPd.InsEvent(FAUDES_PD_LAMBDA);
1570 
1571  //lambda stack symbol
1572  Idx lambdaSS = rPd.InsStackSymbol(FAUDES_PD_LAMBDA);
1573 
1574  StateSet::Iterator stateit;
1575  TransSet::Iterator transit;
1576  PopPushSet::const_iterator ppIt;
1577 
1578  Idx src,trg,lastState;
1579  std::vector<Idx> oldPop,oldPush,pop,push;
1580  std::vector<Idx>::iterator popit;
1581  //remember for each sub-vector of pop the new state
1582  std::map<std::vector<Idx>,Idx> popStateMap;
1583  std::map<std::vector<Idx>,Idx>::iterator mapit;
1584 
1585  //remove all multiple pop-transition
1586  //e.g. (p,a,x1x2...xN,w,q) =>
1587  //(p,lambda,x1,lambda,p1), (p1,lambda,x2,lambda,p2), ... , (pN-1,lambda,xN,xN,pN),(pN,a,xN,w,q)
1588  //note: by the previous call of there is no lambda pop
1589  for(stateit = pd.StatesBegin(); stateit != pd.StatesEnd(); ++stateit){
1590  popStateMap.clear();
1591  for (transit = pd.TransRelBegin(*stateit); transit != pd.TransRelEnd(*stateit); ++transit) {
1592  for (ppIt = pd.PopPushBegin(*transit); ppIt != pd.PopPushEnd(*transit); ++ppIt) {
1593  //get pop/push
1594  oldPop = ppIt->first;
1595  oldPush = ppIt->second;
1596 
1597  //ensure transition doesn't pop lambda
1598  if(pd.IsStackSymbolLambda(oldPop.front())){
1599  std::stringstream errstr;
1600  errstr << "While executing RemoveMultPop(): Found transition that pop lambda, which is not allowed !" << std::endl;
1601  throw Exception("RemoveMultPop", errstr.str(), 1001);
1602  }
1603 
1604  //lastState contains the src for the next iteration
1605  lastState = transit->X1;
1606  for (popit = oldPop.begin(); popit != oldPop.end(); ++popit) {
1607  std::vector<Idx> tmpPop(oldPop.begin(),popit+1);
1608  src = lastState;
1609 
1610  //check if derivation of sup-pop exists
1611  mapit = popStateMap.find(tmpPop);
1612  if(mapit != popStateMap.end()){
1613  trg = mapit->second;
1614  }else{
1615  //if not, create new state
1616  trg = rPd.InsState();
1617  popStateMap[tmpPop] = trg;
1618  }
1619 
1620  //get pop for new transition
1621  pop.clear();
1622  pop.push_back(*popit);
1623 
1624  //get push for new transition
1625  push.clear();
1626  if(std::distance(popit, oldPop.end() ) == 1)
1627  //if last element of pop, push it
1628  push.push_back(*popit);
1629  else
1630  //else push lambda
1631  push.push_back(lambdaSS);
1632 
1633  //add transition
1634  rPd.SetTransition(src, lambdaEv, trg, pop, push);
1635 
1636  //set new last state
1637  lastState = trg;
1638  }
1639 
1640  //create transition to original trg
1641  src = lastState;
1642  pop.clear();
1643  pop.push_back(oldPop.back());
1644 
1645  //add transition (pN,a,xN,w,q)
1646  rPd.SetTransition(src, transit->Ev, transit->X2, pop, oldPush);
1647  }
1648  }
1649  }
1650  return rPd;
1651 }
1652 
1653 /* *************************
1654  * InTransitionSize
1655  * *************************/
1657  uint count = 0;
1658 
1659  // alternative order X2-Ev-X1
1660  TransSetX2EvX1 transByX2;
1661  TransSetX2EvX1::Iterator titEnd,transit;
1662 
1663  // copy and re-order transrel
1664  rPd.TransRel().ReSort(transByX2);
1665 
1666  //Set the iterator to a variable, so it won't be recalculated every iteration.
1667  titEnd = transByX2.EndByX2(trg);
1668 
1669  //for each incoming transition
1670  for(transit = transByX2.BeginByX2(trg); transit != titEnd; ++transit){
1671  if(rPd.PopPush(*transit).empty())
1672  //if no pop-push pair, just add one
1673  count++;
1674  else
1675  //else each pop-push pair represent a different transition
1676  count += rPd.PopPush(*transit).size();
1677  }
1678 
1679  return count;
1680 }
1681 
1682 /* *************************
1683  * PossibleAdjacentMerges
1684  * *************************/
1685 std::set<std::pair <Transition,Transition> > PossibleAdjacentMerges (Idx q, const PushdownGenerator& pd){
1686 
1687  //result and temporary set
1688  std::set<std::pair <Transition,Transition> > res,tmp;
1689 
1690  // If no out edges, nothing to do
1691  if(!pd.ExistsTransition(q))
1692  return res;
1693 
1694  //Set the iterator to a variable, so it won't be recalculated every iteration.
1695  TransSet::Iterator transRel1Begin, transRel1End,transRel1it,
1696  transRel2Begin, transRel2End, transRel2it;
1697 
1698  //init iterators
1699  transRel1Begin = pd.TransRelBegin(q);
1700  transRel1End = pd.TransRelEnd(q);
1701 
1702  //for each transition from state q
1703  for(transRel1it = transRel1Begin; transRel1it != transRel1End ; ++transRel1it){
1704  Idx q2 = transRel1it->X2;
1705 
1706  //ignore self-loop
1707  if(q == q2)
1708  continue;
1709  //ignore leading to marked state
1710  if(pd.ExistsMarkedState(q2))
1711  continue;
1712  //ignore leading to init state
1713  if(q2 == pd.InitState())
1714  continue;
1715  //ignore, if no transitions from q2
1716  if(!pd.ExistsTransition(q2))
1717  continue;
1718  //ignore if current transition isn't the only transition that leads to q2
1719  if(InTransitionSize(q2,pd) != 1)
1720  continue;
1721 
1722  //Set the iterator to a variable, so it won't be recalculated every iteration.
1723  transRel2Begin = pd.TransRelBegin(q2);
1724  transRel2End = pd.TransRelEnd(q2);
1725  tmp.clear();
1726 
1727  bool canNotMerge = false;
1728  transRel2it = transRel2Begin;
1729  while((transRel2it != transRel2End) && !canNotMerge){
1730  //Transitions can not merge, if...
1731  canNotMerge = canNotMerge
1732  //...its a transition from a marked state to a not marked state
1733  || (pd.ExistsMarkedState(transRel2it->X1) && !pd.ExistsMarkedState(transRel2it->X2))
1734  //...selfe loop
1735  || (transRel2it->X1 == transRel2it->X2)
1736  //...the event are not lambda
1737  || (!pd.IsEventLambda(transRel1it->Ev) && !pd.IsEventLambda(transRel2it->Ev));
1738 
1739  //if almost one transition can not merge, clear all
1740  if(canNotMerge)
1741  tmp.clear();
1742  else
1743  tmp.insert(std::make_pair(*transRel1it,*transRel2it));
1744 
1745  ++transRel2it;
1746  }
1747 
1748  res.insert(tmp.begin(),tmp.end());
1749  }
1750 
1751  return res;
1752 
1753 }
1754 
1755 /* *************************
1756  * CombinedTransitions
1757  * *************************/
1758 bool CombinedTransitions(Idx q,PushdownGenerator& rPd, /*std::set<Idx>&*/ StateSet& next,/*std::set<Idx>&*/ StateSet& done){
1759  bool debug = false;
1760 
1761  std::multimap<Transition, std::pair<std::vector<Idx>, std::vector<Idx> > > toRmTrans;
1762  std::multimap<Transition, std::pair<std::vector<Idx>, std::vector<Idx> > >::iterator toRmTransit;
1763 
1764  std::pair<Transition, std::pair<std::vector<Idx>, std::vector<Idx> > > pdtransition;
1765  std::pair<std::vector<Idx>, std::vector<Idx> > pp;
1766  std::vector<Idx> pop1,push1, pop2, push2, newPop, newPush;
1767 
1768  Transition trans1,trans2;
1769  TransSet::Iterator tit,tit_end;
1770 
1771  std::set<std::pair <Transition,Transition> > pairs ;
1772  std::set<std::pair <Transition,Transition> >::iterator pairsIt;
1773  PopPushSet::const_iterator pp1it, pp2it;
1774 
1775  DEBUG_PRINTF(debug,"CombinedTransitions: Start combine edge for "+rPd.StateStr(q),"");
1776 
1777  //get all possible mergeable pairs
1778  pairs = PossibleAdjacentMerges(q,rPd);
1779  DEBUG_PRINTF(debug,"mup done "+rPd.StateStr(q),"");
1780 
1781  if(!pairs.empty()){
1782  bool merged = false;
1783 
1784  //try to combine edges
1785  for(pairsIt = pairs.begin(); pairsIt != pairs.end(); ++pairsIt){
1786  //get transitions
1787  trans1 = pairsIt->first;
1788  trans2 = pairsIt->second;
1789 
1790  DEBUG_PRINTF(debug,"CombinedTransitions: Try ("+trans1.Str()+"/"+trans2.Str()+")","");
1791 
1792  for(pp1it = rPd.PopPushBegin(trans1); pp1it != rPd.PopPushEnd(trans1); ++pp1it){
1793  for(pp2it = rPd.PopPushBegin(trans2); pp2it != rPd.PopPushEnd(trans2); ++pp2it){
1794  // pop/push of first transition
1795  pop1 = pp1it->first;
1796  push1 = pp1it->second;
1797 
1798  //pop/push of second transition
1799  std::vector<Idx> pop2 = pp2it->first;
1800  std::vector<Idx> push2 = pp2it->second;
1801 
1802  //check if push1 and pop2 match
1803  if(std::equal(push1.begin(),push1.begin() + std::min(push1.size(),pop2.size()) ,pop2.begin())){
1804  Idx ev = (rPd.IsEventLambda(trans1.Ev))? trans2.Ev : trans1.Ev;
1805  newPop.clear();
1806  newPush.clear();
1807 
1808  if(!rPd.IsStackSymbolLambda(pop1.front()))
1809  newPop = pop1;
1810 
1811  if(push1.size() <= pop2.size()){
1812  //newPop = pop1 :: (pop2\push1)
1813  newPop.insert(newPop.end(),pop2.begin()+ push1.size(), pop2.end());
1814  }
1815 
1816  if(newPop.size() == 1){
1817  if(!rPd.IsStackSymbolLambda(push2.front()))
1818  newPush = push2;
1819 
1820  if(pop2.size() <= push1.size())
1821  //newPush = push1\pop2
1822  newPush.insert(newPush.end(),push1.begin() + pop2.size(), push1.end());
1823 
1824  Idx lambda = rPd.InsStackSymbol(FAUDES_PD_LAMBDA);
1825  if(newPop.empty()) newPop.push_back(lambda);
1826  if(newPush.empty())newPush.push_back(lambda);
1827 
1828  //remember to remove old transitions
1829  pp = std::make_pair(pop1,push1);
1830  pdtransition = std::make_pair(trans1,pp);
1831  toRmTrans.insert(pdtransition);
1832 
1833  pp = std::make_pair(pop2,push2);
1834  pdtransition = std::make_pair(trans2,pp);
1835  toRmTrans.insert(pdtransition);
1836 
1837  // set new Transition
1838  rPd.SetTransition(trans1.X1,ev,trans2.X2,newPop,newPush);
1839 
1840  Transition nt = *rPd.FindTransition(trans1.X1,ev,trans2.X2);
1841 
1842  DEBUG_PRINTF(debug,
1843  "CombinedTransitions: Merge ("+ trans1.Str()+ " | "+ trans2.Str() + ") to "+ nt.Str() +"\n","");
1844 
1845  next.Insert(q);
1846  merged = true;
1847  }
1848  else
1849  DEBUG_PRINTF(debug,"CombinedTransitions: New Pop != 1","");
1850 
1851  }// pop-push incompatible
1852  else
1853  DEBUG_PRINTF(debug,"CombinedTransitions: Pop - Push incompatible","");
1854  }
1855  }
1856  }//for
1857 
1858  // remove merged transitions
1859  for(toRmTransit = toRmTrans.begin(); toRmTransit != toRmTrans.end(); ++toRmTransit)
1860  rPd.ClrTransition(toRmTransit->first,toRmTransit->second.first,toRmTransit->second.second);
1861 
1862  if(merged){
1863  return true;
1864  }
1865 
1866  }// pairs empty
1867  else
1868  DEBUG_PRINTF(debug,"CombinedTransitions: Pairs empty","");
1869 
1870  // if no transition merged together, get successor states
1871  StateSet succStates;
1872 
1873  tit = rPd.TransRelBegin(q);
1874  tit_end = rPd.TransRelEnd(q);
1875  for (; tit != tit_end; ++tit) {
1876  succStates.Insert(tit->X2);
1877  }
1878 
1879  next.InsertSet(succStates);
1880  done.Insert(q);
1881 
1882  return false;
1883 }
1884 
1885 /* *************************
1886  * MergeAdjacentTransitions
1887  * *************************/
1889 
1890  bool merged;
1891  StateSet todo, done,next;
1892  StateSet::Iterator it;
1893 
1894  //repeat until all possible transitions are merged together
1895  do{
1896 
1897  //clean sets
1898  todo.Clear();
1899  done.Clear();
1900 
1901  //start with init state
1902  todo.Insert(rPd.InitState());
1903 
1904  //initially no transition merged
1905  merged = false;
1906 
1907  //check if at least one merge is possible
1908  while(!todo.Empty()){
1909  next.Clear();
1910 
1911  for(it = todo.Begin(); it != todo.End(); ++it){
1912  merged = merged || CombinedTransitions(*it,rPd,next,done);
1913  }
1914 
1915  todo.Clear();
1916 
1917  todo = next - done;
1918  }
1919  }while(merged);
1920 }
1921 
1922 
1923 
1924 
1925 
1926 
1927 } // namespace faudes
1928 

libFAUDES 2.26g --- 2015.08.17 --- c++ api documentaion by doxygen