op_observercomputation.cpp
Go to the documentation of this file.
1 /** @file op_observercomputation.cpp
2 
3 Methods to compute natural projections that exhibit the obsrver property.
4 The observer algorithm is elaborated in
5 K. C. Wong and W. M. Wonham, "On the Computation of Observers in Discrete Event
6 Systems," Discrete Event Dynamic Systems, vol. 14, no. 1, pp. 55-107, 2004.
7 In addition, methods to compute natural projections that exhibit
8 output control consistency (OCC) and local control consistency (LCC) are provided. See for example
9 K. Schmidt and C. Breindl, "On Maximal Permissiveness of Hierarchical and Modular Supervisory
10 Control Approaches for Discrete Event Systems," Workshop on Discrete Event Systems, 2008.
11 Furthermore, an algorithm for computing natural observers without changing event labels as
12 presented in
13 Lei Feng; Wonham, W.M., "On the Computation of Natural Observers in Discrete-Event Systems,"
14 Decision and Control, 2006 45th IEEE Conference on , vol., no., pp.428-433, 13-15 Dec. 2006
15 is 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 
37 #include "op_observercomputation.h"
38 #include "cfl_localgen.h"
39 
40 using namespace std;
41 
42 namespace faudes{
43 
44 
45 // calculateDynamicSystemClosedObs(rGen, rHighAlph, rGenDyn)
46 void 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 
62  TransSetX2EvX1::Iterator tItByX2Ev;
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)
159 void 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)
195 void 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;
205  TransSet::Iterator tIt;
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 
252 bool 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 
278 bool 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)
303 void 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
310  TransSet::Iterator tIt;
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 
387 void 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)
413 Idx 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)
433 Int 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)
454 Int 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)
476 Int 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)
497 Int 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)
520 void 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)
634 bool 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)
667 void 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)
678 void 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)
701 void 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)
746 void 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)
757 void 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)
780 void 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)
825 void 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)
836 void 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)
859 void 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)
979 void 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)
1085 void 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)
1132 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){
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)
1171 void 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)
1198 void 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)
1245 void 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)
1272 void 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)
1319 void 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)
1424 void 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)
1463 bool 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)
1848 void 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
1871 void 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)
1897 void insertRelabeledEvents(System& rGenPlant, const map<Idx,set<Idx> >& rMapRelabeledEvents) {
1898  Alphabet dummy;
1899  insertRelabeledEvents(rGenPlant,rMapRelabeledEvents,dummy);
1900 }
1901 
1902 // insertRelabeledEvents(rGenPlant, rMapRelabeledEvents)
1903 void 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  */
1927 void insertRelabeledEvents(Generator& rGenPlant, const EventRelabelMap& rMapRelabeledEvents, EventSet& rNewEvents) {
1928  insertRelabeledEvents(rGenPlant, rMapRelabeledEvents.StlMap(), rNewEvents);
1929 }
1930 
1931 /**
1932  * Rti convenience wrapper
1933  */
1934 void 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
1943 FAUDES_TYPE_IMPLEMENTATION(EventRelabelMap,EventRelabelMap,Type)
1944 
1945 // construct/destruct
1947 EventRelabelMap::EventRelabelMap(const EventRelabelMap& rOther) : Type() {mMap=rOther.mMap; }
1949 
1950 // clear
1951 void EventRelabelMap::Clear(void) { mMap.clear(); }
1952 
1953 // assignment/equality
1955 bool EventRelabelMap::DoEqual(const EventRelabelMap& rOther) const { return mMap==rOther.mMap;}
1956 
1957 // access
1958 const std::map<Idx, std::set<Idx> >& EventRelabelMap::StlMap(void) const { return mMap;}
1959 std::map<Idx, std::set<Idx> >& EventRelabelMap::StlMap(void) { return mMap;}
1960 void EventRelabelMap::StlMap(const std::map<Idx, std::set<Idx> >& rMap) { mMap=rMap;}
1961 
1962 
1963 
1964 }// namespace
1965 
Helper functions for projected generators.
#define FAUDES_TYPE_IMPLEMENTATION(ftype, ctype, cbase)
faudes type implementation macros, overall
Definition: cfl_types.h:946
Attribute class to model event controllability properties.
Minimal Attribute.
Rti convenience wrapper for relabeling maps.
virtual void DoAssign(const EventRelabelMap &rSrc)
virtual bool DoEqual(const EventRelabelMap &rOther) const
virtual void Clear(void)
Clear configuration data.
const std::map< Idx, std::set< Idx > > & StlMap(void) const
std::map< Idx, std::set< Idx > > mMap
Set of indices.
Definition: cfl_indexset.h:78
Idx Insert(void)
Insert new index to set.
Set of indices with symbolic names.
Definition: cfl_nameset.h:69
bool Exists(const Idx &rIndex) const
Test existence of index.
bool Insert(const Idx &rIndex)
Add an element by index.
virtual bool Erase(const Idx &rIndex)
Delete element by index.
std::string Symbol(Idx index) const
Symbolic name lookup.
Iterator class for high-level api to TBaseSet.
Definition: cfl_baseset.h:387
Set of Transitions.
Definition: cfl_transset.h:242
Iterator Begin(void) const
Iterator to begin of set.
Iterator End(void) const
Iterator to end of set.
Iterator BeginByX2(Idx x2) const
Iterator to first Transition specified by successor state x2.
Iterator EndByX2(Idx x2) const
Iterator to first Transition after specified successor state x2.
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
Iterator on transition.
Definition: cfl_transset.h:269
void EventAttribute(Idx index, const EventAttr &rAttr)
Set attribute for existing event.
bool InsEvent(Idx index)
Add an existing event to alphabet by index.
const TaEventSet< EventAttr > & Alphabet(void) const
Return const reference to alphabet.
bool SetTransition(Idx x1, Idx ev, Idx x2)
Add a transition to generator by indices.
Set of indices with symbolic names and attributes.
Definition: cfl_nameset.h:564
virtual bool Insert(const Idx &rIndex)
Add an element by index.
Definition: cfl_nameset.h:988
Generator with controllability attributes.
EventSet ControllableEvents(void) const
Get EventSet with controllable events.
void SetControllable(Idx index)
Mark event controllable (by index)
Triple (X1,Ev,X2) to represent current state, event and next state.
Definition: cfl_transset.h:57
Idx X1
Current state.
Definition: cfl_transset.h:99
Idx X2
Next state.
Definition: cfl_transset.h:108
Base class of all libFAUDES objects that participate in the run-time interface.
Definition: cfl_types.h:239
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
Write configuration data to a string.
Definition: cfl_types.cpp:169
Base class of all FAUDES generators.
StateSet::Iterator StatesBegin(void) const
Iterator to Begin() of state set.
const TransSet & TransRel(void) const
Return reference to transition relation.
bool SetTransition(Idx x1, Idx ev, Idx x2)
Add a transition to generator by indices.
const EventSet & Alphabet(void) const
Return const reference to alphabet.
void ClearTransRel(void)
Clear all transitions.
TransSet::Iterator TransRelBegin(void) const
Iterator to Begin() of transition relation.
void ClrTransition(Idx x1, Idx ev, Idx x2)
Remove a transition by indices.
SymbolTable * EventSymbolTablep(void) const
Get Pointer to EventSymbolTable currently used by this vGenerator.
bool DelEvent(Idx index)
Delete event from generator by index.
virtual void EventAttribute(Idx index, const Type &rAttr)
Set attribute for existing event.
void InjectStates(const StateSet &rNewStates)
Inject a complete state set without consistency checks (without attributes)
EventSet::Iterator AlphabetBegin(void) const
Iterator to Begin() of alphabet.
std::string TStr(const Transition &rTrans) const
Return pretty printable transition (eg for debugging)
std::string StateName(Idx index) const
State name lookup.
virtual void DotWrite(const std::string &rFileName) const
Writes generator to dot input format.
void Name(const std::string &rName)
Set the generator's name.
StateSet::Iterator StatesEnd(void) const
Iterator to End() of state set.
TransSet::Iterator TransRelEnd(void) const
Iterator to End() of transition relation.
std::string EStr(Idx index) const
Pretty printable event name for index (eg for debugging).
bool InsEvent(Idx index)
Add an existing event to alphabet by index.
std::string EventName(Idx index) const
Event name lookup.
EventSet::Iterator AlphabetEnd(void) const
Iterator to End() of alphabet.
Idx Size(void) const
Get generator size (number of states)
std::string SStr(Idx index) const
Return pretty printable state name for index (eg for debugging)
virtual void Clear(void)
Clear generator data.
bool ExistsMarkedState(Idx index) const
Test existence of state in mMarkedStates.
const StateSet & States(void) const
Return reference to state set.
void InjectAlphabet(const EventSet &rNewalphabet)
Set mpAlphabet without consistency check.
bool Empty(void) const
Test whether if the TBaseSet is Empty.
Definition: cfl_baseset.h:1824
bool Exists(const T &rElem) const
Test existence of element.
Definition: cfl_baseset.h:2115
IndexSet StateSet
Definition: cfl_indexset.h:271
virtual void Clear(void)
Clear all set.
Definition: cfl_baseset.h:1902
Iterator End(void) const
Iterator to the end of set.
Definition: cfl_baseset.h:1896
virtual void InsertSet(const TBaseSet &rOtherSet)
Insert elements given by rOtherSet.
Definition: cfl_baseset.h:1987
Iterator Begin(void) const
Iterator to the begin of set.
Definition: cfl_baseset.h:1891
virtual const AttributeVoid & Attribute(const T &rElem) const
Attribute access.
Definition: cfl_baseset.h:2290
const std::string & Name(void) const
Return name of TBaseSet.
Definition: cfl_baseset.h:1755
Idx Size(void) const
Get Size of TBaseSet.
Definition: cfl_baseset.h:1819
void ComputeBisimulation(const Generator &rGenOrig, map< Idx, Idx > &rMapStateToPartition)
Computation of the coarsest bisimulation relation for a specified generator.
Int calcMSAObserverLCC(const Generator &rGen, const EventSet &rControllableEvents, EventSet &rHighAlph)
MSA-observer computation including local control consistency (LCC) by adding events to the high-level...
Idx calcClosedObserver(const Generator &rGen, EventSet &rHighAlph)
L(G)-observer computation by adding events to the high-level alphabet.
Int calcNaturalObserverLCC(const Generator &rGen, const EventSet &rControllableEvents, EventSet &rHighAlph)
Lm(G)-observer computation including local control consistency (LCC) by adding events to the high-lev...
void ExtendHighAlphabet(const Generator &rGen, EventSet &rHighAlph, map< Idx, Idx > &rMapStateToPartition)
Extension of the high-level alphabet to achieve the Lm-observer property.
Int calcNaturalObserver(const Generator &rGen, EventSet &rHighAlph)
Lm(G)-observer computation by adding events to the high-level alphabet.
Int calcMSAObserver(const Generator &rGen, EventSet &rHighAlph)
MSA-observer computation by adding events to the high-level alphabet.
libFAUDES resides within the namespace faudes.
uint32_t Idx
Type definition for index type (allways 32bit)
bool recursiveCheckMSABackward(const Generator &rGen, const TransSetX2EvX1 &rRevTransSet, const EventSet &rHighAlph, Idx currentState, StateSet &rDoneStates)
Check if the msa-observer conditions is fulfilled for a given state.
void calcAbstAlphObs(System &rGenObs, EventSet &rHighAlph, EventSet &rNewHighAlph, EventRelabelMap &rMapRelabeledEvents)
Rti convenience wrapper.
void recursiveCheckLCC(const TransSetX2EvX1 &rRevTransSet, const EventSet &rControllableEvents, const EventSet &rHighAlph, Idx currentState, StateSet &rDoneStates)
Find states that fulfill the lcc condition.
void calcAbstAlphMSA(Generator &rGenObs, EventSet &rControllableEvents, EventSet &rHighAlph, EventSet &rNewHighAlph, map< Transition, Idx > &rMapChangedTrans)
MSA-observer computation.
void calculateDynamicSystemMSA(const Generator &rGen, EventSet &rHighAlph, Generator &rGenDyn)
Computation of the dynamic system for Delta_msa (local fulfillment of the msa-observer property).
void insertRelabeledEvents(Generator &rGenPlant, const EventRelabelMap &rMapRelabeledEvents)
Rti convenience wrapper.
void calculateDynamicSystemClosedObs(const Generator &rGen, EventSet &rHighAlph, Generator &rGenDyn)
Computation of the dynamic system for Delta_sigma (reachable states after the occurrence of one high-...
void calculateDynamicSystemLCC(const Generator &rGen, const EventSet &rControllableEvents, const EventSet &rHighAlph, Generator &rGenDyn)
Computation of the dynamic system for Delta_lcc (fulfillment of the local control consistency propert...
void LocalCoaccessibleReach(const TransSetX2EvX1 &rRevTransRel, const EventSet &rHighAlph, Idx lowState, StateSet &rCoaccessibleReach)
Compute the coaccessible reach for a local automaton.
void calcAbstAlphMSALCC(Generator &rGenObs, EventSet &rControllableEvents, EventSet &rHighAlph, EventSet &rNewHighAlph, map< Transition, Idx > &rMapChangedTrans)
MSA-observer computation including local control consistency (LCC).
void LocalAccessibleReach(const Generator &rLowGen, const EventSet &rHighAlph, Idx lowState, StateSet &rAccessibleReach)
Compute the accessible reach for a local automaton.
std::string ToStringInteger(Int number)
integer to string
Definition: cfl_helper.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)
Check if the msa-observer conditions is fulfilled for a given state.
bool relabel(Generator &rGenRelabel, EventSet &rControllableEvents, EventSet &rHighAlph, map< Idx, Idx > &rMapStateToPartition, map< Transition, Transition > &rMapChangedTransReverse, map< Transition, Idx > &rMapChangedTrans, map< Idx, EventSet > &rMapRelabeledEvents)
Relabeling algorithm for the computation of an Lm-observer.
void calcAbstAlphClosed(Generator &rGenObs, EventSet &rControllableEvents, EventSet &rHighAlph, EventSet &rNewHighAlph, map< Transition, Idx > &rMapChangedTrans)
L(G)-observer computation.
void calcAbstAlphObsLCC(Generator &rGenObs, EventSet &rControllableEvents, EventSet &rHighAlph, EventSet &rNewHighAlph, map< Transition, Idx > &rMapChangedTrans)
Lm-observer computation including local control consistency (LCC).
long int Int
Type definition for integer type (let target system decide, minimum 32bit)
void calculateDynamicSystemObs(const Generator &rGen, EventSet &rHighAlph, Generator &rGenDyn)
Computation of the dynamic system for Delta_obs (local reachability of a marked state).
#define OP_DF(expr)
Definition: op_debug.h:31
Methods to compute natural projections that exhibit the observer property.

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