pd_alg_main.cpp
Go to the documentation of this file.
1 /** @file pd_alg_main.cpp Top-Level functions*/
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 
11 #include "pd_alg_main.h"
12 
13 namespace faudes {
14 
15 //ConstructController(rSpec, rPlant, rResPd)
16 void PushdownConstructController(const PushdownGenerator& rSpec, const System& rPlant,
17  PushdownGenerator& rResPd, bool debug) {
18  FUNCTION(__FUNCTION__); //scope log
19  FD_DF("ConstructController(" << &rSpec << "," << &rPlant << ")");
20 
21  // warn if rPlant or rSpec isn't deterministic
22  if (!rPlant.IsDeterministic())
23  FD_WARN("The given system automaton (plant) is not deterministic ! "
24  "May use Deterministic(const Generator&,Generator& rResGen) ");
25 
26  if (!rSpec.IsDeterministic())
27  FD_WARN("The given pushdown automaton (spec) is not deterministic !");
28 
29  // prepare result
30  PushdownGenerator* pResPd = &rResPd;
31  if (&rResPd == &rSpec) {
32  pResPd = rResPd.New();
33  }
34 
35  DEBUG_PRINTF(debug, "Specification", rSpec);
36  DEBUG_PRINTF(debug, "Plant", rPlant);
37 
38  //pre combine of specification and plant
39  ConstructControllerPreCombine(rSpec, rPlant, *pResPd);
40  DEBUG_PRINTF(debug, "PreComp", *pResPd);
41  FD_DF("ConstructController: PreCombine done !");
42 
43  if(!pResPd->Empty()){
44  //start algorithm loop
45  //count loops for debugging
46  int loopcounter =ConstructControllerLoop(*pResPd, rPlant, *pResPd, 0);
47  DEBUG_PRINTF(debug, "Controller", *pResPd);
48  FD_DF("ConstructController: Done after " + ToStringInteger(loopcounter) +" iterations !");
49  }
50 
51  // copy result
52  if (pResPd != &rResPd) {
53  pResPd->Move(rResPd);
54  delete pResPd;
55  }
56 }
57 
58 //ConstructControllerPreCombine(rSpec, rPlant, rResPd)
60  const System& rPlant, PushdownGenerator& rResPd, bool debug) {
61  FUNCTION(__FUNCTION__); //scope log
62  FD_DF("ConstructControllerPreCombine(" << &rSpec << "," << &rPlant << ")");
63 
64  //create product generator of plant and specification
65  PushdownGenerator rPd = Times(rPlant, rSpec);
66  DEBUG_PRINTF(debug, "PreTimes", rPd);
67  FD_DF("ConstructControllerPreCombine: Times done !");
68 
69  //make product generator non-blocking
70  PushdownBlockfree(rPd,rPd);
71  DEBUG_PRINTF(debug, "PreBlockfree", rPd);
72  FD_DF("ConstructControllerPreCombine: Blockfree done !");
73 
74  // return result
75  rResPd = rPd;
76 }
77 
78 //ConstructControllerLoop(rContr, rPlant, rResPd, loopcounter)
80  const System& rPlant, PushdownGenerator& rResPd, int loopcounter, bool debug) {
81  FUNCTION(__FUNCTION__); //scope log
82  loopcounter++; //count iterations
83 
84  //annotate iteration for debugging
85  std::string iteration = ToStringInteger(loopcounter)+ "_Iteration";
86  FD_DF("ConstructControllerLoop(" << &rContr << "," << &rPlant << ") " + iteration);
87 
88  DEBUG_PRINTF(debug, ("LoopControllerCandidate_" + iteration), rContr);
89 
90  //generator to return
92 
93  //create product generator
94  rPd = Times(rPlant, rContr);
95  DEBUG_PRINTF(debug, ("LoopTimes_" + iteration), rPd);
96 
97  //trim the generator
99  DEBUG_PRINTF(debug, ("LoopTimesTrim_" + iteration), rPd);
100 
101  //split states into heads and ears
102  rPd = Split(rPd);
103  DEBUG_PRINTF(debug, ("LoopSplit_" + iteration), rPd);
104  FD_DF("ConstructControllerLoop: Split done !");
105 
106  //trim the generator
108  DEBUG_PRINTF(debug, ("LoopSplitTrim_" + iteration), rPd);
109 
110  //get accessible part
111  PushdownAccessible(rPd, rPd);
112  DEBUG_PRINTF(debug, ("LoopAC_" + iteration), rPd);
113 
114  if(rPd.Empty())
115  rResPd = rPd;
116 
117  //save number of states
118  uint numberOfStates = rPd.Size();
119 
120  //set lambda event controllable
122 
123  //remove non-controllable ears
124  rPd = Rnce(rPd, rPlant);
125  DEBUG_PRINTF(debug, ("LoopRnce_" + iteration), rPd);
126 
127  if (numberOfStates == rPd.Size()) {
128  DEBUG_PRINTF(debug, ("LoopEnd_" + iteration), rContr);
129  //if no states were removed
130  // copy controller to result
131  rResPd = PushdownGenerator(rContr);
132  //return number of iterations
133  return loopcounter;
134  } else {
135  DEBUG_PRINTF(debug, "numberOfStates != rPd.Size()", "");
136 
137  //make temporary controller non-blocking
138  PushdownBlockfree(rPd,rPd);
139  DEBUG_PRINTF(debug, "LoopBlockfree_" + iteration, rPd);
140 
141  //start next loop iteration
142  return ConstructControllerLoop(rPd, rPlant, rResPd, loopcounter);
143  }
144 }
145 
146 
147 
148 /* *************************
149  * PushdownBlockfree
150  * *************************/
151 void PushdownBlockfree(const PushdownGenerator& pd, PushdownGenerator& resPd, bool debug) {
152  FUNCTION(__FUNCTION__); //scop log
153  FD_DF("PushdownBlockfree(" << &pd << "," << &resPd << ")");
154 
155  //warning if pd isn't deterministic
156  if (!pd.IsDeterministic())
157  FD_WARN("PushdownBlockfree: The given pushdown automaton is not deterministic !");
158 
159  //take a copy of the old generator
160  PushdownGenerator rPd(pd);
161  DEBUG_PRINTF(debug,"BlockfreeInput",rPd);
162 
163  //trim input
165  //if no initial or no marked state exists, return empty generator
166  resPd = rPd;
167  return;
168  }
169  DEBUG_PRINTF(debug,"BlockfreeInputTrim",rPd);
170 
171  //create SDPDA
172  rPd = SPDA(rPd);
173  DEBUG_PRINTF(debug,"BlockfreeSDPDA",rPd);
174 
175  //trim SDPDA
177  //if no initial or no marked state exists, return empty generator
178  resPd = rPd;
179  return;
180  }
181  DEBUG_PRINTF(debug,"BlockfreeSDPDATrim",rPd);
182 
183  //remove double acceptance
184  rPd = Nda(rPd);
185  DEBUG_PRINTF(debug,"BlockfreeNda",rPd);
186 
187  //trim Nda
189  //if no initial or no marked state exists, return empty generator
190  resPd = rPd;
191  return;
192  }
193  DEBUG_PRINTF(debug,"BlockfreeNdaTrim",rPd);
194 
195  //convert to grammar
196  Grammar gr = Sp2Lr(rPd,0);
197  DEBUG_PRINTF(debug,"BlockfreeSp2Lr",gr.Str());
198 
199  //remove non-productive productions
200  gr = Rnpp(gr);
201  DEBUG_PRINTF(debug,"BlockfreeRnpp",gr.Str());
202 
203  //remove unreachable productions
204  gr = Rup(gr);
205  DEBUG_PRINTF(debug,"BlockfreeRup",gr.Str());
206 
207  //if no productions exists, return empty generator
208  if(gr.GrammarProductions().empty()){
209  resPd.Clear();
210  return;
211  }
212 
213  //augment grammar
214  //create temporary automaton to create a new event for the augment terminal
215  //and a new stack symbol for the augment nonterminal
216  PushdownGenerator tempPd = rPd;
217 
218  std::string freshEventName = rPd.UniqueEventName("augSymbol");
219  //create fresh terminal
220  Terminal t(tempPd.InsEvent(freshEventName));
221 
222  std::vector<Idx> v;
223  //no need for this stack symbol to be unique, because no nonterminal should contain 0
224  Idx stackSymbolIdx = tempPd.InsStackSymbol(StackSymbol("augSymbol"));
225  v.push_back(stackSymbolIdx);
226  Nonterminal nt(0, v);
227 
228  //Augments the grammar such that a new grammar production will be inserted
229  Grammar augGr = Aug(gr, nt, t);
230  DEBUG_PRINTF(debug,"BlockfreeAugGr",augGr.Str());
231 
232  //construct the goto generator for the augmented grammar
233  GotoGenerator gotoGen = Lrm(augGr, 1);
234 
235  //construct a parser for the grammar
236  Lr1Parser parser = Lrp(gr, augGr, gotoGen, 1, t);
237  DEBUG_PRINTF(debug,"BlockfreeLrParser",parser.Str());
238 
239  //detach augment symbol
240  DetachAugSymbol(parser);
241  DEBUG_PRINTF(debug,"BlockfreeDetachAugSymbol",parser.Str());
242 
243  // Transform following actions
244  // (q,a,p,a) => ((q,lambda),a,(p,a),lambda) , ((q,a),lambda,(p,a),lambda)
245  // (q,a,p,lambda) => ((q,lambda),a,(p,lambda),lambda) , ((q,a),lambda,(p,lambda),lambda)
246  parser = TransformParserAction(parser);
247  DEBUG_PRINTF(debug,"BlockfreeTransformedParserActions",parser.Str());
248 
249  //convert parser to pushdown generator
250  rPd = LrParser2EPDA(parser);
251  DEBUG_PRINTF(debug,"BlockfreeLrParser2EPDA",rPd);
252 
253  //trim / remove unreachable states
254  if(!PushdownTrim(rPd, 0)){
255  //if no initial or no marked state exists, return empty generator
256  resPd = rPd;
257  return;
258  }
259  DEBUG_PRINTF(debug,"BlockfreeLrParser2EPDATrim",rPd);
260 
261  //annotate stack symbols with "old"
262  rPd = RenameStackSymbold("old",rPd);
263 
264  //merge adjacent transitions
266  DEBUG_PRINTF(debug,"BlockfreeMergeAdjTrans",rPd);
267 
268  //trim / remove unreachable states
269  if(!PushdownTrim(rPd, 0)){
270  //if no initial or no marked state exists, return empty generator
271  resPd = rPd;
272  return;
273  }
274  DEBUG_PRINTF(debug,"BlockfreeMergeAdjTransTrim",rPd);
275 
276  //removes transitions that pop lambda
277  rPd = RemoveLambdaPop(rPd);
278  DEBUG_PRINTF(debug,"BlockfreeRemoveLambdaPop",rPd);
279 
280  //split transitions popping more than one stack symbol into more transitions
281  rPd = RemoveMultPop(rPd);
282  DEBUG_PRINTF(debug,"BlockfreeRemoveMultPop",rPd);
283 
284  //removes transitions that pop lambda
285  rPd = RemoveLambdaPop(rPd);
286  DEBUG_PRINTF(debug,"BlockfreeRemoveLambdaPop",rPd);
287 
288  //trim
290  //if no initial or no marked state exists, return empty generator
291  resPd = rPd;
292  return;
293  }
294 
295  //merge adjacent transitions
297  DEBUG_PRINTF(debug,"BlockfreeMergeAdjTransTrim",rPd);
298 
299  //trim
301  //if no initial or no marked state exists, return empty generator
302  resPd = rPd;
303  return;
304  }
305 
306  //set correct flags for controllability and observability
307  CorrectEvents(pd, rPd);
308 
309  //return resulting generator
310  resPd = rPd;
311  DEBUG_PRINTF(debug,"BlockfreeResult",rPd);
312 }
313 
314 
315 
316 
317 void PushdownAccessible(const PushdownGenerator& pd, PushdownGenerator& resPd, bool coacc, bool debug) {
318  FUNCTION(__FUNCTION__); //scope log
319  FD_DF("PushdownAccessible(" << &pd << "," << &resPd << ")");
320 
321  //warning if pd isn't deterministic
322  if (!pd.IsDeterministic())
323  FD_WARN("PushdownBlockfree: The given pushdown automaton is not deterministic !");
324 
325  // if no initial state exists,
326  //their exists no accessible states or transitions
327  if(pd.InitStates().Empty()){
328  resPd = pd;
329  resPd.ClearStates();
330  resPd.ClearTransRel();
331  return;
332  }
333 
334  //take a copy of the old generator
336  DEBUG_PRINTF(debug,"AccessibleInput",tmp);
337 
338  //remember changes from DPDA to SDPDA
339  TransformationHistoryVec history;
340 
341  //create SDPDA
342  tmp = SPDA(tmp, &history);
343  DEBUG_PRINTF(debug,"AccessibleSdpda",tmp);
344 
345  if(coacc){
346  //trim SDPDA
348  DEBUG_PRINTF(debug,"AccessibleSdpdaTrim",tmp);
349  }
350 
351  //convert to grammar
352  Grammar gr = Sp2Lr(tmp,0,true);
353  DEBUG_PRINTF(debug,"AccessibleSp2Lr",gr.Str());
354 
355  if(coacc){
356  //remove non-productive productions
357  gr = Rnpp(gr);
358  DEBUG_PRINTF(debug,"AccessibleRnpp",gr.Str());
359  }
360 
361  //remove unreachable productions
362  gr = Rup(gr);
363  DEBUG_PRINTF(debug,"AccessibleRup",gr.Str());
364 
365  //get remaining generator
366  tmp = RemainingPd(gr, tmp);
367 
368  if(coacc){
369  //remove not (co)accessible states
370  PushdownTrim(tmp,0);
371  } else {
372  //remove inaccessible states
373  tmp.vGenerator::Accessible();
374  }
375 
376  DEBUG_PRINTF(debug,"AccessibleRemaining",tmp);
377 
378  //recreate DPDA
379  tmp = RebuildFromSPDA(tmp, history);
380  DEBUG_PRINTF(debug,"AccessibleRebuildFromSPDA",tmp);
381 
382  //compare with given DPDA
383  TransSet::Iterator transit;
384  PopPushSet::const_iterator ppit;
385  PushdownGenerator rPd(pd);
386  for (transit = pd.TransRelBegin(); transit != pd.TransRelEnd(); transit++) {
387  for (ppit = pd.PopPushBegin(*transit); ppit != pd.PopPushEnd(*transit);
388  ppit++) {
389  if (!tmp.ExistsTransition(*transit, ppit->first, ppit->second)) {
390  rPd.ClrTransition(*transit, ppit->first, ppit->second);
391  }
392  }
393  }
394 
395  if(coacc){
396  //remove not (co)accessible states
397  PushdownTrim(tmp,0);
398  } else {
399  //remove inaccessible states
400  tmp.vGenerator::Accessible();
401  }
402 
403  DEBUG_PRINTF(debug,"AccessibleEnd",rPd);
404 
405  //return resulting generator
406  resPd = rPd;
407 }
408 
409 
410 
411 /* *************************
412  * Transient
413  * *************************/
415 
416  TransSet::Iterator transit;
417  StateSet rStates;
418  //iterate over all transitions
419  for (transit = pd.TransRelBegin(); transit != pd.TransRelEnd(); transit++) {
420 
421  //add start state of lambda read transition to set
422  if (pd.IsEventLambda(transit->Ev)) {
423  rStates.Insert(transit->X1);
424  }
425  }
426 
427  return rStates;
428 }
429 
430 /* *************************
431  * Rnce
432  * *************************/
434  FUNCTION(__FUNCTION__); //scope log
435  FD_DF("Rnce(" << &pd << "," << &s << ")");
436 
437  StateSet transientStates = Transient(pd);
438  StateSet ucEars;
439  EventSet uc = pd.UncontrollableEvents();
440  StateSet::Iterator stateit;
441  EventSet::Iterator eventit;
442  Idx oldState;
443 
444  //iterate over all states
445  for (stateit = pd.StatesBegin(); stateit != pd.StatesEnd(); stateit++) {
446 
447  //get the merge attribute, which must be either an ear or a heads
448  const MergeStateSplit* mss =
449  dynamic_cast<const MergeStateSplit*>(pd.Merge(*stateit));
450  if (mss == NULL) {
451  std::stringstream errstr;
452  errstr
453  << "State in Rnce was neither head nor ear, check correctness of Merge attribute"
454  << std::endl;
455  throw Exception("Rnce", errstr.str(), 1001);
456  }
457 
458  //only look at ears
459  if (mss->IsHead()) {
460  continue;
461  }
462 
463  //only look at transient ears
464  if (transientStates.Exists(*stateit)) {
465  continue;
466  }
467 
468  //check the current state for each uncontrollable event
469  for (eventit = uc.Begin(); eventit != uc.End(); eventit++) {
470 
471  //only look at states whose corresponding dfa state allows this
472  //uncontrollable event
473  oldState = pd.DfaState(*stateit);
474  if (!s.ExistsTransition(oldState, *eventit)) {
475  continue;
476  }
477 
478  //only look at states that do not allow the uncontrollable event to happen
479  if (pd.ExistsTransition(*stateit, *eventit)) {
480  continue;
481  }
482 
483  //all these states are uncontrollable ears
484  ucEars.Insert(*stateit);
485  }
486  }
487  PushdownGenerator rPd = pd;
488  rPd.DelStates(ucEars);
489  return rPd;
490 }
491 
492 /* *************************
493  * Times
494  * *************************/
496  FUNCTION(__FUNCTION__); //scope log
497  FD_DF("Times(" << &s << "," << &pd << ")");
498 
499  //result generator
500  PushdownGenerator rPd;
501  rPd.Name(s.Name() + " | " + pd.Name());
502 
503  //map to remember which states get merged into which
504  std::map<std::pair<Idx, Idx>, Idx> stateMap;
505 
506  StateSet::Iterator pdStateit, sStateit;
507  Idx newState;
508  std::vector<Idx> oldStatesVector;
509  //construct states as cartesian prodcut of both generators states
510  for (pdStateit = pd.StatesBegin(); pdStateit != pd.StatesEnd();
511  pdStateit++) {
512  for (sStateit = s.StatesBegin(); sStateit != s.StatesEnd();
513  sStateit++) {
514 
515  //add new state for each pair of states and save it in the map
516  newState = rPd.InsState();
517  stateMap.insert(
518  std::make_pair(std::make_pair(*sStateit, *pdStateit),
519  newState));
520 
521  //add information about parent states
522  oldStatesVector.clear();
523  oldStatesVector.push_back(*sStateit);
524  oldStatesVector.push_back(*pdStateit);
525  MergeStates oldStates = MergeStates(oldStatesVector);
526  rPd.SetMerge(newState, oldStates);
527  rPd.SetDfaState(newState, *sStateit);
528 
529  //if both states are init states, the new state is an init state as well
530  if (*pdStateit == pd.InitState() && *sStateit == s.InitState()) {
531  rPd.SetInitState(newState);
532  }
533 
534  //if both states are final states, the new state is a final state as well
535  if (pd.ExistsMarkedState(*pdStateit)
536  && s.ExistsMarkedState(*sStateit)) {
537  rPd.SetMarkedState(newState);
538  }
539  }
540  }
541 
542  //stack symbols are the same as the pushdown generator's stack symbols
543  rPd.InsStackSymbols(pd.StackSymbols());
544 
545  //stack bottom is the same as the pushdown generator's stack bottom
547 
548  //the new event set is the intersection of both old event sets
549  IntersectEvents(s, pd, rPd);
550 
551  //add lambda event if there was a lambda event in the pushdown generator's event set
552  if (pd.Alphabet().Exists(FAUDES_PD_LAMBDA)) {
554  }
555 
556  Idx newX1, newX2;
557  std::string sEvName, pdEvName;
558  //add transitions to rPd. Iterate over all pushdown generator transitions
559  TransSet::Iterator pdTransit, sTransit;
560  PopPushSet::const_iterator ppsit;
561  for (pdTransit = pd.TransRelBegin(); pdTransit != pd.TransRelEnd();
562  pdTransit++) {
563 
564  //look at every pop push set of the transition
565  for (ppsit = pd.PopPushBegin(*pdTransit);
566  ppsit != pd.PopPushEnd(*pdTransit); ppsit++) {
567 
568  pdEvName = pd.EventName(pdTransit->Ev);
569  //for every no-read transition (q,lambda,w,w',q') of pd and every state p of s,
570  //add a transition ((p,q),lambda,w,w',(p,q'))
571  if (pdEvName.compare(FAUDES_PD_LAMBDA) == 0) {
572  for (sStateit = s.StatesBegin(); sStateit != s.StatesEnd();
573  sStateit++) {
574 
575  //find new states corresponding to (p,q), and (p,q')
576  newX1 = stateMap.find(
577  std::make_pair(*sStateit, pdTransit->X1))->second;
578  newX2 = stateMap.find(
579  std::make_pair(*sStateit, pdTransit->X2))->second;
580 
581  //add transition
582  rPd.SetTransition(newX1, rPd.EventIndex(FAUDES_PD_LAMBDA),
583  newX2, ppsit->first, ppsit->second);
584  }
585  }
586  //for every read transition (q,a,w,w',q') of pd and every transition (p,a,p')
587  //of s, add a transition ((p,q),a,w,w',(p',q'))
588  else {
589 
590  //iterate over all system transitions
591  for (sTransit = s.TransRelBegin(); sTransit != s.TransRelEnd();
592  sTransit++) {
593 
594  sEvName = s.EventName(sTransit->Ev);
595  //compare the transition events
596  if (pdEvName.compare(sEvName) == 0) {
597 
598  //find new states corresponding to (p,q), and (p',q')
599  newX1 =
600  stateMap.find(
601  std::make_pair(sTransit->X1,
602  pdTransit->X1))->second;
603  newX2 =
604  stateMap.find(
605  std::make_pair(sTransit->X2,
606  pdTransit->X2))->second;
607 
608  //add transition
609  rPd.SetTransition(newX1, rPd.EventIndex(sEvName), newX2,
610  ppsit->first, ppsit->second);
611  }
612  }
613  }
614  }
615  }
616  // set statenames
617  if (s.StateNamesEnabled() && pd.StateNamesEnabled()
618  && rPd.StateNamesEnabled())
619  SetComposedStateNames(s, pd, stateMap, rPd);
620  else
621  rPd.ClearStateNames();
622 
623  return rPd;
624 }
625 
626 /* *************************
627  * IntersectEvents
628  * *************************/
629 void IntersectEvents(const System& s, const PushdownGenerator& pd,
630  PushdownGenerator& rPd) {
631 
632  EventSet::Iterator pdEventit, sEventit;
633  for (pdEventit = pd.AlphabetBegin(); pdEventit != pd.AlphabetEnd();
634  pdEventit++) {
635  for (sEventit = s.AlphabetBegin(); sEventit != s.AlphabetEnd();
636  sEventit++) {
637  if (*pdEventit == *sEventit) {
638  //controllable and observable
639  if (pd.Controllable(*pdEventit) && s.Controllable(*sEventit)
640  && pd.Observable(*pdEventit)
641  && s.Observable(*sEventit)) {
642  rPd.InsControllableEvent(*pdEventit);
643  }
644  //controllable and not observable
645  else if (pd.Controllable(*pdEventit)
646  && s.Controllable(*sEventit)
647  && !pd.Observable(*pdEventit)
648  && !s.Observable(*sEventit)) {
649  rPd.InsControllableEvent(*pdEventit);
650  rPd.ClrObservable(*pdEventit);
651  }
652  //not controllable, but observable
653  else if (!pd.Controllable(*pdEventit)
654  && !s.Controllable(*sEventit)
655  && pd.Observable(*pdEventit)
656  && s.Observable(*sEventit)) {
657  rPd.InsEvent(*pdEventit);
658  }
659  //neither controllable nor observable
660  else if (!pd.Controllable(*pdEventit)
661  && !s.Controllable(*sEventit)
662  && !pd.Observable(*pdEventit)
663  && !s.Observable(*sEventit)) {
664  rPd.InsUnobservableEvent(*pdEventit);
665  }
666  }
667  }
668  }
669 }
670 
671 /* *************************
672  * Split
673  * *************************/
675  FUNCTION(__FUNCTION__); //scope log
676  FD_DF("Split(" << &pd << ")");
677 
678  //copy the generator
679  PushdownGenerator rPd = pd;
680 
681  //insert lambda event in case it has not already been added
683 
684  //clear transition relation and states, because they will be replaced
685  rPd.ClearTransRel();
686  StateSet::Iterator stateit = rPd.StatesBegin();
687  while (stateit != rPd.StatesEnd()) {
688  rPd.DelState(*(stateit++)); // fixed: 2013-12-17
689  }
690 
691  //map ears and stack symbols to their heads for later reference
692  std::multimap<Idx, std::pair<Idx, Idx> > headEarMap;
693  //map ears and stack symbols to the states of the old generator for later reference.
694  //headMap<headIdx,oldIdx>, earMap<oldIdx,headIdx>
695  std::map<Idx, Idx> headMap, earMap;
696 
697  StackSymbolSet::Iterator ssit;
698  Idx newHead, newEar;
699  //insert new states as ears and heads
700  for (stateit = pd.StatesBegin(); stateit != pd.StatesEnd(); stateit++) {
701 
702  //insert a head for each state in the old generator
703  newHead = rPd.InsState();
704  MergeStateSplit mss(*stateit);
705  rPd.SetMerge(newHead, mss);
706  rPd.SetDfaState(newHead, pd.DfaState(*stateit));
707 
708  //if the state was the initial state in the old generator, this head
709  //is an initial state as well
710  if (pd.ExistsInitState(*stateit)) {
711  rPd.SetInitState(newHead);
712  }
713 
714  //save head in map
715  headMap.insert(std::make_pair(*stateit, newHead));
716 
717  //insert an ear for each state in the old generator and each stack symbol
718  //except lambda
719  for (ssit = rPd.StackSymbolsBegin(); ssit != rPd.StackSymbolsEnd();
720  ssit++) {
721  if (!rPd.IsStackSymbolLambda(*ssit)) {
722  newEar = rPd.InsState();
723  MergeStateSplit mss(*stateit, *ssit);
724  rPd.SetMerge(newEar, mss);
725  rPd.SetDfaState(newEar, pd.DfaState(*stateit));
726 
727  //if the state was a final state in the old generator, this ears
728  //is a final state as well
729  if (pd.ExistsMarkedState(*stateit)) {
730  rPd.SetMarkedState(newEar);
731  }
732 
733  //save ear in map
734  earMap.insert(std::make_pair(newEar, *stateit));
735  //save pair of head and ear in map
736  headEarMap.insert(
737  std::make_pair(newHead, std::make_pair(newEar, *ssit)));
738 
739  }
740  }
741  }
742 
743  TransSet::Iterator transit;
744  PopPushSet::const_iterator popPushit;
745  std::multimap<Idx, std::pair<Idx, Idx> >::iterator headEarit;
746  std::vector<Idx> ssvector;
747  Idx head, ear, startState, endState, event;
748  Idx stackSymbol;
749  //insert transitions
750  //iterate over all ears
751  for (headEarit = headEarMap.begin(); headEarit != headEarMap.end();
752  headEarit++) {
753 
754  //insert transition from head to ear
755  head = headEarit->first;
756  ear = headEarit->second.first;
757  stackSymbol = headEarit->second.second;
758 
759  ssvector.clear();
760  ssvector.push_back(stackSymbol);
761 
762  rPd.SetTransition(head, rPd.EventIndex(FAUDES_PD_LAMBDA), ear, ssvector,
763  ssvector);
764 
765  //connect ears to heads
766  for (transit = pd.TransRelBegin(); transit != pd.TransRelEnd();
767  transit++) {
768  for (popPushit = pd.PopPushBegin(*transit);
769  popPushit != pd.PopPushEnd(*transit); popPushit++) {
770 
771  //determine if this ear is associated with the transitions start state and
772  //determine if the ear has the same stack symbol as the transition's
773  //pop symbol (the pop vector is supposed to contain only one stack symbol).
774  //if both are true:
775  if (earMap.find(ear)->second == transit->X1
776  && stackSymbol == *popPushit->first.begin()) {
777 
778  //look up the head associated with the transition's end state
779  endState = headMap.find(transit->X2)->second;
780  startState = ear;
781  event = rPd.EventIndex(pd.EventName(transit->Ev));
782 
783  //insert transition from ear to head
784  rPd.SetTransition(startState, event, endState,
785  popPushit->first, popPushit->second);
786  }
787  }
788  }
789  }
790  return rPd;
791 }
792 
793 
794 /* *************************
795  * CorrectEvents
796  * *************************/
797 void CorrectEvents(const PushdownGenerator& correctPd, PushdownGenerator& pd) {
798  EventSet::Iterator correctevit, evit;
799  for (evit = pd.AlphabetBegin(); evit != pd.AlphabetEnd(); evit++) {
800  for (correctevit = correctPd.AlphabetBegin();
801  correctevit != correctPd.AlphabetEnd(); correctevit++) {
802  if (*evit == *correctevit) {
803  //controllable
804  if (correctPd.Controllable(*correctevit)) {
805  pd.SetControllable(*evit);
806  }
807  //uncontrollable
808  else {
809  pd.ClrControllable(*evit);
810  }
811 
812  //observable
813  if (correctPd.Observable(*correctevit)) {
814  pd.SetObservable(*evit);
815  }
816  //uncontrollable
817  else {
818  pd.ClrObservable(*evit);
819  }
820  }
821  }
822  }
823 }
824 
825 
826 
827 
828 
829 
830 
831 
832 /* *************************
833  * timeval_subtract
834  * *************************/
835 int timeval_subtract(timeval* result, timeval* x, timeval* y) {
836  //FUNCTION(__FUNCTION__);
837 
838  /* Perform the carry for the later subtraction by updating y. */
839  if (x->tv_usec < y->tv_usec) {
840  int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
841  y->tv_usec -= 1000000 * nsec;
842  y->tv_sec += nsec;
843  }
844  if (x->tv_usec - y->tv_usec > 1000000) {
845  int nsec = (x->tv_usec - y->tv_usec) / 1000000;
846  y->tv_usec += 1000000 * nsec;
847  y->tv_sec -= nsec;
848  }
849 
850  /* Compute the time remaining to wait.
851  tv_usec is certainly positive. */
852  result->tv_sec = x->tv_sec - y->tv_sec;
853  result->tv_usec = x->tv_usec - y->tv_usec;
854 
855  /* Return 1 if result is negative. */
856  return x->tv_sec < y->tv_sec;
857 }
858 
859 } // namespace faudes
860 

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