pd_alg_nb_sub_a.cpp
Go to the documentation of this file.
1 /** @file pd_alg_nb_sub_a.cpp Nonblock subfunctions, part A */
2 
3 
4 /* Pushdown plugin for FAU Discrete Event Systems Library (libfaudes)
5 
6  Copyright (C) 2013 Stefan Jacobi, Sven Schneider, Anne-Kathrin Hess
7 
8 */
9 
10 #include "pd_alg_nb_sub_a.h"
11 
12 namespace faudes {
13 
14 
15 /* *************************
16  * Filter
17  * *************************/
18 std::set<Nonterminal> Filter(const std::set<Nonterminal>& symbolSet, const GrammarSymbolVector& w){
19 
20  //resulting set
21  std::set<Nonterminal> rSet;
22 
23  GrammarSymbolVector::const_iterator wit;
24  std::set<Nonterminal>::const_iterator ntit;
25  //iterate over all symbols of the word
26  for(wit = w.begin(); wit != w.end(); wit++){
27  //test if current symbol is a nonterminal
28  ConstNonterminalPtr nt = std::tr1::dynamic_pointer_cast<const Nonterminal>(*wit);
29  if(nt != NULL){
30 
31  //look for the symbol in the nonterminal set
32  ntit = symbolSet.find(*nt);
33 
34  //if the symbol was found, insert it into resulting set
35  if(ntit != symbolSet.end()){
36  rSet.insert(*ntit);
37  }
38  }
39  }
40  return rSet;
41 }
42 
43 
44 /* *************************
45  * Rnpp1
46  * *************************/
47 std::set<Nonterminal> Rnpp1(const Grammar& gr, const std::set<Nonterminal>& ntSet){
48 
49 
50  std::set<Nonterminal> rSet, filterSet;
51  //copy resulting set from set of already eliminated nonterminals
52  rSet = ntSet;
53 
54  std::set<GrammarProduction>::const_iterator pit;
55  //iterate over all productions
56 
57  for(pit = gr.GrammarProductions().begin(); pit != gr.GrammarProductions().end(); pit++){
58 
59  filterSet = Filter(gr.Nonterminals(),pit->Rhs());
60 
61  //test if the nonterminals on the right hand side of the production are all in
62  //the set of eliminable nonterminals (i. e., they are eliminable)
63  //if so, then the nonterminal on the left hand side is eliminable as well
64  if(std::includes(ntSet.begin(), ntSet.end(), filterSet.begin(), filterSet.end())){
65  //insert left hand side into set of eliminable terminals
66  rSet.insert(pit->Lhs());
67  }
68  }
69  return rSet;
70 }
71 
72 /* *************************
73  * Rnppl
74  * *************************/
75 std::set<Nonterminal> Rnppl(const Grammar& gr, const std::set<Nonterminal>& ntSet){
76 
77  //get nonterminals that are eliminable in one step
78  std::set<Nonterminal> rSet = Rnpp1(gr,ntSet);
79  //look if that changed anything
80  if(ntSet != rSet){
81  //if any changes were detected, go on
82  rSet = Rnppl(gr,rSet);
83  }
84  return rSet;
85 }
86 
87 /* *************************
88  * Rnpp
89  * *************************/
90 Grammar Rnpp(const Grammar& gr){
91 
92  //the grammar to be returned. keep the start symbol
93  Grammar rGr(gr.StartSymbol());
94 
95  //compute removable nonterminals
96  std::set<Nonterminal> removableNts = Rnppl(gr,std::set<Nonterminal>());
97 
98  std::set<GrammarProduction> productions;
99  //if the start symbol is a removable nonterminal
100 
101  if(removableNts.find(gr.StartSymbol()) != removableNts.end()){
102 
103  std::set<GrammarProduction>::const_iterator gpit;
104  //iterate over grammar productions A -> w
105  for(gpit = gr.GrammarProductionsBegin(); gpit != gr.GrammarProductionsEnd(); gpit++){
106 
107  //convert A to GrammarSymbolPtr and put it togther with w into a vector
108  Nonterminal* a = new Nonterminal(gpit->Lhs());
109  NonterminalPtr aPtr(a);
110  GrammarSymbolVector symbols(gpit->Rhs());
111  symbols.push_back(aPtr);
112 
113  std::set<Nonterminal> filteredSet;
114  //filter all nonterminals that are in A and w
115  filteredSet = Filter(gr.Nonterminals(), symbols);
116 
117  //test if filteredSet is a subset of the removable nonterminals
118  if(std::includes(removableNts.begin(), removableNts.end(), filteredSet.begin(), filteredSet.end())){
119  productions.insert(*gpit);
120  }
121  }
122  }
123 
124  //keep the terminals
125  rGr.InsTerminals(gr.Terminals());
126 
127  //keep only removable nonterminals
128  rGr.InsNonterminals(removableNts);
129 
130  //keep only the productions from above
131  rGr.InsGrammarProductions(productions);
132 
133  return rGr;
134 }
135 
136 /* *************************
137  * Sp2Lr
138  * *************************/
140 
141  Grammar rGr;
142 
143  StateSet::Iterator stateit1, stateit2;
144  EventSet::Iterator eventit;
145  TransSet::Iterator transit;
146  StackSymbolSet::Iterator ssit;
147  PopPushSet::const_iterator ppit;
148  std::vector<Idx> ssVector, pop, push;
149  std::vector<Idx>::const_iterator popit, pushit;
151 
152  //Terminals
153 
154  //terminals equal the generator's events
155  for(eventit = pd.AlphabetBegin(); eventit != pd.AlphabetEnd(); eventit++){
156  rGr.InsTerminal(Terminal(*eventit));
157  }
158 
159  //Nonterminals
160 
161  //for every state
162  for(stateit1 = pd.StatesBegin(); stateit1 != pd.StatesEnd(); stateit1++){
163 
164  //insert end nonterminal for every stack symbol
165  for(ssit = pd.StackSymbolsBegin(); ssit != pd.StackSymbolsEnd(); ssit++){
166  if(!pd.IsStackSymbolLambda(*ssit)){
167  ssVector.clear();
168  ssVector.push_back(*ssit);
169  rGr.InsNonterminal(Nonterminal(*stateit1,ssVector));
170  }
171  }
172 
173  //insert mid nonterminal for every state and every stack symbol
174  for(stateit2 = pd.StatesBegin(); stateit2 != pd.StatesEnd(); stateit2++){
175  for(ssit = pd.StackSymbolsBegin(); ssit != pd.StackSymbolsEnd(); ssit++){
176  if(!pd.IsStackSymbolLambda(*ssit)){
177  ssVector.clear();
178  ssVector.push_back(*ssit);
179  rGr.InsNonterminal(Nonterminal(*stateit1,ssVector,*stateit2));
180  }
181  }
182  }
183  }
184  //Start Symbol
185  ssVector.clear();
186  ssVector.push_back(pd.StackBottom());
187  rGr.SetStartSymbol(Nonterminal(pd.InitState(),ssVector));
188 
189  //Grammar Productions
190  //for every transition
191  for(transit = pd.TransRelBegin(); transit != pd.TransRelEnd(); transit++){
192  for(ppit = pd.PopPushBegin(*transit); ppit != pd.PopPushEnd(*transit); ppit++){
193 
194  pop = ppit->first;
195  std::vector<Idx> b = pop;
196  push = ppit->second;
197  Idx qi = transit->X1;
198  Idx qj = transit->X2;
199  Idx a = transit->Ev;
200 
201  //read transition (qi,a,b,b,qj)
202  if(!pd.IsEventLambda(transit->Ev)){
203 
204  //insert production (qi,b) --> a(qj,b)
205  Nonterminal ntLhs(qi,b);
206  Nonterminal* ntRhs = new Nonterminal(qj,b);
207  GrammarSymbolPtr ntRhsPtr(ntRhs);
208  Terminal* t = new Terminal(a);
209  GrammarSymbolPtr tPtr(t);
210  rhs.clear();
211  rhs.push_back(tPtr);
212  rhs.push_back(ntRhsPtr);
213  rGr.InsGrammarProduction(GrammarProduction(ntLhs,rhs));
214 
215  //for every state qt
216  for(stateit1 = pd.StatesBegin(); stateit1 != pd.StatesEnd(); stateit1++){
217 
218  Idx qt = *stateit1;
219 
220  //insert production (qi,b,qt) --> a (qj,b,qt)
221  Nonterminal ntLhs(qi,b,qt);
222  Nonterminal* ntRhs = new Nonterminal(qj,b,qt);
223  GrammarSymbolPtr ntRhsPtr(ntRhs);
224  rhs.clear();
225  rhs.push_back(tPtr);
226  rhs.push_back(ntRhsPtr);
227  rGr.InsGrammarProduction(GrammarProduction(ntLhs,rhs));
228  }
229  }
230  else{
231 
232  //pop transition (qi,lambda,b,lambda,qj)
233  if(pd.IsStackSymbolLambda(push.front())){
234 
235  //insert production (qi,b,qj) --> lambda
236  Nonterminal ntLhs(qi,b,qj);
237  Terminal* t = new Terminal(transit->Ev);
238  GrammarSymbolPtr tPtr(t);
239  rhs.clear();
240  rhs.push_back(tPtr);
241  rGr.InsGrammarProduction(GrammarProduction(ntLhs,rhs));
242  }
243 
244  //push transition (qi,lambda,b,cb,qj)
245  else if(push.size() == 2){
246 
247  std::vector<Idx> c;
248  c.push_back(push.front());
249 
250  //insert production (qi,b) --> (qj,c)
251  Nonterminal ntLhs(qi,b);
252  Nonterminal* ntRhs = new Nonterminal(qj,c);
253  GrammarSymbolPtr ntRhsPtr(ntRhs);
254  rhs.clear();
255  rhs.push_back(ntRhsPtr);
256  rGr.InsGrammarProduction(GrammarProduction(ntLhs,rhs));
257 
258  //for every state qs
259  for(stateit1 = pd.StatesBegin(); stateit1 != pd.StatesEnd(); stateit1++){
260 
261  Idx qs = *stateit1;
262 
263  //insert production (qi,b) --> (qj,c,qs)(qs,b)
264  Nonterminal ntLhs(qi,b);
265  Nonterminal* ntRhs1 = new Nonterminal(qj,c,qs);
266  GrammarSymbolPtr ntRhs1Ptr(ntRhs1);
267  Nonterminal* ntRhs2 = new Nonterminal(qs,b);
268  GrammarSymbolPtr ntRhs2Ptr(ntRhs2);
269  rhs.clear();
270  rhs.push_back(ntRhs1Ptr);
271  rhs.push_back(ntRhs2Ptr);
272  rGr.InsGrammarProduction(GrammarProduction(ntLhs,rhs));
273 
274  //for every state qt
275  for(stateit2 = pd.StatesBegin(); stateit2 != pd.StatesEnd(); stateit2++){
276 
277  Idx qt = *stateit2;
278 
279  //insert production (qi,b,qt) --> (qj,c,qs)(qs,b,qt)
280  Nonterminal ntLhs(qi,b,qt);
281  Nonterminal* ntRhs1 = new Nonterminal(qj,c,qs);
282  GrammarSymbolPtr ntRhs1Ptr(ntRhs1);
283  Nonterminal* ntRhs2 = new Nonterminal(qs,b,qt);
284  GrammarSymbolPtr ntRhs2Ptr(ntRhs2);
285  rhs.clear();
286  rhs.push_back(ntRhs1Ptr);
287  rhs.push_back(ntRhs2Ptr);
288  rGr.InsGrammarProduction(GrammarProduction(ntLhs,rhs));
289  }
290  }
291  }
292  }
293  }
294  }
295 
296  //for every final state q and every stack symbol b
297  for(stateit1 = pd.MarkedStatesBegin(); stateit1 != pd.MarkedStatesEnd(); stateit1++){
298  for(ssit = pd.StackSymbolsBegin(); ssit != pd.StackSymbolsEnd(); ssit++){
299  if(!pd.IsStackSymbolLambda(*ssit)){
300 
301 
302  //insert a production ((q,b) --> lambda)
303  ssVector.clear();
304  ssVector.push_back(*ssit);
305  Nonterminal nt(*stateit1,ssVector);
307  GrammarSymbolPtr tPtr(t);
309  v.push_back(tPtr);
310  GrammarProduction gp(nt,v);
311  rGr.InsGrammarProduction(gp);
312  }
313  }
314  }
315  return rGr;
316 }
317 
318 /* *************************
319  * Sp2Lr2
320  * *************************/
322 
323  Grammar rGr;
324 
325  StateSet::Iterator stateit1, stateit2;
326  EventSet::Iterator eventit;
327  TransSet::Iterator transit;
328  StackSymbolSet::Iterator ssit;
329  PopPushSet::const_iterator ppit;
330  std::vector<Idx> ssVector, pop, push;
331  std::vector<Idx>::const_iterator popit, pushit;
333 
334  //Terminals
335 
336  //terminals equal the generator's events
337  for(eventit = pd.AlphabetBegin(); eventit != pd.AlphabetEnd(); eventit++){
338  rGr.InsTerminal(Terminal(*eventit));
339  }
340  //Start Symbol
341  ssVector.clear();
342  ssVector.push_back(pd.StackBottom());
343  rGr.SetStartSymbol(Nonterminal(pd.InitState(),ssVector));
344 
345  //Grammar Productions
346 
347  //for every final state q and every stack symbol b
348  for(stateit1 = pd.MarkedStatesBegin(); stateit1 != pd.MarkedStatesEnd(); stateit1++){
349  for(ssit = pd.StackSymbolsBegin(); ssit != pd.StackSymbolsEnd(); ssit++){
350  if(!pd.IsStackSymbolLambda(*ssit)){
351 
352  //save used nonterminal
353  ssVector.clear();
354  ssVector.push_back(*ssit);
355  Nonterminal nt(*stateit1,ssVector);
356  rGr.InsNonterminal(nt);
357 
358  //insert a production ((q,b) --> lambda)
360  GrammarSymbolPtr tPtr(t);
362  v.push_back(tPtr);
363  GrammarProduction gp(nt,v);
364  rGr.InsGrammarProduction(gp);
365  //std::cout << "inserting " << gp.Str() << std::endl;
366  }
367  }
368  }
369 
370 
371  //generate reducible productions until no more productions can be generated
372  uint oldSize = 0;
373 
374  while(rGr.GrammarProductions().size() != oldSize){
375 
376  //save old number of grammar productions
377  oldSize = rGr.GrammarProductions().size();
378 
379  //try to generate new grammar productions for each transition
380  for(transit = pd.TransRelBegin(); transit != pd.TransRelEnd(); transit++){
381  for(ppit = pd.PopPushBegin(*transit); ppit != pd.PopPushEnd(*transit); ppit++){
382 
383  pop = ppit->first;
384  std::vector<Idx> b = pop;
385  push = ppit->second;
386  Idx qi = transit->X1;
387  Idx qj = transit->X2;
388  Idx a = transit->Ev;
389 
390  //read transition (qi,a,b,b,qj)
391  if(!pd.IsEventLambda(transit->Ev)){
392 
393  //insert production (qi,b) --> a(qj,b)
394  Nonterminal ntLhs(qi,b);
395  Terminal* t = new Terminal(a);
396  GrammarSymbolPtr tPtr(t);
397  Nonterminal* ntRhs = new Nonterminal(qj,b);
398  GrammarSymbolPtr ntRhsPtr(ntRhs);
399  //... but only if (qj,b) is reducible
400  if(rGr.Nonterminals().find(*ntRhs) != rGr.NonterminalsEnd()){
401 
402  //save lhs nonterminal as reducible
403  rGr.InsNonterminal(ntLhs);
404 
405  //insert production
406  rhs.clear();
407  rhs.push_back(tPtr);
408  rhs.push_back(ntRhsPtr);
409  rGr.InsGrammarProduction(GrammarProduction(ntLhs,rhs));
410  //std::cout << "inserting " << GrammarProduction(ntLhs,rhs).Str() << std::endl;
411  }
412 
413  //for every state qt
414  for(stateit1 = pd.StatesBegin(); stateit1 != pd.StatesEnd(); stateit1++){
415 
416  Idx qt = *stateit1;
417 
418  //insert production (qi,b,qt) --> a (qj,b,qt)
419  Nonterminal ntLhs(qi,b,qt);
420  Nonterminal* ntRhs = new Nonterminal(qj,b,qt);
421  //... but only if (qj,b,qt) is reducible
422  if(rGr.Nonterminals().find(*ntRhs) != rGr.NonterminalsEnd()){
423 
424  //save lhs nonterminal as reducible
425  rGr.InsNonterminal(ntLhs);
426 
427  //insert production
428  GrammarSymbolPtr ntRhsPtr(ntRhs);
429  rhs.clear();
430  rhs.push_back(tPtr);
431  rhs.push_back(ntRhsPtr);
432  rGr.InsGrammarProduction(GrammarProduction(ntLhs,rhs));
433  //std::cout << "inserting " << GrammarProduction(ntLhs,rhs).Str() << std::endl;
434  }
435  }
436  }
437  else{
438 
439  //pop transition (qi,lambda,b,lambda,qj)
440  if(pd.IsStackSymbolLambda(push.front())){
441 
442  //save lhs nonterminal as reducible
443  Nonterminal ntLhs(qi,b,qj);
444  rGr.InsNonterminal(ntLhs);
445 
446  //insert production (qi,b,qj) --> lambda
447  Terminal* t = new Terminal(transit->Ev);
448  GrammarSymbolPtr tPtr(t);
449  rhs.clear();
450  rhs.push_back(tPtr);
451  rGr.InsGrammarProduction(GrammarProduction(ntLhs,rhs));
452  //std::cout << " inserting " << GrammarProduction(ntLhs,rhs).Str() << std::endl;
453  }
454 
455  //push transition (qi,lambda,b,cb,qj)
456  else if(push.size() == 2){
457 
458  std::vector<Idx> c;
459  c.push_back(push.front());
460 
461  //insert production (qi,b) --> (qj,c)
462  Nonterminal ntLhs(qi,b);
463  Nonterminal* ntRhs = new Nonterminal(qj,c);
464  GrammarSymbolPtr ntRhsPtr(ntRhs);
465  //... but only if (qj,c) is reducible
466  if(rGr.Nonterminals().find(*ntRhs) != rGr.NonterminalsEnd()){
467 
468  //save lhs nonterminal as reducible
469  rGr.InsNonterminal(ntLhs);
470 
471  //insert production
472  rhs.clear();
473  rhs.push_back(ntRhsPtr);
474  rGr.InsGrammarProduction(GrammarProduction(ntLhs,rhs));
475  //std::cout << "inserting " << GrammarProduction(ntLhs,rhs).Str() << std::endl;
476  }
477 
478  //for every state qs
479  for(stateit1 = pd.StatesBegin(); stateit1 != pd.StatesEnd(); stateit1++){
480 
481  Idx qs = *stateit1;
482 
483  //insert production (qi,b) --> (qj,c,qs)(qs,b)
484  Nonterminal ntLhs(qi,b);
485  Nonterminal* ntRhs1 = new Nonterminal(qj,c,qs);
486  GrammarSymbolPtr ntRhs1Ptr(ntRhs1);
487  Nonterminal* ntRhs2 = new Nonterminal(qs,b);
488  GrammarSymbolPtr ntRhs2Ptr(ntRhs2);
489  //... but only if (qj,c,qs) and (qs,b) are reducible
490  if(rGr.Nonterminals().find(*ntRhs1) != rGr.NonterminalsEnd() &&
491  rGr.Nonterminals().find(*ntRhs2) != rGr.NonterminalsEnd()){
492 
493  //save lhs nonterminal as reducible
494  rGr.InsNonterminal(ntLhs);
495 
496  //insert production
497  rhs.clear();
498  rhs.push_back(ntRhs1Ptr);
499  rhs.push_back(ntRhs2Ptr);
500  rGr.InsGrammarProduction(GrammarProduction(ntLhs,rhs));
501  //std::cout << "inserting " << GrammarProduction(ntLhs,rhs).Str() << std::endl;
502  }
503 
504  //for every state qt
505  for(stateit2 = pd.StatesBegin(); stateit2 != pd.StatesEnd(); stateit2++){
506 
507  Idx qt = *stateit2;
508 
509  //insert production (qi,b,qt) --> (qj,c,qs)(qs,b,qt)
510  Nonterminal ntLhs(qi,b,qt);
511  Nonterminal* ntRhs1 = new Nonterminal(qj,c,qs);
512  GrammarSymbolPtr ntRhs1Ptr(ntRhs1);
513  Nonterminal* ntRhs2 = new Nonterminal(qs,b,qt);
514  GrammarSymbolPtr ntRhs2Ptr(ntRhs2);
515  //... but only if (qj,c,qs) and (qs,b,qt) are reducible
516  if(rGr.Nonterminals().find(*ntRhs1) != rGr.NonterminalsEnd() &&
517  rGr.Nonterminals().find(*ntRhs2) != rGr.NonterminalsEnd()){
518 
519  //save lhs nonterminal as reducible
520  rGr.InsNonterminal(ntLhs);
521 
522  //insert production
523  rhs.clear();
524  rhs.push_back(ntRhs1Ptr);
525  rhs.push_back(ntRhs2Ptr);
526  rGr.InsGrammarProduction(GrammarProduction(ntLhs,rhs));
527  //std::cout << "inserting " << GrammarProduction(ntLhs,rhs).Str() << std::endl;
528  }
529  }
530  }
531  }
532  }
533  }
534  }
535 
536 
537  }
538  return rGr;
539 }
540 
541 /* *************************
542  * Rup
543  * *************************/
544 Grammar Rup(const Grammar& gr){
545  Grammar rGr;
546 
547  //copy terminals and start symbol from the old grammar
548  rGr.InsTerminals(gr.Terminals());
549  rGr.SetStartSymbol(gr.StartSymbol());
550 
551  std::set<GrammarProduction> todoProductions, reachableProductions;
552  std::set<GrammarProduction>::const_iterator gpit;
553  std::set<Nonterminal> usedNonterminals;
554 
555  //start with the start symbol, which is always used in a grammar
556  usedNonterminals.insert(gr.StartSymbol());
557 
558  //get productions with start symbol as righthand side
559  for(gpit = gr.GrammarProductionsBegin(); gpit != gr.GrammarProductionsEnd(); gpit++){
560  if(gpit->Lhs() == gr.StartSymbol()){
561  todoProductions.insert(*gpit);
562  }
563  }
564 
565  //look at all todo productions
566  while(!todoProductions.empty()){
567 
568  //get the current todo production
569  GrammarProduction currentGp(*todoProductions.begin());
570  todoProductions.erase(currentGp);
571 
572  //since this production was reached, it is a reachable production
573  reachableProductions.insert(currentGp);
574 
575  //insert all nonterminals of the current production into set of used nonterminals
576  std::set<Nonterminal> filtered = Filter(gr.Nonterminals(),currentGp.Rhs());
577  usedNonterminals.insert(filtered.begin(), filtered.end());
578 
579  //look at all productions
580  for(gpit = gr.GrammarProductionsBegin(); gpit != gr.GrammarProductionsEnd(); gpit++){
581  //if they have any of the used nonterminals on their lefthand side, insert them
582  //into the todo productions
583  if(usedNonterminals.find(gpit->Lhs()) != usedNonterminals.end()){
584  todoProductions.insert(*gpit);
585  }
586  }
587 
588  //do not look at already reachable productions twice
589  //this avoids infinite loops
590  for(gpit = reachableProductions.begin(); gpit != reachableProductions.end(); gpit++){
591  todoProductions.erase(*gpit);
592  }
593  }
594 
595  //insert all used nonterminals and all reachable productions
596  rGr.InsNonterminals(usedNonterminals);
597  rGr.InsGrammarProductions(reachableProductions);
598 
599  return rGr;
600 }
601 
602 
603 } // namespace faudes
604 

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