syn_synthequiv.cpp
Go to the documentation of this file.
1 /** @file syn_synthequiv.cpp Synthesis-observation equivalence **/
2 
3 /* FAU Discrete Event Systems Library (libfaudes)
4 
5  Copyright (C) 2015 Hao Zhou, Thomas Moor
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 "syn_synthequiv.h"
24 
25 /*
26 Notes:
27 
28 This file is extracted from "libzhou.h" and "libzhou.cpp",
29 originally written by Hao Zhou in course of his Master Thesis.
30 The merge is meant to minimise the public interface and to decouple
31 side effects of further development of libFAUDES.
32 
33 */
34 
35 // pragmatic coding ... ok its not a header
36 using namespace std;
37 
38 namespace faudes {
39 
40 /*
41 ****************************************************************
42 ****************************************************************
43 PART 1: Partition
44 ****************************************************************
45 ****************************************************************
46 */
47 
48 struct Pnode {
49 
50  /** unique partition index */
51  Idx index;
52 
53  /** Associated set of states */
54  std::set<Idx> states;
55 
56  /** number of states in this coset */
57  Idx nsize;
58 
59 };
60 
61 /*
62 ****************************************************************
63 ****************************************************************
64 PART 2: SOE
65 
66 The class SOE is used to compute the coarsest synthesis-observation-equivalence
67 relation and to maintain relevant data structures required for the particular implementation.
68 
69 ****************************************************************
70 ****************************************************************
71 */
72 
73 class SOE {
74 
75 public:
76 
77  /**
78  * Contructor:
79  * keep a reference to the generator and initialize the partition and the W-Tree
80  * to represent the universal equivalence relation, i.e. every two states are equivalent.
81  *
82  * @param rGenOrig
83  * Original generator
84  * @param rConAlph
85  * controllable events
86  * @param rLocAlph
87  * local events
88  */
89  SOE(const Generator& rGenOrig, const EventSet& rConAlph, const EventSet& rLocAlph);
90 
91  /**
92  * Destructor
93  */
94  ~SOE(void);
95 
96  /**
97  * Perform fixpoint iteration to obtain the coarset synthesis-observation-equivalence
98  */
99  void refine(void);
100 
101  /**
102  * Extract output generator that represents the resulting quotient automaton.
103  * (need to invoke refine() befor)
104  *
105  * @param rMapStateToPartition
106  * Maps each state to its equivalence class
107  * @param rGenPart
108  * Generator representing the result of the computation.
109  * Each state corresponds to an euivalence class
110  */
111  void partition(std::map<Idx,Idx>& rMapStateToPartition, Generator& rGenPart);
112 
113 private:
114 
115  /**
116  * internal representation of transition relation with consecutive indexed states and events
117  */
118  struct State {
119  /** Part 1 */
121  vector< vector<Idx> > suc; // only for Initialization
122  vector< vector<Idx> > pre; // only for Initialization
123 
124  /** Part 2 (only via an transition) */
125  vector< vector<Idx> > shaconPre; // precessors with a shared controllable event
126  vector< vector<Idx> > shauncPre; // precessors with a shared uncontrollable event
127  vector<Idx> locconPre; // precessors with a local controllable event
128  vector<Idx> locuncPre; // precessors with a local uncontrollable event
129 
130  /** Part 3: */
131  // the primal precessors which continuously via local uncontrollable events to this state
132  vector<Idx> locuncPres;
133 
134  // the precessors which firstly via a shared uncontrollable event and then
135  // continuously via local uncontrollable events to this state
136  vector< vector<Idx> > shauncPres;
137  };
138 
139  /**
140  * a relation according to SOE in one block
141  */
142  struct Relation {
143  Idx ev; // Event
144  std::set<Idx> pre; // Precessors
145  };
146 
147  /**
148  * vector of all states [starting with 1]
149  */
150  std::vector<State> states;
151 
152  /**
153  * vector of all events [starting with 1]
154  */
155  std::vector<Idx> events;
156 
157  /**
158  * keep a reference to automaton
159  */
160  const Generator* gen;
161 
162  /**
163  * vorious eventsets of interest
164  */
165  std::set<Idx> uncalph; // uncontrollable events
166  std::set<Idx> conalph; // controllable events
167  std::set<Idx> localph; // local events
168  std::set<Idx> shaalph; // shared events
169 
170  std::set<Idx> locuncalph; // local uncontrollable events
171  std::set<Idx> locconalph; // local controllable events
172  std::set<Idx> shauncalph; // shared uncontrollable events
173  std::set<Idx> shaconalph; // shared controllable events
174 
175  /**
176  * Counter to assign a unique index to each node [debugging/cosmetic only]
177  */
179 
180  /**
181  * W-tree contains all blocks ever created [required for destruction]
182  */
183  std::vector<Pnode*> W;
184 
185  /**
186  * set of nodes that form current partition, i.e. leaves of W.
187  */
188  std::set<Pnode*> ro;
189 
190  /**
191  * set of nodes that can possibly split classes in ro
192  */
193  std::set<Pnode*> roDividers;
194 
195  /**
196  * construct 2st Part of Struct "State"
197  */
198  void initStateMember_Pre();
199 
200  /**
201  * construct 3st Part of Struct "State"
202  */
203  void initStateMember_Pres();
204 
205  /**
206  * insert new node in W-tree with empty stateset
207  */
208  Pnode* newnode();
209 
210  /**
211  * refine current partition with respect to coset B
212  *
213  * @param B
214  * coset
215  */
216  void partitionClass(Pnode& B);
217 
218  /**
219  * construct all relations with respect to coset B
220  *
221  * @param B
222  * coset
223  * @param relations
224  * vector of all relations
225  */
226  void computeRel(Pnode& B, std::vector<Relation>& relations);
227 
228  /**
229  * collect all states from coset B which are equivalent to the speicified state
230  * and determine the related nodes which is possibly to be splitted
231  *
232  * @param B
233  * coset
234  * @param rel
235  * a specified relation
236  * @param tb
237  * all equivalent states with respect to rel
238  * @param todo
239  * all related nodes which is possibly to be splitted
240  */
241  void computeEquStates(Pnode& B, Relation& rel, std::set<Idx>& tb, std::stack<Pnode*>& todo);
242 
243  /**
244  * implementation part for function "computeEquStates"
245  * it is organized as follows with respect to various cases:
246  */
247  void relCase_1(Pnode& B, Relation& rel, set<Idx>& tb, stack<Pnode*>& todo);
248  void relCase_2(Pnode& B, Relation& rel, set<Idx>& tb, stack<Pnode*>& todo);
249  void relCase_3(Pnode& B, Relation& rel, set<Idx>& tb, stack<Pnode*>& todo);
250  void relCase_4(Pnode& B, Relation& rel, set<Idx>& tb, stack<Pnode*>& todo);
251 
252 };
253 
254 
255 // maintain W-tree: new node
256 Pnode* SOE::newnode(void)
257 {
258  Pnode* nn= new Pnode();
259  nn->nsize=0;
260  nn->index=nxidx;
261  nxidx++;
262  W.push_back(nn);
263  return nn;
264 }
265 
266 
267 // destruct
268 SOE::~SOE(void)
269 {
270  std::vector<Pnode*>::iterator wit=W.begin();
271  for(; wit!=W.end(); ++wit) delete *wit;
272 }
273 
274 
275 // Constructor SOE(rGenOrig, rConAlph, rLocAlph)
276 SOE::SOE(const Generator& rGenOrig, const EventSet& rConAlph, const EventSet& rLocAlph)
277 {
278  gen = &rGenOrig;
279  nxidx=1;
280 
281  // encode transition relation [effectively buffer log-n search]
282  std::map<Idx,Idx> smap;
283  std::map<Idx,Idx> emap;
284  Idx max=0;
285 
286  events.resize(gen->Alphabet().Size()+1);
287  EventSet::Iterator eit=gen->AlphabetBegin();
288  for(; eit != gen->AlphabetEnd(); ++eit) {
289  emap[*eit]=++max;
290  events[max]=*eit;
291  }
292 
293  max=0;
294  states.resize(gen->States().Size()+1);
295  StateSet::Iterator sit=gen->StatesBegin();
296  for(; sit != gen->StatesEnd(); ++sit) {
297  smap[*sit]=++max;
298  states[max].idx=*sit;
299  states[max].pre.resize(events.size());
300  states[max].suc.resize(events.size());
301  states[max].shaconPre.resize(events.size());
302  states[max].shauncPre.resize(events.size());
303  states[max].shauncPres.resize(events.size());
304  }
305 
306  TransSet::Iterator tit=gen->TransRelBegin();
307  for(; tit != gen->TransRelEnd(); ++tit) {
308  states[smap[tit->X2]].pre[emap[tit->Ev]].push_back(smap[tit->X1]);
309  states[smap[tit->X1]].suc[emap[tit->Ev]].push_back(smap[tit->X2]);
310  }
311 
312  // construct various alphabets
313  eit=rConAlph.Begin();
314  for(; eit != rConAlph.End(); ++eit) conalph.insert(emap[*eit]); // controllable
315  eit=rLocAlph.Begin();
316  for(; eit != rLocAlph.End(); ++eit) localph.insert(emap[*eit]); // local
317  Idx ev=1;
318  for(; ev < events.size(); ++ev)
319  if(conalph.find(ev) == conalph.end()) uncalph.insert(ev); // uncontrollable
320  ev=1;
321  for(; ev < events.size(); ++ev)
322  if(localph.find(ev) == localph.end()) shaalph.insert(ev); // shared
323 
324  std::set_intersection(localph.begin(), localph.end(), uncalph.begin(), uncalph.end(),
325  std::inserter(locuncalph, locuncalph.begin())); // locunc
326  std::set_intersection(localph.begin(), localph.end(), conalph.begin(), conalph.end(),
327  std::inserter(locconalph, locconalph.begin())); // loccon
328  std::set_intersection(shaalph.begin(), shaalph.end(), uncalph.begin(), uncalph.end(),
329  std::inserter(shauncalph, shauncalph.begin())); // shaunc
330  std::set_intersection(shaalph.begin(), shaalph.end(), conalph.begin(), conalph.end(),
331  std::inserter(shaconalph, shaconalph.begin())); // shacon
332 
333  // for Pre and Pres
334  initStateMember_Pre();
335  initStateMember_Pres();
336 
337  // create universal partition holding the complete state set
338  Pnode* universe = newnode();
339  Idx st=1;
340  for(;st<states.size();++st) universe->states.insert(st);
341  universe->nsize = universe->states.size();
342 
343  ro.insert(universe);
344  roDividers.insert(universe);
345 
346 }
347 
348 // continue to add other member in State
349 void SOE::initStateMember_Pre()
350 {
351  // helpers
352  std::set<Idx>::iterator sit;
353  std::vector<Idx>::iterator vit;
354 
355  // construct State.shaconPre
356  sit=shaconalph.begin();
357  for(; sit!=shaconalph.end(); ++sit) {
358  Idx idx=1;
359  for(; idx < states.size(); ++idx) {
360  vit=states[idx].pre[*sit].begin();
361  for(;vit!=states[idx].pre[*sit].end();++vit)
362  states[idx].shaconPre[*sit].push_back(*vit);
363  }
364  }
365 
366  // construct State.shauncPre
367  sit=shauncalph.begin();
368  for(;sit!=shauncalph.end();++sit) {
369  Idx idx=1;
370  for(;idx<states.size();++idx) {
371  vit=states[idx].pre[*sit].begin();
372  for(;vit!=states[idx].pre[*sit].end();++vit)
373  states[idx].shauncPre[*sit].push_back(*vit);
374  }
375  }
376 
377  // construct State.locconPre
378  sit=locconalph.begin();
379  for(;sit!=locconalph.end();++sit) {
380  Idx idx=1;
381  for(;idx<states.size();++idx) {
382  vit=states[idx].pre[*sit].begin();
383  for(;vit!=states[idx].pre[*sit].end();++vit)
384  states[idx].locconPre.push_back(*vit);
385  }
386  }
387 
388  // construct State.locuncPre
389  sit=locuncalph.begin();
390  for(;sit!=locuncalph.end();++sit) {
391  Idx idx=1;
392  for(;idx<states.size();++idx) {
393  vit=states[idx].pre[*sit].begin();
394  for(;vit!=states[idx].pre[*sit].end();++vit)
395  states[idx].locuncPre.push_back(*vit);
396  }
397  }
398 
399 }
400 
401 void SOE::initStateMember_Pres()
402 {
403  // helpers
404  std::stack<Idx> todo;
405  std::vector<Idx>::iterator vit;
406  std::vector<Idx>::iterator Ivit;
407 
408  // construct locuncPres
409  Idx idx=1;
410  for(;idx<states.size();++idx) {
411  vit=states[idx].locuncPre.begin();
412  for(;vit!=states[idx].locuncPre.end();++vit) {
413  todo.push(*vit);
414  while(!todo.empty()) {
415  Idx st=todo.top();
416  todo.pop();
417  if(std::find(states[idx].locuncPres.begin(),states[idx].locuncPres.end(),st)
418  !=states[idx].locuncPres.end()) continue;
419  states[idx].locuncPres.push_back(st);
420  Ivit=states[st].locuncPre.begin();
421  for(;Ivit!=states[st].locuncPre.end();++Ivit)
422  todo.push(*Ivit);
423  }
424  }
425  }
426 
427  std::set<Idx> tempset;
428  std::set<Idx>::iterator sit;
429  std::vector<Idx>::iterator IIvit;
430 
431  // construct shauncPres ( without near, i.e. without shauncPre )
432  sit=shauncalph.begin();
433  for(;sit!=shauncalph.end();++sit) {
434  Idx idx=1;
435  for(;idx<states.size();++idx) {
436  vit=states[idx].locuncPre.begin();
437  for(;vit!=states[idx].locuncPre.end();++vit) {
438  todo.push(*vit);
439  while(!todo.empty()){
440  Idx st=todo.top();
441  todo.pop();
442  if(tempset.find(st)!=tempset.end()) continue;
443  tempset.insert(st);
444  Ivit=states[st].locuncPre.begin();
445  for(;Ivit!=states[st].locuncPre.end();++Ivit)
446  todo.push(*vit);
447  IIvit=states[st].shauncPre[*sit].begin();
448  for(;IIvit!=states[st].shauncPre[*sit].end();++IIvit)
449  states[st].shauncPres[*sit].push_back(*IIvit);
450  }
451  }
452  }
453  }
454 
455 }
456 // SOE::partitionClass(B)
457 void SOE::partitionClass(Pnode& B)
458 {
459 
460  // helpers
461  vector<Relation> relations;
462  std::stack<Pnode*> todo; // the related node in a particular relation
463  std::vector<Pnode*> addSet;
464  std::vector<Pnode*> removeSet;
465  // iterators
466  vector<Relation>::iterator relIt;
467  std::vector<Pnode*>::iterator addIt;
468  std::vector<Pnode*>::iterator remIt;
469 
470  // collect all relations for this block
471  computeRel(B, relations); // *extra funktion:1
472 
473  // loop over every relation
474  relIt=relations.begin();
475  for(; relIt!=relations.end(); ++relIt) {
476  //std::cout<<" now coming to one relation"<<std::endl;
477  // compute all equivalent states for the relation
478  std::set<Idx> tb;
479  computeEquStates(B, *relIt, tb, todo); // *extra funktion:2
480  //std::cout<<" todo is empty ->"<<(true==todo.empty()?"yes":"no")<<std::endl;
481 
482  // iteration over all cosets on todo-stack
483  while(!todo.empty()) {
484  Pnode* rop=todo.top();
485  todo.pop();
486 
487  // skip Nr.1: singletons
488  if(rop->nsize==1) continue;
489  // skip Nr.2: if it is the last node (repeated), then now is empty
490  if(rop->states.empty()) continue;
491 
492  // compute intersection of relstates with current candidate coset
493  std::set<Idx> sXinter;
494  std::set_intersection(rop->states.begin(), rop->states.end(),
495  tb.begin(), tb.end(),
496  std::inserter(sXinter, sXinter.begin()));
497 
498  // skip Nr.3 : the current coset is a subset of relstates
499  if(sXinter.size()==rop->states.size()) continue;
500 
501  // delete from ro and roDividers
502  roDividers.erase(rop);
503  removeSet.push_back(rop);
504 
505  // set up new node for intersection
506  Pnode* nXinter= newnode();
507  nXinter->states.swap(sXinter);
508  nXinter->nsize=sXinter.size();
509 
510  // set up new node for difference
511  Pnode* nXdiff = newnode();
512  std::set_difference(rop->states.begin(), rop->states.end(), nXinter->states.begin(),
513  nXinter->states.end(),
514  std::inserter(nXdiff->states, nXdiff->states.begin()));
515  nXdiff->nsize=nXdiff->states.size();
516 
517  // record that the new cosets have to be added to ro and roDividers
518  addSet.push_back(nXinter);
519  addSet.push_back(nXdiff);
520  roDividers.insert(nXinter);
521  roDividers.insert(nXdiff);
522 
523  // delete stateSet of split coset as the states are now stored in the child cosets
524  rop->states.clear();
525 
526  } // end loop over all related nodes with the particular relation in todo
527 
528  // delete split partitions from ro
529  for(remIt=removeSet.begin(); remIt!=removeSet.end(); ++remIt) ro.erase(*remIt);
530  removeSet.clear();
531 
532  // insert the new cosets into ro
533  for(addIt=addSet.begin(); addIt!=addSet.end(); ++addIt) ro.insert(*addIt);
534  addSet.clear();
535 
536  // if dividers has been split, then no more continue
537  if(B.states.empty()) return;
538 
539  } // end loop over all relations
540 
541  // delete coset B from roDividers
542  roDividers.erase(&B);
543 
544 }
545 
546 // computeRel(B, relations)
547 // collect complete relations in this block and save in relations
548 void SOE::computeRel(Pnode& B, std::vector<Relation>& relations)
549 {
550 
551  // helpers
552  Relation rel;
553  // iterators
554  std::set<Idx>::iterator sit; // states in node
555  std::set<Idx>::iterator evit; // event iterator
556  std::vector<Idx>::iterator vit; // pre states
557 
558  // *relation cases keep in the sequence (wichtig or a better sequence)
559 
560  // relation case 1: shared controllable
561  for(evit=shaconalph.begin(); evit!=shaconalph.end(); ++evit) {
562  // loop all states in B
563  for(sit=B.states.begin(); sit!=B.states.end(); ++sit) {
564  // collect ev and pre if possible
565  vit=states[*sit].shaconPre[*evit].begin();
566  for(;vit!=states[*sit].shaconPre[*evit].end();++vit) {
567  rel.pre.clear();
568  rel.ev=*evit;
569  rel.pre.insert(*vit);
570  relations.push_back(rel);
571  }
572  }
573  }
574 
575  // relation case 2: shared uncontrollable
576  for(evit=shauncalph.begin();evit!=shauncalph.end();++evit) {
577  rel.pre.clear();
578  rel.ev=*evit;
579  // loop all states in B
580  for(sit=B.states.begin(); sit!=B.states.end(); ++sit) {
581  //
582  vit=states[*sit].shauncPre[*evit].begin();
583  for(;vit!=states[*sit].shauncPre[*evit].end();++vit) {
584  rel.pre.insert(*vit);
585  }
586  }
587  if(!rel.pre.empty()) relations.push_back(rel);
588  }
589 
590  // relation case 3: local controllable
591  for(evit=locconalph.begin(); evit!=locconalph.end(); ++evit) {
592  // loop all states in B
593  for(sit=B.states.begin(); sit!=B.states.end(); ++sit) {
594  // collect ev and pre if possible
595  vit=states[*sit].locconPre.begin();
596  for(;vit!=states[*sit].locconPre.end();++vit) {
597  rel.pre.clear();
598  rel.ev=*evit;
599  rel.pre.insert(*vit);
600  relations.push_back(rel);
601  }
602  }
603  }
604 
605  // relation case 4: local uncontrollable
606  rel.pre.clear();
607  for(evit=locuncalph.begin();evit!=locuncalph.end();++evit) {
608  rel.ev=*evit;
609  // loop all states in B
610  for(sit=B.states.begin(); sit!=B.states.end(); ++sit) {
611  vit=states[*sit].locuncPre.begin();
612  for(;vit!=states[*sit].locuncPre.end();++vit)
613  rel.pre.insert(*vit);
614  }
615  }
616  if(!rel.pre.empty()) relations.push_back(rel);
617 
618 }
619 
620 // computeEquStates(B, rel, tb, todo)
621 // add info to "tb" and "todo"
622 void SOE::computeEquStates(Pnode& B, Relation& rel, std::set<Idx>& tb,
623  std::stack<Pnode*>& todo)
624 {
625  // select one through "rel.ev" from 4 cases
626 
627  // case 1: shared controllable event
628  if(shaconalph.find(rel.ev)!=shaconalph.end()) {
629  relCase_1(B, rel, tb, todo); return;}
630  // case 2: shared uncontrollable event
631  else if(shauncalph.find(rel.ev)!=shauncalph.end()) {
632  relCase_2(B, rel, tb, todo); return;}
633  // case 3: local controllable event
634  else if(locconalph.find(rel.ev)!=locconalph.end()) {
635  relCase_3(B, rel, tb, todo); return;}
636  // case 4: local uncontrollable event
637  else if(locuncalph.find(rel.ev)!=locuncalph.end()) {
638  relCase_4(B, rel, tb, todo); return;}
639  else
640  std::cout<<"####[SOE]this can not happen[SOE]####\n";
641 
642 }
643 
644 // case1: shared controllable
645 //relCase_1(B, rel, tb, todo)
646 void SOE::relCase_1(Pnode& B, Relation& rel, set<Idx>& tb, stack<Pnode*>& todo)
647 {
648 
649  //helpers
650  std::stack<Idx> stodo;
651  std::set<Idx>::iterator sit;
652  std::vector<Idx>::iterator vit;
653  std::set<Pnode*>::iterator roIt;
654 
655  // find the related pnode which include the states in "rel"
656  sit=rel.pre.begin();
657  for(; sit!=rel.pre.end(); ++sit) {
658  roIt=ro.begin();
659  for(; roIt!=ro.end(); ++roIt) {
660  if((*roIt)->states.find(*sit)!=(*roIt)->states.end()) {
661  todo.push(*roIt);
662  break;
663  }
664  }
665  }
666 
667  // part1: near
668  sit=B.states.begin();
669  for(;sit!=B.states.end();++sit) {
670  vit=states[*sit].shaconPre[rel.ev].begin();
671  for(;vit!=states[*sit].shaconPre[rel.ev].end();++vit)
672  stodo.push(*vit);
673  }
674 
675  // Part2: far
676  while(!stodo.empty()) {
677  Idx idx=stodo.top();
678  stodo.pop();
679  if(tb.find(idx)!=tb.end()) continue;
680  tb.insert(idx);
681  // local uncontrollable
682  vit=states[idx].locuncPre.begin();
683  for(;vit!=states[idx].locuncPre.end();++vit)
684  stodo.push(*vit);
685  // local controllable + condition
686  vit=states[idx].locconPre.begin();
687  for(;vit!=states[idx].locconPre.end();++vit)
688  if(todo.top()->states.find(*vit)!=todo.top()->states.end())
689  stodo.push(*vit);
690  }
691 
692 }
693 
694 // case2: shared uncontrollable
695 // relCase_2(B, rel, tb, todo)
696 void SOE::relCase_2(Pnode& B, Relation& rel, set<Idx>& tb, stack<Pnode*>& todo)
697 {
698 
699  //helpers
700  std::set<Idx>::iterator sit;
701  std::vector<Idx>::iterator vit;
702  std::set<Pnode*>::iterator roIt;
703 
704  // find the related pnode which include the states in "rel"
705  sit=rel.pre.begin();
706  for(; sit!=rel.pre.end(); ++sit) {
707  roIt=ro.begin();
708  for(; roIt!=ro.end(); ++roIt) {
709  if((*roIt)->states.find(*sit)!=(*roIt)->states.end()) {
710  todo.push(*roIt);
711  break;
712  }
713  }
714  }
715 
716  // part 1.1 (near)
717  tb=rel.pre;
718 
719  // part 1.2 (far)
720  sit=B.states.begin();
721  for(; sit != B.states.end(); ++sit) {
722  vit=states[*sit].shauncPres[rel.ev].begin();
723  for(; vit!=states[*sit].shauncPres[rel.ev].end(); ++vit) tb.insert(*vit);
724  }
725 
726  // part 2
727  sit=tb.begin();
728  for(; sit != tb.end(); ++sit) {
729  vit=states[*sit].locuncPres.begin();
730  for(; vit != states[*sit].locuncPres.end(); ++vit) tb.insert(*vit);
731  }
732 
733 }
734 
735 // case3: local controllable
736 //relCase_3(B, rel, tb, todo)
737 void SOE::relCase_3(Pnode& B, Relation& rel, set<Idx>& tb, stack<Pnode*>& todo)
738 {
739 
740  //helpers
741  std::stack<Idx> stodo;
742  std::set<Idx>::iterator sit;
743  std::vector<Idx>::iterator vit;
744  std::set<Pnode*>::iterator roIt;
745 
746  // find the related pnode which include the states in "rel"
747  sit=rel.pre.begin();
748  for(; sit!=rel.pre.end(); ++sit) {
749  roIt=ro.begin();
750  for(; roIt!=ro.end(); ++roIt) {
751  if((*roIt)->states.find(*sit)!=(*roIt)->states.end()) {
752  todo.push(*roIt);
753  break;
754  }
755  }
756  }
757 
758  // all states in B belongs to "tb"
759  tb=B.states;
760 
761  // Part1; near
762  sit=B.states.begin();
763  for(; sit!=B.states.end(); ++sit) {
764  vit=states[*sit].locconPre.begin();
765  for(; vit != states[*sit].locconPre.end(); ++vit)
766  stodo.push(*vit);
767  }
768 
769  // Part2: far
770  while(!stodo.empty()) {
771  Idx idx=stodo.top();
772  stodo.pop();
773  if(tb.find(idx)!=tb.end()) continue;
774  tb.insert(idx);
775  // local uncontrollable
776  vit=states[idx].locuncPre.begin();
777  for(;vit!=states[idx].locuncPre.end();++vit)
778  stodo.push(*vit);
779  // local controllable + condition
780  vit=states[idx].locconPre.begin();
781  for(;vit!=states[idx].locconPre.end();++vit)
782  if(todo.top()->states.find(*vit)!=todo.top()->states.end())
783  stodo.push(*vit);
784  }
785 
786 }
787 
788 // case 4: local uncontrollable
789 // relCase_4(B, rel, tb, todo)
790 void SOE::relCase_4(Pnode& B, Relation& rel, set<Idx>& tb, stack<Pnode*>& todo)
791 {
792 
793  // helpers
794  std::vector<Idx>::iterator vit;
795  std::set<Idx>::iterator sit;
796  std::set<Pnode*>::iterator roIt;
797 
798  // find the related pnode which include the states in "rel"
799  sit=rel.pre.begin();
800  for(; sit!=rel.pre.end(); ++sit) {
801  roIt=ro.begin();
802  for(; roIt!=ro.end(); ++roIt) {
803  if((*roIt)->states.find(*sit)!=(*roIt)->states.end()) {
804  todo.push(*roIt);
805  break;
806  }
807  }
808  }
809 
810  // part1: B himself
811  tb=B.states;
812 
813  // Part2:collect equivalent states to tb w.r.t. this case
814  sit=B.states.begin();
815  for(; sit != B.states.end(); ++sit) {
816  vit=states[*sit].locuncPres.begin();
817  for(; vit != states[*sit].locuncPres.end(); ++vit)
818  tb.insert(*vit);
819  }
820 
821 }
822 
823 // SOE::refine()
824 void SOE::refine()
825 {
826  FD_DF("SOE::refine()");
827 
828  //helpers
829  std::set<Pnode*>::iterator roDivIt;
830 
831  while(!roDividers.empty()) {
832  roDivIt=roDividers.begin();
833  partitionClass(**roDivIt);
834  }
835 }
836 
837 
838 // SOE::partition(rMapStateToPartition, rGenPart)
839 void SOE::partition(std::map<Idx,Idx>& rMapStateToPartition, Generator& rGenPart) {
840 
841  FD_DF("SOE::partition(rMapStateToPartition," << rGenPart.Name() << ")");
842 
843  // prepare result
844  rGenPart.Clear();
845  rGenPart.Name(gen->Name());
846  rMapStateToPartition.clear();
847 
848  // loop over all elements of ro and create a new state for every coset in ro (ro contains the set of equivalence classes)
849  std::set<Pnode*>::iterator cRoIt = ro.begin();
850  std::set<Pnode*>::iterator cRoItEnd = ro.end();
851  std::set<Idx>::iterator cSIt;
852  std::set<Idx>::iterator cSItEnd;
853 
854 
855  for(; cRoIt != cRoItEnd; ++cRoIt) {
856  // have a new state
857  std::ostringstream ostr;
858 
859  Idx newstate = rGenPart.InsState();
860 
861  // loop over all original states in current coset
862  cSIt=(*cRoIt)->states.begin();
863  cSItEnd=(*cRoIt)->states.end();
864  for(; cSIt != cSItEnd; ++cSIt) {
865  // retrieve source state idx
866  Idx st=states[*cSIt].idx;
867  // map every state of the original generator to its equivalence class (= state in rGenPart)
868  // by creating an entry in the map rMapStateToPartition
869  rMapStateToPartition[st] = newstate;
870  // set state names for resulting generator
871  if(rGenPart.StateNamesEnabled()) {
872  if(gen->StateName(st)!="") ostr << gen->StateName(st) << ",";
873  else ostr << st << ",";
874  }
875  // set init states
876  if(gen->ExistsInitState(st))
877  rGenPart.SetInitState(newstate);
878  // set marked states
879  if(gen->ExistsMarkedState(st))
880  rGenPart.SetMarkedState(newstate);
881  }
882 
883  // set state name
884  if(rGenPart.StateNamesEnabled()) {
885  std::string statename = ostr.str();
886  if(statename.length()>=1) statename.erase(statename.length()-1);
887  statename = "{" + statename + "}";
888  rGenPart.StateName(newstate, statename);
889  }
890  }
891 
892  // create transition relation
893  // iterate over all transitions of the original generator
894  TransSet::Iterator tIt = gen->TransRelBegin();
895  TransSet::Iterator tItEnd = gen->TransRelEnd();
896  for(; tIt != tItEnd; ++tIt) {
897  rGenPart.InsEvent(tIt->Ev);
898  rGenPart.SetTransition(rMapStateToPartition[tIt->X1], tIt->Ev,
899  rMapStateToPartition[tIt->X2]);
900  }
901 
902 
903 }
904 
905 /*
906 *********************************************
907 *********************************************
908 PART 3: application interface
909 
910 Minimal application interface based on plain functions.
911 *********************************************
912 *********************************************
913 */
914 
915 // ComputeSOE(rGenOrig, rLocAlph, rLocAlph, rMapStateToPartition, rGenPart)
916 void ComputeSynthObsEquiv(const Generator& rGenOrig,
917  const EventSet& rConAlph,
918  const EventSet& rLocAlph,
919  std::map<Idx,Idx>& rMapStateToPartition,
920  Generator& rResGen) {
921 
922  // test condition: rConAlph,rLocAlph \subseteq rGenOrig.Alphabet()
923 
924  // Construct an instance of the SOE class from rGenOrig
925  SOE soe = SOE(rGenOrig, rConAlph, rLocAlph);
926  // method to compute the SOE on rGenOrig
927  soe.refine();
928  soe.partition(rMapStateToPartition, rResGen);
929 
930 }
931 
932 } //namespace
#define FD_DF(message)
Debug: optional report on user functions.
Set of indices with symbolic names.
Definition: cfl_nameset.h:69
std::set< Idx > localph
std::vector< Pnode * > W
W-tree contains all blocks ever created [required for destruction].
void partition(std::map< Idx, Idx > &rMapStateToPartition, Generator &rGenPart)
Extract output generator that represents the resulting quotient automaton.
const Generator * gen
keep a reference to automaton
Idx nxidx
Counter to assign a unique index to each node [debugging/cosmetic only].
std::set< Idx > locuncalph
std::set< Idx > shaconalph
std::vector< Idx > events
vector of all events [starting with 1]
std::set< Idx > shaalph
std::set< Idx > shauncalph
void refine(void)
Perform fixpoint iteration to obtain the coarset synthesis-observation-equivalence.
std::set< Idx > uncalph
vorious eventsets of interest
std::set< Pnode * > ro
set of nodes that form current partition, i.e.
std::set< Idx > locconalph
std::set< Pnode * > roDividers
set of nodes that can possibly split classes in ro
std::set< Idx > conalph
std::vector< State > states
vector of all states [starting with 1]
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
Iterator on transition.
Definition: cfl_transset.h:269
Base class of all FAUDES generators.
bool SetTransition(Idx x1, Idx ev, Idx x2)
Add a transition to generator by indices.
EventSet::Iterator AlphabetBegin(void) const
Iterator to Begin() of alphabet.
void SetInitState(Idx index)
Set an existing state as initial state by index.
std::string StateName(Idx index) const
State name lookup.
void Name(const std::string &rName)
Set the generator's name.
Idx InsState(void)
Add new anonymous state to generator.
void SetMarkedState(Idx index)
Set an existing state as marked state by index.
bool StateNamesEnabled(void) const
Whether libFAUEDS functions are requested to generate state names.
bool InsEvent(Idx index)
Add an existing event to alphabet by index.
virtual void Clear(void)
Clear generator data.
Iterator End(void) const
Iterator to the end of set.
Definition: cfl_baseset.h:1896
Iterator Begin(void) const
Iterator to the begin of set.
Definition: cfl_baseset.h:1891
void ComputeSynthObsEquiv(const Generator &rGenOrig, const EventSet &rConAlph, const EventSet &rLocAlph, std::map< Idx, Idx > &rMapStateToPartition, Generator &rResGen)
Synthesis-observation equivalence.
libFAUDES resides within the namespace faudes.
uint32_t Idx
Type definition for index type (allways 32bit)
std::set< Idx > states
Associated set of states.
a relation according to SOE in one block
internal representation of transition relation with consecutive indexed states and events
vector< vector< Idx > > shauncPre
vector< vector< Idx > > shauncPres
vector< vector< Idx > > suc
vector< Idx > locuncPres
Part 3:
vector< vector< Idx > > shaconPre
Part 2 (only via an transition)
vector< Idx > locuncPre
vector< Idx > locconPre
vector< vector< Idx > > pre
Synthesis-observation equivalence.

libFAUDES 2.32b --- 2024.03.01 --- c++ api documentaion by doxygen