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.SetUnion(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.SetUnion(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  vector<Idx> newPartitions;
418  EventSet origAlph;
419  Generator genPart;
420  while(origAlph != rHighAlph){
421  origAlph = rHighAlph;
422  dynGen.Clear();
423  // compute the dynamic system for the given generator and high-level alphabet
424  calculateDynamicSystemClosedObs(rGen, rHighAlph, dynGen);
425  // compute the quasi conqruence
426  mapStateToPartition.clear();
427  newPartitions.clear();
428  genPart.Clear();
429  calcBisimulation(dynGen, mapStateToPartition, genPart, newPartitions);
430  // Extend the high-level alphabet according to the algorithm of Lei
431  ExtendHighAlphabet(rGen, rHighAlph, mapStateToPartition);
432  }
433  return genPart.Size();
434 }
435 
436 // calcNaturalObserver(rGen,rHighAlph)
437 Int calcNaturalObserver(const Generator& rGen, EventSet& rHighAlph){
438  // helpers
439  Generator dynGen;
440  map<Idx,Idx> mapStateToPartition;
441  vector<Idx> newPartitions;
442  EventSet origAlph;
443  Generator genPart;
444  while(origAlph != rHighAlph){
445  origAlph = rHighAlph;
446  dynGen.Clear();
447  // compute the dynamic system for the given generator and high-level alphabet
448  calculateDynamicSystemClosedObs(rGen, rHighAlph, dynGen);
449  calculateDynamicSystemObs(rGen, rHighAlph, dynGen);
450  // compute the quasi conqruence
451  mapStateToPartition.clear();
452  newPartitions.clear();
453  genPart.Clear();
454  calcBisimulation(dynGen, mapStateToPartition, genPart, newPartitions);
455  // Extend the high-level alphabet according to the algorithm of Lei
456  ExtendHighAlphabet(rGen, rHighAlph, mapStateToPartition);
457  }
458  return genPart.Size();
459 }
460 
461 // calcNaturalObserverLCC(rGen,rHighAlph)
462 Int calcNaturalObserverLCC(const Generator& rGen, const EventSet& rControllableEvents, EventSet& rHighAlph){
463  // helpers
464  Generator dynGen;
465  map<Idx,Idx> mapStateToPartition;
466  vector<Idx> newPartitions;
467  EventSet origAlph;
468  Generator genPart;
469  while(origAlph != rHighAlph){
470  origAlph = rHighAlph;
471  dynGen.Clear();
472  // compute the dynamic system for the given generator and high-level alphabet
473  calculateDynamicSystemClosedObs(rGen, rHighAlph, dynGen);
474  calculateDynamicSystemLCC(rGen, rControllableEvents, rHighAlph, dynGen);
475  calculateDynamicSystemObs(rGen, rHighAlph, dynGen);
476  // compute the quasi conqruence
477  mapStateToPartition.clear();
478  newPartitions.clear();
479  genPart.Clear();
480  calcBisimulation(dynGen, mapStateToPartition, genPart, newPartitions);
481  // Extend the high-level alphabet according to the algorithm of Lei
482  ExtendHighAlphabet(rGen, rHighAlph, mapStateToPartition);
483  }
484  return genPart.Size();
485 }
486 
487 // calcMSAObserver(rGen,rHighAlph)
488 Int calcMSAObserver(const Generator& rGen, EventSet& rHighAlph){
489  // helpers
490  Generator dynGen;
491  map<Idx,Idx> mapStateToPartition;
492  vector<Idx> newPartitions;
493  EventSet origAlph;
494  Generator genPart;
495  while(origAlph != rHighAlph){
496  origAlph = rHighAlph;
497  dynGen.Clear();
498  // compute the dynamic system for the given generator and high-level alphabet
499  calculateDynamicSystemClosedObs(rGen, rHighAlph, dynGen);
500  calculateDynamicSystemMSA(rGen, rHighAlph, dynGen);
501  // compute the quasi conqruence
502  mapStateToPartition.clear();
503  newPartitions.clear();
504  genPart.Clear();
505  calcBisimulation(dynGen, mapStateToPartition, genPart, newPartitions);
506  // Extend the high-level alphabet according to the algorithm of Lei
507  ExtendHighAlphabet(rGen, rHighAlph, mapStateToPartition);
508  }
509  return genPart.Size();
510 }
511 
512 // calcMSAObserverLCC(rGen,rHighAlph)
513 Int calcMSAObserverLCC(const Generator& rGen, const EventSet& rControllableEvents, EventSet& rHighAlph){
514  // helpers
515  Generator dynGen;
516  map<Idx,Idx> mapStateToPartition;
517  vector<Idx> newPartitions;
518  EventSet origAlph;
519  Generator genPart;
520  while(origAlph != rHighAlph){
521  origAlph = rHighAlph;
522  dynGen.Clear();
523  // compute the dynamic system for the given generator and high-level alphabet
524  calculateDynamicSystemClosedObs(rGen, rHighAlph, dynGen);
525  calculateDynamicSystemLCC(rGen, rControllableEvents, rHighAlph, dynGen);
526  calculateDynamicSystemMSA(rGen, rHighAlph, dynGen);
527  // compute the quasi conqruence
528  mapStateToPartition.clear();
529  newPartitions.clear();
530  genPart.Clear();
531  calcBisimulation(dynGen, mapStateToPartition, genPart, newPartitions);
532  // Extend the high-level alphabet according to the algorithm of Lei
533  ExtendHighAlphabet(rGen, rHighAlph, mapStateToPartition);
534  }
535  return genPart.Size();
536 }
537 
538 
539 // ExtendHighAlphabet(rGen,rHighAlph,rMapStateToPartition)
540 void ExtendHighAlphabet(const Generator& rGen, EventSet& rHighAlph, map<Idx,Idx>& rMapStateToPartition){
541 
542  OP_DF("relabel(" << rGen.Name() << "," << rHighAlph.Name() << ", rMapStateToPartition)");
543 
544  // helpers
545  map<Idx,Idx>::const_iterator spIt, spEndIt;
546  spIt = rMapStateToPartition.begin();
547  spEndIt = rMapStateToPartition.end();
548  // Determine map from Partition to states from the rMapStateToPartition
549  map<Idx,StateSet> partitionToStateMap; // (coset,states)
550  map<Idx,StateSet>::iterator fIt, fEndIt;
551  for( ; spIt != spEndIt; spIt++){
552  fIt = partitionToStateMap.find(spIt->second);
553  if(fIt == partitionToStateMap.end() ){
554  partitionToStateMap[spIt->second] = StateSet();
555  }
556  partitionToStateMap[spIt->second].Insert(spIt->first);
557 
558  }
559  // local events that lead to a different coset
560  EventSet localViolatingEvents;
561  // local events that appear inside the cosets
562  EventSet localEvents;
563  // vector for the nondeterministic exit states for each coset
564  map<Idx,vector<pair<StateSet, Idx> > > nondeterministicStates; // coset, nondet states, event)
565  StateSet::Iterator stIt, stEndIt;
566  // Go through all cosets and identify local violating events and all local events
567  fIt = partitionToStateMap.begin();
568  fEndIt = partitionToStateMap.end();
569  for( ; fIt != fEndIt; fIt++){
570  // Current Coset
571  Idx currentCoset = fIt->first;
572  // Examine all states of the current coset
573  stIt = fIt->second.Begin();
574  stEndIt = fIt->second.End();
575  // map from event to exit states and goal cosets
576  map<Idx,map<Idx,pair<StateSet,IndexSet> > > eventStatesMap; // (coset, event, exit states, goal cosets)
577 
578  for( ; stIt != stEndIt; stIt++){
579  TransSet::Iterator tIt, tEndIt;
580  tIt = rGen.TransRelBegin(*stIt);
581  tEndIt = rGen.TransRelEnd(*stIt);
582  for( ; tIt != tEndIt; tIt++){
583  // local event
584  if(!rHighAlph.Exists(tIt->Ev) ){
585  // unobservable transition to other coset
586  if(rMapStateToPartition[tIt->X2] != currentCoset){
587  localViolatingEvents.Insert(tIt->Ev);
588  localEvents.Erase(tIt->Ev);
589  }
590  else{
591  if(!localViolatingEvents.Exists(tIt->Ev) )
592  localEvents.Insert(tIt->Ev);
593  }
594  }
595  // high-level event
596  else{
597  eventStatesMap[fIt->first][tIt->Ev].first.Insert(*stIt);
598  eventStatesMap[fIt->first][tIt->Ev].second.Insert(rMapStateToPartition[tIt->X2]);
599  }
600  }
601  }
602  map<Idx,pair<StateSet,IndexSet> >::const_iterator seIt, seEndIt;
603  seIt = eventStatesMap[fIt->first].begin();
604  seEndIt = eventStatesMap[fIt->first].end();
605  for( ; seIt != seEndIt; seIt ++){
606  // if there is more than one goal coset, the current event introduces nondeterminism in the current coset
607  if(seIt->second.second.Size() > 1){
608  nondeterministicStates[fIt->first].push_back(make_pair(StateSet(),0) );
609  nondeterministicStates[fIt->first].back().first = seIt->second.first;
610  nondeterministicStates[fIt->first].back().second = seIt->first;
611  }
612  }
613  }
614  // All outgoing transitions for any coset are determined. Now, the localViolatingEvents are added
615  // to the high-level alphabet, and the remaining nondeterministic transitions are found
616  rHighAlph = rHighAlph + localViolatingEvents;
617  // 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)
618  if(localViolatingEvents.Empty() == true){
619  // Go through all cosets and identify local violating events and all local events
620  rHighAlph = rHighAlph + localEvents;
621  EventSet::Iterator eIt, eEndIt;
622  eIt = localEvents.Begin();
623  eEndIt = localEvents.End();
624  // check which local events can be removed from the high-level alphabet
625  for( ; eIt != eEndIt; eIt++){
626  rHighAlph.Erase(*eIt);
627  // go through all states of all cosets and check if rHighAlph splits all cosets
628  fIt = partitionToStateMap.begin();
629  fEndIt = partitionToStateMap.end();
630  for( ; fIt != fEndIt; fIt++){
631  if(nondeterministicStates[fIt->first].empty() == true) // no need to split if there are no nondeterministic states
632  continue;
633  stIt = fIt->second.Begin();
634  stEndIt = fIt->second.End();
635  bool erase = true;
636  // Now, all combinations with nondeterministic exit states have to be checked
637  for( ; stIt != stEndIt; stIt++){
638  // if the rHighAlph does not split the coset, the current event cannot be removed
639  if(!CheckSplit(rGen, rHighAlph, nondeterministicStates[fIt->first], *stIt) ){
640  rHighAlph.Insert(*eIt);
641  erase = false;
642  break;
643  }
644  }
645  if(erase == false)
646  break;
647  }
648  }
649  }
650 }
651 
652 
653 // CheckSplit(rGen,rSplitAlphabet,rNondeterministicStates,entryState)
654 bool CheckSplit(const Generator& rGen, const EventSet& rSplitAlphabet, const vector<pair<StateSet, Idx> >& rNondeterministicStates, Idx entryState){
655  StateSet accessibleReach;
656  // compute the local accessible reach for the current entry state
657  LocalAccessibleReach(rGen, rSplitAlphabet, entryState, accessibleReach);
658  // check if for any of the nondeterministic state sets, more than one state appears in the local accessible reach
659  vector<pair<StateSet, Idx> >::const_iterator vsIt, vsEndIt;
660  vsIt = rNondeterministicStates.begin();
661  vsEndIt = rNondeterministicStates.end();
662  bool split = true;
663  for( ; vsIt != vsEndIt; vsIt++){
664  StateSet nondetExit = vsIt->first * accessibleReach;
665  StateSet::Iterator stIt, stEndIt;
666  stIt = nondetExit.Begin();
667  stEndIt = nondetExit.End();
668  StateSet nondetReach;
669  // collect the goal states of the nondeterministic exit states
670  for( ; stIt != stEndIt; stIt++){
671  nondetReach.Insert(rGen.TransRelBegin(*stIt, vsIt->second)->X2);
672  }
673  if( nondetReach.Size() > 1){
674  split = false;
675  break;
676  }
677  }
678  return split;
679 }
680 
681 // ==================================================================================
682 // Functions for the computation of the high-level alphabet with relabeling
683 // ==================================================================================
684 
685 
686 // calcAbstAlphClosed(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
687 void calcAbstAlphClosed(System& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) {
688  OP_DF("calcAbstAlphClosed(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
689  // The controllable events are separated from the System. All functions that are successively
690  // called, are defined for Generators
691  EventSet cntrevs = rGenObs.ControllableEvents();
692  calcAbstAlphClosed(rGenObs, cntrevs , rHighAlph, rNewHighAlph, rMapRelabeledEvents);
693  // the controllable events that have been changed by the called function are set in the System cGenObs
694  rGenObs.SetControllable(cntrevs);
695 }
696 
697 // calcAbstAlphClosed(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
698 void calcAbstAlphClosed(Generator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) {
699  OP_DF("calcAbstAlphClosed(" << rGenObs.Name() << "," << "rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
700  // The function called next returns a relabeled generator and a map of relabeled transitions
701  map<Transition,Idx> changedtrans;
702  calcAbstAlphClosed(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans);
703  // for later use, the relabeled transitions are converted into relabeled events
704  // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty
705  map<Transition,Idx>::iterator rtEndIt = changedtrans.end();
706  map<Transition,Idx>::iterator rtIt = changedtrans.begin();
707  for(; rtIt != rtEndIt; rtIt++){
708  if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){// if the event does not exist, yet, a nex element in the map is created
709  rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>();
710  if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist
711  rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
712  }
713  else { // a new label is inserted into the map
714  if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist
715  rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
716  }
717  }
718 }
719 
720 // calcAbstAlphClosed(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans)
721 void calcAbstAlphClosed(Generator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans)
722 {
723  OP_DF("calcAbstAlphClosed(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)");
724  // Initialization of variables
725  rNewHighAlph = rHighAlph;
726  rMapChangedTrans.clear();
727  Generator genDyn(rGenObs);
728  map<Transition,Transition> mapChangedTransReverse;
729  vector<Idx> newPartitions;
730  map<Idx,Idx> mapStateToPartition;
731  map<Idx, EventSet> mapRelabeledEvents;
732  bool done=false;
733  #ifdef DF_PLOT
734  Idx iterationCount=1;
735  string name;
736  #endif
737  // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition.
738  // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs
739  // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition.
740  while(done==false)
741  {
742  // compute the dynamic system for the given generator and high-level alphabet
743  calculateDynamicSystemClosedObs(rGenObs, rNewHighAlph, genDyn);
744  #ifdef DF_PLOT
745  name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToStringInteger(iterationCount));
746  genDyn.DotWrite(name);
747  #endif
748 
749  Generator genPart;
750  mapStateToPartition.clear();
751  newPartitions.clear();
752 
753  // compute coarsest quasi-congruence on the dynamic system
754  calcBisimulation(genDyn, mapStateToPartition, genPart, newPartitions);
755  #ifdef DF_PLOT
756  name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToStringInteger(iterationCount));
757  genPart.DotWrite(name);
758  ++iterationCount;
759  #endif
760 
761  // check if quotient automaton is deterministic and free of unobservable events
762  // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly
763  done=relabel(rGenObs, rControllableEvents, rNewHighAlph, newPartitions, mapStateToPartition, mapChangedTransReverse, rMapChangedTrans, mapRelabeledEvents);
764  }
765 }
766 
767 
768 // calcAbstAlphObs(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
769 void calcAbstAlphObs(System& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) {
770  OP_DF("calcAbstAlphObs(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
771  // The controllable events are separated from the System. All functions that are successively
772  // called, are defined for Generators
773  EventSet cntrevs = rGenObs.ControllableEvents();
774  calcAbstAlphObs(rGenObs, cntrevs , rHighAlph, rNewHighAlph, rMapRelabeledEvents);
775  // the controllable events that have been changed by the called function are set in the System cGenObs
776  rGenObs.SetControllable(cntrevs);
777 }
778 
779 // calcAbstAlphObs(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
780 void calcAbstAlphObs(Generator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) {
781  OP_DF("calcAbstAlphObs(" << rGenObs.Name() << "," << "rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
782  // The function called next returns a relabeled generator and a map of relabeled transitions
783  map<Transition,Idx> changedtrans;
784  calcAbstAlphObs(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans);
785  // for later use, the relabeled transitions are converted into relabeled events
786  // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty
787  map<Transition,Idx>::iterator rtEndIt = changedtrans.end();
788  map<Transition,Idx>::iterator rtIt = changedtrans.begin();
789  for(; rtIt != rtEndIt; rtIt++){
790  if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){// if the event does not exist, yet, a nex element in the map is created
791  rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>();
792  if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist
793  rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
794  }
795  else { // a new label is inserted into the map
796  if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist
797  rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
798  }
799  }
800 }
801 
802 // calcAbstAlphObs(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans)
803 void calcAbstAlphObs(Generator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans)
804 {
805  OP_DF("calcAbstAlphObs(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)");
806  // Initialization of variables
807  rNewHighAlph = rHighAlph;
808  rMapChangedTrans.clear();
809  Generator genDyn(rGenObs);
810  map<Transition,Transition> mapChangedTransReverse;
811  vector<Idx> newPartitions;
812  map<Idx,Idx> mapStateToPartition;
813  map<Idx, EventSet> mapRelabeledEvents;
814  bool done=false;
815  #ifdef DF_PLOT
816  Idx iterationCount=1;
817  string name;
818  #endif
819  // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition.
820  // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs
821  // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition.
822  while(done==false)
823  {
824  // compute the dynamic system for the given generator and high-level alphabet
825  calculateDynamicSystemClosedObs(rGenObs, rNewHighAlph, genDyn);
826  calculateDynamicSystemObs(rGenObs, rNewHighAlph, genDyn);
827  #ifdef DF_PLOT
828  name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToStringInteger(iterationCount));
829  genDyn.DotWrite(name);
830  #endif
831 
832  Generator genPart;
833  mapStateToPartition.clear();
834  newPartitions.clear();
835 
836  // compute coarsest quasi-congruence on the dynamic system
837  calcBisimulation(genDyn, mapStateToPartition, genPart, newPartitions);
838  #ifdef DF_PLOT
839  name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToStringInteger(iterationCount));
840  genPart.DotWrite(name);
841  ++iterationCount;
842  #endif
843 
844  // check if quotient automaton is deterministic and free of unobservable events
845  // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly
846  done=relabel(rGenObs, rControllableEvents, rNewHighAlph, newPartitions, mapStateToPartition, mapChangedTransReverse, rMapChangedTrans, mapRelabeledEvents);
847  }
848 }
849 
850 
851 // calcAbstAlphMSA(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
852 void calcAbstAlphMSA(System& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) {
853  OP_DF("calcAbstAlphMSA(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
854  // The controllable events are separated from the System. All functions that are successively
855  // called, are defined for Generators
856  EventSet cntrevs = rGenObs.ControllableEvents();
857  calcAbstAlphMSA(rGenObs, cntrevs , rHighAlph, rNewHighAlph, rMapRelabeledEvents);
858  // the controllable events that have been changed by the called function are set in the System cGenObs
859  rGenObs.SetControllable(cntrevs);
860 }
861 
862 // calcAbstAlphMSA(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
863 void calcAbstAlphMSA(Generator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) {
864  OP_DF("calcAbstAlphMSA(" << rGenObs.Name() << "," << "rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
865  // The function called next returns a relabeled generator and a map of relabeled transitions
866  map<Transition,Idx> changedtrans;
867  calcAbstAlphMSA(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans);
868  // for later use, the relabeled transitions are converted into relabeled events
869  // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty
870  map<Transition,Idx>::iterator rtEndIt = changedtrans.end();
871  map<Transition,Idx>::iterator rtIt = changedtrans.begin();
872  for(; rtIt != rtEndIt; rtIt++){
873  if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){// if the event does not exist, yet, a nex element in the map is created
874  rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>();
875  if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist
876  rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
877  }
878  else { // a new label is inserted into the map
879  if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist
880  rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
881  }
882  }
883 }
884 
885 // calcAbstAlphMSA(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans)
886 void calcAbstAlphMSA(Generator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans)
887 {
888  OP_DF("calcAbstAlphMSA(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)");
889  // Initialization of variables
890  rNewHighAlph = rHighAlph;
891  rMapChangedTrans.clear();
892  Generator genDyn(rGenObs);
893  map<Transition,Transition> mapChangedTransReverse;
894  vector<Idx> newPartitions;
895  map<Idx,Idx> mapStateToPartition;
896  map<Idx, EventSet> mapRelabeledEvents;
897  bool done=false;
898  #ifdef DF_PLOT
899  Idx iterationCount=1;
900  string name;
901  #endif
902  // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition.
903  // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs
904  // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition.
905  while(done==false)
906  {
907  // compute the dynamic system for the given generator and high-level alphabet
908  calculateDynamicSystemClosedObs(rGenObs, rNewHighAlph, genDyn);
909  calculateDynamicSystemMSA(rGenObs, rNewHighAlph, genDyn);
910  #ifdef DF_PLOT
911  name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToStringInteger(iterationCount));
912  genDyn.DotWrite(name);
913  #endif
914 
915  Generator genPart;
916  mapStateToPartition.clear();
917  newPartitions.clear();
918 
919  // compute coarsest quasi-congruence on the dynamic system
920  calcBisimulation(genDyn, mapStateToPartition, genPart, newPartitions);
921  #ifdef DF_PLOT
922  name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToStringInteger(iterationCount));
923  genPart.DotWrite(name);
924  ++iterationCount;
925  #endif
926 
927  // check if quotient automaton is deterministic and free of unobservable events
928  // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly
929  done=relabel(rGenObs, rControllableEvents, rNewHighAlph, newPartitions, mapStateToPartition, mapChangedTransReverse, rMapChangedTrans, mapRelabeledEvents);
930  }
931 }
932 
933 
934 // // calcAbstAlphObsOCC(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
935 // void calcAbstAlphObsOCC(System& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents){
936 // OP_DF("calcAbstAlphObsOCC(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
937 // // The controllable events are separated from the System. All functions that are successively
938 // // called, are defined for Generators
939 // map<Transition,Idx> changedtrans;
940 // EventSet rControllableEvents = rGenObs.ControllableEvents();
941 // // The function called next returns a relabeled generator and a map of relabeled transitions
942 // calcAbstAlphObsOCC(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans);
943 // // for later use, the relabeled transitions are converted into relabeled events
944 // // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty
945 // map<Transition,Idx>::iterator rtEndIt = changedtrans.end();
946 // map<Transition,Idx>::iterator rtIt = changedtrans.begin();
947 // for(; rtIt != rtEndIt; rtIt++){
948 // if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){
949 // rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>();
950 // if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist
951 // rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
952 // } else {
953 // if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist
954 // rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
955 // }
956 // }
957 // // the controllable events that have been changed by the called function are set in the System cGenObs
958 // rGenObs.SetControllable(rControllableEvents);
959 // }
960 
961 // // calcAbstAlphObsOCC(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans)
962 // void calcAbstAlphObsOCC(Generator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans)
963 // {
964 // OP_DF("calcAbstAlphObsOCC(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)");
965 // // Initialization of variables
966 // rNewHighAlph = rHighAlph;
967 // rMapChangedTrans.clear();
968 // Generator genDyn(rGenObs);
969 // map<Transition,Transition> mapChangedTransReverse;
970 // vector<Idx> newPartitions;
971 // map<Idx,Idx> mapStateToPartition;
972 // map<Idx, EventSet> mapRelabeledEvents;
973 // bool done=false;
974 // #ifdef DF_PLOT
975 // Idx iterationCount=1;
976 // string name;
977 // #endif
978 // // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition
979 // // and output control consistency (OCC).
980 // // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs
981 // // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition and OCC.
982 // while(done==false)
983 // {
984 // // compute dynamic system for Lm-observer and OCC on rGenObs
985 // calculateDynamicSystemObsOCC(rGenObs, rControllableEvents, rNewHighAlph, genDyn);
986 // #ifdef DF_PLOT
987 // name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToStringInteger(iterationCount));
988 // genDyn.DotWrite(name);
989 // #endif
990 //
991 // Generator genPart;
992 // mapStateToPartition.clear();
993 // newPartitions.clear();
994 // // compute coarsest quasi-congruence on the dynamic system
995 // calcBisimulation(genDyn, mapStateToPartition, genPart, newPartitions);
996 // #ifdef DF_PLOT
997 // name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToStringInteger(iterationCount));
998 // genPart.DotWrite(name);
999 // ++iterationCount;
1000 // #endif
1001 //
1002 // // check if quotient automaton is deterministic and free of unobservable events
1003 // // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly
1004 // done=relabel(rGenObs, rControllableEvents, rNewHighAlph, newPartitions, mapStateToPartition, mapChangedTransReverse, rMapChangedTrans, mapRelabeledEvents);
1005 // }
1006 // }
1007 /*
1008 // calculateDynamicSystemObsOCC(rGen, rControllableEvents, rHighAlph, rGenDyn)
1009 void calculateDynamicSystemObsOCC(const Generator& rGen, EventSet& rControllableEvents, EventSet& rHighAlph, Generator& rGenDyn){
1010  OP_DF("calculateDynamicSystemObsOCC(" << rGen.Name() << "," << rControllableEvents.Name() << "," << rHighAlph.Name() << "," << rGenDyn.Name() << ")");
1011  // transition relation sorted in reverse order for backwards reachability
1012  TransSetX2EvX1 tset_X2EvX1;
1013  rGen.TransRel(tset_X2EvX1);
1014 
1015  // prepare generator rGenDyn
1016  rGenDyn.ClearTransRel();
1017  rGenDyn.InjectAlphabet(rHighAlph); // all high-level events are contained in the alphabet of rGenDyn
1018  // labels for transitions to marked states and for controllable paths
1019  std::string eventname = ( rGenDyn.EventSymbolTablep())->UniqueSymbol("cLabel_1");
1020  Idx cLabel = (rGenDyn.EventSymbolTablep())->InsEntry(eventname);
1021  eventname = ( rGenDyn.EventSymbolTablep())->UniqueSymbol("mLabel_1");
1022  Idx mLabel = (rGenDyn.EventSymbolTablep())->InsEntry(eventname);
1023  rGenDyn.InsEvent(cLabel);
1024  rGenDyn.InsEvent(mLabel);
1025  rGenDyn.InjectInitStates(rGen.InitStates() );
1026  rGenDyn.InjectStates(rGen.States() );
1027  rGenDyn.InjectMarkedStates(rGen.MarkedStates() );
1028 
1029  // maps for the construction of the dynamic system
1030  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
1031  map<Idx, StateSet> entryLocalStatesMap; // map from entry states to locally forward reachable states
1032  StateSet::Iterator stIt, stEndIt;
1033  stIt = rGen.StatesBegin();
1034  stEndIt = rGen.StatesEnd();
1035  TransSet::Iterator tsIt, tsEndIt;
1036  bool isExitState;
1037  // go through all states of the original generator
1038  for(; stIt != stEndIt; stIt++){
1039  OP_DF("calculateDynamicSystemObsOCC: loop over all states; current state: " << rGen.StateName(*stIt)
1040  << " [" << *stIt << "]");
1041  // determine the marked states that are locally reachable from the current state and insert
1042  // transitions labeled with mLabel in rGenDyn
1043  forwardReachabilityObs(rGen, rHighAlph, *stIt, mLabel, rGenDyn);
1044  // if the current state is an exit state, carry out the backward reachability to determine
1045  // which states can be reached on a controllable/uncontrollable path -> store in exitLocalStatesMap
1046  // in this case, also determine the corresponding entry states and compute their locally reachable states
1047  // for the entryLocalStatesMap
1048  tsIt = rGen.TransRelBegin(*stIt);
1049  tsEndIt = rGen.TransRelEnd(*stIt);
1050  isExitState = false;
1051  for( ; tsIt != tsEndIt; tsIt++){
1052  if(rHighAlph.Exists(tsIt->Ev) ){
1053  OP_DF("calculateDynamicSystemObsOCC: current state is an exit-state");
1054  isExitState = true;
1055  // if the local reach for the connected entry state has not been computed, yet, insert it in the
1056  // entryLocalStatesMap
1057  if( entryLocalStatesMap.find(tsIt->X2) == entryLocalStatesMap.end() ){
1058  entryLocalStatesMap[tsIt->X2] = StateSet();
1059  LocalAccessibleReach(rGen,rHighAlph, tsIt->X2, entryLocalStatesMap[tsIt->X2]);
1060  }
1061  }
1062  }
1063  // if the current state is an exit state, compute the backward local reach with the controllability properties of the
1064  // paths to locally backward reachable states
1065  if(isExitState == true){
1066  StateSet doneStates;
1067  exitLocalStatesMap[*stIt][*stIt] = false; // the exit state is reachable from the exit state via an uncontrollable path
1068  doneStates.Insert(*stIt);
1069  backwardReachabilityObsOCC(tset_X2EvX1, rControllableEvents, rHighAlph, *stIt, *stIt, false, exitLocalStatesMap, doneStates);
1070 
1071  }
1072 
1073  }
1074  // the generator rGenDyn is constructed by connecting all exit and entry states with their local state sets
1075  map<Idx, map<Idx, bool> >::const_iterator elIt, elEndIt;
1076  elIt = exitLocalStatesMap.begin();
1077  elEndIt = exitLocalStatesMap.end();
1078  map<Idx,bool>::const_iterator lcIt, lcEndIt;
1079  StateSet::Iterator exIt, exEndIt;
1080  map<Idx,StateSet>::const_iterator enIt;
1081 
1082  for( ; elIt != elEndIt; elIt++){
1083  lcEndIt = elIt->second.end();
1084  // go over all entry states reachable from the current exit state (via all feasible high-level events)
1085  tsIt = rGen.TransRel().Begin(elIt->first);
1086  tsEndIt = rGen.TransRel().End(elIt->first);
1087  for( ; tsIt != tsEndIt; tsIt++){
1088  OP_DF("calculateDynamicSystemObsOCC: insert transitions for the high-level event" << rGen.EventName(tsIt->Ev) << "[" << tsIt->Ev << "]");
1089  if(rHighAlph.Exists(tsIt->Ev) ){
1090  bool controllable = rControllableEvents.Exists(tsIt->Ev);
1091  enIt = entryLocalStatesMap.find(tsIt->X2);
1092  stEndIt = enIt->second.End();
1093  // iterate over all locally backward reachable states from current exit state
1094  for(lcIt = elIt->second.begin(); lcIt != lcEndIt; lcIt ++){
1095  // iterate over all locally forward reachable states from current entry state
1096  for( stIt = enIt->second.Begin(); stIt != stEndIt; stIt++){
1097  OP_DF("calculateDynamicSystemObsOCC: Transition added to resulting generator: " <<
1098  rGenDyn.TStr(Transition(lcIt->first,tsIt->Ev,*stIt)));
1099 
1100  rGenDyn.SetTransition(lcIt->first,tsIt->Ev,*stIt); // insert a transition for each local state combination
1101  if( controllable || lcIt->second ){ // insert an clabel transition if the local path is controllable or the high-level event is controllable
1102  OP_DF("calculateDynamicSystemObsOCC: cLabel-Transition added to resulting generator: " <<
1103  rGenDyn.TStr(Transition(lcIt->first,cLabel,*stIt)));
1104 
1105  rGenDyn.SetTransition(lcIt->first,cLabel,*stIt);
1106  }
1107  }
1108  }
1109  }
1110  }
1111  }
1112 }
1113 
1114 // forwardReachabilityObs(rGen, rHighAlph, lowState, mLabel, rGenDyn)
1115 void forwardReachabilityObs(const Generator& rGen, const EventSet& rHighAlph, Idx lowState, Idx mLabel, Generator& rGenDyn) {
1116  OP_DF("forwardReachabilityObs(" << rGen.Name() << "," << rHighAlph.Name() << "," << lowState << "," << rGenDyn.EventName(mLabel) << "," << rGenDyn.Name() << ")");
1117  // helpers:
1118  // iterators
1119  TransSet::Iterator tIt;
1120  TransSet::Iterator tEndIt;
1121  // todo list
1122  std::stack<Idx> todo;
1123 
1124  // algorithm: the locally reachable states from lowState are evaluated. If a reachable state is marked,
1125  // a transition with mLabel is inserted from lowState to that state is inserted in rGenDyn.
1126  todo.push(lowState);
1127  StateSet doneStates;
1128  // if lowState is marked itself, the dynamic system contains a selfloop with the mlabel
1129  if(rGen.MarkedStates().Exists(lowState) ){
1130  OP_DF("forwardReachabilityObs: Transition with mLabel added to resulting generator: " <<
1131  rGenDyn.TStr(Transition(lowState,mLabel,lowState)));
1132  rGenDyn.SetTransition(lowState, mLabel, lowState);
1133  }
1134 
1135  doneStates.Insert(lowState);
1136  // the local reachability is evaluated until no new state is found
1137  while (! todo.empty()) {
1138  const Idx current = todo.top();
1139  todo.pop();
1140  tIt = rGen.TransRelBegin(current);
1141  tEndIt = rGen.TransRelEnd(current);
1142  for (; tIt != tEndIt; ++tIt) {
1143  // if the current transition is labeled with a high level event, it is skipped
1144  if (rHighAlph.Exists(tIt->Ev)) {
1145  continue;
1146  }
1147  // if the successor state has not been found, yst (not in doneStates)
1148  else if (! doneStates.Exists(tIt->X2)) {
1149  todo.push(tIt->X2);
1150  if(rGen.MarkedStates().Exists(tIt->X2) ){
1151  OP_DF("forwardReachabilityObs: Transition with mLabel added to resulting generator: " <<
1152  rGenDyn.TStr(Transition(lowState,mLabel,tIt->X2)));
1153  rGenDyn.SetTransition(lowState, mLabel, tIt->X2);
1154  }
1155  doneStates.Insert(tIt->X2);
1156  }
1157  }
1158  }
1159 }*/
1160 
1161 // backwardReachabilityObsOCC(rTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, currentState, controllablePath, rExitLocalStatesMap, rDoneStates)
1162 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){
1163  OP_DF("backwardReachabilityObsOCC(rTransSetX2EvX1," << rControllableEvents.Name() << "," << rHighAlph.Name() << "," << exitState << "," << currentState << "," << controllablePath << ",rExitLocalStatesMap, rDoneStates)");
1164  // 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
1165  // the controllability properties of the state do not change on the current path
1166 
1167  // helpers
1168  TransSetX2EvX1::Iterator tsIt, tsEndIt;
1169  tsIt = rTransSetX2EvX1.BeginByX2(currentState);
1170  tsEndIt = rTransSetX2EvX1.EndByX2(currentState);
1171  bool currentControllablePath;
1172  // we iterate over all backward transitions of the currentState to establish backward reachability
1173  for( ;tsIt != tsEndIt; tsIt++){
1174  // 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
1175  if( !rHighAlph.Exists(tsIt->Ev) && tsIt->X1 != exitState){
1176  // if the state has not been visited, yet, the controllability of the current path are set in the rExitLocalStatesMap
1177  if( !rDoneStates.Exists(tsIt->X1) ){
1178  rDoneStates.Insert(tsIt->X1);
1179  // the path is controllable if the current transition has a controllable event or the path was already controllable
1180  currentControllablePath = rControllableEvents.Exists(tsIt->Ev) || controllablePath;
1181  rExitLocalStatesMap[exitState][tsIt->X1] = currentControllablePath;
1182  // as the state has not been visited, yet, it is subject to a new backward reachability
1183  backwardReachabilityObsOCC(rTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, tsIt->X1, currentControllablePath, rExitLocalStatesMap, rDoneStates);
1184  }
1185  else{ // for an existing state, the controllability value can change from uncontrollable to controllable (if
1186  // a new controllable path has been found). It is important to note, that the OCC condition implies that
1187  // if there is one controllable path, then the the state is flagged controllable except for the case of the
1188  // given exitState that is always uncontrollable
1189  currentControllablePath = rControllableEvents.Exists(tsIt->Ev) || controllablePath;
1190  if(rExitLocalStatesMap[exitState][tsIt->X1] != currentControllablePath && currentControllablePath == true){
1191  rExitLocalStatesMap[exitState][tsIt->X1] = true;
1192  // as the controllabiity attribute of the current state changed it is subject to a new backward reachability
1193  backwardReachabilityObsOCC(rTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, tsIt->X1, true, rExitLocalStatesMap, rDoneStates);
1194  }
1195  }
1196  }
1197  }
1198 }
1199 
1200 // calcAbstAlphObsLCC(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
1201 void calcAbstAlphObsLCC(System& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents){
1202  OP_DF("calcAbstAlphObsLCC(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
1203  // The controllable events are separated from the System. All functions that are successively
1204  // called, are defined for Generators
1205  map<Transition,Idx> changedtrans;
1206  EventSet rControllableEvents = rGenObs.ControllableEvents();
1207  // The function called next returns a relabeled generator and a map of relabeled transitions
1208  calcAbstAlphObsLCC(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans);
1209  // for later use, the relabeled transitions are converted into relabeled events
1210  // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty
1211  map<Transition,Idx>::iterator rtEndIt = changedtrans.end();
1212  map<Transition,Idx>::iterator rtIt = changedtrans.begin();
1213  for(; rtIt != rtEndIt; rtIt++){
1214  if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){
1215  rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>();
1216  if(rGenObs.Alphabet().Exists(rtIt->second) )
1217  rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
1218  } else {
1219  if(rGenObs.Alphabet().Exists(rtIt->second) )
1220  rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
1221  }
1222  }
1223  // the controllable events that have been changed by the called function are set in the System cGenObs
1224  rGenObs.SetControllable(rControllableEvents);
1225 }
1226 
1227 // calcAbstAlphObsLCC(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans)
1228 void calcAbstAlphObsLCC(Generator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans)
1229 {
1230  OP_DF("calcAbstAlphObsLCC(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)");
1231  // Initialization of variables
1232  rNewHighAlph = rHighAlph;
1233  rMapChangedTrans.clear();
1234  Generator genDyn(rGenObs);
1235  map<Transition,Transition> mapChangedTransReverse;
1236  vector<Idx> newPartitions;
1237  map<Idx,Idx> mapStateToPartition;
1238  map<Idx, EventSet> mapRelabeledEvents;
1239  bool done=false;
1240  #ifdef DF_PLOT
1241  Idx iterationCount=1;
1242  string name;
1243  #endif
1244  // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition
1245  // and local control consistency (LCC).
1246  // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs
1247  // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition and LCC.
1248  while(done==false)
1249  {
1250  // compute the dynamic system for the given generator and high-level alphabet
1251  calculateDynamicSystemClosedObs(rGenObs, rNewHighAlph, genDyn);
1252  calculateDynamicSystemLCC(rGenObs, rControllableEvents, rNewHighAlph, genDyn);
1253  calculateDynamicSystemObs(rGenObs, rNewHighAlph, genDyn);
1254  #ifdef DF_PLOT
1255  name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToStringInteger(iterationCount));
1256  genDyn.DotWrite(name);
1257  #endif
1258 
1259  Generator genPart;
1260  mapStateToPartition.clear();
1261  newPartitions.clear();
1262  // compute coarsest quasi-congruence on the dynamic system
1263  calcBisimulation(genDyn, mapStateToPartition, genPart, newPartitions);
1264  #ifdef DF_PLOT
1265  name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToStringInteger(iterationCount));
1266  genPart.DotWrite(name);
1267  ++iterationCount;
1268  #endif
1269 
1270  // check if quotient automaton is deterministic and free of unobservable events
1271  // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly
1272  done=relabel(rGenObs, rControllableEvents, rNewHighAlph, newPartitions, mapStateToPartition, mapChangedTransReverse, rMapChangedTrans, mapRelabeledEvents);
1273  }
1274 }
1275 
1276 
1277 // calcAbstAlphMSALCC(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
1278 void calcAbstAlphMSALCC(System& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents){
1279  OP_DF("calcAbstAlphMSALCC(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
1280  // The controllable events are separated from the System. All functions that are successively
1281  // called, are defined for Generators
1282  map<Transition,Idx> changedtrans;
1283  EventSet rControllableEvents = rGenObs.ControllableEvents();
1284  // The function called next returns a relabeled generator and a map of relabeled transitions
1285  calcAbstAlphMSALCC(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans);
1286  // for later use, the relabeled transitions are converted into relabeled events
1287  // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty
1288  map<Transition,Idx>::iterator rtEndIt = changedtrans.end();
1289  map<Transition,Idx>::iterator rtIt = changedtrans.begin();
1290  for(; rtIt != rtEndIt; rtIt++){
1291  if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){
1292  rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>();
1293  if(rGenObs.Alphabet().Exists(rtIt->second) )
1294  rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
1295  } else {
1296  if(rGenObs.Alphabet().Exists(rtIt->second) )
1297  rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
1298  }
1299  }
1300  // the controllable events that have been changed by the called function are set in the System cGenObs
1301  rGenObs.SetControllable(rControllableEvents);
1302 }
1303 
1304 // calcAbstAlphMSALCC(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans)
1305 void calcAbstAlphMSALCC(Generator& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans)
1306 {
1307  OP_DF("calcAbstAlphMSALCC(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)");
1308  // Initialization of variables
1309  rNewHighAlph = rHighAlph;
1310  rMapChangedTrans.clear();
1311  Generator genDyn(rGenObs);
1312  map<Transition,Transition> mapChangedTransReverse;
1313  vector<Idx> newPartitions;
1314  map<Idx,Idx> mapStateToPartition;
1315  map<Idx, EventSet> mapRelabeledEvents;
1316  bool done=false;
1317  #ifdef DF_PLOT
1318  Idx iterationCount=1;
1319  string name;
1320  #endif
1321  // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition
1322  // and local control consistency (LCC).
1323  // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs
1324  // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition and LCC.
1325  while(done==false)
1326  {
1327  // compute the dynamic system for the given generator and high-level alphabet
1328  calculateDynamicSystemClosedObs(rGenObs, rNewHighAlph, genDyn);
1329  calculateDynamicSystemLCC(rGenObs, rControllableEvents, rNewHighAlph, genDyn);
1330  calculateDynamicSystemMSA(rGenObs, rNewHighAlph, genDyn);
1331  #ifdef DF_PLOT
1332  name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToStringInteger(iterationCount));
1333  genDyn.DotWrite(name);
1334  #endif
1335 
1336  Generator genPart;
1337  mapStateToPartition.clear();
1338  newPartitions.clear();
1339  // compute coarsest quasi-congruence on the dynamic system
1340  calcBisimulation(genDyn, mapStateToPartition, genPart, newPartitions);
1341  #ifdef DF_PLOT
1342  name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToStringInteger(iterationCount));
1343  genPart.DotWrite(name);
1344  ++iterationCount;
1345  #endif
1346 
1347  // check if quotient automaton is deterministic and free of unobservable events
1348  // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly
1349  done=relabel(rGenObs, rControllableEvents, rNewHighAlph, newPartitions, mapStateToPartition, mapChangedTransReverse, rMapChangedTrans, mapRelabeledEvents);
1350  }
1351 }
1352 
1353 /*
1354 // calculateDynamicSystemObsLCC(rGen, rControllableEvents, rHighAlph, rGenDyn)
1355 void calculateDynamicSystemObsLCC(const Generator& rGen, EventSet& rControllableEvents, EventSet& rHighAlph, Generator& rGenDyn){
1356  OP_DF("calculateDynamicSystemObsLCC(" << rGen.Name() << "," << rControllableEvents.Name() << "," << rHighAlph.Name() << "," << rGenDyn.Name() << ")");
1357  // transition relation sorted in reverse order for backwards reachability
1358  TransSetX2EvX1 tset_X2EvX1;
1359  rGen.TransRel(tset_X2EvX1);
1360 
1361  // prepare generator rGenDyn
1362  rGenDyn.ClearTransRel();
1363  rGenDyn.InjectAlphabet(rHighAlph);
1364  std::string eventname = ( rGenDyn.EventSymbolTablep())->UniqueSymbol("ucLabel_1");
1365  Idx ucLabel = (rGenDyn.EventSymbolTablep())->InsEntry(eventname);
1366  eventname = ( rGenDyn.EventSymbolTablep())->UniqueSymbol("mLabel_1");
1367  Idx mLabel = (rGenDyn.EventSymbolTablep())->InsEntry(eventname);
1368  rGenDyn.InsEvent(ucLabel);
1369  rGenDyn.InsEvent(mLabel);
1370  rGenDyn.InjectInitStates(rGen.InitStates() );
1371  rGenDyn.InjectStates(rGen.States() );
1372  rGenDyn.InjectMarkedStates(rGen.MarkedStates() );
1373 
1374  // maps for the construction of the dynamic system
1375  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
1376  map<Idx, StateSet> entryLocalStatesMap; // map from entry states to locally forward reachable states
1377  StateSet::Iterator stIt, stEndIt;
1378  stIt = rGen.StatesBegin();
1379  stEndIt = rGen.StatesEnd();
1380  TransSet::Iterator tsIt, tsEndIt;
1381  bool isExitState;
1382  // go through all states of the original generator
1383  for(; stIt != stEndIt; stIt++){
1384  OP_DF("calculateDynamicSystemObsLCC: loop over all states; current state: " << rGen.StateName(*stIt)
1385  << " [" << *stIt << "]");
1386  // determine the marked states that are locally reachable from the current state and insert
1387  // transitions labeled with mLabel in rGenDyn
1388  forwardReachabilityObs(rGen, rHighAlph, *stIt, mLabel, rGenDyn);
1389  // if the current state is an exit state, carry out the backward reachability to determine
1390  // which states can be reached on a controllable/uncontrollable path -> store in exitLocalStatesMap
1391  // in this case, also determine the corresponding entry states and compute their locally reachable states
1392  // for the entryLocalStatesMap
1393  tsIt = rGen.TransRelBegin(*stIt);
1394  tsEndIt = rGen.TransRelEnd(*stIt);
1395  isExitState = false;
1396  for( ; tsIt != tsEndIt; tsIt++){
1397  if(rHighAlph.Exists(tsIt->Ev) ){
1398  OP_DF("calculateDynamicSystemObsLCC: current state is an exit-state");
1399  isExitState = true;
1400  // if the local reach for the connected entry state has not been computed, yet, insert it in the
1401  // entryLocalStatesMap
1402  if( entryLocalStatesMap.find(tsIt->X2) == entryLocalStatesMap.end() ){
1403  entryLocalStatesMap[tsIt->X2] = StateSet();
1404  LocalAccessibleReach(rGen,rHighAlph, tsIt->X2, entryLocalStatesMap[tsIt->X2]);
1405  }
1406  }
1407  }
1408  // if the current state is an exit state, compute the backward local reach with the controllability properties of the
1409  // paths to locally backward reachable states
1410  if(isExitState == true){
1411  StateSet doneStates;
1412  exitLocalStatesMap[*stIt][*stIt] = false; // the exit state is reachable from the exit state via an uncontrollable path
1413  doneStates.Insert(*stIt);
1414  backwardReachabilityObsLCC(tset_X2EvX1, rControllableEvents, rHighAlph, *stIt, *stIt, false, exitLocalStatesMap, doneStates);
1415 
1416  }
1417 
1418  }
1419  // the generator rGenDyn is constructed by connecting all exit and entry states with their local state sets
1420  map<Idx, map<Idx, bool> >::const_iterator elIt, elEndIt;
1421  elIt = exitLocalStatesMap.begin();
1422  elEndIt = exitLocalStatesMap.end();
1423  map<Idx,bool>::const_iterator lcIt, lcEndIt;
1424  StateSet::Iterator exIt, exEndIt;
1425  map<Idx,StateSet>::const_iterator enIt;
1426 
1427  for( ; elIt != elEndIt; elIt++){
1428  lcEndIt = elIt->second.end();
1429  // go over all entry states reachable from the current exit state (via all feasible high-level events)
1430  tsIt = rGen.TransRel().Begin(elIt->first);
1431  tsEndIt = rGen.TransRel().End(elIt->first);
1432  for( ; tsIt != tsEndIt; tsIt++){
1433  OP_DF("calculateDynamicSystemObsLCC: insert transitions for the high-level event" << rGen.EventName(tsIt->Ev) << "[" << tsIt->Ev << "]");
1434  if(rHighAlph.Exists(tsIt->Ev) ){
1435  bool controllable = rControllableEvents.Exists(tsIt->Ev);
1436  enIt = entryLocalStatesMap.find(tsIt->X2);
1437  stEndIt = enIt->second.End();
1438  // iterate over all locally backward reachable states from current exit state
1439  for(lcIt = elIt->second.begin(); lcIt != lcEndIt; lcIt ++){
1440  // iterate over all locally forward reachable states from current entry state
1441  for( stIt = enIt->second.Begin(); stIt != stEndIt; stIt++){
1442  OP_DF("calculateDynamicSystemObsLCC: Transition added to resulting generator: " <<
1443  rGenDyn.TStr(Transition(lcIt->first,tsIt->Ev,*stIt)));
1444 
1445  rGenDyn.SetTransition(lcIt->first,tsIt->Ev,*stIt); // insert a transition for each local state combination
1446  if( !(controllable || lcIt->second) ){ // insert an uclabel transition if the local path is uncontrollable
1447  OP_DF("calculateDynamicSystemObsLCC: cLabel-Transition added to resulting generator: " <<
1448  rGenDyn.TStr(Transition(lcIt->first,ucLabel,*stIt)));
1449 
1450  rGenDyn.SetTransition(lcIt->first,ucLabel,*stIt);
1451  }
1452  }
1453  }
1454  }
1455  }
1456  }
1457 }
1458 
1459 // backwardReachabilityObsLCC(crTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, currentState, controllablePath, rExitLocalStatesMap, rDoneStates)
1460 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){
1461  OP_DF("backwardReachabilityObsOCC(rTransSetX2EvX1," << rControllableEvents.Name() << "," << rHighAlph.Name() << "," << exitState << "," << currentState << "," << controllablePath << ",rExitLocalStatesMap, rDoneStates)");
1462  // 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
1463  // the controllability properties of the state do not change on the current path
1464 
1465  // helpers
1466  TransSetX2EvX1::Iterator tsIt, tsEndIt;
1467  tsIt = rTransSetX2EvX1.BeginByX2(currentState);
1468  tsEndIt = rTransSetX2EvX1.EndByX2(currentState);
1469  bool currentControllablePath;
1470  // we iterate over all backward transitions of the currentState to establish backward reachability
1471  for( ;tsIt != tsEndIt; tsIt++){
1472  // 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
1473  if( !rHighAlph.Exists(tsIt->Ev) && tsIt->X1 != exitState){
1474  // if the state has not been visited, yet, the controllability of the current path are set in the rExitLocalStatesMap
1475  if( !rDoneStates.Exists(tsIt->X1) ){
1476  rDoneStates.Insert(tsIt->X1);
1477  // the path is uncontrollable if the current transition has an uncontrollable event or the path was already uncontrollable
1478  currentControllablePath = rControllableEvents.Exists(tsIt->Ev) || controllablePath;
1479  rExitLocalStatesMap[exitState][tsIt->X1] = currentControllablePath;
1480  // as the state has not been visited, yet, it is subject to a new backward reachability
1481  backwardReachabilityObsLCC(rTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, tsIt->X1, currentControllablePath, rExitLocalStatesMap, rDoneStates);
1482  }
1483  else{ // for an existing state, the controllability value can change from controllable to uncontrollable (if
1484  // a new uncontrollable path has been found). It is important to note, that the LCC condition implies that
1485  // if there is one uncontrollable path, then the state is flagged uncontrollable except for the case of the
1486  // given exitState that is always uncontrollable
1487  currentControllablePath = rControllableEvents.Exists(tsIt->Ev) || controllablePath;
1488  if(rExitLocalStatesMap[exitState][tsIt->X1] != currentControllablePath && currentControllablePath == false){
1489  rExitLocalStatesMap[exitState][tsIt->X1] = currentControllablePath;
1490  // as the controllabiity attribute of the current state changed it is subject to a new backward reachability
1491  backwardReachabilityObsLCC(rTransSetX2EvX1, rControllableEvents, rHighAlph, exitState, tsIt->X1, false, rExitLocalStatesMap, rDoneStates);
1492  }
1493  }
1494  }
1495  }
1496 }*/
1497 
1498 // relabel(rGenRelabel, rControllableEvents, rHighAlph, rNewPartitions, rMapStateToPartition, rMapChangedTransReverse, rMapChangedTrans, rMapRelabeledEvents)
1499 bool relabel(Generator& rGenRelabel, EventSet& rControllableEvents, EventSet& rHighAlph, vector<Idx>& rNewPartitions, map<Idx,Idx>& rMapStateToPartition, map<Transition,Transition>& rMapChangedTransReverse, map<Transition,Idx>& rMapChangedTrans, map<Idx, EventSet>& rMapRelabeledEvents)
1500 {
1501 
1502  OP_DF("relabel(" << rGenRelabel.Name() << "," << rControllableEvents.Name() << "," << rHighAlph.Name() << ", rNewPartition, rMapStateToPartition, rMapChangedTransReverse, rMapChangedTrans, rMapRelabeledEvents)");
1503 
1504  // helpers
1505 
1506  // keep track of how transitions between cosets have been relabeled
1507  // first Idx: coset from where transition starts, second Idx: high-level event,
1508  // third Idx: other coset, where transition ends, forth Idx: new high-level event
1509  map<Idx, map<Idx, map<Idx, Idx> > > mapRelabel;
1510 
1511  // set of low-level events, that have not been relabeled
1512  set<Idx> notRelabeledLowEvents;
1513  // transition relation of the original version of rGenRelabel
1514  const TransSet& transSet = rGenRelabel.TransRel();
1515  TransSet::Iterator tIt = transSet.Begin();
1516  TransSet::Iterator tItEnd = transSet.End();
1517  // vector that contains pairs of original and changed transitions
1518  vector<pair<TransSet::Iterator,Transition> > editTransSet;
1519  // prepare data structure for keeping track of how transitions were relabeled
1520  vector<Idx>::iterator newPartIt = rNewPartitions.begin();
1521  vector<Idx>::iterator newPartItEnd = rNewPartitions.end();
1522  for(; newPartIt != newPartItEnd; ++newPartIt)
1523  mapRelabel[*newPartIt]=map<Idx, map <Idx, Idx> >();
1524 
1525  // algorithm: The relabeling according to the state partition as computed by the bisimulation algorithm is
1526  // performed. A high-level transitions is relebaled with a new event, if a transition with the same event leads
1527  // from the same coset to a different coset (non-determinism in the projected automaton). A low-level transition
1528  // is relabeled if it connects different cosets (corresponds to unobservable transition betweeen cosets). The
1529  // also has build-in procedures to take care that as few new event labels as possible are introduced.
1530 
1531  // iteration over all transitions of rGenRelabel
1532  for(; tIt != tItEnd; ++tIt)
1533  {
1534  OP_DF("relabel: current transition: " << rGenRelabel.TStr(*tIt) );
1535  Idx indexX1Partition=rMapStateToPartition[tIt->X1];
1536  OP_DF("relabel: X1 belongs to coset with index " << indexX1Partition);
1537  Idx indexX2Partition=rMapStateToPartition[tIt->X2];
1538  OP_DF("relabel: X2 belongs to coset with index " << indexX2Partition);
1539 
1540  //check if current transition is labeled with a high-level-event
1541  if(rHighAlph.Exists(tIt->Ev))
1542  {
1543  OP_DF("relabel: Event is high-level event");
1544  // In the first case, there exists no entry for this transition in mapRelabel. Hence, this is the
1545  // first occurence of tIt->Ev leaving the coset of tIt->X1 found in the iteration.
1546  // Thus, there is no need to relabel this event. Store transition in mapRelabel
1547  if(mapRelabel[indexX1Partition].find(tIt->Ev) == mapRelabel[indexX1Partition].end())
1548  {
1549  mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition]=tIt->Ev;
1550  OP_DF("relabel: First occurence of the current event leaving the current X1-coset");
1551  }
1552  // Otherwise, there exists an entry for the current event leaving the current X1-coset. It has to be
1553  // verified if the transition goes to the same coset as the previously found transitions or not.
1554  else
1555  {
1556  // check if a transition with the same event has already been found that enters the same X2-coset. If
1557  // yes, the same label as for this transition is chosen. If not, a new label is introduced.
1558  if(mapRelabel[indexX1Partition][tIt->Ev].find(indexX2Partition) != mapRelabel[indexX1Partition][tIt->Ev].end())
1559  {
1560  if(mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition] != tIt->Ev)
1561  {
1562  OP_DF("relabel: the same event leading to the same X2-coset has already been relabeld before. The current transition is relabeld correspondingly");
1563  pair<TransSet::Iterator,Transition> newPair;
1564  newPair.first=tIt;
1565  newPair.second = Transition(tIt->X1,mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition],tIt->X2);
1566  editTransSet.push_back(newPair);
1567  }
1568  else //nothing to be done
1569  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");
1570  }
1571  // there are entries of tIt->Ev, but no one leads to the same X2-coset.
1572  // Check if new labels created before can be reused. If not, create a new one
1573  // and eliminate the non-determinism by relebeling the current transition tIt with this event
1574  else
1575  {
1576  bool createNewLabel = false;
1577  // check if the event already has been relabeled for some other transition
1578  if(rMapRelabeledEvents.find(tIt->Ev) != rMapRelabeledEvents.end())
1579  {
1580  EventSet::Iterator lsIt = rMapRelabeledEvents[tIt->Ev].Begin();
1581  EventSet::Iterator lsItEnd = rMapRelabeledEvents[tIt->Ev].End();
1582  for(; lsIt != lsItEnd; ++lsIt)
1583  {
1584  createNewLabel = false;
1585  map<Idx,Idx>::iterator mapIt = mapRelabel[indexX1Partition][tIt->Ev].begin();
1586  map<Idx,Idx>::iterator mapItEnd = mapRelabel[indexX1Partition][tIt->Ev].end();
1587  for(; mapIt != mapItEnd; ++mapIt)
1588  {
1589  // if the currently investigated label has already been used in
1590  // the current coset for a transition to another coset, relabeling is necessary
1591  if(mapIt->second == *lsIt)
1592  {
1593  createNewLabel = true;
1594  break;
1595  }
1596  }
1597  // use an old label if possible
1598  if(createNewLabel == false)
1599  {
1600  pair<TransSet::Iterator,Transition> newPair;
1601  newPair.first=tIt;
1602  newPair.second = Transition(tIt->X1,*lsIt,tIt->X2);
1603  editTransSet.push_back(newPair);
1604  OP_DF("relabel: An event was found that can be reused: " << rGenRelabel.EventName(*lsIt));
1605  break;
1606  }
1607  }
1608  }
1609  // if no useable labels are available, a new label has to be introduced
1610  else
1611  {
1612  createNewLabel = true;
1613  }
1614  // no label could be found that can be reused
1615  if(createNewLabel == true)
1616  {
1617  // create a new label and relabel the current transition with it
1618  std::string eventName = ( rGenRelabel.EventSymbolTablep())->UniqueSymbol(rGenRelabel.EventSymbolTablep()->Symbol(tIt->Ev) + "newHLevent_1");
1619  Idx newLabel = (rGenRelabel.EventSymbolTablep())->InsEntry(eventName);
1620 
1621  rGenRelabel.InsEvent(eventName);
1622  // if the original is controllable, the attribute of the new event is also controllable
1623  if(rControllableEvents.Exists(tIt->Ev)){
1624  rControllableEvents.Insert(newLabel);
1625  }
1626  OP_DF("relabel: No event that can be reused could be found. The new event " << rGenRelabel.EventName(newLabel) << " was created");
1627  rHighAlph.Insert(newLabel);
1628  //create the new transition and remember that the old one has to be replaced with the new one
1629  pair<TransSet::Iterator,Transition> newPair;
1630  newPair.first=tIt;
1631  newPair.second = Transition(tIt->X1,newLabel,tIt->X2);
1632  editTransSet.push_back(newPair);
1633  rMapRelabeledEvents[tIt->Ev].Insert(newLabel);
1634  }
1635  }
1636  }
1637  }
1638  // the current transition is labeled with a low-level event
1639  else
1640  {
1641  OP_DF("relabel: Event is low-level event");
1642  // potential relabeling is only necessary if the low-level transition leaves its coset
1643  if(indexX1Partition != indexX2Partition)
1644  {
1645  // transition connects two cosets and it is the first occurrence of the event.
1646  // Create a new event and relabel the transition with it
1647  if(rMapRelabeledEvents.find(tIt->Ev) == rMapRelabeledEvents.end())
1648  {
1649  std::string eventName = ( rGenRelabel.EventSymbolTablep())->UniqueSymbol(rGenRelabel.EventSymbolTablep()->Symbol(tIt->Ev) + "newHLevent_1");
1650  Idx newLabel = (rGenRelabel.EventSymbolTablep())->InsEntry(eventName);
1651  rGenRelabel.InsEvent(eventName);
1652  // insert the new event in the high-level alphabet and set its controllability property
1653  rHighAlph.Insert(newLabel);
1654  if(rControllableEvents.Exists(tIt->Ev)){
1655  rControllableEvents.Insert(newLabel);
1656  }
1657  OP_DF("relabel: First occurence of current low-level event " << rGenRelabel.EventName(tIt->Ev)
1658  << " between cosets. The new event " << rGenRelabel.EventName(newLabel) << " was created");
1659  mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition]=newLabel;
1660  rMapRelabeledEvents[tIt->Ev].Insert(newLabel);
1661  pair<TransSet::Iterator,Transition> newPair;
1662  newPair.first=tIt;
1663  newPair.second = Transition(tIt->X1,newLabel,tIt->X2);
1664  editTransSet.push_back(newPair);
1665  }
1666  // there are entries of tIt->Ev, but no one leads to the same X2-coset.
1667  // Check if new labels created before can be reused. If not, create a new one
1668  // and eliminate the non-determinism by relebeling the current transition tIt with this event
1669  else
1670  {
1671  EventSet::Iterator lsIt = rMapRelabeledEvents[tIt->Ev].Begin();
1672  EventSet::Iterator lsItEnd = rMapRelabeledEvents[tIt->Ev].End();
1673  bool createNewLabel = true;
1674  for(; lsIt != lsItEnd; ++lsIt)
1675  {
1676  bool labelFound = false;
1677  // check if the event already has been relabeled for some other transition
1678  if(mapRelabel.find(indexX1Partition) == mapRelabel.end())
1679  {
1680  // if the currently investigated label has already been used in
1681  // the current coset for a transition to another coset, relabeling is necessary
1682  labelFound = true;
1683  }
1684  else
1685  {
1686  // label lsIt can be reused as this is the first low-level transition leaving the X1-coset
1687  if(mapRelabel[indexX1Partition].find(tIt->Ev) == mapRelabel[indexX1Partition].end())
1688  {
1689  labelFound = true;
1690  }
1691  else
1692  {
1693  // a transition with the same original event tIt->Ev leaving the X1-coset has been found before
1694  // and it entered a different X2-coset. Check if one of them was relabeled with lsIt. If yes, then lsIt can
1695  // not be reused and the next event has to be examined. If no, lsIt can be reused
1696  if(mapRelabel[indexX1Partition][tIt->Ev].find(indexX2Partition) == mapRelabel[indexX1Partition][tIt->Ev].end())
1697  {
1698  map<Idx,Idx>::iterator mapIt=mapRelabel[indexX1Partition][tIt->Ev].begin();
1699  map<Idx,Idx>::iterator mapItEnd=mapRelabel[indexX1Partition][tIt->Ev].end();
1700  labelFound = true;
1701  for(; mapIt != mapItEnd; ++ mapIt)
1702  {
1703  if(mapIt->second== *lsIt)
1704  {
1705  labelFound = false;
1706  break;
1707  }
1708  }
1709  }
1710  // a transition with the same original event tIt-Ev leaving the X1-coset has been found before
1711  // and it entered the same X2-coset. Reuse the corresponding label
1712  else
1713  {
1714  pair<TransSet::Iterator,Transition> newPair;
1715  newPair.first=tIt;
1716  newPair.second = Transition(tIt->X1,mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition],tIt->X2);
1717  editTransSet.push_back(newPair);
1718  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]));
1719  createNewLabel = false;
1720  break;
1721  }
1722  }
1723  }
1724  // reuse existing event
1725  if(labelFound == true)
1726  {
1727  pair<TransSet::Iterator,Transition> newPair;
1728  newPair.first=tIt;
1729  newPair.second = Transition(tIt->X1,*lsIt,tIt->X2);
1730  editTransSet.push_back(newPair);
1731  OP_DF("relabele: Low level event " << rGenRelabel.EventName(tIt->Ev) << " is relabeled with " << rGenRelabel.EventName(*lsIt) << " which can be reused");
1732  mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition]=*lsIt;
1733  createNewLabel = false;
1734  break;
1735  }
1736  } //end for
1737  // a new label has to be created and the corresponding transition is inserted
1738  if(createNewLabel == true)
1739  {
1740  std::string eventName = ( rGenRelabel.EventSymbolTablep())->UniqueSymbol(rGenRelabel.EventSymbolTablep()->Symbol(tIt->Ev) + "newHLevent_1"); //??
1741  Idx newLabel = (rGenRelabel.EventSymbolTablep())->InsEntry(eventName);
1742  rGenRelabel.InsEvent(eventName);
1743  // insert the new event in the high-level alphabet and set its controllability property
1744  rHighAlph.Insert(newLabel);
1745  if(rControllableEvents.Exists(tIt->Ev) ){
1746  rControllableEvents.Insert(newLabel);
1747  }
1748  OP_DF("relabel: No label could be reused, and the new event " << rGenRelabel.EventName(newLabel) << " was created");
1749  mapRelabel[indexX1Partition][tIt->Ev][indexX2Partition]=newLabel;
1750  pair<TransSet::Iterator,Transition> newPair;
1751  newPair.first=tIt;
1752  newPair.second = Transition(tIt->X1,newLabel,tIt->X2);
1753  editTransSet.push_back(newPair);
1754  rMapRelabeledEvents[tIt->Ev].Insert(newLabel);
1755  }
1756  }
1757  }
1758  // the low-level event does not have to be relabeled
1759  else //indexX1Partition==indexX2Partition
1760  {
1761  notRelabeledLowEvents.insert(tIt->Ev);
1762  }
1763  }
1764  }
1765 
1766 
1767  // It is possible that events need not be relabeled. For example, if all occurrences of a low-level event have to
1768  // be relabeled and added to the high-level alphabet, it is possible to just add the original low-level event
1769  // to the high-level alphabet without any relabeling. Note that this information is only available after all
1770  // transitions have been evaluated.
1771  vector<pair<TransSet::Iterator,Transition> >::iterator etSetIt = editTransSet.begin();
1772  vector<pair<TransSet::Iterator,Transition> >::iterator etSetItEnd = editTransSet.end();
1773  set<Idx> insertHighEvents;
1774  set<Idx> deleteHighEvents;
1775  bool quotAuotTrue=true;
1776 
1777  OP_DF("relabel: Trying to avoid unnecessariy new labels");
1778  // All relabeled transitions are checked
1779  for(etSetIt = editTransSet.begin(); etSetIt != editTransSet.end(); ++etSetIt)
1780  {
1781  Idx oldEvent = etSetIt->first->Ev;
1782  Idx newEvent = etSetIt->second.Ev;
1783  OP_DF("relabel: Checking transition X1=" << rGenRelabel.StateName(etSetIt->first->X1)<< " ["<<etSetIt->first->X1
1784  << "] Ev=" << rGenRelabel.EventName(oldEvent) << " X2=" << rGenRelabel.StateName(etSetIt->first->X2)
1785  << " [" << etSetIt->first->X2 << "] which shall be relabeled with event " << rGenRelabel.EventName(newEvent));
1786  // 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.
1787  if(notRelabeledLowEvents.find(oldEvent) == notRelabeledLowEvents.end() && !rHighAlph.Exists(oldEvent))
1788  {
1789  OP_DF("relabel: There is no low-level event " << rGenRelabel.EventName(oldEvent) << " left");
1790  insertHighEvents.insert(oldEvent);
1791  // if a low-level event has been relabeled, the automaton under investigation is not the desired quotient automaton, yet.
1792  quotAuotTrue=false;
1793  // if newEvent is the first new event created for relabeling oldEvent, the relabeling is discarded
1794  if(rMapRelabeledEvents[oldEvent].Find(newEvent) == rMapRelabeledEvents[oldEvent].Begin())
1795  {
1796  OP_DF("relabel: Transition will not be relabeled");
1797  // if newEvent is the only event created for relabeling oldEvent, delete newEvent from rGenRelabel
1798  if(rMapRelabeledEvents[oldEvent].Find(newEvent)==(--(rMapRelabeledEvents[oldEvent].End())))
1799  {
1800  OP_DF("relabel: newEvent is the first and last event in rMapRelabeledEvents[oldEvent]");
1801  deleteHighEvents.insert(newEvent);
1802  }
1803  // delete pair<original Transition, new Transition>
1804  vector<pair<TransSet::Iterator,Transition> >::iterator helpIt = etSetIt;
1805  helpIt--;
1806  editTransSet.erase(etSetIt);
1807  etSetIt = helpIt;
1808  }
1809  else
1810  {
1811  // find predecessor of newEvent in map rMapRelabeledEvents[oldEvent] and use that event for relabeling
1812  Idx newLabel = *(--(rMapRelabeledEvents[oldEvent].Find(newEvent)));
1813  etSetIt->second.Ev = newLabel;
1814  // delete newEvent from rGenRelabel if it is no longer needed
1815  if(rMapRelabeledEvents[oldEvent].Find(newEvent)==(--(rMapRelabeledEvents[oldEvent].End())))
1816  {
1817  deleteHighEvents.insert(newEvent);
1818  }
1819  }
1820  }
1821  }
1822  // update the rMapRelabeledEvents with the changes
1823  // as the relabeling of oldEvent is discarded, it is removed from the map of relebeled events and
1824  // reinserted into the map of not relabeled events
1825 
1826  // mofidy alphabet of rGenRelabel and the abstraction alphabet by inserting the new high-level events and deleting the not needed new event labels.
1827  set<Idx>::iterator setIt = insertHighEvents.begin();
1828  set<Idx>::iterator setItEnd = insertHighEvents.end();
1829  for(; setIt!= setItEnd; ++ setIt)
1830  {
1831  rHighAlph.Insert(*setIt);
1832  }
1833  setIt = deleteHighEvents.begin();
1834  setItEnd = deleteHighEvents.end();
1835  for(; setIt != setItEnd; ++setIt)
1836  {
1837  rGenRelabel.DelEvent(*setIt);
1838  rHighAlph.Erase(*setIt);
1839  rControllableEvents.Erase(*setIt); // controllable event is erased if it does not exist anymore. Schmidt 10/07
1840  }
1841 
1842  rControllableEvents = rControllableEvents * rGenRelabel.Alphabet(); // Schmidt 10/07
1843  // 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
1844  if(editTransSet.empty()&& quotAuotTrue== true)
1845  {
1846  OP_DF("relabel: Leaving function relabel with true");
1847  return true;
1848  }
1849 
1850  // delete original trnasitions and create relabeled transitions in rGenRelabel
1851  etSetIt = editTransSet.begin();
1852  etSetItEnd = editTransSet.end();
1853  for(; etSetIt != etSetItEnd; ++etSetIt)
1854  {
1855  map<Transition,Transition>::iterator mrIt;
1856  mrIt=rMapChangedTransReverse.find(*(etSetIt->first));
1857  // 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.
1858  if(mrIt!=rMapChangedTransReverse.end())
1859  {
1860  Transition originalTrans = mrIt->second;
1861  (rMapChangedTrans.find(originalTrans))->second = (etSetIt->second).Ev;
1862  rMapChangedTransReverse.erase(mrIt);
1863  rMapChangedTransReverse[etSetIt->second]=originalTrans;
1864  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));
1865  }
1866  // the current relabeled transition is simply inserted in the rMapChangedTrans map with its original transition if it is the first relabeling.
1867  else
1868  {
1869  rMapChangedTransReverse[etSetIt->second]=*(etSetIt->first);
1870  rMapChangedTrans[*(etSetIt->first)]=(etSetIt->second).Ev;
1871  OP_DF("relabel: First relabeling of transition X1=" << rGenRelabel.SStr((etSetIt->first)->X1)
1872  << " Ev=" << rGenRelabel.EStr((etSetIt->first)->Ev) << " X2= " << rGenRelabel.SStr((etSetIt->first)->X2) << " new label is " << rGenRelabel.EStr((etSetIt->second).Ev));
1873  }
1874  // The old transition is removed and the new transition is inserted into rGenRelabel
1875  rGenRelabel.ClrTransition(etSetIt->first);
1876  rGenRelabel.SetTransition(etSetIt->second);
1877  }
1878 
1879  OP_DF("relabel: leaving function with false");
1880  return false;
1881 }
1882 
1883 // insertRelabeledEvents(rGenPlant, rMapRelabeledEvents, rNewEvents)
1884 void insertRelabeledEvents(System& rGenPlant, const map<Idx,set<Idx> >& rMapRelabeledEvents, Alphabet& rNewEvents) {
1885  map<Idx,set<Idx> >::const_iterator reEndIt = rMapRelabeledEvents.end();
1886  TransSet::Iterator tsEndIt = rGenPlant.TransRelEnd();
1887  TransSet::Iterator tsIt = rGenPlant.TransRelBegin();
1888  // check all transitions of rGenPlant
1889  for(; tsIt != tsEndIt; tsIt++){
1890  map<Idx,set<Idx> >::const_iterator reIt = rMapRelabeledEvents.find(tsIt->Ev);
1891  if(reIt == reEndIt) continue;
1892  AttributeCFlags attr = rGenPlant.EventAttribute(tsIt->Ev);
1893  set<Idx>::const_iterator rsEndIt = reIt->second.end();
1894  set<Idx>::const_iterator rsIt = reIt->second.begin();
1895  // if a transition with an event that gets new labels has been found, parallel transitions
1896  // with the new events are added to rGenPlant
1897  for(; rsIt != rsEndIt; rsIt++){
1898  rGenPlant.InsEvent(*rsIt,attr);
1899  rNewEvents.Insert(*rsIt,attr);
1900  rGenPlant.SetTransition(tsIt->X1,*rsIt,tsIt->X2);
1901  }
1902  }
1903 }
1904 
1905 // insertRelabeledEvents(rGenPlant, rMapRelabeledEvents, rNewEvents)
1906 // tm: alternative, smart on attributes
1907 void insertRelabeledEvents(Generator& rGenPlant, const map<Idx,set<Idx> >& rMapRelabeledEvents, EventSet& rNewEvents) {
1908  map<Idx,set<Idx> >::const_iterator reEndIt = rMapRelabeledEvents.end();
1909  TransSet::Iterator tsEndIt = rGenPlant.TransRelEnd();
1910  TransSet::Iterator tsIt = rGenPlant.TransRelBegin();
1911  // check all transitions of rGenPlant
1912  for(; tsIt != tsEndIt; tsIt++){
1913  map<Idx,set<Idx> >::const_iterator reIt = rMapRelabeledEvents.find(tsIt->Ev);
1914  if(reIt == reEndIt) continue;
1915  AttributeVoid* attrp = rGenPlant.EventAttribute(tsIt->Ev).Copy();
1916  set<Idx>::const_iterator rsEndIt = reIt->second.end();
1917  set<Idx>::const_iterator rsIt = reIt->second.begin();
1918  // if a transition with an event that gets new labels has been found, parallel transitions
1919  // with the new events are added to rGenPlant
1920  for(; rsIt != rsEndIt; rsIt++){
1921  rGenPlant.InsEvent(*rsIt);
1922  rGenPlant.EventAttribute(*rsIt,*attrp);
1923  rNewEvents.Insert(*rsIt);
1924  rNewEvents.Attribute(*rsIt,*attrp);
1925  rGenPlant.SetTransition(tsIt->X1,*rsIt,tsIt->X2);
1926  // should also copy transition attribute
1927  }
1928  delete attrp;
1929  }
1930 }
1931 
1932 // insertRelabeledEvents(rGenPlant, rMapRelabeledEvents)
1933 void insertRelabeledEvents(System& rGenPlant, const map<Idx,set<Idx> >& rMapRelabeledEvents) {
1934  Alphabet dummy;
1935  insertRelabeledEvents(rGenPlant,rMapRelabeledEvents,dummy);
1936 }
1937 
1938 // insertRelabeledEvents(rGenPlant, rMapRelabeledEvents)
1939 void insertRelabeledEvents(Generator& rGenPlant, const map<Idx,set<Idx> >& rMapRelabeledEvents) {
1940  EventSet dummy;
1941  insertRelabeledEvents(rGenPlant,rMapRelabeledEvents,dummy);
1942 }
1943 
1944 
1945 
1946 
1947 /**
1948  * Rti convenience wrapper
1949  */
1951  System& rGenObs,
1952  EventSet& rHighAlph,
1953  EventSet& rNewHighAlph,
1954  EventRelabelMap& rMapRelabeledEvents)
1955 {
1956  calcAbstAlphObs(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents.StlMap());
1957 }
1958 
1959 
1960 /**
1961  * Rti convenience wrapper
1962  */
1963 void insertRelabeledEvents(Generator& rGenPlant, const EventRelabelMap& rMapRelabeledEvents, EventSet& rNewEvents) {
1964  insertRelabeledEvents(rGenPlant, rMapRelabeledEvents.StlMap(), rNewEvents);
1965 }
1966 
1967 /**
1968  * Rti convenience wrapper
1969  */
1970 void insertRelabeledEvents(Generator& rGenPlant, const EventRelabelMap& rMapRelabeledEvents) {
1971  insertRelabeledEvents(rGenPlant, rMapRelabeledEvents.StlMap());
1972 }
1973 
1974 /**
1975  * Rti wrapper class implementation
1976  */
1977 
1978 // std faudes type
1979 FAUDES_TYPE_IMPLEMENTATION(EventRelabelMap,EventRelabelMap,Type)
1980 
1981 // construct/destruct
1983 EventRelabelMap::EventRelabelMap(const EventRelabelMap& rOther) : Type() {mMap=rOther.mMap; }
1985 
1986 // clear
1987 void EventRelabelMap::Clear(void) { mMap.clear(); }
1988 
1989 // assignment/equality
1991 bool EventRelabelMap::DoEqual(const EventRelabelMap& rOther) const { return mMap==rOther.mMap;}
1992 
1993 // access
1994 const std::map<Idx, std::set<Idx> >& EventRelabelMap::StlMap(void) const { return mMap;}
1995 std::map<Idx, std::set<Idx> >& EventRelabelMap::StlMap(void) { return mMap;}
1996 void EventRelabelMap::StlMap(const std::map<Idx, std::set<Idx> >& rMap) { mMap=rMap;}
1997 
1998 
1999 
2000 }// namespace
2001 

libFAUDES 2.24g --- 2014.09.15 --- c++ api documentaion by doxygen