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/*
26Notes:
27
28This file is extracted from "libzhou.h" and "libzhou.cpp",
29originally written by Hao Zhou in course of his Master Thesis.
30The merge is meant to minimise the public interface and to decouple
31side effects of further development of libFAUDES.
32
33*/
34
35// pragmatic coding ... ok its not a header
36using namespace std;
37
38namespace faudes {
39
40/*
41****************************************************************
42****************************************************************
43PART 1: Partition
44****************************************************************
45****************************************************************
46*/
47
48struct 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****************************************************************
64PART 2: SOE
65
66The class SOE is used to compute the coarsest synthesis-observation-equivalence
67relation and to maintain relevant data structures required for the particular implementation.
68
69****************************************************************
70****************************************************************
71*/
72
73class SOE {
74
75public:
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
113private:
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 */
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 */
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
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
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)
276SOE::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
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
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
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
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)
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
548void 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"
622void 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)
646void 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)
696void 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)
737void 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)
790void 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()
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)
839void 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
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*********************************************
908PART 3: application interface
909
910Minimal application interface based on plain functions.
911*********************************************
912*********************************************
913*/
914
915// ComputeSOE(rGenOrig, rLocAlph, rLocAlph, rMapStateToPartition, rGenPart)
916void 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)
const std::string & Name(void) const
std::set< Idx > localph
std::vector< Pnode * > W
void computeEquStates(Pnode &B, Relation &rel, std::set< Idx > &tb, std::stack< Pnode * > &todo)
void partition(std::map< Idx, Idx > &rMapStateToPartition, Generator &rGenPart)
const Generator * gen
void partitionClass(Pnode &B)
void initStateMember_Pre()
std::set< Idx > locuncalph
void relCase_4(Pnode &B, Relation &rel, set< Idx > &tb, stack< Pnode * > &todo)
std::set< Idx > shaconalph
std::vector< Idx > events
std::set< Idx > shaalph
void relCase_1(Pnode &B, Relation &rel, set< Idx > &tb, stack< Pnode * > &todo)
std::set< Idx > shauncalph
void initStateMember_Pres()
void refine(void)
void relCase_3(Pnode &B, Relation &rel, set< Idx > &tb, stack< Pnode * > &todo)
Pnode * newnode()
std::set< Idx > uncalph
SOE(const Generator &rGenOrig, const EventSet &rConAlph, const EventSet &rLocAlph)
std::set< Pnode * > ro
std::set< Idx > locconalph
std::set< Pnode * > roDividers
void relCase_2(Pnode &B, Relation &rel, set< Idx > &tb, stack< Pnode * > &todo)
std::set< Idx > conalph
void computeRel(Pnode &B, std::vector< Relation > &relations)
std::vector< State > states
StateSet::Iterator StatesBegin(void) const
bool SetTransition(Idx x1, Idx ev, Idx x2)
const EventSet & Alphabet(void) const
TransSet::Iterator TransRelBegin(void) const
EventSet::Iterator AlphabetBegin(void) const
void SetInitState(Idx index)
std::string StateName(Idx index) const
StateSet::Iterator StatesEnd(void) const
TransSet::Iterator TransRelEnd(void) const
void SetMarkedState(Idx index)
bool StateNamesEnabled(void) const
bool InsEvent(Idx index)
EventSet::Iterator AlphabetEnd(void) const
bool ExistsInitState(Idx index) const
virtual void Clear(void)
bool ExistsMarkedState(Idx index) const
const StateSet & States(void) const
Iterator End(void) const
Iterator Begin(void) const
Idx Size(void) const
void ComputeSynthObsEquiv(const Generator &rGenOrig, const EventSet &rConAlph, const EventSet &rLocAlph, std::map< Idx, Idx > &rMapStateToPartition, Generator &rResGen)
uint32_t Idx
std::set< Idx > states
std::vector< Idx > states
vector< vector< Idx > > shauncPre
vector< vector< Idx > > shauncPres
vector< vector< Idx > > suc
vector< Idx > locuncPres
vector< vector< Idx > > shaconPre
vector< Idx > locuncPre
vector< Idx > locconPre
vector< vector< Idx > > pre

libFAUDES 2.33k --- 2025.09.16 --- c++ api documentaion by doxygen