cfl_parallel.cpp
Go to the documentation of this file.
1 /** @file cfl_parallel.cpp parallel composition */
2 
3 /* FAU Discrete Event Systems Library (libfaudes)
4 
5  Copyright (C) 2006 Bernd Opitz
6  Exclusive copyright is granted to Klaus Schmidt
7 
8  This library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU Lesser General Public
10  License as published by the Free Software Foundation; either
11  version 2.1 of the License, or (at your option) any later version.
12 
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public
19  License along with this library; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
21 
22 
23 #include "cfl_parallel.h"
24 #include "cfl_conflequiv.h"
25 
26 /* turn on debugging for this file */
27 //#undef FD_DF
28 //#define FD_DF(a) FD_WARN(a);
29 
30 namespace faudes {
31 
32 // Parallel(rGen1, rGen2, res)
33 void Parallel(const Generator& rGen1, const Generator& rGen2, Generator& rResGen) {
34  // helpers:
35  std::map< std::pair<Idx,Idx>, Idx> cmap;
36  // prepare result
37  Generator* pResGen = &rResGen;
38  if(&rResGen== &rGen1 || &rResGen== &rGen2) {
39  pResGen= rResGen.New();
40  }
41  // doit
42  Parallel(rGen1, rGen2, cmap, *pResGen);
43  // copy result
44  if(pResGen != &rResGen) {
45  pResGen->Move(rResGen);
46  delete pResGen;
47  }
48 }
49 
50 
51 // Parallel for multiple Generators
52 void Parallel(
53  const GeneratorVector& rGenVec,
54  Generator& rResGen)
55 {
56  // helpers:
57  std::map< std::pair<Idx,Idx>, Idx> cmap;
58  // prepare result
59  rResGen.Clear();
60  bool rnames=rResGen.StateNamesEnabled();
61  // ignore empty
62  if(rGenVec.Size()==0) {
63  return;
64  }
65  // copy one
66  rResGen=rGenVec.At(0);
67  rResGen.StateNamesEnabled(rnames);
68  // run parallel
69  for(GeneratorVector::Position i=1; i<rGenVec.Size(); i++) {
70  Parallel(rResGen,rGenVec.At(i),cmap,rResGen);
71  FD_DF("Parallel() cnt " << i << " states " << rResGen.Size());
72  FD_DF("Parallel() cnt " << i << " coreach " << rResGen.CoaccessibleSet().Size());
73  }
74 }
75 
76 // Parallel for multiple Generators, nonblocking part only
78  const GeneratorVector& rGenVec,
79  Generator& rResGen)
80 {
81  // prepare result
82  rResGen.Clear();
83  bool rnames=rResGen.StateNamesEnabled();
84  // ignore empty
85  if(rGenVec.Size()==0) {
86  return;
87  }
88  // copy one
89  rResGen=rGenVec.At(0);
90  rResGen.StateNamesEnabled(rnames);
91  // run parallel
92  for(GeneratorVector::Position i=1; i<rGenVec.Size(); i++) {
93  RemoveNonCoaccessibleOut(rResGen);
94  FD_DF("ParallelLive() cnt " << i << " certconf trans #" << rResGen.TransRel().Size());
95  ParallelLive(rResGen,rGenVec.At(i),rResGen);
96  FD_DF("ParallelLive() cnt " << i << " parallel trans #" << rResGen.TransRel().Size());
97  }
98 }
99 
100 // Parallel for Generators, transparent for event attributes.
102  const Generator& rGen1,
103  const Generator& rGen2,
104  Generator& rResGen)
105 {
106  FD_DF("aParallel(...)");
107 
108  // inputs have to agree on attributes of shared events:
109  bool careattr=rGen1.Alphabet().EqualAttributes(rGen2.Alphabet());
110 
111  // prepare result
112  Generator* pResGen = &rResGen;
113  if(&rResGen== &rGen1 || &rResGen== &rGen2) {
114  pResGen= rResGen.New();
115  }
116 
117  // make product composition of inputs
118  Parallel(rGen1,rGen2,*pResGen);
119 
120  // copy all attributes of input alphabets
121  if(careattr) {
122  pResGen->EventAttributes(rGen1.Alphabet());
123  pResGen->EventAttributes(rGen2.Alphabet());
124  }
125 
126  // copy result
127  if(pResGen != &rResGen) {
128  pResGen->Move(rResGen);
129  delete pResGen;
130  }
131 
132  FD_DF("aParallel(...): done");
133 }
134 
135 
136 // Parallel for multiple Generators, transparent for event attributes.
138  const GeneratorVector& rGenVec,
139  Generator& rResGen)
140 {
141 
142  // inputs have to agree on attributes of pairwise shared events:
143  bool careattr=true;
144  for(GeneratorVector::Position i=0; i<rGenVec.Size(); i++)
145  for(GeneratorVector::Position j=0; j<i; j++)
146  if(!rGenVec.At(i).Alphabet().EqualAttributes(rGenVec.At(j).Alphabet()))
147  careattr=false;
148 
149  // ignore empty
150  if(rGenVec.Size()==0) {
151  return;
152  }
153 
154  // copy one
155  if(rGenVec.Size()==1) {
156  rResGen=rGenVec.At(0);
157  return;
158  }
159 
160  // run parallel
161  Parallel(rGenVec.At(0),rGenVec.At(1),rResGen);
162  for(GeneratorVector::Position i=2; i<rGenVec.Size(); i++)
163  Parallel(rGenVec.At(i),rResGen,rResGen);
164 
165  // fix alphabet
166  if(careattr) {
167  for(GeneratorVector::Position i=0; i<rGenVec.Size(); i++)
168  rResGen.EventAttributes(rGenVec.At(i).Alphabet());
169  }
170 
171 }
172 
173 
174 // aParallel(rGen1, rGen2, rCompositionMap, res)
176  const Generator& rGen1,
177  const Generator& rGen2,
178  ProductCompositionMap& rCompositionMap,
179  Generator& rResGen)
180 {
181 
182  // inputs have to agree on attributes of shared events:
183  bool careattr=rGen1.Alphabet().EqualAttributes(rGen2.Alphabet());
184 
185  // prepare result
186  Generator* pResGen = &rResGen;
187  if(&rResGen== &rGen1 || &rResGen== &rGen2) {
188  pResGen= rResGen.New();
189  }
190 
191  // make product composition of inputs
192  Parallel(rGen1,rGen2,rCompositionMap.StlMap(),*pResGen);
193 
194  // copy all attributes of input alphabets
195  if(careattr) {
196  pResGen->EventAttributes(rGen1.Alphabet());
197  pResGen->EventAttributes(rGen2.Alphabet());
198  }
199 
200  // copy result
201  if(pResGen != &rResGen) {
202  pResGen->Move(rResGen);
203  delete pResGen;
204  }
205 
206 }
207 
208 // Parallel(rGen1, rGen2, rCompositionMap, res)
209 void Parallel(
210  const Generator& rGen1,
211  const Generator& rGen2,
212  ProductCompositionMap& rCompositionMap,
213  Generator& rResGen)
214 {
215  // make product composition of inputs
216  Parallel(rGen1,rGen2,rCompositionMap.StlMap(),rResGen);
217 }
218 
219 // Parallel(rGen1, rGen2, rCompositionMap, mark1, mark2, res)
220 void Parallel(
221  const Generator& rGen1, const Generator& rGen2,
222  ProductCompositionMap& rCompositionMap,
223  StateSet& rMark1,
224  StateSet& rMark2,
225  Generator& rResGen)
226 {
227 
228  // do the composition
229  Parallel(rGen1,rGen2,rCompositionMap,rResGen);
230 
231  // clear marking
232  rMark1.Clear();
233  rMark2.Clear();
234 
235  /*
236  see tmoor 20110208
237 
238  // catch special cases: a
239  if(rGen1.AlphabetSize()==0) {
240  rMark2=rGen2.MarkedStates();
241  return;
242  }
243 
244  // catch special cases: b
245  if(rGen2.AlphabetSize()==0) {
246  rMark1=rGen1.MarkedStates();
247  return;
248  }
249  */
250 
251  // retrieve marking from reverse composition map
252  StateSet::Iterator sit;
253  for(sit=rResGen.StatesBegin(); sit!=rResGen.StatesEnd(); ++sit) {
254  Idx s1=rCompositionMap.Arg1State(*sit);
255  Idx s2=rCompositionMap.Arg2State(*sit);
256  if(rGen1.ExistsMarkedState(s1)) rMark1.Insert(*sit);
257  if(rGen2.ExistsMarkedState(s2)) rMark1.Insert(*sit);
258  }
259 }
260 
261 
262 // Parallel(rGen1, rGen2, rCompositionMap, res, live_only)
263 void Parallel(
264  const Generator& rGen1, const Generator& rGen2,
265  std::map< std::pair<Idx,Idx>, Idx>& rCompositionMap,
266  Generator& rResGen,
267  bool live_only)
268 {
269  FD_DF("Parallel(" << &rGen1 << "," << &rGen2 << ")");
270 
271  /*
272  re-consider the special cases:
273 
274  if Sigma_1=0, we have either
275  -- L_res=L_2 (if L_1!=0)
276  -- L_res=0 (if L_1==0)
277 
278  the below special cases do not handle this correct,
279  nor do they setup the composition map; thus, we drop
280  the special cases; tmoor 20110208
281  */
282 
283  /*
284  // special case: empty alphabet
285  if(rGen1.AlphabetSize()==0) {
286  rResGen=rGen2;
287  rResGen.Name(rGen2.Name());
288  return;
289  }
290 
291  // special case: empty alphabet
292  if(rGen2.AlphabetSize()==0) {
293  rResGen=rGen1;
294  rResGen.Name(rGen1.Name());
295  return;
296  }
297  */
298 
299  // prepare result
300  Generator* pResGen = &rResGen;
301  if(&rResGen== &rGen1 || &rResGen== &rGen2) {
302  pResGen= rResGen.New();
303  }
304  pResGen->Clear();
305  pResGen->Name(CollapsString(rGen1.Name()+"||"+rGen2.Name()));
306  rCompositionMap.clear();
307 
308  // create res alphabet
309  EventSet::Iterator eit;
310  for (eit = rGen1.AlphabetBegin(); eit != rGen1.AlphabetEnd(); ++eit) {
311  pResGen->InsEvent(*eit);
312  }
313  for (eit = rGen2.AlphabetBegin(); eit != rGen2.AlphabetEnd(); ++eit) {
314  pResGen->InsEvent(*eit);
315  }
316  FD_DF("Parallel: inserted indices in rResGen.alphabet( "
317  << pResGen->AlphabetToString() << ")");
318 
319  // know each aruments coaccessible set
320  StateSet gen1live, gen2live;
321  if(live_only) {
322  gen1live=rGen1.CoaccessibleSet();
323  gen2live=rGen2.CoaccessibleSet();
324  }
325 
326  // shared events
327  EventSet sharedalphabet = rGen1.Alphabet() * rGen2.Alphabet();
328  FD_DF("Parallel: shared events: " << sharedalphabet.ToString());
329 
330  // todo stack
331  std::stack< std::pair<Idx,Idx> > todo;
332  // current pair, new pair
333  std::pair<Idx,Idx> currentstates, newstates;
334  // state
335  Idx tmpstate;
336  StateSet::Iterator lit1,lit2;
337  TransSet::Iterator tit1, tit1_end, tit2, tit2_end;
338  std::map< std::pair<Idx,Idx>, Idx>::iterator rcit;
339 
340  // push all combinations of initial states on todo stack
341  FD_DF("Parallel: adding all combinations of initial states to todo:");
342  for (lit1 = rGen1.InitStatesBegin(); lit1 != rGen1.InitStatesEnd(); ++lit1) {
343  for (lit2 = rGen2.InitStatesBegin(); lit2 != rGen2.InitStatesEnd(); ++lit2) {
344  newstates = std::make_pair(*lit1, *lit2);
345  tmpstate = pResGen->InsInitState();
346  rCompositionMap[newstates] = tmpstate;
347  FD_DF("Parallel: (" << *lit1 << "|" << *lit2 << ") -> "
348  << rCompositionMap[newstates]);
349  if(live_only) {
350  if(!gen1live.Exists(newstates.first)) continue;
351  if(!gen2live.Exists(newstates.second)) continue;
352  }
353  todo.push(newstates);
354  FD_DF("Parallel: todo push: (" << newstates.first << "|"
355  << newstates.second << ") -> "
356  << rCompositionMap[newstates]);
357  }
358  }
359 
360  // start algorithm
361  FD_DF("Parallel: processing reachable states:");
362  while (! todo.empty()) {
363  // allow for user interrupt
364  // LoopCallback();
365  // allow for user interrupt, incl progress report
366  FD_WPC(rCompositionMap.size(),rCompositionMap.size()+todo.size(),"Parallel(): processing");
367  // get next reachable state from todo stack
368  currentstates = todo.top();
369  todo.pop();
370  FD_DF("Parallel: processing (" << currentstates.first << "|"
371  << currentstates.second << ") -> "
372  << rCompositionMap[currentstates]);
373  // iterate over all rGen1 transitions
374  // (includes execution of shared events)
375  tit1 = rGen1.TransRelBegin(currentstates.first);
376  tit1_end = rGen1.TransRelEnd(currentstates.first);
377  for(; tit1 != tit1_end; ++tit1) {
378  // if event not shared
379  if(! sharedalphabet.Exists(tit1->Ev)) {
380  FD_DF("Parallel: exists only in rGen1");
381  newstates = std::make_pair(tit1->X2, currentstates.second);
382  // add to result if composition state is new
383  rcit = rCompositionMap.find(newstates);
384  if(rcit == rCompositionMap.end()) {
385  tmpstate = pResGen->InsState();
386  rCompositionMap[newstates] = tmpstate;
387  bool dopush=true;
388  if(live_only) {
389  dopush= gen1live.Exists(newstates.first) && gen2live.Exists(newstates.second);
390  }
391  if(dopush) {
392  todo.push(newstates);
393  FD_DF("Parallel: todo push: (" << newstates.first << "|"
394  << newstates.second << ") -> "
395  << rCompositionMap[newstates]);
396  }
397  } else {
398  tmpstate = rcit->second;
399  }
400  pResGen->SetTransition(rCompositionMap[currentstates], tit1->Ev, tmpstate);
401  FD_DF("Parallel: add transition to new generator: "
402  << rCompositionMap[currentstates] << "-" << tit1->Ev << "-"
403  << tmpstate);
404  }
405  // if shared event
406  else {
407  FD_DF("Parallel: common event");
408  // find shared transitions
409  tit2 = rGen2.TransRelBegin(currentstates.second, tit1->Ev);
410  tit2_end = rGen2.TransRelEnd(currentstates.second, tit1->Ev);
411  for (; tit2 != tit2_end; ++tit2) {
412  newstates = std::make_pair(tit1->X2, tit2->X2);
413  // add to result if composition state is new
414  rcit = rCompositionMap.find(newstates);
415  if (rcit == rCompositionMap.end()) {
416  tmpstate = pResGen->InsState();
417  rCompositionMap[newstates] = tmpstate;
418  bool dopush=true;
419  if(live_only) {
420  dopush= gen1live.Exists(newstates.first) && gen2live.Exists(newstates.second);
421  }
422  if(dopush) {
423  todo.push(newstates);
424  FD_DF("Parallel: todo push: (" << newstates.first << "|"
425  << newstates.second << ") -> "
426  << rCompositionMap[newstates]);
427  }
428  } else {
429  tmpstate = rcit->second;
430  }
431  pResGen->SetTransition(rCompositionMap[currentstates],
432  tit1->Ev, tmpstate);
433  FD_DF("Parallel: add transition to new generator: "
434  << rCompositionMap[currentstates] << "-"
435  << tit1->Ev << "-" << tmpstate);
436  }
437  }
438  }
439  // iterate over all rGen2 transitions
440  // (without execution of shared events)
441  tit2 = rGen2.TransRelBegin(currentstates.second);
442  tit2_end = rGen2.TransRelEnd(currentstates.second);
443  for (; tit2 != tit2_end; ++tit2) {
444  if (! sharedalphabet.Exists(tit2->Ev)) {
445  FD_DF("Parallel: exists only in rGen2");
446  newstates = std::make_pair(currentstates.first, tit2->X2);
447  // add to todo list if composition state is new
448  rcit = rCompositionMap.find(newstates);
449  if(rcit == rCompositionMap.end()) {
450  tmpstate = pResGen->InsState();
451  rCompositionMap[newstates] = tmpstate;
452  bool dopush=true;
453  if(live_only) {
454  dopush= gen1live.Exists(newstates.first) && gen2live.Exists(newstates.second);
455  }
456  if(dopush) {
457  todo.push(newstates);
458  FD_DF("Parallel: todo push: (" << newstates.first << "|"
459  << newstates.second << ") -> "
460  << rCompositionMap[newstates]);
461  }
462  } else {
463  tmpstate = rcit->second;
464  }
465  pResGen->SetTransition(rCompositionMap[currentstates],
466  tit2->Ev, tmpstate);
467  FD_DF("Parallel: add transition to new generator: "
468  << rCompositionMap[currentstates] << "-"
469  << tit2->Ev << "-" << tmpstate);
470  }
471  }
472  }
473 
474  // set marked states
475  rcit=rCompositionMap.begin();
476  while(rcit!=rCompositionMap.end()) {
477  if(rGen1.ExistsMarkedState(rcit->first.first))
478  if(rGen2.ExistsMarkedState(rcit->first.second))
479  pResGen->SetMarkedState(rcit->second);
480  ++rcit;
481  }
482  FD_DF("Parallel: marked states: " << pResGen->MarkedStatesToString());
483 
484  // copy result
485  if(pResGen != &rResGen) {
486  rResGen = *pResGen;
487  delete pResGen;
488  }
489  // set statenames
490  if(rGen1.StateNamesEnabled() && rGen2.StateNamesEnabled() && rResGen.StateNamesEnabled())
491  SetComposedStateNames(rGen1, rGen2, rCompositionMap, rResGen);
492  else
493  rResGen.StateNamesEnabled(false);
494 }
495 
496 // API wrapper ParallelLive
498  const Generator& rGen1, const Generator& rGen2,
499  std::map< std::pair<Idx,Idx>, Idx>& rCompositionMap,
500  Generator& rResGen)
501 {
502  FD_DF("ParallelLive(" << &rGen1 << "," << &rGen2 << ")");
503  Parallel(rGen1,rGen2,rCompositionMap,rResGen,true);
504 }
505 
506 // API wrapper ParallelLive
508  const Generator& rGen1, const Generator& rGen2,
509  Generator& rResGen)
510 {
511  FD_DF("ParallelLive(" << &rGen1 << "," << &rGen2 << ")");
512  std::map< std::pair<Idx,Idx>, Idx> cmap;
513  Parallel(rGen1,rGen2,cmap,rResGen,true);
514 }
515 
516 // Product(rGen1, rGen2, res)
517 void Product(const Generator& rGen1, const Generator& rGen2, Generator& rResGen) {
518  std::map< std::pair<Idx,Idx>, Idx> cmap;
519  // doit
520  Product(rGen1, rGen2, cmap, rResGen);
521 }
522 
523 
524 // Product for Generators, transparent for event attributes.
525 void aProduct(
526  const Generator& rGen1,
527  const Generator& rGen2,
528  Generator& rResGen)
529 {
530 
531  // inputs have to agree on attributes of shared events:
532  bool careattr=rGen1.Alphabet().EqualAttributes(rGen2.Alphabet());
533 
534  // prepare result
535  Generator* pResGen = &rResGen;
536  if(&rResGen== &rGen1 || &rResGen== &rGen2) {
537  pResGen= rResGen.New();
538  }
539 
540  // make product composition of inputs
541  Product(rGen1,rGen2,*pResGen);
542 
543  // copy all attributes of input alphabets
544  if(careattr) {
545  pResGen->EventAttributes(rGen1.Alphabet());
546  pResGen->EventAttributes(rGen2.Alphabet());
547  }
548 
549  // copy result
550  if(pResGen != &rResGen) {
551  pResGen->Move(rResGen);
552  delete pResGen;
553  }
554 
555 }
556 
557 
558 // aProduct(rGen1, rGen2, rCompositionMap, res)
559 void aProduct(
560  const Generator& rGen1,
561  const Generator& rGen2,
562  ProductCompositionMap& rCompositionMap,
563  Generator& rResGen)
564 {
565  // inputs have to agree on attributes of shared events:
566  bool careattr=rGen1.Alphabet().EqualAttributes(rGen2.Alphabet());
567 
568  // prepare result
569  Generator* pResGen = &rResGen;
570  if(&rResGen== &rGen1 || &rResGen== &rGen2) {
571  pResGen= rResGen.New();
572  }
573 
574  // make product composition of inputs
575  Product(rGen1,rGen2,rCompositionMap.StlMap(),*pResGen);
576 
577  // copy all attributes of input alphabets
578  if(careattr) {
579  pResGen->EventAttributes(rGen1.Alphabet());
580  pResGen->EventAttributes(rGen2.Alphabet());
581  }
582 
583  // copy result
584  if(pResGen != &rResGen) {
585  pResGen->Move(rResGen);
586  delete pResGen;
587  }
588 
589 }
590 
591 // Product(rGen1, rGen2, rCompositionMap, mark1, mark2, res)
592 void Product(
593  const Generator& rGen1, const Generator& rGen2,
594  std::map< std::pair<Idx,Idx>, Idx>& rCompositionMap,
595  StateSet& rMark1,
596  StateSet& rMark2,
597  Generator& rResGen)
598 {
599 
600  // do the composition
601  Product(rGen1,rGen2,rCompositionMap,rResGen);
602 
603  // clear marking
604  rMark1.Clear();
605  rMark2.Clear();
606 
607  // retrieve marking from reverse composition map
608  std::map< std::pair<Idx,Idx>, Idx>::iterator rit;
609  for(rit=rCompositionMap.begin(); rit!=rCompositionMap.end(); ++rit){
610  if(rGen1.ExistsMarkedState(rit->first.first)) rMark1.Insert(rit->second);
611  if(rGen2.ExistsMarkedState(rit->first.second)) rMark2.Insert(rit->second);
612  }
613 }
614 
615 
616 // Product(rGen1, rGen2, rCompositionMap, res)
617 void Product(
618  const Generator& rGen1, const Generator& rGen2,
619  std::map< std::pair<Idx,Idx>, Idx>& rCompositionMap,
620  Generator& rResGen)
621 {
622  FD_DF("Product(" << rGen1.Name() << "," << rGen2.Name() << ")");
623  FD_DF("Product(): state counts " << rGen1.Size() << "/" << rGen2.Size());
624 
625  // prepare result
626  Generator* pResGen = &rResGen;
627  if(&rResGen== &rGen1 || &rResGen== &rGen2) {
628  pResGen= rResGen.New();
629  }
630  pResGen->Clear();
631  rCompositionMap.clear();
632 
633  // shared alphabet
634  pResGen->InjectAlphabet(rGen1.Alphabet() * rGen2.Alphabet());
635  FD_DF("Product: shared alphabet: "
636  << (rGen1.Alphabet() * rGen2.Alphabet()).ToString());
637 
638  // todo stack
639  std::stack< std::pair<Idx,Idx> > todo;
640  // current pair, new pair
641  std::pair<Idx,Idx> currentstates, newstates;
642  // state
643  Idx tmpstate;
644 
645  StateSet::Iterator lit1, lit2;
646  TransSet::Iterator tit1, tit1_end, tit2, tit2_end, tit2_begin;
647  std::map< std::pair<Idx,Idx>, Idx>::iterator rcit;
648 
649  // push all combinations of initial states on todo stack
650  FD_DF("Product: adding all combinations of initial states to todo:");
651  for (lit1 = rGen1.InitStatesBegin();
652  lit1 != rGen1.InitStatesEnd(); ++lit1) {
653  for (lit2 = rGen2.InitStatesBegin();
654  lit2 != rGen2.InitStatesEnd(); ++lit2) {
655  currentstates = std::make_pair(*lit1, *lit2);
656  todo.push(currentstates);
657  rCompositionMap[currentstates] = pResGen->InsInitState();
658  FD_DF("Product: (" << *lit1 << "|" << *lit2 << ") -> "
659  << rCompositionMap[currentstates]);
660  }
661  }
662 
663  // start algorithm
664  FD_DF("Product: processing reachable states:");
665  while (! todo.empty()) {
666  // allow for user interrupt
667  // LoopCallback();
668  // allow for user interrupt, incl progress report
669  FD_WPC(rCompositionMap.size(),rCompositionMap.size()+todo.size(),"Product(): processing");
670  // get next reachable state from todo stack
671  currentstates = todo.top();
672  todo.pop();
673  FD_DF("Product: processing (" << currentstates.first << "|"
674  << currentstates.second << ") -> " << rCompositionMap[currentstates]);
675  // iterate over all rGen1 and rGen2 transitions
676  tit1 = rGen1.TransRelBegin(currentstates.first);
677  tit1_end = rGen1.TransRelEnd(currentstates.first);
678  tit2 = rGen2.TransRelBegin(currentstates.second);
679  tit2_end = rGen2.TransRelEnd(currentstates.second);
680  while((tit1 != tit1_end) && (tit2 != tit2_end)) {
681  // sync event by tit1
682  if(tit1->Ev < tit2->Ev) {
683  ++tit1;
684  continue;
685  }
686  // sync event by tit2
687  if(tit1->Ev > tit2->Ev) {
688  ++tit2;
689  continue;
690  }
691  // shared event: iterate tit2
692  tit2_begin = tit2;
693  while(tit2 != tit2_end) {
694  // break iteration
695  if(tit1->Ev != tit2->Ev) break;
696  // successor composition state
697  newstates = std::make_pair(tit1->X2, tit2->X2);
698  // add to todo list if composition state is new
699  rcit = rCompositionMap.find(newstates);
700  if(rcit == rCompositionMap.end()) {
701  todo.push(newstates);
702  tmpstate = pResGen->InsState();
703  rCompositionMap[newstates] = tmpstate;
704  //if(tmpstate%1000==0)
705  FD_DF("Product: todo push: (" << newstates.first << "|"
706  << newstates.second << ") -> " << rCompositionMap[newstates] << " todo #" << todo.size());
707  } else {
708  tmpstate = rcit->second;
709  }
710  // set transition in result
711  pResGen->SetTransition(rCompositionMap[currentstates], tit1->Ev, tmpstate);
712  FD_DF("Product: add transition to new generator: "
713  << rCompositionMap[currentstates] << "-" << tit1->Ev << "-" << tmpstate);
714  ++tit2;
715  }
716  // increment tit1
717  ++tit1;
718  // reset tit2 (needed for non-deterministic case)
719  if(tit1 != tit1_end)
720  if(tit1->Ev == tit2_begin->Ev)
721  tit2=tit2_begin;
722  }
723  } // todo
724 
725 
726  // set marked states (tmoor 2024: reorganised for performance)
727  rcit=rCompositionMap.begin();
728  while(rcit!=rCompositionMap.end()) {
729  if(rGen1.ExistsMarkedState(rcit->first.first))
730  if(rGen2.ExistsMarkedState(rcit->first.second))
731  pResGen->SetMarkedState(rcit->second);
732  ++rcit;
733  }
734  FD_DF("Parallel: marked states: " << pResGen->MarkedStatesToString());
735 
736  // copy result (TODO: use move)
737  if(pResGen != &rResGen) {
738  rResGen = *pResGen;
739  delete pResGen;
740  }
741  // set statenames
742  if(rGen1.StateNamesEnabled() && rGen2.StateNamesEnabled() && rResGen.StateNamesEnabled())
743  SetComposedStateNames(rGen1, rGen2, rCompositionMap, rResGen);
744  else
745  rResGen.ClearStateNames();
746 
747  FD_DF("Product(...): done");
748 }
749 
750 
751 
752 // SetParallelStateNames
754  const Generator& rGen1, const Generator& rGen2,
755  const std::map< std::pair<Idx,Idx>, Idx>& rCompositionMap,
756  Generator& rGen12)
757 {
758  std::map< std::pair<Idx,Idx>, Idx>::const_iterator rcit;
759  for(rcit=rCompositionMap.begin(); rcit!=rCompositionMap.end(); rcit++) {
760  Idx x1=rcit->first.first;
761  Idx x2=rcit->first.second;
762  Idx x12=rcit->second;
763  if(!rGen12.ExistsState(x12)) continue;
764  std::string name1= rGen1.StateName(x1);
765  if(name1=="") name1=ToStringInteger(x1);
766  std::string name2= rGen2.StateName(x2);
767  if(name2=="") name2=ToStringInteger(x2);
768  std::string name12= name1 + "|" + name2;
769  name12=rGen12.UniqueStateName(name12);
770  rGen12.StateName(x12,name12);
771  }
772 }
773 
774 
775 // CompositionMap1
777  const std::map< std::pair<Idx,Idx>, Idx>& rCompositionMap,
778  std::map<Idx,Idx>& rCompositionMap1)
779 {
780  rCompositionMap1.clear();
781  std::map< std::pair<Idx,Idx>, Idx>::const_iterator rcit;
782  for(rcit=rCompositionMap.begin(); rcit!=rCompositionMap.end(); rcit++)
783  rCompositionMap1.insert(std::pair<Idx,Idx>(rcit->second,rcit->first.first));
784 }
785 
786 
787 // CompositionMap2
789  const std::map< std::pair<Idx,Idx>, Idx>& rCompositionMap,
790  std::map<Idx,Idx>& rCompositionMap2)
791 {
792  rCompositionMap2.clear();
793  std::map< std::pair<Idx,Idx>, Idx>::const_iterator rcit;
794  for(rcit=rCompositionMap.begin(); rcit!=rCompositionMap.end(); rcit++)
795  rCompositionMap2.insert(std::pair<Idx,Idx>(rcit->second,rcit->first.second));
796 }
797 
798 
799 /**
800  * Rti wrapper class implementation
801  */
802 
803 // std faudes type
804 FAUDES_TYPE_IMPLEMENTATION(ProductCompositionMap,ProductCompositionMap,Type)
805 
806 // construct
808  mCompiled=true;
809 }
810 
811 // construct
813  DoAssign(rOther);
814 }
815 
816 // destruct
818 }
819 
820 // clear
822  mCompositionMap.clear();
823  mCompiled=true;
824  mArg1Map.clear();
825  mArg2Map.clear();
826 }
827 
828 // assignment
831  mCompiled=rSrc.mCompiled;
832  mArg1Map=rSrc.mArg1Map;
833  mArg2Map=rSrc.mArg2Map;
834 }
835 
836 // equality
838  return mCompositionMap==rOther.mCompositionMap;
839 }
840 
841 // C++/STL access
842 const std::map< std::pair<Idx,Idx> , Idx >& ProductCompositionMap::StlMap(void) const {
843  return mCompositionMap;
844 }
845 
846 // C++/STL access
847 std::map< std::pair<Idx,Idx> , Idx >& ProductCompositionMap::StlMap(void) {
848  mCompiled=false;
849  return mCompositionMap;
850 }
851 
852 // C++/STL access
853 void ProductCompositionMap::StlMap(const std::map< std::pair<Idx,Idx> , Idx >& rMap) {
854  mCompositionMap=rMap;
855  mCompiled=false;
856 }
857 
858 // access
860  std::pair<Idx,Idx> x12(x1,x2);
861  std::map< std::pair<Idx,Idx> , Idx >::const_iterator x12it=mCompositionMap.find(x12);
862  if(x12it==mCompositionMap.end()) return 0;
863  return x12it->second;
864 }
865 
866 // access
868  if(!mCompiled) {
869  mArg1Map.clear();
870  mArg2Map.clear();
871  std::map< std::pair<Idx,Idx>, Idx>::const_iterator rcit;
872  for(rcit=mCompositionMap.begin(); rcit!=mCompositionMap.end(); rcit++) {
873  mArg1Map.insert(std::pair<Idx,Idx>(rcit->second,rcit->first.first));
874  mArg2Map.insert(std::pair<Idx,Idx>(rcit->second,rcit->first.second));
875  }
876  mCompiled=true;
877  }
878  std::map< Idx , Idx >::const_iterator x1it=mArg1Map.find(x1);
879  if(x1it==mArg1Map.end()) return 0;
880  return x1it->second;
881 }
882 
883 // access
885  if(!mCompiled) {
886  mArg1Map.clear();
887  mArg2Map.clear();
888  std::map< std::pair<Idx,Idx>, Idx>::const_iterator rcit;
889  for(rcit=mCompositionMap.begin(); rcit!=mCompositionMap.end(); rcit++) {
890  mArg1Map.insert(std::pair<Idx,Idx>(rcit->second,rcit->first.first));
891  mArg2Map.insert(std::pair<Idx,Idx>(rcit->second,rcit->first.second));
892  }
893  mCompiled=true;
894  }
895  std::map< Idx , Idx >::const_iterator x2it=mArg2Map.find(x2);
896  if(x2it==mArg2Map.end()) return 0;
897  return x2it->second;
898 }
899 
900 
901 
902 } // name space
#define FD_WPC(cntnow, contdone, message)
#define FD_DF(message)
#define FAUDES_TYPE_IMPLEMENTATION(ftype, ctype, cbase)
Definition: cfl_types.h:959
const std::string & Name(void) const
Definition: cfl_types.cpp:422
bool Exists(const Idx &rIndex) const
bool DoEqual(const ProductCompositionMap &rOther) const
Idx Arg1State(Idx s12) const
std::map< Idx, Idx > mArg2Map
Definition: cfl_parallel.h:73
std::map< Idx, Idx > mArg1Map
Definition: cfl_parallel.h:72
void DoAssign(const ProductCompositionMap &rSrc)
const std::map< std::pair< Idx, Idx >, Idx > & StlMap(void) const
Idx CompState(Idx s1, Idx s2) const
Idx Arg2State(Idx s12) const
std::map< std::pair< Idx, Idx >, Idx > mCompositionMap
Definition: cfl_parallel.h:69
std::vector< int >::size_type Position
virtual const T & At(const Position &pos) const
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
Definition: cfl_transset.h:273
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
Definition: cfl_types.cpp:175
Idx Size(void) const
StateSet::Iterator StatesBegin(void) const
StateSet::Iterator InitStatesBegin(void) const
const TransSet & TransRel(void) const
bool SetTransition(Idx x1, Idx ev, Idx x2)
const EventSet & Alphabet(void) const
virtual void Move(vGenerator &rGen)
std::string MarkedStatesToString(void) const
TransSet::Iterator TransRelBegin(void) const
EventSet::Iterator AlphabetBegin(void) const
virtual vGenerator * New(void) const
void ClearStateNames(void)
bool ExistsState(Idx index) const
std::string StateName(Idx index) const
StateSet::Iterator StatesEnd(void) const
TransSet::Iterator TransRelEnd(void) const
void SetMarkedState(Idx index)
virtual void EventAttributes(const EventSet &rEventSet)
bool StateNamesEnabled(void) const
bool InsEvent(Idx index)
StateSet::Iterator InitStatesEnd(void) const
EventSet::Iterator AlphabetEnd(void) const
StateSet CoaccessibleSet(void) const
Idx Size(void) const
virtual void Clear(void)
bool ExistsMarkedState(Idx index) const
std::string AlphabetToString(void) const
std::string UniqueStateName(const std::string &rName) const
void InjectAlphabet(const EventSet &rNewalphabet)
bool Exists(const T &rElem) const
Definition: cfl_baseset.h:2180
virtual void Clear(void)
Definition: cfl_baseset.h:1962
bool EqualAttributes(const TBaseSet &rOtherSet) const
Definition: cfl_baseset.h:2261
Idx Size(void) const
Definition: cfl_baseset.h:1782
void Product(const Generator &rGen1, const Generator &rGen2, Generator &rResGen)
void aParallel(const Generator &rGen1, const Generator &rGen2, Generator &rResGen)
void aProduct(const Generator &rGen1, const Generator &rGen2, Generator &rResGen)
void Parallel(const Generator &rGen1, const Generator &rGen2, Generator &rResGen)
uint32_t Idx
void SetComposedStateNames(const Generator &rGen1, const Generator &rGen2, const std::map< std::pair< Idx, Idx >, Idx > &rCompositionMap, Generator &rGen12)
void RemoveNonCoaccessibleOut(Generator &g)
void CompositionMap1(const std::map< std::pair< Idx, Idx >, Idx > &rCompositionMap, std::map< Idx, Idx > &rCompositionMap1)
void ParallelLive(const GeneratorVector &rGenVec, Generator &rResGen)
std::string ToStringInteger(Int number)
Definition: cfl_utils.cpp:43
void CompositionMap2(const std::map< std::pair< Idx, Idx >, Idx > &rCompositionMap, std::map< Idx, Idx > &rCompositionMap2)
std::string CollapsString(const std::string &rString, unsigned int len)
Definition: cfl_utils.cpp:91

libFAUDES 2.33h --- 2025.06.18 --- c++ api documentaion by doxygen