op_observercomputation.cpp
Go to the documentation of this file.
1/** @file op_observercomputation.cpp
2
3Methods to compute natural projections that exhibit the obsrver property.
4The observer algorithm is elaborated in
5K. C. Wong and W. M. Wonham, "On the Computation of Observers in Discrete Event
6Systems," Discrete Event Dynamic Systems, vol. 14, no. 1, pp. 55-107, 2004.
7In addition, methods to compute natural projections that exhibit
8output control consistency (OCC) and local control consistency (LCC) are provided. See for example
9K. Schmidt and C. Breindl, "On Maximal Permissiveness of Hierarchical and Modular Supervisory
10Control Approaches for Discrete Event Systems," Workshop on Discrete Event Systems, 2008.
11Furthermore, an algorithm for computing natural observers without changing event labels as
12presented in
13Lei Feng; Wonham, W.M., "On the Computation of Natural Observers in Discrete-Event Systems,"
14Decision and Control, 2006 45th IEEE Conference on , vol., no., pp.428-433, 13-15 Dec. 2006
15is implemented.
16*/
17
18/* FAU Discrete Event Systems Library (libfaudes)
19
20 Copyright (C) 2006 Bernd Opitz
21 Exclusive copyright is granted to Klaus Schmidt
22
23 This library is free software; you can redistribute it and/or
24 modify it under the terms of the GNU Lesser General Public
25 License as published by the Free Software Foundation; either
26 version 2.1 of the License, or (at your option) any later version.
27
28 This library is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
31 Lesser General Public License for more details.
32
33 You should have received a copy of the GNU Lesser General Public
34 License along with this library; if not, write to the Free Software
35 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
36
38#include "cfl_localgen.h"
39
40using namespace std;
41
42namespace faudes{
43
44
45// calculateDynamicSystemClosedObs(rGen, rHighAlph, rGenDyn)
46void calculateDynamicSystemClosedObs(const Generator& rGen, EventSet& rHighAlph, Generator& rGenDyn)
47{
48 OP_DF("calculateDynamicSystemClosedObs(" << rGen.Name() << "," << rHighAlph.Name() << "," << rGenDyn.Name() << ")");
49 // transition relation sorted in reverse order for backwards reachability
50 TransSetX2EvX1 tset_X2EvX1;
51 rGen.TransRel(tset_X2EvX1);
52
53 // prepare generator rGenDyn
54 rGenDyn.ClearTransRel();
55 rGenDyn.InjectAlphabet(rHighAlph); // all high-level events are contained in the alphabet of rGenDyn
56 rGenDyn.InjectStates(rGen.States() ); // the dynamic system has all states of rGen
57
58 // helpers
59 EventSet::Iterator eIt = rGenDyn.AlphabetBegin();
60 EventSet::Iterator eItEnd = rGenDyn.AlphabetEnd();
61
63 TransSetX2EvX1::Iterator tItByX2EvEnd;
64 StateSet reach;
65 // map from exit states (Idx) to high-level event (Idx) and reachable entry state (Idx)
66 map<Idx,vector<pair<Idx,Idx> > > exitStateToEventState;
67 StateSet::Iterator sIt;
68 StateSet::Iterator sItEnd;
70 TransSet::Iterator tItEnd;
71 map<Idx,StateSet> entryStateToLocalReach;
72 map<Idx,vector<pair<Idx,Idx> > >::iterator esIt;
73 map<Idx,vector<pair<Idx,Idx> > >::iterator esItEnd;
74 // algorithm for computing the dynamic system
75 // loop over all states of original generator
76 StateSet::Iterator stateSetIt = rGen.StatesBegin();
77 StateSet::Iterator stateSetItEnd = rGen.StatesEnd();
78 // flag that indicates if the current state is an entry state
79 bool isEntryState = false;
80 for( ; stateSetIt != stateSetItEnd; ++stateSetIt) {
81 OP_DF("calculateDynamicSystemClosedObs: loop over all states; current state: " << rGen.StateName(*stateSetIt)
82 << " [" << *stateSetIt << "]");
83 // check if current state (*stateSetIt) is an entry-state (a backward transition with
84 // a high-level event exists. If yes, the locally reachable states (reach) are stored in
85 // the entryStateToLocalReach map
86 isEntryState = false;
87 tItByX2Ev=tset_X2EvX1.BeginByX2(*stateSetIt);
88 tItByX2EvEnd=tset_X2EvX1.EndByX2(*stateSetIt);
89 for(; tItByX2Ev != tItByX2EvEnd; ++tItByX2Ev)
90 {
91 OP_DF("calculateDynamicSystemClosedObs: checking transition : " << rGen.TStr(*tItByX2Ev));
92 if(rHighAlph.Exists(tItByX2Ev->Ev)){
93 isEntryState = true;
94 OP_DF("calculateDynamicSystemClosedObs: current state is an entry-state");
95 // insert the exit state and the high-level event with the reachable entry state into the exitStates set
96 esIt = exitStateToEventState.find(tItByX2Ev->X1);
97 if(esIt == exitStateToEventState.end() ){
98 exitStateToEventState[tItByX2Ev->X1] = vector<pair<Idx,Idx> >();
99 }
100 exitStateToEventState[tItByX2Ev->X1].push_back(make_pair(tItByX2Ev->Ev,tItByX2Ev->X2) );
101 }
102 }
103 if(isEntryState == true){
104 // compute locally reachable states for current entry state and insert it into entryStateToLocalReach
105 reach.Clear();
106 LocalAccessibleReach(rGen, rHighAlph, *stateSetIt, reach);
107 OP_DF("calculateDynamicSystemClosedObs: states in local reach: \n " << reach.ToString() );
108 entryStateToLocalReach[*stateSetIt]=reach;
109 }
110 }
111 // after this loop we have the set of exit states in exitStates and a map from entry states to their
112 // locally reachable state set entryStateToLocalReach
113
114 // create the transition structure of the dynamic system
115 esIt = exitStateToEventState.begin();
116 esItEnd = exitStateToEventState.end();
117 vector<pair <Idx,Idx> >::iterator vIt;
118 vector<pair <Idx,Idx> >::iterator vItEnd;
119 // To construct the dynamic system, each local state has to be connected to all states in
120 // the local accessible reach of entry states that can be reached via a high-level event.
121 // We compute the local backward reach of each exit state and find the corresponding entry states in
122 // the map exitStateToEventState
123 StateSet exitStateBackwardReach;
124 StateSet::Iterator brIt, brItEnd;
125 map<Idx,StateSet>::const_iterator enIt;
126 for(; esIt != esItEnd; ++esIt)
127 {
128 // compute the locally backwards reachable states
129 exitStateBackwardReach.Clear();
130 LocalCoaccessibleReach(tset_X2EvX1, rHighAlph, esIt->first, exitStateBackwardReach);
131
132 vIt = esIt->second.begin();
133 vItEnd = esIt->second.end();
134 brItEnd = exitStateBackwardReach.End();
135 // loop over all pairs (Ev,X2) of current exit state and insert transitions from all states in the
136 // backwards reach
137 for( ; vIt != vItEnd; ++vIt)
138 {
139 brIt = exitStateBackwardReach.Begin();
140 // go over all backwards reachable states
141 for( ; brIt != brItEnd; brIt++){
142 // find the set of reachable states from exit state
143 enIt = entryStateToLocalReach.find(vIt->second);
144 sIt = enIt->second.Begin();
145 sItEnd = enIt->second.End();
146 // go over all reachable states from the entry states
147 for( ; sIt != sItEnd; sIt++){
148 rGenDyn.SetTransition(*brIt,vIt->first,*sIt);
149 OP_DF("calculateDynamicSystemClosedObs: Transition added to resulting generator: " <<
150 rGenDyn.TStr(Transition(*brIt,vIt->first,*sIt)));
151 }
152 }
153 }
154 }
155 OP_DF("calculateDynamicSystemClosedObs: leaving function");
156}
157
158// calculateDynamicSystemObs(rGen, rHighAlph, rGenDyn)
159void calculateDynamicSystemObs(const Generator& rGen, EventSet& rHighAlph, Generator& rGenDyn)
160{
161 OP_DF("calculateDynamicSystemObs(" << rGen.Name() << "," << rHighAlph.Name() << "," << rGenDyn.Name() << ")");
162 // prepare generator rGenDyn
163 // locally reachable states
164 StateSet reach;
165 StateSet::Iterator stIt, stEndIt;
166 // label for transitions to marked states in the dynamic system
167 std::string eventname = ( rGenDyn.EventSymbolTablep())->UniqueSymbol("obsLabel");
168 Idx obsLabel = (rGenDyn.EventSymbolTablep())->InsEntry(eventname);
169 rGenDyn.InsEvent(obsLabel);
170 // algorithm for computing the dynamic system
171 // loop over all states of original generator
172 StateSet::Iterator stateSetIt = rGen.StatesBegin();
173 StateSet::Iterator stateSetItEnd = rGen.StatesEnd();
174 for( ; stateSetIt != stateSetItEnd; ++stateSetIt) {
175 OP_DF("calculateDynamicSystemObs: loop over all states; current state: " << rGen.StateName(*stateSetIt)
176 << " [" << *stateSetIt << "]");
177 // compute locally reachable states for current state
178 reach.Clear();
179 LocalAccessibleReach(rGen, rHighAlph, *stateSetIt, reach);
180 OP_DF("calculateDynamicSystemObs: states in local reach: \n " << reach.ToString() );
181 stIt = reach.Begin();
182 stEndIt = reach.End();
183 for( ; stIt != stEndIt; stIt++){
184 if(rGen.ExistsMarkedState(*stIt) ){
185 rGenDyn.SetTransition(*stateSetIt,obsLabel,*stIt);
186 OP_DF("calculateDynamicSystemObs: Transition added to resulting generator: " <<
187 rGenDyn.TStr(Transition(*stateSetIt,obsLabel,*stIt)));
188 }
189 }
190 }
191 OP_DF("calculateDynamicSystemObs: leaving function");
192}
193
194// calculateDynamicSystemMSA(rGen, rHighAlph, rGenDyn)
195void calculateDynamicSystemMSA(const Generator& rGen, EventSet& rHighAlph, Generator& rGenDyn)
196{
197 OP_DF("calculateDynamicSystemMSA(" << rGen.Name() << "," << rHighAlph.Name() << "," << rGenDyn.Name() << ")");
198 // transition relation sorted in reverse order for backwards reachability
199 TransSetX2EvX1 tset_X2EvX1;
200 rGen.TransRel(tset_X2EvX1);
201
202 // prepare generator rGenDyn
203 // set of states already investigated
204 StateSet doneStates, goodStates;
206 TransSet::Iterator tEndIt;
207 // label for transitions for msa-accepting states in the dynamic system
208 std::string eventname = ( rGenDyn.EventSymbolTablep())->UniqueSymbol("msaLabel");
209 Idx msaLabel = (rGenDyn.EventSymbolTablep())->InsEntry(eventname);
210 rGenDyn.InsEvent(msaLabel);
211 // algorithm for computing the dynamic system
212 // loop over all states of original generator
213 StateSet::Iterator stateSetIt = rGen.StatesBegin();
214 StateSet::Iterator stateSetItEnd = rGen.StatesEnd();
215 // flag that indicates if the current state is an entry state
216 for( ; stateSetIt != stateSetItEnd; ++stateSetIt) {
217 // if the state is known to be good (msa holds), it does not have to be considered again
218 if(goodStates.Exists(*stateSetIt) )
219 continue;
220
221 OP_DF("calculateDynamicSystemMSA: loop over all states; current state: " << rGen.StateName(*stateSetIt)
222 << " [" << *stateSetIt << "]");
223 doneStates.Clear();
224 bool msaHolds = recursiveCheckMSAForward(rGen, rHighAlph, *stateSetIt, doneStates);
225 // if all forward transitions lead to marked states, all states that have been reached are states where msa holds
226 if(msaHolds == true){
227 goodStates.InsertSet(doneStates);
228 continue;
229 }
230 doneStates.Clear();
231 msaHolds = recursiveCheckMSABackward(rGen, tset_X2EvX1, rHighAlph, *stateSetIt, doneStates);
232 // if all backward transitions lead to marked states, all states that have been reached are states where msa holds
233 if(msaHolds == true){
234 goodStates.InsertSet(doneStates);
235 continue;
236 }
237 // otherwise, msa is violated for the current state. Then, msa-transitions are introduced to all states
238 // reachable via a high-level event
239 else{
240 tIt = rGenDyn.TransRelBegin(*stateSetIt);
241 tEndIt = rGenDyn.TransRelEnd(*stateSetIt);
242 for( ; tIt != tEndIt; tIt++){
243 rGenDyn.SetTransition(*stateSetIt,msaLabel,tIt->X2);
244 OP_DF("calculateDynamicSystemObs: Transition added to resulting generator: " <<
245 rGenDyn.TStr(Transition(*stateSetIt,msaLabel,tIt->X2)));
246 }
247 }
248 }
249 OP_DF("calculateDynamicSystemMSA: leaving function");
250}
251
252bool recursiveCheckMSAForward(const Generator& rGen, const EventSet& rHighAlph, Idx currentState, StateSet& rDoneStates){
253 // if the current state is marked, no violation of MSA occurs
254 rDoneStates.Insert(currentState);
255 if(rGen.ExistsMarkedState(currentState) ){
256 return true;
257 }
258 TransSet::Iterator tIt, tEndIt;
259 tIt = rGen.TransRelBegin(currentState);
260 tEndIt = rGen.TransRelEnd(currentState);
261 for( ; tIt != tEndIt; tIt++){
262 if(rHighAlph.Exists( tIt->Ev) ){
263 return false;
264 }
265 else if(rDoneStates.Exists( tIt->X2) )
266 continue;
267 else{
268 bool msaHolds = recursiveCheckMSAForward(rGen, rHighAlph, tIt->X2, rDoneStates);
269 if(msaHolds == false)
270 return false;
271 }
272 }
273 return true;
274
275}
276
277
278bool recursiveCheckMSABackward(const Generator& rGen, const TransSetX2EvX1& rRevTransSet, const EventSet& rHighAlph, Idx currentState, StateSet& rDoneStates){
279 // if the current state is marked, no violation of MSA occurs
280 rDoneStates.Insert(currentState);
281 if(rGen.ExistsMarkedState(currentState) ){
282 return true;
283 }
284 TransSetX2EvX1::Iterator tIt, tEndIt;
285 tIt = rRevTransSet.BeginByX2(currentState);
286 tEndIt = rRevTransSet.EndByX2(currentState);
287 for( ; tIt != tEndIt; tIt++){
288 if(rHighAlph.Exists( tIt->Ev) ){
289 return false;
290 }
291 else if(rDoneStates.Exists( tIt->X1) )
292 continue;
293 else{
294 bool msaHolds = recursiveCheckMSABackward(rGen, rRevTransSet, rHighAlph, tIt->X1, rDoneStates);
295 if(msaHolds == false)
296 return false;
297 }
298 }
299 return true;
300}
301
302//calculateDynamicSystemLCC(rGen, rControllableEvents, rHighAlph, rGenDyn)
303void calculateDynamicSystemLCC(const Generator& rGen, const EventSet& rControllableEvents, const EventSet& rHighAlph, Generator& rGenDyn){
304 OP_DF("calculateDynamicSystemLCC(" << rGen.Name() << "," << rControllableEvents.Name() << "," << rHighAlph.Name() << "," << rGenDyn.Name() << ")");
305 // transition relation sorted in reverse order for backwards reachability
306 TransSetX2EvX1 tset_X2EvX1;
307 rGen.TransRel(tset_X2EvX1);
308
309 // prepare generator rGenDyn
311 TransSet::Iterator tEndIt;
312 // labels for transitions for states with uncontrollable successor strings in the dynamic system
313 // eventLCCLabel maps the original event to the LCCLabel in the dynamic system
314 EventSet::Iterator eIt, eEndIt;
315 map<Idx, Idx> eventLCCLabel;
316 eIt = rHighAlph.Begin();
317 eEndIt = rHighAlph.End();
318 for( ; eIt != eEndIt; eIt++){
319 if(!rControllableEvents.Exists(*eIt) ){
320 std::string eventname = ( rGenDyn.EventSymbolTablep())->UniqueSymbol(SymbolTable::GlobalEventSymbolTablep()->Symbol(*eIt) + "LCCLabel");
321 eventLCCLabel[*eIt] = (rGenDyn.EventSymbolTablep())->InsEntry(eventname);
322 rGenDyn.InsEvent(eventLCCLabel[*eIt] );
323 }
324 }
325 // map from exit states (Idx) to uncontrollable high-level events (Idx)
326 map<Idx,vector<Idx> > exitStateToEvents;
327 map<Idx,vector<Idx> >::const_iterator esIt, esEndIt;
328 // algorithm for computing the dynamic system
329 // loop over all states of original generator
330 StateSet::Iterator sIt = rGen.StatesBegin();
331 StateSet::Iterator sEndIt = rGen.StatesEnd();
332 for( ; sIt != sEndIt; ++sIt) {
333 OP_DF("calculateDynamicSystemLCC: loop over all states; current state: " << rGen.StateName(*sIt)
334 << " [" << *sIt << "]");
335 // check if current state (*stateSetIt) is an exit-state (a forward transition with
336 // a high-level event exists. If yes, the outgoing high-level events are stored
337 tIt = rGen.TransRelBegin(*sIt);
338 tEndIt = rGen.TransRelEnd(*sIt);
339 for(; tIt != tEndIt; ++tIt)
340 {
341 OP_DF("calculateDynamicSystemLCC: checking transition : " << rGen.TStr(*tIt));
342 // if the event is an uncontrollable high-level event, it is inserted for the current exit state
343 if(rHighAlph.Exists(tIt->Ev) && !rControllableEvents.Exists(tIt->Ev) ){
344 OP_DF("calculateDynamicSystemLCC: current state is an exit-state");
345 // insert the exit state and the high-level event into the exitStates set
346 esIt = exitStateToEvents.find(*sIt);
347 if(esIt == exitStateToEvents.end() ){
348 exitStateToEvents[*sIt] = vector<Idx>();
349 }
350 exitStateToEvents[*sIt].push_back(tIt->Ev);
351 }
352 }
353 }
354 // after this loop, we have the set of exit states with their outgoing uncontrollable high-level events.
355 // Now we compute the backwards reachable state via uncontrollable strings to determine all states where lcc holds
356 esIt = exitStateToEvents.begin();
357 esEndIt = exitStateToEvents.end();
358 vector<Idx>::const_iterator vIt, vEndIt;
359 // set of states already investigated
360 StateSet doneStates;
361 for( ; esIt != esEndIt; esIt++){
362 doneStates.Clear();
363 recursiveCheckLCC(tset_X2EvX1, rControllableEvents, rHighAlph, esIt->first, doneStates);
364 // add the uncontrollable transition labels to all states found in the backward reachability
365 // transitions are introduced to all states that are reachable via strings including one high-level event
366 vIt = esIt->second.begin();
367 vEndIt = esIt->second.end();
368 // loop over all uncontrollable high-level events in the current exit state
369 for( ; vIt != vEndIt; vIt++){
370 sIt = doneStates.Begin();
371 sEndIt = doneStates.End();
372 // loop over all backward reachable states
373 for( ; sIt != sEndIt; sIt++){
374 TransSet::Iterator dsIt, dsEndIt;
375 dsIt = rGenDyn.TransRelBegin(*sIt);
376 dsEndIt = rGenDyn.TransRelEnd(*sIt);
377 // loop over all states reachable via strings with one high-level event (these states are already encoded
378 // in rGenDyn if calculateDynamicSystemClosedObs is called before calculateDynamicSystemLCC)
379 for( ; dsIt != dsEndIt; dsIt++){
380 rGenDyn.SetTransition(*sIt, eventLCCLabel[*vIt], dsIt->X2);
381 }
382 }
383 }
384 }
385}
386
387void recursiveCheckLCC(const TransSetX2EvX1& rRevTransSet, const EventSet& rControllableEvents, const EventSet& rHighAlph, Idx currentState, StateSet& rDoneStates){
388 // insert the current state into the backward reachable states via uncontrollable strings
389 rDoneStates.Insert(currentState);
390 // helpers
391 TransSetX2EvX1::Iterator tIt, tEndIt;
392 tIt = rRevTransSet.BeginByX2(currentState);
393 tEndIt = rRevTransSet.EndByX2(currentState);
394 // loop over all outgoing transitions in the current state
395 for( ; tIt != tEndIt; tIt++){
396 // if the transition is a high-level transition, we stop the backward reachability
397 if(rHighAlph.Exists(tIt->Ev) ){
398 // if the transition is uncontrollable, an uncontrollable string has been found -> LCC is fulfilled
399 continue;
400 }
401 // if the event is an uncontrollable low-level event, we go backward along uncontrollable transitions
402 else{
403 if(!rControllableEvents.Exists(tIt->Ev) && !rDoneStates.Exists(tIt->X1) ){
404 recursiveCheckLCC(rRevTransSet,rControllableEvents,rHighAlph,tIt->X1,rDoneStates);
405 }
406 }
407 }
408 // the end of the loop is reached, if no more uncontrollable event has been found from the current state
409}
410
411
412// calcClosedObserver(rGen,rHighAlph)
413Idx calcClosedObserver(const Generator& rGen, EventSet& rHighAlph){
414 // helpers
415 Generator dynGen;
416 map<Idx,Idx> mapStateToPartition;
417 EventSet origAlph;
418 Generator genPart;
419 while(origAlph != rHighAlph){
420 origAlph = rHighAlph;
421 dynGen.Clear();
422 // compute the dynamic system for the given generator and high-level alphabet
423 calculateDynamicSystemClosedObs(rGen, rHighAlph, dynGen);
424 // compute the quasi conqruence
425 ComputeBisimulation(dynGen, mapStateToPartition, genPart);
426 // Extend the high-level alphabet according to the algorithm of Lei
427 ExtendHighAlphabet(rGen, rHighAlph, mapStateToPartition);
428 }
429 return genPart.Size();
430}
431
432// calcNaturalObserver(rGen,rHighAlph)
433Int calcNaturalObserver(const Generator& rGen, EventSet& rHighAlph){
434 // helpers
435 Generator dynGen;
436 map<Idx,Idx> mapStateToPartition;
437 EventSet origAlph;
438 Generator genPart;
439 while(origAlph != rHighAlph){
440 origAlph = rHighAlph;
441 dynGen.Clear();
442 // compute the dynamic system for the given generator and high-level alphabet
443 calculateDynamicSystemClosedObs(rGen, rHighAlph, dynGen);
444 calculateDynamicSystemObs(rGen, rHighAlph, dynGen);
445 // compute the quasi conqruence
446 ComputeBisimulation(dynGen, mapStateToPartition, genPart);
447 // Extend the high-level alphabet according to the algorithm of Lei
448 ExtendHighAlphabet(rGen, rHighAlph, mapStateToPartition);
449 }
450 return genPart.Size();
451}
452
453// calcNaturalObserverLCC(rGen,rHighAlph)
454Int calcNaturalObserverLCC(const Generator& rGen, const EventSet& rControllableEvents, EventSet& rHighAlph){
455 // helpers
456 Generator dynGen;
457 map<Idx,Idx> mapStateToPartition;
458 EventSet origAlph;
459 Generator genPart;
460 while(origAlph != rHighAlph){
461 origAlph = rHighAlph;
462 dynGen.Clear();
463 // compute the dynamic system for the given generator and high-level alphabet
464 calculateDynamicSystemClosedObs(rGen, rHighAlph, dynGen);
465 calculateDynamicSystemLCC(rGen, rControllableEvents, rHighAlph, dynGen);
466 calculateDynamicSystemObs(rGen, rHighAlph, dynGen);
467 // compute the quasi conqruence
468 ComputeBisimulation(dynGen, mapStateToPartition, genPart);
469 // Extend the high-level alphabet according to the algorithm of Lei
470 ExtendHighAlphabet(rGen, rHighAlph, mapStateToPartition);
471 }
472 return genPart.Size();
473}
474
475// calcMSAObserver(rGen,rHighAlph)
476Int calcMSAObserver(const Generator& rGen, EventSet& rHighAlph){
477 // helpers
478 Generator dynGen;
479 map<Idx,Idx> mapStateToPartition;
480 EventSet origAlph;
481 Generator genPart;
482 while(origAlph != rHighAlph){
483 origAlph = rHighAlph;
484 dynGen.Clear();
485 // compute the dynamic system for the given generator and high-level alphabet
486 calculateDynamicSystemClosedObs(rGen, rHighAlph, dynGen);
487 calculateDynamicSystemMSA(rGen, rHighAlph, dynGen);
488 // compute the quasi conqruence
489 ComputeBisimulation(dynGen, mapStateToPartition, genPart);
490 // Extend the high-level alphabet according to the algorithm of Lei
491 ExtendHighAlphabet(rGen, rHighAlph, mapStateToPartition);
492 }
493 return genPart.Size();
494}
495
496// calcMSAObserverLCC(rGen,rHighAlph)
497Int calcMSAObserverLCC(const Generator& rGen, const EventSet& rControllableEvents, EventSet& rHighAlph){
498 // helpers
499 Generator dynGen;
500 map<Idx,Idx> mapStateToPartition;
501 EventSet origAlph;
502 Generator genPart;
503 while(origAlph != rHighAlph){
504 origAlph = rHighAlph;
505 dynGen.Clear();
506 // compute the dynamic system for the given generator and high-level alphabet
507 calculateDynamicSystemClosedObs(rGen, rHighAlph, dynGen);
508 calculateDynamicSystemLCC(rGen, rControllableEvents, rHighAlph, dynGen);
509 calculateDynamicSystemMSA(rGen, rHighAlph, dynGen);
510 // compute the quasi conqruence
511 ComputeBisimulation(dynGen, mapStateToPartition, genPart);
512 // Extend the high-level alphabet according to the algorithm of Lei
513 ExtendHighAlphabet(rGen, rHighAlph, mapStateToPartition);
514 }
515 return genPart.Size();
516}
517
518
519// ExtendHighAlphabet(rGen,rHighAlph,rMapStateToPartition)
520void ExtendHighAlphabet(const Generator& rGen, EventSet& rHighAlph, map<Idx,Idx>& rMapStateToPartition){
521
522 OP_DF("relabel(" << rGen.Name() << "," << rHighAlph.Name() << ", rMapStateToPartition)");
523
524 // helpers
525 map<Idx,Idx>::const_iterator spIt, spEndIt;
526 spIt = rMapStateToPartition.begin();
527 spEndIt = rMapStateToPartition.end();
528 // Determine map from Partition to states from the rMapStateToPartition
529 map<Idx,StateSet> partitionToStateMap; // (coset,states)
530 map<Idx,StateSet>::iterator fIt, fEndIt;
531 for( ; spIt != spEndIt; spIt++){
532 fIt = partitionToStateMap.find(spIt->second);
533 if(fIt == partitionToStateMap.end() ){
534 partitionToStateMap[spIt->second] = StateSet();
535 }
536 partitionToStateMap[spIt->second].Insert(spIt->first);
537
538 }
539 // local events that lead to a different coset
540 EventSet localViolatingEvents;
541 // local events that appear inside the cosets
542 EventSet localEvents;
543 // vector for the nondeterministic exit states for each coset
544 map<Idx,vector<pair<StateSet, Idx> > > nondeterministicStates; // coset, nondet states, event)
545 StateSet::Iterator stIt, stEndIt;
546 // Go through all cosets and identify local violating events and all local events
547 fIt = partitionToStateMap.begin();
548 fEndIt = partitionToStateMap.end();
549 for( ; fIt != fEndIt; fIt++){
550 // Current Coset
551 Idx currentCoset = fIt->first;
552 // Examine all states of the current coset
553 stIt = fIt->second.Begin();
554 stEndIt = fIt->second.End();
555 // map from event to exit states and goal cosets
556 map<Idx,map<Idx,pair<StateSet,IndexSet> > > eventStatesMap; // (coset, event, exit states, goal cosets)
557
558 for( ; stIt != stEndIt; stIt++){
559 TransSet::Iterator tIt, tEndIt;
560 tIt = rGen.TransRelBegin(*stIt);
561 tEndIt = rGen.TransRelEnd(*stIt);
562 for( ; tIt != tEndIt; tIt++){
563 // local event
564 if(!rHighAlph.Exists(tIt->Ev) ){
565 // unobservable transition to other coset
566 if(rMapStateToPartition[tIt->X2] != currentCoset){
567 localViolatingEvents.Insert(tIt->Ev);
568 localEvents.Erase(tIt->Ev);
569 }
570 else{
571 if(!localViolatingEvents.Exists(tIt->Ev) )
572 localEvents.Insert(tIt->Ev);
573 }
574 }
575 // high-level event
576 else{
577 eventStatesMap[fIt->first][tIt->Ev].first.Insert(*stIt);
578 eventStatesMap[fIt->first][tIt->Ev].second.Insert(rMapStateToPartition[tIt->X2]);
579 }
580 }
581 }
582 map<Idx,pair<StateSet,IndexSet> >::const_iterator seIt, seEndIt;
583 seIt = eventStatesMap[fIt->first].begin();
584 seEndIt = eventStatesMap[fIt->first].end();
585 for( ; seIt != seEndIt; seIt ++){
586 // if there is more than one goal coset, the current event introduces nondeterminism in the current coset
587 if(seIt->second.second.Size() > 1){
588 nondeterministicStates[fIt->first].push_back(make_pair(StateSet(),0) );
589 nondeterministicStates[fIt->first].back().first = seIt->second.first;
590 nondeterministicStates[fIt->first].back().second = seIt->first;
591 }
592 }
593 }
594 // All outgoing transitions for any coset are determined. Now, the localViolatingEvents are added
595 // to the high-level alphabet, and the remaining nondeterministic transitions are found
596 rHighAlph = rHighAlph + localViolatingEvents;
597 // Only if there were no local violating events added to the high-level alphabet, the nondeterministic transitions are checked (Modification with respect to Lei Feng's algorithm)
598 if(localViolatingEvents.Empty() == true){
599 // Go through all cosets and identify local violating events and all local events
600 rHighAlph = rHighAlph + localEvents;
601 EventSet::Iterator eIt, eEndIt;
602 eIt = localEvents.Begin();
603 eEndIt = localEvents.End();
604 // check which local events can be removed from the high-level alphabet
605 for( ; eIt != eEndIt; eIt++){
606 rHighAlph.Erase(*eIt);
607 // go through all states of all cosets and check if rHighAlph splits all cosets
608 fIt = partitionToStateMap.begin();
609 fEndIt = partitionToStateMap.end();
610 for( ; fIt != fEndIt; fIt++){
611 if(nondeterministicStates[fIt->first].empty() == true) // no need to split if there are no nondeterministic states
612 continue;
613 stIt = fIt->second.Begin();
614 stEndIt = fIt->second.End();
615 bool erase = true;
616 // Now, all combinations with nondeterministic exit states have to be checked
617 for( ; stIt != stEndIt; stIt++){
618 // if the rHighAlph does not split the coset, the current event cannot be removed
619 if(!CheckSplit(rGen, rHighAlph, nondeterministicStates[fIt->first], *stIt) ){
620 rHighAlph.Insert(*eIt);
621 erase = false;
622 break;
623 }
624 }
625 if(erase == false)
626 break;
627 }
628 }
629 }
630}
631
632
633// CheckSplit(rGen,rSplitAlphabet,rNondeterministicStates,entryState)
634bool CheckSplit(const Generator& rGen, const EventSet& rSplitAlphabet, const vector<pair<StateSet, Idx> >& rNondeterministicStates, Idx entryState){
635 StateSet accessibleReach;
636 // compute the local accessible reach for the current entry state
637 LocalAccessibleReach(rGen, rSplitAlphabet, entryState, accessibleReach);
638 // check if for any of the nondeterministic state sets, more than one state appears in the local accessible reach
639 vector<pair<StateSet, Idx> >::const_iterator vsIt, vsEndIt;
640 vsIt = rNondeterministicStates.begin();
641 vsEndIt = rNondeterministicStates.end();
642 bool split = true;
643 for( ; vsIt != vsEndIt; vsIt++){
644 StateSet nondetExit = vsIt->first * accessibleReach;
645 StateSet::Iterator stIt, stEndIt;
646 stIt = nondetExit.Begin();
647 stEndIt = nondetExit.End();
648 StateSet nondetReach;
649 // collect the goal states of the nondeterministic exit states
650 for( ; stIt != stEndIt; stIt++){
651 nondetReach.Insert(rGen.TransRelBegin(*stIt, vsIt->second)->X2);
652 }
653 if( nondetReach.Size() > 1){
654 split = false;
655 break;
656 }
657 }
658 return split;
659}
660
661// ==================================================================================
662// Functions for the computation of the high-level alphabet with relabeling
663// ==================================================================================
664
665
666// calcAbstAlphClosed(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
667void calcAbstAlphClosed(System& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) {
668 OP_DF("calcAbstAlphClosed(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
669 // The controllable events are separated from the System. All functions that are successively
670 // called, are defined for Generators
671 EventSet cntrevs = rGenObs.ControllableEvents();
672 calcAbstAlphClosed(rGenObs, cntrevs , rHighAlph, rNewHighAlph, rMapRelabeledEvents);
673 // the controllable events that have been changed by the called function are set in the System cGenObs
674 rGenObs.SetControllable(cntrevs);
675}
676
677// calcAbstAlphClosed(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
678void calcAbstAlphClosed(Generator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) {
679 OP_DF("calcAbstAlphClosed(" << rGenObs.Name() << "," << "rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
680 // The function called next returns a relabeled generator and a map of relabeled transitions
681 map<Transition,Idx> changedtrans;
682 calcAbstAlphClosed(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans);
683 // for later use, the relabeled transitions are converted into relabeled events
684 // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty
685 map<Transition,Idx>::iterator rtEndIt = changedtrans.end();
686 map<Transition,Idx>::iterator rtIt = changedtrans.begin();
687 for(; rtIt != rtEndIt; rtIt++){
688 if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){// if the event does not exist, yet, a nex element in the map is created
689 rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>();
690 if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist
691 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
692 }
693 else { // a new label is inserted into the map
694 if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist
695 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
696 }
697 }
698}
699
700// calcAbstAlphClosed(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans)
701void calcAbstAlphClosed(Generator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans)
702{
703 OP_DF("calcAbstAlphClosed(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)");
704 // Initialization of variables
705 rNewHighAlph = rHighAlph;
706 rMapChangedTrans.clear();
707 Generator genDyn(rGenObs);
708 map<Transition,Transition> mapChangedTransReverse;
709 map<Idx,Idx> mapStateToPartition;
710 map<Idx, EventSet> mapRelabeledEvents;
711 bool done=false;
712 #ifdef DF_PLOT
713 Idx iterationCount=1;
714 string name;
715 #endif
716 // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition.
717 // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs
718 // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition.
719 while(done==false)
720 {
721 // compute the dynamic system for the given generator and high-level alphabet
722 calculateDynamicSystemClosedObs(rGenObs, rNewHighAlph, genDyn);
723 #ifdef DF_PLOT
724 name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToStringInteger(iterationCount));
725 genDyn.DotWrite(name);
726 #endif
727
728
729 // compute coarsest quasi-congruence on the dynamic system
730 Generator genPart;
731 ComputeBisimulation(genDyn, mapStateToPartition, genPart);
732 #ifdef DF_PLOT
733 name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToStringInteger(iterationCount));
734 genPart.DotWrite(name);
735 ++iterationCount;
736 #endif
737
738 // check if quotient automaton is deterministic and free of unobservable events
739 // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly
740 done=relabel(rGenObs, rControllableEvents, rNewHighAlph, mapStateToPartition, mapChangedTransReverse, rMapChangedTrans, mapRelabeledEvents);
741 }
742}
743
744
745// calcAbstAlphObs(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
746void calcAbstAlphObs(System& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) {
747 OP_DF("calcAbstAlphObs(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
748 // The controllable events are separated from the System. All functions that are successively
749 // called, are defined for Generators
750 EventSet cntrevs = rGenObs.ControllableEvents();
751 calcAbstAlphObs(rGenObs, cntrevs , rHighAlph, rNewHighAlph, rMapRelabeledEvents);
752 // the controllable events that have been changed by the called function are set in the System cGenObs
753 rGenObs.SetControllable(cntrevs);
754}
755
756// calcAbstAlphObs(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
757void calcAbstAlphObs(Generator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) {
758 OP_DF("calcAbstAlphObs(" << rGenObs.Name() << "," << "rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
759 // The function called next returns a relabeled generator and a map of relabeled transitions
760 map<Transition,Idx> changedtrans;
761 calcAbstAlphObs(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans);
762 // for later use, the relabeled transitions are converted into relabeled events
763 // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty
764 map<Transition,Idx>::iterator rtEndIt = changedtrans.end();
765 map<Transition,Idx>::iterator rtIt = changedtrans.begin();
766 for(; rtIt != rtEndIt; rtIt++){
767 if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){// if the event does not exist, yet, a nex element in the map is created
768 rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>();
769 if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist
770 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
771 }
772 else { // a new label is inserted into the map
773 if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist
774 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
775 }
776 }
777}
778
779// calcAbstAlphObs(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans)
780void calcAbstAlphObs(Generator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans)
781{
782 OP_DF("calcAbstAlphObs(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)");
783 // Initialization of variables
784 rNewHighAlph = rHighAlph;
785 rMapChangedTrans.clear();
786 Generator genDyn(rGenObs);
787 map<Transition,Transition> mapChangedTransReverse;
788 map<Idx,Idx> mapStateToPartition;
789 map<Idx, EventSet> mapRelabeledEvents;
790 bool done=false;
791 #ifdef DF_PLOT
792 Idx iterationCount=1;
793 string name;
794 #endif
795 // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition.
796 // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs
797 // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition.
798 while(done==false)
799 {
800 // compute the dynamic system for the given generator and high-level alphabet
801 calculateDynamicSystemClosedObs(rGenObs, rNewHighAlph, genDyn);
802 calculateDynamicSystemObs(rGenObs, rNewHighAlph, genDyn);
803 #ifdef DF_PLOT
804 name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToStringInteger(iterationCount));
805 genDyn.DotWrite(name);
806 #endif
807
808 // compute coarsest quasi-congruence on the dynamic system
809 Generator genPart;
810 ComputeBisimulation(genDyn, mapStateToPartition, genPart);
811 #ifdef DF_PLOT
812 name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToStringInteger(iterationCount));
813 genPart.DotWrite(name);
814 ++iterationCount;
815 #endif
816
817 // check if quotient automaton is deterministic and free of unobservable events
818 // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly
819 done=relabel(rGenObs, rControllableEvents, rNewHighAlph, mapStateToPartition, mapChangedTransReverse, rMapChangedTrans, mapRelabeledEvents);
820 }
821}
822
823
824// calcAbstAlphMSA(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
825void calcAbstAlphMSA(System& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) {
826 OP_DF("calcAbstAlphMSA(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
827 // The controllable events are separated from the System. All functions that are successively
828 // called, are defined for Generators
829 EventSet cntrevs = rGenObs.ControllableEvents();
830 calcAbstAlphMSA(rGenObs, cntrevs , rHighAlph, rNewHighAlph, rMapRelabeledEvents);
831 // the controllable events that have been changed by the called function are set in the System cGenObs
832 rGenObs.SetControllable(cntrevs);
833}
834
835// calcAbstAlphMSA(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
836void calcAbstAlphMSA(Generator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) {
837 OP_DF("calcAbstAlphMSA(" << rGenObs.Name() << "," << "rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
838 // The function called next returns a relabeled generator and a map of relabeled transitions
839 map<Transition,Idx> changedtrans;
840 calcAbstAlphMSA(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans);
841 // for later use, the relabeled transitions are converted into relabeled events
842 // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty
843 map<Transition,Idx>::iterator rtEndIt = changedtrans.end();
844 map<Transition,Idx>::iterator rtIt = changedtrans.begin();
845 for(; rtIt != rtEndIt; rtIt++){
846 if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){// if the event does not exist, yet, a nex element in the map is created
847 rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>();
848 if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist
849 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
850 }
851 else { // a new label is inserted into the map
852 if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist
853 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
854 }
855 }
856}
857
858// calcAbstAlphMSA(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans)
859void calcAbstAlphMSA(Generator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans)
860{
861 OP_DF("calcAbstAlphMSA(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)");
862 // Initialization of variables
863 rNewHighAlph = rHighAlph;
864 rMapChangedTrans.clear();
865 Generator genDyn(rGenObs);
866 map<Transition,Transition> mapChangedTransReverse;
867 map<Idx,Idx> mapStateToPartition;
868 map<Idx, EventSet> mapRelabeledEvents;
869 bool done=false;
870 #ifdef DF_PLOT
871 Idx iterationCount=1;
872 string name;
873 #endif
874 // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition.
875 // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs
876 // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition.
877 while(done==false)
878 {
879 // compute the dynamic system for the given generator and high-level alphabet
880 calculateDynamicSystemClosedObs(rGenObs, rNewHighAlph, genDyn);
881 calculateDynamicSystemMSA(rGenObs, rNewHighAlph, genDyn);
882 #ifdef DF_PLOT
883 name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToStringInteger(iterationCount));
884 genDyn.DotWrite(name);
885 #endif
886
887
888 // compute coarsest quasi-congruence on the dynamic system
889 Generator genPart;
890 ComputeBisimulation(genDyn, mapStateToPartition, genPart);
891 #ifdef DF_PLOT
892 name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToStringInteger(iterationCount));
893 genPart.DotWrite(name);
894 ++iterationCount;
895 #endif
896
897 // check if quotient automaton is deterministic and free of unobservable events
898 // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly
899 done=relabel(rGenObs, rControllableEvents, rNewHighAlph, mapStateToPartition, mapChangedTransReverse, rMapChangedTrans, mapRelabeledEvents);
900 }
901}
902
903
904// // calcAbstAlphObsOCC(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
905// void calcAbstAlphObsOCC(System& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents){
906// OP_DF("calcAbstAlphObsOCC(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
907// // The controllable events are separated from the System. All functions that are successively
908// // called, are defined for Generators
909// map<Transition,Idx> changedtrans;
910// EventSet rControllableEvents = rGenObs.ControllableEvents();
911// // The function called next returns a relabeled generator and a map of relabeled transitions
912// calcAbstAlphObsOCC(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans);
913// // for later use, the relabeled transitions are converted into relabeled events
914// // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty
915// map<Transition,Idx>::iterator rtEndIt = changedtrans.end();
916// map<Transition,Idx>::iterator rtIt = changedtrans.begin();
917// for(; rtIt != rtEndIt; rtIt++){
918// if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){
919// rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>();
920// if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist
921// rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
922// } else {
923// if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist
924// rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
925// }
926// }
927// // the controllable events that have been changed by the called function are set in the System cGenObs
928// rGenObs.SetControllable(rControllableEvents);
929// }
930
931// // calcAbstAlphObsOCC(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans)
932// void calcAbstAlphObsOCC(Generator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans)
933// {
934// OP_DF("calcAbstAlphObsOCC(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)");
935// // Initialization of variables
936// rNewHighAlph = rHighAlph;
937// rMapChangedTrans.clear();
938// Generator genDyn(rGenObs);
939// map<Transition,Transition> mapChangedTransReverse;
940// vector<Idx> newPartitions;
941// map<Idx,Idx> mapStateToPartition;
942// map<Idx, EventSet> mapRelabeledEvents;
943// bool done=false;
944// #ifdef DF_PLOT
945// Idx iterationCount=1;
946// string name;
947// #endif
948// // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition
949// // and output control consistency (OCC).
950// // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs
951// // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition and OCC.
952// while(done==false)
953// {
954// // compute dynamic system for Lm-observer and OCC on rGenObs
955// calculateDynamicSystemObsOCC(rGenObs, rControllableEvents, rNewHighAlph, genDyn);
956// #ifdef DF_PLOT
957// name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToStringInteger(iterationCount));
958// genDyn.DotWrite(name);
959// #endif
960//
961// Generator genPart;
962// mapStateToPartition.clear();
963// newPartitions.clear();
964// // compute coarsest quasi-congruence on the dynamic system
965// ComputeBisimulation(genDyn, mapStateToPartition, genPart, newPartitions);
966// #ifdef DF_PLOT
967// name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToStringInteger(iterationCount));
968// genPart.DotWrite(name);
969// ++iterationCount;
970// #endif
971//
972// // check if quotient automaton is deterministic and free of unobservable events
973// // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly
974// done=relabel(rGenObs, rControllableEvents, rNewHighAlph, newPartitions, mapStateToPartition, mapChangedTransReverse, rMapChangedTrans, mapRelabeledEvents);
975// }
976// }
977/*
978// calculateDynamicSystemObsOCC(rGen, rControllableEvents, rHighAlph, rGenDyn)
979void calculateDynamicSystemObsOCC(const Generator& rGen, EventSet& rControllableEvents, EventSet& rHighAlph, Generator& rGenDyn){
980 OP_DF("calculateDynamicSystemObsOCC(" << rGen.Name() << "," << rControllableEvents.Name() << "," << rHighAlph.Name() << "," << rGenDyn.Name() << ")");
981 // transition relation sorted in reverse order for backwards reachability
982 TransSetX2EvX1 tset_X2EvX1;
983 rGen.TransRel(tset_X2EvX1);
984
985 // prepare generator rGenDyn
986 rGenDyn.ClearTransRel();
987 rGenDyn.InjectAlphabet(rHighAlph); // all high-level events are contained in the alphabet of rGenDyn
988 // labels for transitions to marked states and for controllable paths
989 std::string eventname = ( rGenDyn.EventSymbolTablep())->UniqueSymbol("cLabel_1");
990 Idx cLabel = (rGenDyn.EventSymbolTablep())->InsEntry(eventname);
991 eventname = ( rGenDyn.EventSymbolTablep())->UniqueSymbol("mLabel_1");
992 Idx mLabel = (rGenDyn.EventSymbolTablep())->InsEntry(eventname);
993 rGenDyn.InsEvent(cLabel);
994 rGenDyn.InsEvent(mLabel);
995 rGenDyn.InjectInitStates(rGen.InitStates() );
996 rGenDyn.InjectStates(rGen.States() );
997 rGenDyn.InjectMarkedStates(rGen.MarkedStates() );
998
999 // maps for the construction of the dynamic system
1000 map<Idx, map<Idx, bool> > exitLocalStatesMap; // map from each exit state to locally backward reachable states and a boolean that is false if there exists an uncontrollable path to the exit state
1001 map<Idx, StateSet> entryLocalStatesMap; // map from entry states to locally forward reachable states
1002 StateSet::Iterator stIt, stEndIt;
1003 stIt = rGen.StatesBegin();
1004 stEndIt = rGen.StatesEnd();
1005 TransSet::Iterator tsIt, tsEndIt;
1006 bool isExitState;
1007 // go through all states of the original generator
1008 for(; stIt != stEndIt; stIt++){
1009 OP_DF("calculateDynamicSystemObsOCC: loop over all states; current state: " << rGen.StateName(*stIt)
1010 << " [" << *stIt << "]");
1011 // determine the marked states that are locally reachable from the current state and insert
1012 // transitions labeled with mLabel in rGenDyn
1013 forwardReachabilityObs(rGen, rHighAlph, *stIt, mLabel, rGenDyn);
1014 // if the current state is an exit state, carry out the backward reachability to determine
1015 // which states can be reached on a controllable/uncontrollable path -> store in exitLocalStatesMap
1016 // in this case, also determine the corresponding entry states and compute their locally reachable states
1017 // for the entryLocalStatesMap
1018 tsIt = rGen.TransRelBegin(*stIt);
1019 tsEndIt = rGen.TransRelEnd(*stIt);
1020 isExitState = false;
1021 for( ; tsIt != tsEndIt; tsIt++){
1022 if(rHighAlph.Exists(tsIt->Ev) ){
1023 OP_DF("calculateDynamicSystemObsOCC: current state is an exit-state");
1024 isExitState = true;
1025 // if the local reach for the connected entry state has not been computed, yet, insert it in the
1026 // entryLocalStatesMap
1027 if( entryLocalStatesMap.find(tsIt->X2) == entryLocalStatesMap.end() ){
1028 entryLocalStatesMap[tsIt->X2] = StateSet();
1029 LocalAccessibleReach(rGen,rHighAlph, tsIt->X2, entryLocalStatesMap[tsIt->X2]);
1030 }
1031 }
1032 }
1033 // if the current state is an exit state, compute the backward local reach with the controllability properties of the
1034 // paths to locally backward reachable states
1035 if(isExitState == true){
1036 StateSet doneStates;
1037 exitLocalStatesMap[*stIt][*stIt] = false; // the exit state is reachable from the exit state via an uncontrollable path
1038 doneStates.Insert(*stIt);
1039 backwardReachabilityObsOCC(tset_X2EvX1, rControllableEvents, rHighAlph, *stIt, *stIt, false, exitLocalStatesMap, doneStates);
1040
1041 }
1042
1043 }
1044 // the generator rGenDyn is constructed by connecting all exit and entry states with their local state sets
1045 map<Idx, map<Idx, bool> >::const_iterator elIt, elEndIt;
1046 elIt = exitLocalStatesMap.begin();
1047 elEndIt = exitLocalStatesMap.end();
1048 map<Idx,bool>::const_iterator lcIt, lcEndIt;
1049 StateSet::Iterator exIt, exEndIt;
1050 map<Idx,StateSet>::const_iterator enIt;
1051
1052 for( ; elIt != elEndIt; elIt++){
1053 lcEndIt = elIt->second.end();
1054 // go over all entry states reachable from the current exit state (via all feasible high-level events)
1055 tsIt = rGen.TransRel().Begin(elIt->first);
1056 tsEndIt = rGen.TransRel().End(elIt->first);
1057 for( ; tsIt != tsEndIt; tsIt++){
1058 OP_DF("calculateDynamicSystemObsOCC: insert transitions for the high-level event" << rGen.EventName(tsIt->Ev) << "[" << tsIt->Ev << "]");
1059 if(rHighAlph.Exists(tsIt->Ev) ){
1060 bool controllable = rControllableEvents.Exists(tsIt->Ev);
1061 enIt = entryLocalStatesMap.find(tsIt->X2);
1062 stEndIt = enIt->second.End();
1063 // iterate over all locally backward reachable states from current exit state
1064 for(lcIt = elIt->second.begin(); lcIt != lcEndIt; lcIt ++){
1065 // iterate over all locally forward reachable states from current entry state
1066 for( stIt = enIt->second.Begin(); stIt != stEndIt; stIt++){
1067 OP_DF("calculateDynamicSystemObsOCC: Transition added to resulting generator: " <<
1068 rGenDyn.TStr(Transition(lcIt->first,tsIt->Ev,*stIt)));
1069
1070 rGenDyn.SetTransition(lcIt->first,tsIt->Ev,*stIt); // insert a transition for each local state combination
1071 if( controllable || lcIt->second ){ // insert an clabel transition if the local path is controllable or the high-level event is controllable
1072 OP_DF("calculateDynamicSystemObsOCC: cLabel-Transition added to resulting generator: " <<
1073 rGenDyn.TStr(Transition(lcIt->first,cLabel,*stIt)));
1074
1075 rGenDyn.SetTransition(lcIt->first,cLabel,*stIt);
1076 }
1077 }
1078 }
1079 }
1080 }
1081 }
1082}
1083
1084// forwardReachabilityObs(rGen, rHighAlph, lowState, mLabel, rGenDyn)
1085void forwardReachabilityObs(const Generator& rGen, const EventSet& rHighAlph, Idx lowState, Idx mLabel, Generator& rGenDyn) {
1086 OP_DF("forwardReachabilityObs(" << rGen.Name() << "," << rHighAlph.Name() << "," << lowState << "," << rGenDyn.EventName(mLabel) << "," << rGenDyn.Name() << ")");
1087 // helpers:
1088 // iterators
1089 TransSet::Iterator tIt;
1090 TransSet::Iterator tEndIt;
1091 // todo list
1092 std::stack<Idx> todo;
1093
1094 // algorithm: the locally reachable states from lowState are evaluated. If a reachable state is marked,
1095 // a transition with mLabel is inserted from lowState to that state is inserted in rGenDyn.
1096 todo.push(lowState);
1097 StateSet doneStates;
1098 // if lowState is marked itself, the dynamic system contains a selfloop with the mlabel
1099 if(rGen.MarkedStates().Exists(lowState) ){
1100 OP_DF("forwardReachabilityObs: Transition with mLabel added to resulting generator: " <<
1101 rGenDyn.TStr(Transition(lowState,mLabel,lowState)));
1102 rGenDyn.SetTransition(lowState, mLabel, lowState);
1103 }
1104
1105 doneStates.Insert(lowState);
1106 // the local reachability is evaluated until no new state is found
1107 while (! todo.empty()) {
1108 const Idx current = todo.top();
1109 todo.pop();
1110 tIt = rGen.TransRelBegin(current);
1111 tEndIt = rGen.TransRelEnd(current);
1112 for (; tIt != tEndIt; ++tIt) {
1113 // if the current transition is labeled with a high level event, it is skipped
1114 if (rHighAlph.Exists(tIt->Ev)) {
1115 continue;
1116 }
1117 // if the successor state has not been found, yst (not in doneStates)
1118 else if (! doneStates.Exists(tIt->X2)) {
1119 todo.push(tIt->X2);
1120 if(rGen.MarkedStates().Exists(tIt->X2) ){
1121 OP_DF("forwardReachabilityObs: Transition with mLabel added to resulting generator: " <<
1122 rGenDyn.TStr(Transition(lowState,mLabel,tIt->X2)));
1123 rGenDyn.SetTransition(lowState, mLabel, tIt->X2);
1124 }
1125 doneStates.Insert(tIt->X2);
1126 }
1127 }
1128 }
1129}*/
1130
1131// backwardReachabilityObsOCC(rTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, currentState, controllablePath, rExitLocalStatesMap, rDoneStates)
1132void backwardReachabilityObsOCC(const TransSetX2EvX1& rTransSetX2EvX1, const EventSet& rControllableEvents, const EventSet& rHighAlph, Idx exitState, Idx currentState, bool controllablePath, map<Idx, map<Idx, bool> >& rExitLocalStatesMap, StateSet& rDoneStates){
1133 OP_DF("backwardReachabilityObsOCC(rTransSetX2EvX1," << rControllableEvents.Name() << "," << rHighAlph.Name() << "," << exitState << "," << currentState << "," << controllablePath << ",rExitLocalStatesMap, rDoneStates)");
1134 // go along all backward transitions. Discard the goal state if it is reached via a high-level event or if it is in the rDoneStates and
1135 // the controllability properties of the state do not change on the current path
1136
1137 // helpers
1138 TransSetX2EvX1::Iterator tsIt, tsEndIt;
1139 tsIt = rTransSetX2EvX1.BeginByX2(currentState);
1140 tsEndIt = rTransSetX2EvX1.EndByX2(currentState);
1141 bool currentControllablePath;
1142 // we iterate over all backward transitions of the currentState to establish backward reachability
1143 for( ;tsIt != tsEndIt; tsIt++){
1144 // states reachable via a high-level event are not in the local backward reach and the controllability property of the current exitState does not change
1145 if( !rHighAlph.Exists(tsIt->Ev) && tsIt->X1 != exitState){
1146 // if the state has not been visited, yet, the controllability of the current path are set in the rExitLocalStatesMap
1147 if( !rDoneStates.Exists(tsIt->X1) ){
1148 rDoneStates.Insert(tsIt->X1);
1149 // the path is controllable if the current transition has a controllable event or the path was already controllable
1150 currentControllablePath = rControllableEvents.Exists(tsIt->Ev) || controllablePath;
1151 rExitLocalStatesMap[exitState][tsIt->X1] = currentControllablePath;
1152 // as the state has not been visited, yet, it is subject to a new backward reachability
1153 backwardReachabilityObsOCC(rTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, tsIt->X1, currentControllablePath, rExitLocalStatesMap, rDoneStates);
1154 }
1155 else{ // for an existing state, the controllability value can change from uncontrollable to controllable (if
1156 // a new controllable path has been found). It is important to note, that the OCC condition implies that
1157 // if there is one controllable path, then the the state is flagged controllable except for the case of the
1158 // given exitState that is always uncontrollable
1159 currentControllablePath = rControllableEvents.Exists(tsIt->Ev) || controllablePath;
1160 if(rExitLocalStatesMap[exitState][tsIt->X1] != currentControllablePath && currentControllablePath == true){
1161 rExitLocalStatesMap[exitState][tsIt->X1] = true;
1162 // as the controllabiity attribute of the current state changed it is subject to a new backward reachability
1163 backwardReachabilityObsOCC(rTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, tsIt->X1, true, rExitLocalStatesMap, rDoneStates);
1164 }
1165 }
1166 }
1167 }
1168}
1169
1170// calcAbstAlphObsLCC(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
1171void calcAbstAlphObsLCC(System& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents){
1172 OP_DF("calcAbstAlphObsLCC(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
1173 // The controllable events are separated from the System. All functions that are successively
1174 // called, are defined for Generators
1175 map<Transition,Idx> changedtrans;
1176 EventSet rControllableEvents = rGenObs.ControllableEvents();
1177 // The function called next returns a relabeled generator and a map of relabeled transitions
1178 calcAbstAlphObsLCC(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans);
1179 // for later use, the relabeled transitions are converted into relabeled events
1180 // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty
1181 map<Transition,Idx>::iterator rtEndIt = changedtrans.end();
1182 map<Transition,Idx>::iterator rtIt = changedtrans.begin();
1183 for(; rtIt != rtEndIt; rtIt++){
1184 if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){
1185 rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>();
1186 if(rGenObs.Alphabet().Exists(rtIt->second) )
1187 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
1188 } else {
1189 if(rGenObs.Alphabet().Exists(rtIt->second) )
1190 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
1191 }
1192 }
1193 // the controllable events that have been changed by the called function are set in the System cGenObs
1194 rGenObs.SetControllable(rControllableEvents);
1195}
1196
1197// calcAbstAlphObsLCC(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans)
1198void calcAbstAlphObsLCC(Generator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans)
1199{
1200 OP_DF("calcAbstAlphObsLCC(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)");
1201 // Initialization of variables
1202 rNewHighAlph = rHighAlph;
1203 rMapChangedTrans.clear();
1204 Generator genDyn(rGenObs);
1205 map<Transition,Transition> mapChangedTransReverse;
1206 map<Idx,Idx> mapStateToPartition;
1207 map<Idx, EventSet> mapRelabeledEvents;
1208 bool done=false;
1209 #ifdef DF_PLOT
1210 Idx iterationCount=1;
1211 string name;
1212 #endif
1213 // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition
1214 // and local control consistency (LCC).
1215 // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs
1216 // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition and LCC.
1217 while(done==false)
1218 {
1219 // compute the dynamic system for the given generator and high-level alphabet
1220 calculateDynamicSystemClosedObs(rGenObs, rNewHighAlph, genDyn);
1221 calculateDynamicSystemLCC(rGenObs, rControllableEvents, rNewHighAlph, genDyn);
1222 calculateDynamicSystemObs(rGenObs, rNewHighAlph, genDyn);
1223 #ifdef DF_PLOT
1224 name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToStringInteger(iterationCount));
1225 genDyn.DotWrite(name);
1226 #endif
1227
1228 // compute coarsest quasi-congruence on the dynamic system
1229 Generator genPart;
1230 ComputeBisimulation(genDyn, mapStateToPartition, genPart);
1231 #ifdef DF_PLOT
1232 name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToStringInteger(iterationCount));
1233 genPart.DotWrite(name);
1234 ++iterationCount;
1235 #endif
1236
1237 // check if quotient automaton is deterministic and free of unobservable events
1238 // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly
1239 done=relabel(rGenObs, rControllableEvents, rNewHighAlph, mapStateToPartition, mapChangedTransReverse, rMapChangedTrans, mapRelabeledEvents);
1240 }
1241}
1242
1243
1244// calcAbstAlphMSALCC(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
1245void calcAbstAlphMSALCC(System& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents){
1246 OP_DF("calcAbstAlphMSALCC(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
1247 // The controllable events are separated from the System. All functions that are successively
1248 // called, are defined for Generators
1249 map<Transition,Idx> changedtrans;
1250 EventSet rControllableEvents = rGenObs.ControllableEvents();
1251 // The function called next returns a relabeled generator and a map of relabeled transitions
1252 calcAbstAlphMSALCC(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans);
1253 // for later use, the relabeled transitions are converted into relabeled events
1254 // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty
1255 map<Transition,Idx>::iterator rtEndIt = changedtrans.end();
1256 map<Transition,Idx>::iterator rtIt = changedtrans.begin();
1257 for(; rtIt != rtEndIt; rtIt++){
1258 if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){
1259 rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>();
1260 if(rGenObs.Alphabet().Exists(rtIt->second) )
1261 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
1262 } else {
1263 if(rGenObs.Alphabet().Exists(rtIt->second) )
1264 rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
1265 }
1266 }
1267 // the controllable events that have been changed by the called function are set in the System cGenObs
1268 rGenObs.SetControllable(rControllableEvents);
1269}
1270
1271// calcAbstAlphMSALCC(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans)
1272void calcAbstAlphMSALCC(Generator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans)
1273{
1274 OP_DF("calcAbstAlphMSALCC(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)");
1275 // Initialization of variables
1276 rNewHighAlph = rHighAlph;
1277 rMapChangedTrans.clear();
1278 Generator genDyn(rGenObs);
1279 map<Transition,Transition> mapChangedTransReverse;
1280 map<Idx,Idx> mapStateToPartition;
1281 map<Idx, EventSet> mapRelabeledEvents;
1282 bool done=false;
1283 #ifdef DF_PLOT
1284 Idx iterationCount=1;
1285 string name;
1286 #endif
1287 // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition
1288 // and local control consistency (LCC).
1289 // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs
1290 // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition and LCC.
1291 while(done==false)
1292 {
1293 // compute the dynamic system for the given generator and high-level alphabet
1294 calculateDynamicSystemClosedObs(rGenObs, rNewHighAlph, genDyn);
1295 calculateDynamicSystemLCC(rGenObs, rControllableEvents, rNewHighAlph, genDyn);
1296 calculateDynamicSystemMSA(rGenObs, rNewHighAlph, genDyn);
1297 #ifdef DF_PLOT
1298 name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToStringInteger(iterationCount));
1299 genDyn.DotWrite(name);
1300 #endif
1301
1302 // compute coarsest quasi-congruence on the dynamic system
1303 Generator genPart;
1304 ComputeBisimulation(genDyn, mapStateToPartition, genPart);
1305 #ifdef DF_PLOT
1306 name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToStringInteger(iterationCount));
1307 genPart.DotWrite(name);
1308 ++iterationCount;
1309 #endif
1310
1311 // check if quotient automaton is deterministic and free of unobservable events
1312 // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly
1313 done=relabel(rGenObs, rControllableEvents, rNewHighAlph, mapStateToPartition, mapChangedTransReverse, rMapChangedTrans, mapRelabeledEvents);
1314 }
1315}
1316
1317/*
1318// calculateDynamicSystemObsLCC(rGen, rControllableEvents, rHighAlph, rGenDyn)
1319void calculateDynamicSystemObsLCC(const Generator& rGen, EventSet& rControllableEvents, EventSet& rHighAlph, Generator& rGenDyn){
1320 OP_DF("calculateDynamicSystemObsLCC(" << rGen.Name() << "," << rControllableEvents.Name() << "," << rHighAlph.Name() << "," << rGenDyn.Name() << ")");
1321 // transition relation sorted in reverse order for backwards reachability
1322 TransSetX2EvX1 tset_X2EvX1;
1323 rGen.TransRel(tset_X2EvX1);
1324
1325 // prepare generator rGenDyn
1326 rGenDyn.ClearTransRel();
1327 rGenDyn.InjectAlphabet(rHighAlph);
1328 std::string eventname = ( rGenDyn.EventSymbolTablep())->UniqueSymbol("ucLabel_1");
1329 Idx ucLabel = (rGenDyn.EventSymbolTablep())->InsEntry(eventname);
1330 eventname = ( rGenDyn.EventSymbolTablep())->UniqueSymbol("mLabel_1");
1331 Idx mLabel = (rGenDyn.EventSymbolTablep())->InsEntry(eventname);
1332 rGenDyn.InsEvent(ucLabel);
1333 rGenDyn.InsEvent(mLabel);
1334 rGenDyn.InjectInitStates(rGen.InitStates() );
1335 rGenDyn.InjectStates(rGen.States() );
1336 rGenDyn.InjectMarkedStates(rGen.MarkedStates() );
1337
1338 // maps for the construction of the dynamic system
1339 map<Idx, map<Idx, bool> > exitLocalStatesMap; // map from each exit state to locally backward reachable states and a boolean that is false if there exists an uncontrollable path to the exit state
1340 map<Idx, StateSet> entryLocalStatesMap; // map from entry states to locally forward reachable states
1341 StateSet::Iterator stIt, stEndIt;
1342 stIt = rGen.StatesBegin();
1343 stEndIt = rGen.StatesEnd();
1344 TransSet::Iterator tsIt, tsEndIt;
1345 bool isExitState;
1346 // go through all states of the original generator
1347 for(; stIt != stEndIt; stIt++){
1348 OP_DF("calculateDynamicSystemObsLCC: loop over all states; current state: " << rGen.StateName(*stIt)
1349 << " [" << *stIt << "]");
1350 // determine the marked states that are locally reachable from the current state and insert
1351 // transitions labeled with mLabel in rGenDyn
1352 forwardReachabilityObs(rGen, rHighAlph, *stIt, mLabel, rGenDyn);
1353 // if the current state is an exit state, carry out the backward reachability to determine
1354 // which states can be reached on a controllable/uncontrollable path -> store in exitLocalStatesMap
1355 // in this case, also determine the corresponding entry states and compute their locally reachable states
1356 // for the entryLocalStatesMap
1357 tsIt = rGen.TransRelBegin(*stIt);
1358 tsEndIt = rGen.TransRelEnd(*stIt);
1359 isExitState = false;
1360 for( ; tsIt != tsEndIt; tsIt++){
1361 if(rHighAlph.Exists(tsIt->Ev) ){
1362 OP_DF("calculateDynamicSystemObsLCC: current state is an exit-state");
1363 isExitState = true;
1364 // if the local reach for the connected entry state has not been computed, yet, insert it in the
1365 // entryLocalStatesMap
1366 if( entryLocalStatesMap.find(tsIt->X2) == entryLocalStatesMap.end() ){
1367 entryLocalStatesMap[tsIt->X2] = StateSet();
1368 LocalAccessibleReach(rGen,rHighAlph, tsIt->X2, entryLocalStatesMap[tsIt->X2]);
1369 }
1370 }
1371 }
1372 // if the current state is an exit state, compute the backward local reach with the controllability properties of the
1373 // paths to locally backward reachable states
1374 if(isExitState == true){
1375 StateSet doneStates;
1376 exitLocalStatesMap[*stIt][*stIt] = false; // the exit state is reachable from the exit state via an uncontrollable path
1377 doneStates.Insert(*stIt);
1378 backwardReachabilityObsLCC(tset_X2EvX1, rControllableEvents, rHighAlph, *stIt, *stIt, false, exitLocalStatesMap, doneStates);
1379
1380 }
1381
1382 }
1383 // the generator rGenDyn is constructed by connecting all exit and entry states with their local state sets
1384 map<Idx, map<Idx, bool> >::const_iterator elIt, elEndIt;
1385 elIt = exitLocalStatesMap.begin();
1386 elEndIt = exitLocalStatesMap.end();
1387 map<Idx,bool>::const_iterator lcIt, lcEndIt;
1388 StateSet::Iterator exIt, exEndIt;
1389 map<Idx,StateSet>::const_iterator enIt;
1390
1391 for( ; elIt != elEndIt; elIt++){
1392 lcEndIt = elIt->second.end();
1393 // go over all entry states reachable from the current exit state (via all feasible high-level events)
1394 tsIt = rGen.TransRel().Begin(elIt->first);
1395 tsEndIt = rGen.TransRel().End(elIt->first);
1396 for( ; tsIt != tsEndIt; tsIt++){
1397 OP_DF("calculateDynamicSystemObsLCC: insert transitions for the high-level event" << rGen.EventName(tsIt->Ev) << "[" << tsIt->Ev << "]");
1398 if(rHighAlph.Exists(tsIt->Ev) ){
1399 bool controllable = rControllableEvents.Exists(tsIt->Ev);
1400 enIt = entryLocalStatesMap.find(tsIt->X2);
1401 stEndIt = enIt->second.End();
1402 // iterate over all locally backward reachable states from current exit state
1403 for(lcIt = elIt->second.begin(); lcIt != lcEndIt; lcIt ++){
1404 // iterate over all locally forward reachable states from current entry state
1405 for( stIt = enIt->second.Begin(); stIt != stEndIt; stIt++){
1406 OP_DF("calculateDynamicSystemObsLCC: Transition added to resulting generator: " <<
1407 rGenDyn.TStr(Transition(lcIt->first,tsIt->Ev,*stIt)));
1408
1409 rGenDyn.SetTransition(lcIt->first,tsIt->Ev,*stIt); // insert a transition for each local state combination
1410 if( !(controllable || lcIt->second) ){ // insert an uclabel transition if the local path is uncontrollable
1411 OP_DF("calculateDynamicSystemObsLCC: cLabel-Transition added to resulting generator: " <<
1412 rGenDyn.TStr(Transition(lcIt->first,ucLabel,*stIt)));
1413
1414 rGenDyn.SetTransition(lcIt->first,ucLabel,*stIt);
1415 }
1416 }
1417 }
1418 }
1419 }
1420 }
1421}
1422
1423// backwardReachabilityObsLCC(crTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, currentState, controllablePath, rExitLocalStatesMap, rDoneStates)
1424void backwardReachabilityObsLCC(const TransSetX2EvX1& rTransSetX2EvX1, const EventSet& rControllableEvents, const EventSet& rHighAlph, Idx exitState, Idx currentState, bool controllablePath, map<Idx, map<Idx, bool> >& rExitLocalStatesMap, StateSet& rDoneStates){
1425 OP_DF("backwardReachabilityObsOCC(rTransSetX2EvX1," << rControllableEvents.Name() << "," << rHighAlph.Name() << "," << exitState << "," << currentState << "," << controllablePath << ",rExitLocalStatesMap, rDoneStates)");
1426 // go along all backward transitions. Discard the goal state if it is reached via a high-level event or if it is in the rDoneStates and
1427 // the controllability properties of the state do not change on the current path
1428
1429 // helpers
1430 TransSetX2EvX1::Iterator tsIt, tsEndIt;
1431 tsIt = rTransSetX2EvX1.BeginByX2(currentState);
1432 tsEndIt = rTransSetX2EvX1.EndByX2(currentState);
1433 bool currentControllablePath;
1434 // we iterate over all backward transitions of the currentState to establish backward reachability
1435 for( ;tsIt != tsEndIt; tsIt++){
1436 // states reachable via a high-level event are not in the local backward reach and the controllability property of the current exitState does not change
1437 if( !rHighAlph.Exists(tsIt->Ev) && tsIt->X1 != exitState){
1438 // if the state has not been visited, yet, the controllability of the current path are set in the rExitLocalStatesMap
1439 if( !rDoneStates.Exists(tsIt->X1) ){
1440 rDoneStates.Insert(tsIt->X1);
1441 // the path is uncontrollable if the current transition has an uncontrollable event or the path was already uncontrollable
1442 currentControllablePath = rControllableEvents.Exists(tsIt->Ev) || controllablePath;
1443 rExitLocalStatesMap[exitState][tsIt->X1] = currentControllablePath;
1444 // as the state has not been visited, yet, it is subject to a new backward reachability
1445 backwardReachabilityObsLCC(rTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, tsIt->X1, currentControllablePath, rExitLocalStatesMap, rDoneStates);
1446 }
1447 else{ // for an existing state, the controllability value can change from controllable to uncontrollable (if
1448 // a new uncontrollable path has been found). It is important to note, that the LCC condition implies that
1449 // if there is one uncontrollable path, then the state is flagged uncontrollable except for the case of the
1450 // given exitState that is always uncontrollable
1451 currentControllablePath = rControllableEvents.Exists(tsIt->Ev) || controllablePath;
1452 if(rExitLocalStatesMap[exitState][tsIt->X1] != currentControllablePath && currentControllablePath == false){
1453 rExitLocalStatesMap[exitState][tsIt->X1] = currentControllablePath;
1454 // as the controllabiity attribute of the current state changed it is subject to a new backward reachability
1455 backwardReachabilityObsLCC(rTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, tsIt->X1, false, rExitLocalStatesMap, rDoneStates);
1456 }
1457 }
1458 }
1459 }
1460}*/
1461
1462// relabel(rGenRelabel, rControllableEvents, rHighAlph, rMapStateToPartition, rMapChangedTransReverse, rMapChangedTrans, rMapRelabeledEvents)
1463bool relabel(Generator& rGenRelabel, EventSet& rControllableEvents, EventSet& rHighAlph, map<Idx,Idx>& rMapStateToPartition, map<Transition,Transition>& rMapChangedTransReverse, map<Transition,Idx>& rMapChangedTrans, map<Idx, EventSet>& rMapRelabeledEvents)
1464{
1465
1466 OP_DF("relabel(" << rGenRelabel.Name() << "," << rControllableEvents.Name() << "," << rHighAlph.Name() << ", rMapStateToPartition, rMapChangedTransReverse, rMapChangedTrans, rMapRelabeledEvents)");
1467
1468 // helpers
1469
1470 // keep track of how transitions between cosets have been relabeled
1471 // first Idx: coset from where transition starts, second Idx: high-level event,
1472 // third Idx: other coset, where transition ends, forth Idx: new high-level event
1473 map<Idx, map<Idx, map<Idx, Idx> > > mapRelabel;
1474
1475 // set of low-level events, that have not been relabeled
1476 set<Idx> notRelabeledLowEvents;
1477 // transition relation of the original version of rGenRelabel
1478 const TransSet& transSet = rGenRelabel.TransRel();
1479 TransSet::Iterator tIt = transSet.Begin();
1480 TransSet::Iterator tItEnd = transSet.End();
1481 // vector that contains pairs of original and changed transitions
1482 vector<pair<TransSet::Iterator,Transition> > editTransSet;
1483 // prepare data structure for keeping track of how transitions were relabeled
1484 map<Idx,Idx>::iterator newPartIt = rMapStateToPartition.begin();
1485 map<Idx,Idx>::iterator newPartItEnd = rMapStateToPartition.end();
1486 for(; newPartIt != newPartItEnd; ++newPartIt)
1487 mapRelabel[newPartIt->second]=map<Idx, map <Idx, Idx> >();
1488
1489 // algorithm: The relabeling according to the state partition as computed by the bisimulation algorithm is
1490 // performed. A high-level transitions is relebaled with a new event, if a transition with the same event leads
1491 // from the same coset to a different coset (non-determinism in the projected automaton). A low-level transition
1492 // is relabeled if it connects different cosets (corresponds to unobservable transition betweeen cosets). The
1493 // also has build-in procedures to take care that as few new event labels as possible are introduced.
1494
1495 // iteration over all transitions of rGenRelabel
1496 for(; tIt != tItEnd; ++tIt)
1497 {
1498 OP_DF("relabel: current transition: " << rGenRelabel.TStr(*tIt) );
1499 Idx indexX1Partition=rMapStateToPartition[tIt->X1];
1500 OP_DF("relabel: X1 belongs to coset with index " << indexX1Partition);
1501 Idx indexX2Partition=rMapStateToPartition[tIt->X2];
1502 OP_DF("relabel: X2 belongs to coset with index " << indexX2Partition);
1503
1504 //check if current transition is labeled with a high-level-event
1505 if(rHighAlph.Exists(tIt->Ev))
1506 {
1507 OP_DF("relabel: Event is high-level event");
1508 // In the first case, there exists no entry for this transition in mapRelabel. Hence, this is the
1509 // first occurence of tIt->Ev leaving the coset of tIt->X1 found in the iteration.
1510 // Thus, there is no need to relabel this event. Store transition in mapRelabel
1511 if(mapRelabel[indexX1Partition].find(tIt->Ev) == mapRelabel[indexX1Partition].end())
1512 {
1513 mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition]=tIt->Ev;
1514 OP_DF("relabel: First occurence of the current event leaving the current X1-coset");
1515 }
1516 // Otherwise, there exists an entry for the current event leaving the current X1-coset. It has to be
1517 // verified if the transition goes to the same coset as the previously found transitions or not.
1518 else
1519 {
1520 // check if a transition with the same event has already been found that enters the same X2-coset. If
1521 // yes, the same label as for this transition is chosen. If not, a new label is introduced.
1522 if(mapRelabel[indexX1Partition][tIt->Ev].find(indexX2Partition) != mapRelabel[indexX1Partition][tIt->Ev].end())
1523 {
1524 if(mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition] != tIt->Ev)
1525 {
1526 OP_DF("relabel: the same event leading to the same X2-coset has already been relabeld before. The current transition is relabeld correspondingly");
1527 pair<TransSet::Iterator,Transition> newPair;
1528 newPair.first=tIt;
1529 newPair.second = Transition(tIt->X1,mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition],tIt->X2);
1530 editTransSet.push_back(newPair);
1531 }
1532 else //nothing to be done
1533 OP_DF("relabel: There already exists a high-level transition from the current X1-coset to the same X2-coset and the current transition ist labeled with the same event. No relabeling necessary");
1534 }
1535 // there are entries of tIt->Ev, but no one leads to the same X2-coset.
1536 // Check if new labels created before can be reused. If not, create a new one
1537 // and eliminate the non-determinism by relebeling the current transition tIt with this event
1538 else
1539 {
1540 bool createNewLabel = false;
1541 // check if the event already has been relabeled for some other transition
1542 if(rMapRelabeledEvents.find(tIt->Ev) != rMapRelabeledEvents.end())
1543 {
1544 EventSet::Iterator lsIt = rMapRelabeledEvents[tIt->Ev].Begin();
1545 EventSet::Iterator lsItEnd = rMapRelabeledEvents[tIt->Ev].End();
1546 for(; lsIt != lsItEnd; ++lsIt)
1547 {
1548 createNewLabel = false;
1549 map<Idx,Idx>::iterator mapIt = mapRelabel[indexX1Partition][tIt->Ev].begin();
1550 map<Idx,Idx>::iterator mapItEnd = mapRelabel[indexX1Partition][tIt->Ev].end();
1551 for(; mapIt != mapItEnd; ++mapIt)
1552 {
1553 // if the currently investigated label has already been used in
1554 // the current coset for a transition to another coset, relabeling is necessary
1555 if(mapIt->second == *lsIt)
1556 {
1557 createNewLabel = true;
1558 break;
1559 }
1560 }
1561 // use an old label if possible
1562 if(createNewLabel == false)
1563 {
1564 pair<TransSet::Iterator,Transition> newPair;
1565 newPair.first=tIt;
1566 newPair.second = Transition(tIt->X1,*lsIt,tIt->X2);
1567 editTransSet.push_back(newPair);
1568 OP_DF("relabel: An event was found that can be reused: " << rGenRelabel.EventName(*lsIt));
1569 break;
1570 }
1571 }
1572 }
1573 // if no useable labels are available, a new label has to be introduced
1574 else
1575 {
1576 createNewLabel = true;
1577 }
1578 // no label could be found that can be reused
1579 if(createNewLabel == true)
1580 {
1581 // create a new label and relabel the current transition with it
1582 std::string eventName = ( rGenRelabel.EventSymbolTablep())->UniqueSymbol(rGenRelabel.EventSymbolTablep()->Symbol(tIt->Ev) + "newHLevent_1");
1583 Idx newLabel = (rGenRelabel.EventSymbolTablep())->InsEntry(eventName);
1584
1585 rGenRelabel.InsEvent(eventName);
1586 // if the original is controllable, the attribute of the new event is also controllable
1587 if(rControllableEvents.Exists(tIt->Ev)){
1588 rControllableEvents.Insert(newLabel);
1589 }
1590 OP_DF("relabel: No event that can be reused could be found. The new event " << rGenRelabel.EventName(newLabel) << " was created");
1591 rHighAlph.Insert(newLabel);
1592 //create the new transition and remember that the old one has to be replaced with the new one
1593 pair<TransSet::Iterator,Transition> newPair;
1594 newPair.first=tIt;
1595 newPair.second = Transition(tIt->X1,newLabel,tIt->X2);
1596 editTransSet.push_back(newPair);
1597 rMapRelabeledEvents[tIt->Ev].Insert(newLabel);
1598 }
1599 }
1600 }
1601 }
1602 // the current transition is labeled with a low-level event
1603 else
1604 {
1605 OP_DF("relabel: Event is low-level event");
1606 // potential relabeling is only necessary if the low-level transition leaves its coset
1607 if(indexX1Partition != indexX2Partition)
1608 {
1609 // transition connects two cosets and it is the first occurrence of the event.
1610 // Create a new event and relabel the transition with it
1611 if(rMapRelabeledEvents.find(tIt->Ev) == rMapRelabeledEvents.end())
1612 {
1613 std::string eventName = ( rGenRelabel.EventSymbolTablep())->UniqueSymbol(rGenRelabel.EventSymbolTablep()->Symbol(tIt->Ev) + "newHLevent_1");
1614 Idx newLabel = (rGenRelabel.EventSymbolTablep())->InsEntry(eventName);
1615 rGenRelabel.InsEvent(eventName);
1616 // insert the new event in the high-level alphabet and set its controllability property
1617 rHighAlph.Insert(newLabel);
1618 if(rControllableEvents.Exists(tIt->Ev)){
1619 rControllableEvents.Insert(newLabel);
1620 }
1621 OP_DF("relabel: First occurence of current low-level event " << rGenRelabel.EventName(tIt->Ev)
1622 << " between cosets. The new event " << rGenRelabel.EventName(newLabel) << " was created");
1623 mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition]=newLabel;
1624 rMapRelabeledEvents[tIt->Ev].Insert(newLabel);
1625 pair<TransSet::Iterator,Transition> newPair;
1626 newPair.first=tIt;
1627 newPair.second = Transition(tIt->X1,newLabel,tIt->X2);
1628 editTransSet.push_back(newPair);
1629 }
1630 // there are entries of tIt->Ev, but no one leads to the same X2-coset.
1631 // Check if new labels created before can be reused. If not, create a new one
1632 // and eliminate the non-determinism by relebeling the current transition tIt with this event
1633 else
1634 {
1635 EventSet::Iterator lsIt = rMapRelabeledEvents[tIt->Ev].Begin();
1636 EventSet::Iterator lsItEnd = rMapRelabeledEvents[tIt->Ev].End();
1637 bool createNewLabel = true;
1638 for(; lsIt != lsItEnd; ++lsIt)
1639 {
1640 bool labelFound = false;
1641 // check if the event already has been relabeled for some other transition
1642 if(mapRelabel.find(indexX1Partition) == mapRelabel.end())
1643 {
1644 // if the currently investigated label has already been used in
1645 // the current coset for a transition to another coset, relabeling is necessary
1646 labelFound = true;
1647 }
1648 else
1649 {
1650 // label lsIt can be reused as this is the first low-level transition leaving the X1-coset
1651 if(mapRelabel[indexX1Partition].find(tIt->Ev) == mapRelabel[indexX1Partition].end())
1652 {
1653 labelFound = true;
1654 }
1655 else
1656 {
1657 // a transition with the same original event tIt->Ev leaving the X1-coset has been found before
1658 // and it entered a different X2-coset. Check if one of them was relabeled with lsIt. If yes, then lsIt can
1659 // not be reused and the next event has to be examined. If no, lsIt can be reused
1660 if(mapRelabel[indexX1Partition][tIt->Ev].find(indexX2Partition) == mapRelabel[indexX1Partition][tIt->Ev].end())
1661 {
1662 map<Idx,Idx>::iterator mapIt=mapRelabel[indexX1Partition][tIt->Ev].begin();
1663 map<Idx,Idx>::iterator mapItEnd=mapRelabel[indexX1Partition][tIt->Ev].end();
1664 labelFound = true;
1665 for(; mapIt != mapItEnd; ++ mapIt)
1666 {
1667 if(mapIt->second== *lsIt)
1668 {
1669 labelFound = false;
1670 break;
1671 }
1672 }
1673 }
1674 // a transition with the same original event tIt-Ev leaving the X1-coset has been found before
1675 // and it entered the same X2-coset. Reuse the corresponding label
1676 else
1677 {
1678 pair<TransSet::Iterator,Transition> newPair;
1679 newPair.first=tIt;
1680 newPair.second = Transition(tIt->X1,mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition],tIt->X2);
1681 editTransSet.push_back(newPair);
1682 OP_DF("relabel: A transition to same X2-coset has already been found and relabeled before; the current transition is also labeled with " << rGenRelabel.EventName(mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition]));
1683 createNewLabel = false;
1684 break;
1685 }
1686 }
1687 }
1688 // reuse existing event
1689 if(labelFound == true)
1690 {
1691 pair<TransSet::Iterator,Transition> newPair;
1692 newPair.first=tIt;
1693 newPair.second = Transition(tIt->X1,*lsIt,tIt->X2);
1694 editTransSet.push_back(newPair);
1695 OP_DF("relabele: Low level event " << rGenRelabel.EventName(tIt->Ev) << " is relabeled with " << rGenRelabel.EventName(*lsIt) << " which can be reused");
1696 mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition]=*lsIt;
1697 createNewLabel = false;
1698 break;
1699 }
1700 } //end for
1701 // a new label has to be created and the corresponding transition is inserted
1702 if(createNewLabel == true)
1703 {
1704 std::string eventName = ( rGenRelabel.EventSymbolTablep())->UniqueSymbol(rGenRelabel.EventSymbolTablep()->Symbol(tIt->Ev) + "newHLevent_1"); //??
1705 Idx newLabel = (rGenRelabel.EventSymbolTablep())->InsEntry(eventName);
1706 rGenRelabel.InsEvent(eventName);
1707 // insert the new event in the high-level alphabet and set its controllability property
1708 rHighAlph.Insert(newLabel);
1709 if(rControllableEvents.Exists(tIt->Ev) ){
1710 rControllableEvents.Insert(newLabel);
1711 }
1712 OP_DF("relabel: No label could be reused, and the new event " << rGenRelabel.EventName(newLabel) << " was created");
1713 mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition]=newLabel;
1714 pair<TransSet::Iterator,Transition> newPair;
1715 newPair.first=tIt;
1716 newPair.second = Transition(tIt->X1,newLabel,tIt->X2);
1717 editTransSet.push_back(newPair);
1718 rMapRelabeledEvents[tIt->Ev].Insert(newLabel);
1719 }
1720 }
1721 }
1722 // the low-level event does not have to be relabeled
1723 else //indexX1Partition==indexX2Partition
1724 {
1725 notRelabeledLowEvents.insert(tIt->Ev);
1726 }
1727 }
1728 }
1729
1730
1731 // It is possible that events need not be relabeled. For example, if all occurrences of a low-level event have to
1732 // be relabeled and added to the high-level alphabet, it is possible to just add the original low-level event
1733 // to the high-level alphabet without any relabeling. Note that this information is only available after all
1734 // transitions have been evaluated.
1735 vector<pair<TransSet::Iterator,Transition> >::iterator etSetIt = editTransSet.begin();
1736 vector<pair<TransSet::Iterator,Transition> >::iterator etSetItEnd = editTransSet.end();
1737 set<Idx> insertHighEvents;
1738 set<Idx> deleteHighEvents;
1739 bool quotAuotTrue=true;
1740
1741 OP_DF("relabel: Trying to avoid unnecessariy new labels");
1742 // All relabeled transitions are checked
1743 for(etSetIt = editTransSet.begin(); etSetIt != editTransSet.end(); ++etSetIt)
1744 {
1745 Idx oldEvent = etSetIt->first->Ev;
1746 Idx newEvent = etSetIt->second.Ev;
1747 OP_DF("relabel: Checking transition X1=" << rGenRelabel.StateName(etSetIt->first->X1)<< " ["<<etSetIt->first->X1
1748 << "] Ev=" << rGenRelabel.EventName(oldEvent) << " X2=" << rGenRelabel.StateName(etSetIt->first->X2)
1749 << " [" << etSetIt->first->X2 << "] which shall be relabeled with event " << rGenRelabel.EventName(newEvent));
1750 // check if the original event is a low-level event and if there is an event left that has not been relabeled. If all events are relabeled, then at least one label can be replaced by the original event label.
1751 if(notRelabeledLowEvents.find(oldEvent) == notRelabeledLowEvents.end() && !rHighAlph.Exists(oldEvent))
1752 {
1753 OP_DF("relabel: There is no low-level event " << rGenRelabel.EventName(oldEvent) << " left");
1754 insertHighEvents.insert(oldEvent);
1755 // if a low-level event has been relabeled, the automaton under investigation is not the desired quotient automaton, yet.
1756 quotAuotTrue=false;
1757 // if newEvent is the first new event created for relabeling oldEvent, the relabeling is discarded
1758 if(rMapRelabeledEvents[oldEvent].Find(newEvent) == rMapRelabeledEvents[oldEvent].Begin())
1759 {
1760 OP_DF("relabel: Transition will not be relabeled");
1761 // if newEvent is the only event created for relabeling oldEvent, delete newEvent from rGenRelabel
1762 if(rMapRelabeledEvents[oldEvent].Find(newEvent)==(--(rMapRelabeledEvents[oldEvent].End())))
1763 {
1764 OP_DF("relabel: newEvent is the first and last event in rMapRelabeledEvents[oldEvent]");
1765 deleteHighEvents.insert(newEvent);
1766 }
1767 // delete pair<original Transition, new Transition>
1768 vector<pair<TransSet::Iterator,Transition> >::iterator helpIt = etSetIt;
1769 helpIt--;
1770 editTransSet.erase(etSetIt);
1771 etSetIt = helpIt;
1772 }
1773 else
1774 {
1775 // find predecessor of newEvent in map rMapRelabeledEvents[oldEvent] and use that event for relabeling
1776 Idx newLabel = *(--(rMapRelabeledEvents[oldEvent].Find(newEvent)));
1777 etSetIt->second.Ev = newLabel;
1778 // delete newEvent from rGenRelabel if it is no longer needed
1779 if(rMapRelabeledEvents[oldEvent].Find(newEvent)==(--(rMapRelabeledEvents[oldEvent].End())))
1780 {
1781 deleteHighEvents.insert(newEvent);
1782 }
1783 }
1784 }
1785 }
1786 // update the rMapRelabeledEvents with the changes
1787 // as the relabeling of oldEvent is discarded, it is removed from the map of relebeled events and
1788 // reinserted into the map of not relabeled events
1789
1790 // mofidy alphabet of rGenRelabel and the abstraction alphabet by inserting the new high-level events and deleting the not needed new event labels.
1791 set<Idx>::iterator setIt = insertHighEvents.begin();
1792 set<Idx>::iterator setItEnd = insertHighEvents.end();
1793 for(; setIt!= setItEnd; ++ setIt)
1794 {
1795 rHighAlph.Insert(*setIt);
1796 }
1797 setIt = deleteHighEvents.begin();
1798 setItEnd = deleteHighEvents.end();
1799 for(; setIt != setItEnd; ++setIt)
1800 {
1801 rGenRelabel.DelEvent(*setIt);
1802 rHighAlph.Erase(*setIt);
1803 rControllableEvents.Erase(*setIt); // controllable event is erased if it does not exist anymore. Schmidt 10/07
1804 }
1805
1806 rControllableEvents = rControllableEvents * rGenRelabel.Alphabet(); // Schmidt 10/07
1807 // check if quotient automaton is deterministic and free of unobservable transitions, i.e., no transitions are relabeled and no low-level events are declared as high-level events
1808 if(editTransSet.empty()&& quotAuotTrue== true)
1809 {
1810 OP_DF("relabel: Leaving function relabel with true");
1811 return true;
1812 }
1813
1814 // delete original trnasitions and create relabeled transitions in rGenRelabel
1815 etSetIt = editTransSet.begin();
1816 etSetItEnd = editTransSet.end();
1817 for(; etSetIt != etSetItEnd; ++etSetIt)
1818 {
1819 map<Transition,Transition>::iterator mrIt;
1820 mrIt=rMapChangedTransReverse.find(*(etSetIt->first));
1821 // if the current relabeled transition has already been relabeled in a previous step of the observer algorithm, the original transition is found in the rMapChangedTransReverse map.
1822 if(mrIt!=rMapChangedTransReverse.end())
1823 {
1824 Transition originalTrans = mrIt->second;
1825 (rMapChangedTrans.find(originalTrans))->second = (etSetIt->second).Ev;
1826 rMapChangedTransReverse.erase(mrIt);
1827 rMapChangedTransReverse[etSetIt->second]=originalTrans;
1828 OP_DF("relabel: The transition X1= " << rGenRelabel.SStr((etSetIt->first)->X1) << " Ev=" << rGenRelabel.EStr((etSetIt->first)->Ev) << " X2= " << rGenRelabel.SStr((etSetIt->first)->X2) << " has already been relabeled in a former iteration step. The original transition was " << rGenRelabel.SStr(originalTrans.X1) << " Ev=" << rGenRelabel.EStr(originalTrans.Ev) << " X2= " << rGenRelabel.SStr(originalTrans.X2) << "; the new label is " << rGenRelabel.EStr((etSetIt->second).Ev));
1829 }
1830 // the current relabeled transition is simply inserted in the rMapChangedTrans map with its original transition if it is the first relabeling.
1831 else
1832 {
1833 rMapChangedTransReverse[etSetIt->second]=*(etSetIt->first);
1834 rMapChangedTrans[*(etSetIt->first)]=(etSetIt->second).Ev;
1835 OP_DF("relabel: First relabeling of transition X1=" << rGenRelabel.SStr((etSetIt->first)->X1)
1836 << " Ev=" << rGenRelabel.EStr((etSetIt->first)->Ev) << " X2= " << rGenRelabel.SStr((etSetIt->first)->X2) << " new label is " << rGenRelabel.EStr((etSetIt->second).Ev));
1837 }
1838 // The old transition is removed and the new transition is inserted into rGenRelabel
1839 rGenRelabel.ClrTransition(etSetIt->first);
1840 rGenRelabel.SetTransition(etSetIt->second);
1841 }
1842
1843 OP_DF("relabel: leaving function with false");
1844 return false;
1845}
1846
1847// insertRelabeledEvents(rGenPlant, rMapRelabeledEvents, rNewEvents)
1848void insertRelabeledEvents(System& rGenPlant, const map<Idx,set<Idx> >& rMapRelabeledEvents, Alphabet& rNewEvents) {
1849 map<Idx,set<Idx> >::const_iterator reEndIt = rMapRelabeledEvents.end();
1850 TransSet::Iterator tsEndIt = rGenPlant.TransRelEnd();
1851 TransSet::Iterator tsIt = rGenPlant.TransRelBegin();
1852 // check all transitions of rGenPlant
1853 for(; tsIt != tsEndIt; tsIt++){
1854 map<Idx,set<Idx> >::const_iterator reIt = rMapRelabeledEvents.find(tsIt->Ev);
1855 if(reIt == reEndIt) continue;
1856 AttributeCFlags attr = rGenPlant.EventAttribute(tsIt->Ev);
1857 set<Idx>::const_iterator rsEndIt = reIt->second.end();
1858 set<Idx>::const_iterator rsIt = reIt->second.begin();
1859 // if a transition with an event that gets new labels has been found, parallel transitions
1860 // with the new events are added to rGenPlant
1861 for(; rsIt != rsEndIt; rsIt++){
1862 rGenPlant.InsEvent(*rsIt,attr);
1863 rNewEvents.Insert(*rsIt,attr);
1864 rGenPlant.SetTransition(tsIt->X1,*rsIt,tsIt->X2);
1865 }
1866 }
1867}
1868
1869// insertRelabeledEvents(rGenPlant, rMapRelabeledEvents, rNewEvents)
1870// tm: alternative, smart on attributes
1871void insertRelabeledEvents(Generator& rGenPlant, const map<Idx,set<Idx> >& rMapRelabeledEvents, EventSet& rNewEvents) {
1872 map<Idx,set<Idx> >::const_iterator reEndIt = rMapRelabeledEvents.end();
1873 TransSet::Iterator tsEndIt = rGenPlant.TransRelEnd();
1874 TransSet::Iterator tsIt = rGenPlant.TransRelBegin();
1875 // check all transitions of rGenPlant
1876 for(; tsIt != tsEndIt; tsIt++){
1877 map<Idx,set<Idx> >::const_iterator reIt = rMapRelabeledEvents.find(tsIt->Ev);
1878 if(reIt == reEndIt) continue;
1879 AttributeVoid* attrp = rGenPlant.EventAttribute(tsIt->Ev).Copy();
1880 set<Idx>::const_iterator rsEndIt = reIt->second.end();
1881 set<Idx>::const_iterator rsIt = reIt->second.begin();
1882 // if a transition with an event that gets new labels has been found, parallel transitions
1883 // with the new events are added to rGenPlant
1884 for(; rsIt != rsEndIt; rsIt++){
1885 rGenPlant.InsEvent(*rsIt);
1886 rGenPlant.EventAttribute(*rsIt,*attrp);
1887 rNewEvents.Insert(*rsIt);
1888 rNewEvents.Attribute(*rsIt,*attrp);
1889 rGenPlant.SetTransition(tsIt->X1,*rsIt,tsIt->X2);
1890 // should also copy transition attribute
1891 }
1892 delete attrp;
1893 }
1894}
1895
1896// insertRelabeledEvents(rGenPlant, rMapRelabeledEvents)
1897void insertRelabeledEvents(System& rGenPlant, const map<Idx,set<Idx> >& rMapRelabeledEvents) {
1898 Alphabet dummy;
1899 insertRelabeledEvents(rGenPlant,rMapRelabeledEvents,dummy);
1900}
1901
1902// insertRelabeledEvents(rGenPlant, rMapRelabeledEvents)
1903void insertRelabeledEvents(Generator& rGenPlant, const map<Idx,set<Idx> >& rMapRelabeledEvents) {
1904 EventSet dummy;
1905 insertRelabeledEvents(rGenPlant,rMapRelabeledEvents,dummy);
1906}
1907
1908
1909
1910
1911/**
1912 * RTI convenience wrapper
1913 */
1915 System& rGenObs,
1916 EventSet& rHighAlph,
1917 EventSet& rNewHighAlph,
1918 EventRelabelMap& rMapRelabeledEvents)
1919{
1920 calcAbstAlphObs(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents.StlMap());
1921}
1922
1923
1924/**
1925 * RTI convenience wrapper
1926 */
1927void insertRelabeledEvents(Generator& rGenPlant, const EventRelabelMap& rMapRelabeledEvents, EventSet& rNewEvents) {
1928 insertRelabeledEvents(rGenPlant, rMapRelabeledEvents.StlMap(), rNewEvents);
1929}
1930
1931/**
1932 * RTI convenience wrapper
1933 */
1934void insertRelabeledEvents(Generator& rGenPlant, const EventRelabelMap& rMapRelabeledEvents) {
1935 insertRelabeledEvents(rGenPlant, rMapRelabeledEvents.StlMap());
1936}
1937
1938/**
1939 * RTI wrapper class implementation
1940 */
1941
1942// std faudes type
1943FAUDES_TYPE_IMPLEMENTATION(EventRelabelMap,EventRelabelMap,Type)
1944
1945// construct/destruct
1949
1950// clear
1951void EventRelabelMap::Clear(void) { mMap.clear(); }
1952
1953// assignment/equality
1955bool EventRelabelMap::DoEqual(const EventRelabelMap& rOther) const { return mMap==rOther.mMap;}
1956
1957// access
1958const std::map<Idx, std::set<Idx> >& EventRelabelMap::StlMap(void) const { return mMap;}
1959std::map<Idx, std::set<Idx> >& EventRelabelMap::StlMap(void) { return mMap;}
1960void EventRelabelMap::StlMap(const std::map<Idx, std::set<Idx> >& rMap) { mMap=rMap;}
1961
1962
1963
1964}// namespace
1965
#define FAUDES_TYPE_IMPLEMENTATION(ftype, ctype, cbase)
Definition cfl_types.h:958
virtual void DoAssign(const EventRelabelMap &rSrc)
virtual bool DoEqual(const EventRelabelMap &rOther) const
const std::map< Idx, std::set< Idx > > & StlMap(void) const
std::map< Idx, std::set< Idx > > mMap
const std::string & Name(void) const
bool Exists(const Idx &rIndex) const
bool Insert(const Idx &rIndex)
virtual bool Erase(const Idx &rIndex)
static SymbolTable * GlobalEventSymbolTablep(void)
std::string Symbol(Idx index) const
Iterator Begin(void) const
Iterator End(void) const
Iterator BeginByX2(Idx x2) const
Iterator EndByX2(Idx x2) const
void EventAttribute(Idx index, const EventAttr &rAttr)
bool InsEvent(Idx index)
const TaEventSet< EventAttr > & Alphabet(void) const
bool SetTransition(Idx x1, Idx ev, Idx x2)
virtual bool Insert(const Idx &rIndex)
EventSet ControllableEvents(void) const
void SetControllable(Idx index)
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
StateSet::Iterator StatesBegin(void) const
const TransSet & TransRel(void) const
bool SetTransition(Idx x1, Idx ev, Idx x2)
const EventSet & Alphabet(void) const
TransSet::Iterator TransRelBegin(void) const
void ClrTransition(Idx x1, Idx ev, Idx x2)
SymbolTable * EventSymbolTablep(void) const
bool DelEvent(Idx index)
virtual void EventAttribute(Idx index, const Type &rAttr)
void InjectStates(const StateSet &rNewStates)
EventSet::Iterator AlphabetBegin(void) const
std::string TStr(const Transition &rTrans) const
std::string StateName(Idx index) const
virtual void DotWrite(const std::string &rFileName) const
StateSet::Iterator StatesEnd(void) const
TransSet::Iterator TransRelEnd(void) const
std::string EStr(Idx index) const
bool InsEvent(Idx index)
std::string EventName(Idx index) const
EventSet::Iterator AlphabetEnd(void) const
Idx Size(void) const
std::string SStr(Idx index) const
virtual void Clear(void)
bool ExistsMarkedState(Idx index) const
const StateSet & States(void) const
void InjectAlphabet(const EventSet &rNewalphabet)
bool Empty(void) const
bool Exists(const T &rElem) const
IndexSet StateSet
virtual void Clear(void)
Iterator End(void) const
virtual void InsertSet(const TBaseSet &rOtherSet)
Iterator Begin(void) const
virtual const AttributeVoid & Attribute(const T &rElem) const
Idx Size(void) const
void ComputeBisimulation(const Generator &rGenOrig, map< Idx, Idx > &rMapStateToPartition)
void calcAbstAlphObsLCC(System &rGenObs, EventSet &rHighAlph, EventSet &rNewHighAlph, map< Idx, set< Idx > > &rMapRelabeledEvents)
Int calcNaturalObserver(const Generator &rGen, EventSet &rHighAlph)
void calcAbstAlphObs(System &rGenObs, EventSet &rHighAlph, EventSet &rNewHighAlph, map< Idx, set< Idx > > &rMapRelabeledEvents)
void calcAbstAlphMSA(System &rGenObs, EventSet &rHighAlph, EventSet &rNewHighAlph, map< Idx, set< Idx > > &rMapRelabeledEvents)
Int calcMSAObserverLCC(const Generator &rGen, const EventSet &rControllableEvents, EventSet &rHighAlph)
void calcAbstAlphClosed(System &rGenObs, EventSet &rHighAlph, EventSet &rNewHighAlph, map< Idx, set< Idx > > &rMapRelabeledEvents)
void calcAbstAlphMSALCC(System &rGenObs, EventSet &rHighAlph, EventSet &rNewHighAlph, map< Idx, set< Idx > > &rMapRelabeledEvents)
Int calcNaturalObserverLCC(const Generator &rGen, const EventSet &rControllableEvents, EventSet &rHighAlph)
Idx calcClosedObserver(const Generator &rGen, EventSet &rHighAlph)
void ExtendHighAlphabet(const Generator &rGen, EventSet &rHighAlph, map< Idx, Idx > &rMapStateToPartition)
Int calcMSAObserver(const Generator &rGen, EventSet &rHighAlph)
uint32_t Idx
bool recursiveCheckMSABackward(const Generator &rGen, const TransSetX2EvX1 &rRevTransSet, const EventSet &rHighAlph, Idx currentState, StateSet &rDoneStates)
void recursiveCheckLCC(const TransSetX2EvX1 &rRevTransSet, const EventSet &rControllableEvents, const EventSet &rHighAlph, Idx currentState, StateSet &rDoneStates)
void calculateDynamicSystemMSA(const Generator &rGen, EventSet &rHighAlph, Generator &rGenDyn)
void calculateDynamicSystemClosedObs(const Generator &rGen, EventSet &rHighAlph, Generator &rGenDyn)
void calculateDynamicSystemLCC(const Generator &rGen, const EventSet &rControllableEvents, const EventSet &rHighAlph, Generator &rGenDyn)
void LocalCoaccessibleReach(const TransSetX2EvX1 &rRevTransRel, const EventSet &rHighAlph, Idx lowState, StateSet &rCoaccessibleReach)
void insertRelabeledEvents(System &rGenPlant, const map< Idx, set< Idx > > &rMapRelabeledEvents, Alphabet &rNewEvents)
void LocalAccessibleReach(const Generator &rLowGen, const EventSet &rHighAlph, Idx lowState, StateSet &rAccessibleReach)
std::string ToStringInteger(Int number)
Definition cfl_utils.cpp:43
bool CheckSplit(const Generator &rGen, const EventSet &rSplitAlphabet, const vector< pair< StateSet, Idx > > &rNondeterministicStates, Idx entryState)
void backwardReachabilityObsOCC(const TransSetX2EvX1 &rTransSetX2EvX1, const EventSet &rControllableEvents, const EventSet &rHighAlph, Idx exitState, Idx currentState, bool controllablePath, map< Idx, map< Idx, bool > > &rExitLocalStatesMap, StateSet &rDoneStates)
bool recursiveCheckMSAForward(const Generator &rGen, const EventSet &rHighAlph, Idx currentState, StateSet &rDoneStates)
bool relabel(Generator &rGenRelabel, EventSet &rControllableEvents, EventSet &rHighAlph, map< Idx, Idx > &rMapStateToPartition, map< Transition, Transition > &rMapChangedTransReverse, map< Transition, Idx > &rMapChangedTrans, map< Idx, EventSet > &rMapRelabeledEvents)
long int Int
void calculateDynamicSystemObs(const Generator &rGen, EventSet &rHighAlph, Generator &rGenDyn)
#define OP_DF(expr)
Definition op_debug.h:31

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