mtc_observercomputation.cpp
Go to the documentation of this file.
1 /** @file mtc_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 */
12 
13 /* FAU Discrete Event Systems Library (libfaudes)
14 
15  Copyright (C) 2006 Bernd Opitz
16  Exclusive copyright is granted to Klaus Schmidt
17 
18  This library is free software; you can redistribute it and/or
19  modify it under the terms of the GNU Lesser General Public
20  License as published by the Free Software Foundation; either
21  version 2.1 of the License, or (at your option) any later version.
22 
23  This library is distributed in the hope that it will be useful,
24  but WITHOUT ANY WARRANTY; without even the implied warranty of
25  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26  Lesser General Public License for more details.
27 
28  You should have received a copy of the GNU Lesser General Public
29  License along with this library; if not, write to the Free Software
30  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
31 
33 #include "cfl_localgen.h"
34 
35 using namespace std;
36 
37 namespace faudes{
38 
39 
40 // calcNaturalObserver(rGen,rHighAlph)
41 Idx calcNaturalObserver(const MtcSystem& rGen, EventSet& rHighAlph){
42  // helpers
43  Generator dynGen;
44  map<Idx,Idx> mapStateToPartition;
45  EventSet origAlph;
46  Generator genPart;
47  while(origAlph != rHighAlph){
48  origAlph = rHighAlph;
49  // compute the dynamic system for the given generator and high-level alphabet
50  calculateDynamicSystemObs(rGen, rHighAlph, dynGen);
51  // compute the quasi conqruence
52  ComputeBisimulation(dynGen, mapStateToPartition, genPart);
53  // Extend the high-level alphabet according to the algorithm of Lei
54  ExtendHighAlphabet(rGen, rHighAlph, mapStateToPartition);
55  }
56  return genPart.Size();
57 }
58 
59 // calcAbstAlphObs(rGenObs, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
60 void calcAbstAlphObs(MtcSystem& rGenObs, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) {
61  OP_DF("calcAbstAlphObs(" << rGenObs.Name() << "," << "rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
62  // The controllable events are separated from the System. All functions that are successively
63  // called, are defined for Generators
64  EventSet cntrevs = rGenObs.ControllableEvents();
65  calcAbstAlphObs(rGenObs, cntrevs , rHighAlph, rNewHighAlph, rMapRelabeledEvents);
66  // the controllable events that have been changed by the called function are set in the System cGenObs
67  rGenObs.SetControllable(cntrevs);
68 }
69 
70 // calcAbstAlphObs(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)
71 void calcAbstAlphObs(MtcSystem& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Idx,set<Idx > > & rMapRelabeledEvents) {
72  OP_DF("calcAbstAlphObs(" << rGenObs.Name() << "," << "rControllableEvents, rHighAlph, rNewHighAlph, rMapRelabeledEvents)");
73  // The function called next returns a relabeled generator and a map of relabeled transitions
74  map<Transition,Idx> changedtrans;
75  calcAbstAlphObs(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, changedtrans);
76  // for later use, the relabeled transitions are converted into relabeled events
77  // note that this function is accumulative, i.e., rMapRelabeledEvents need not be empty
78  map<Transition,Idx>::iterator rtEndIt = changedtrans.end();
79  map<Transition,Idx>::iterator rtIt = changedtrans.begin();
80  for(; rtIt != rtEndIt; rtIt++){
81  if(rMapRelabeledEvents.find(rtIt->first.Ev) == rMapRelabeledEvents.end() ){// if the event does not exist, yet, a nex element in the map is created
82  rMapRelabeledEvents[rtIt->first.Ev] = set<Idx>();
83  if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist
84  rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
85  }
86  else { // a new label is inserted into the map
87  if(rGenObs.Alphabet().Exists(rtIt->second) )// FIXME: there seem to be relabeled transitions that do not exist
88  rMapRelabeledEvents[rtIt->first.Ev].insert(rtIt->second);
89  }
90  }
91 }
92 
93 // calcAbstAlphObs(rGenObs, rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTrans)
94 void calcAbstAlphObs(MtcSystem& rGenObs, EventSet& rControllableEvents, EventSet& rHighAlph, EventSet& rNewHighAlph, map<Transition,Idx>& rMapChangedTrans)
95 {
96  OP_DF("calcAbstAlphObs(" << rGenObs.Name() << ", rControllableEvents, rHighAlph, rNewHighAlph, rMapChangedTRans)");
97  // Initialization of variables
98  rNewHighAlph = rHighAlph;
99  rMapChangedTrans.clear();
100  Generator genDyn(rGenObs);
101  map<Transition,Transition> mapChangedTransReverse;
102  map<Idx,Idx> mapStateToPartition;
103  map<Idx, EventSet> mapRelabeledEvents;
104  bool done=false;
105  #ifdef DF_PLOT
106  Idx iterationCount=1;
107  string name;
108  #endif
109  // observer algorithm: In each step, a dynamic system is computed that fulfills the one-step observer condition.
110  // Iterative application of the bisimulation algorithm and the relabeling procedure yields an automaton rGenObs
111  // that, together with the new high-level alphabet rNewHighAlph fulfills the observer condition.
112  while(done==false)
113  {
114  // compute dynamic system for Lm-observer on rGenObs
115  calculateDynamicSystemObs(rGenObs, rNewHighAlph, genDyn);
116  #ifdef DF_PLOT
117  name = ("./Automata/Plots/" + rGenObs.Name() + "DynamicSystem_" + ToStringInteger(iterationCount));
118  genDyn.DotWrite(name);
119  #endif
120 
121 
122  // compute coarsest quasi-congruence on the dynamic system
123  Generator genPart;
124  ComputeBisimulation(genDyn, mapStateToPartition, genPart);
125  #ifdef DF_PLOT
126  name = ("./Automata/Plots/" + rGenObs.Name() + "Bisimulation_" + ToStringInteger(iterationCount));
127  genPart.DotWrite(name);
128  ++iterationCount;
129  #endif
130 
131  // check if quotient automaton is deterministic and free of unobservable events
132  // and relabel transitions in rGenObs if necessary. The high-level alphabet is modified accordingly
133  done=relabel(rGenObs, rControllableEvents, rNewHighAlph, mapStateToPartition, mapChangedTransReverse, rMapChangedTrans, mapRelabeledEvents);
134  }
135 }
136 
137 // calculateDynamicSystemObs(rGen, rHighAlph, rGenDyn)
138 void calculateDynamicSystemObs(const MtcSystem& rGen, EventSet& rHighAlph, Generator& rGenDyn)
139 {
140  OP_DF("calculateDynamicSystemObs(" << rGen.Name() << "," << rHighAlph.Name() << "," << rGenDyn.Name() << ")");
141  // transition relation sorted in reverse order for backwards reachability
142  TransSetX2EvX1 tset_X2EvX1;
143  rGen.TransRel(tset_X2EvX1);
144 
145  // prepare generator rGenDyn
146  rGenDyn.ClearTransRel();
147  rGenDyn.InjectAlphabet(rHighAlph); // all high-level events are contained in the alphabet of rGenDyn
148 
149  // helpers
150  EventSet::Iterator eIt = rGenDyn.AlphabetBegin();
151  EventSet::Iterator eItEnd = rGenDyn.AlphabetEnd();
152 
153  TransSetX2EvX1::Iterator tItByX2Ev;
154  TransSetX2EvX1::Iterator tItByX2EvEnd;
155  StateSet reach;
156  StateSet::Iterator sIt;
157  StateSet::Iterator sItEnd;
158  TransSet::Iterator tIt;
159  TransSet::Iterator tItEnd;
160  map<Idx,StateSet> entryStateToLocalReach;
161  set<Idx>::iterator esIt, esItEnd;
162  // map that maps a state (first Idx) to a reachable entry state (second Idx) via a high-level event (third Idx)
163  map<Idx,vector<pair<Idx,Idx> > > stateToEntryState;
164  map<Idx,vector<pair<Idx,Idx> > >::iterator stesIt;
165  map<Idx,vector<pair<Idx,Idx> > >::iterator stesItEnd;
166 
167  // generate the color labels for the dynamic system
168  ColorSet allColors = rGen.Colors();
169  ColorSet::Iterator csIt, csEndIt;
170  csIt = allColors.Begin();
171  csEndIt = allColors.End();
172  std::string colorLabel;
173  // maps a unique color index to the index of the associated transition label in teh dynamic system
174  map<Idx,Idx> colorEventMap;
175  for(; csIt != csEndIt; csIt++){
176  colorLabel = ( rGenDyn.EventSymbolTablep())->UniqueSymbol("colorLabel" + rGen.ColorName(*csIt) + "_1");
177  colorEventMap[*csIt] = (rGenDyn.EventSymbolTablep())->InsEntry(colorLabel);
178  }
179 
180  // algorithm for computing the dynamic system
181 
182  // loop over all states of original generator
183  StateSet::Iterator stateSetIt = rGen.StatesBegin();
184  StateSet::Iterator stateSetItEnd = rGen.StatesEnd();
185  for( ; stateSetIt != stateSetItEnd; ++stateSetIt) {
186  OP_DF("calculateDynamicSystemObs: loop over all states; current state: " << rGen.StateName(*stateSetIt)
187  << " [" << *stateSetIt << "]");
188 
189  // compute locally reachable states for current state
190  reach.Clear();
191  LocalAccessibleReach(rGen, rHighAlph, *stateSetIt, reach);
192  OP_DF("calculateDynamicSystemObs: states in local reach: \n " << reach.ToString() );
193 
194  // check if current state (*stateSetIt) is an entry-state (a backward transition with
195  // a high-level event exists. If yes, the locally reachable states (reach) are stored in
196  // the entryStateToLocalReach map
197  tItByX2Ev=tset_X2EvX1.BeginByX2(*stateSetIt);
198  tItByX2EvEnd=tset_X2EvX1.EndByX2(*stateSetIt);
199  for(; tItByX2Ev != tItByX2EvEnd; ++tItByX2Ev)
200  {
201  OP_DF("calculateDynamicSystemObs: checking transition : " << rGen.TStr(*tItByX2Ev));
202  if(rHighAlph.Exists(tItByX2Ev->Ev)){
203  OP_DF("calculateDynamicSystemObs: current state is an entry-state");
204  // map entry-state to its locally reachable states
205  entryStateToLocalReach[*stateSetIt]=reach;
206  break;
207  }
208  }
209  vector<pair<Idx,Idx> > emptyVector;
210  stateToEntryState[*stateSetIt]=emptyVector;
211  // loop over all states in the local reach of current state to determine which marked states
212  // are locally reachable and to determine which high-level events can occur after local strings
213  sIt=reach.Begin();
214  sItEnd=reach.End();
215  Idx colorEvent;
216  for( ; sIt != sItEnd; ++sIt)
217  {
218  // check if state sIt is marked; if yes, create an m-transition (mLabel) between current state and sIt
219  const ColorSet& stateColors = rGen.Colors(*sIt);
220  csIt = stateColors.Begin();
221  csEndIt = stateColors.End();
222  for( ; csIt != csEndIt; csIt++){
223  OP_DF("calculateDynamicSystemObs: marked state " << rGen.SStr(*sIt)
224  << " is locally reachable from current state");
225  colorEvent = colorEventMap[*csIt];
226  rGenDyn.InsEvent(colorEvent ); // ??
227  rGenDyn.InsState(*stateSetIt); // ??
228  rGenDyn.InsState(*sIt); //??
229  rGenDyn.SetTransition(*stateSetIt, colorEvent, *sIt);
230  }
231  // loop over all transitions of current state sIt to determine if high-level events are possible
232  tIt = rGen.TransRelBegin(*sIt);
233  tItEnd = rGen.TransRelEnd(*sIt);
234  for(; tIt != tItEnd; ++tIt)
235  {
236  OP_DF("calculateDynamicSystemObs: Loop over all states in reach; checking transition: "
237  << rGen.TStr(*tIt));
238  if(rHighAlph.Exists(tIt->Ev))
239  {
240  OP_DF("calculateDynamicSystemObs: state " << rGen.SStr(tIt->X2) <<
241  " is an entry state and can be reached from current state" << rGen.SStr(*stateSetIt) << " by event " << rGen.EventName(tIt->Ev));
242  pair<Idx,Idx> newPair;
243  newPair.first=tIt->X2;
244  newPair.second=tIt->Ev;
245  // store the reachable entry state and the corresponding high-level event
246  stateToEntryState[*stateSetIt].push_back(newPair);
247  }
248  }
249  }
250  }
251 
252  // create the transition structure of the dynamic system
253  stesIt = stateToEntryState.begin();
254  stesItEnd = stateToEntryState.end();
255  vector<pair <Idx,Idx> >* pPairs;
256  vector<pair <Idx,Idx> >::iterator vIt;
257  vector<pair <Idx,Idx> >::iterator vItEnd;
258  // To construct the dynamic system, each local state has to be connected to all states in
259  // the local accessible reach of entry states that can be reached via a high-level event.
260  // This information is contained in the stateToEntryState map combined with the entryStateToLocalReach map.
261  // iteration over all entries (X1) of map stateToEntryState
262  for(; stesIt != stesItEnd; ++stesIt)
263  {
264  pPairs=&(stesIt->second);
265  vIt = (*pPairs).begin();
266  vItEnd = (*pPairs).end();
267  // loop over all pairs (Ev,X2) of current entry
268  for( ; vIt != vItEnd; ++vIt)
269  {
270  // check if transition already exists
271  if(!((rGenDyn.TransRel()).Exists(stesIt->first,vIt->second,vIt->first)))
272  {
273  // find local reach of entry state X2
274  StateSet* pLocalReach = &((entryStateToLocalReach.find(vIt->first))->second);
275 
276  // Add a Ev-transition from X1 to every state in the local reach of X2
277  StateSet::Iterator lrsIt = pLocalReach->Begin();
278  StateSet::Iterator lrsItEnd = pLocalReach->End();
279  for(; lrsIt != lrsItEnd; ++lrsIt)
280  {
281  rGenDyn.InsEvent(vIt->second); // ??
282  rGenDyn.InsState(stesIt->first); // ??
283  rGenDyn.InsState(*lrsIt); //??
284  rGenDyn.SetTransition(stesIt->first,vIt->second,*lrsIt);
285  OP_DF("calculateDynamicSystemObs: Transition added to resulting generator: " <<
286  rGenDyn.TStr(Transition(stesIt->first,vIt->second,*lrsIt)));
287  }
288  }
289  }
290  }
291  OP_DF("calculateDynamicSystemObs: leaving function");
292 }
293 
294 }
Helper functions for projected generators.
Container for colors: this is a NameSet with its own static symboltable.
Definition: mtc_colorset.h:41
Set of indices.
Definition: cfl_indexset.h:78
Set of indices with symbolic names.
Definition: cfl_nameset.h:69
bool Exists(const Idx &rIndex) const
Test existence of index.
Iterator class for high-level api to TBaseSet.
Definition: cfl_baseset.h:387
Set of Transitions.
Definition: cfl_transset.h:242
Iterator BeginByX2(Idx x2) const
Iterator to first Transition specified by successor state x2.
Iterator EndByX2(Idx x2) const
Iterator to first Transition after specified successor state x2.
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
Iterator on transition.
Definition: cfl_transset.h:269
const TaEventSet< EventAttr > & Alphabet(void) const
Return const reference to alphabet.
const ATransSet & TransRel(void) const
Return reference to transition relation.
EventSet ControllableEvents(void) const
Get EventSet with controllable events.
void SetControllable(Idx index)
Mark event controllable (by index)
Allows to create colored marking generators (CMGs) as the common five tupel consisting of alphabet,...
Definition: mtc_generator.h:53
std::string ColorName(Idx colorIndex) const
Look up the color name for a given color index.
void Colors(ColorSet &rColors) const
Insert all colors used in the generator to a given ColorSet.
Triple (X1,Ev,X2) to represent current state, event and next state.
Definition: cfl_transset.h:57
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
Write configuration data to a string.
Definition: cfl_types.cpp:169
Base class of all FAUDES generators.
StateSet::Iterator StatesBegin(void) const
Iterator to Begin() of state set.
const TransSet & TransRel(void) const
Return reference to transition relation.
bool SetTransition(Idx x1, Idx ev, Idx x2)
Add a transition to generator by indices.
void ClearTransRel(void)
Clear all transitions.
TransSet::Iterator TransRelBegin(void) const
Iterator to Begin() of transition relation.
SymbolTable * EventSymbolTablep(void) const
Get Pointer to EventSymbolTable currently used by this vGenerator.
EventSet::Iterator AlphabetBegin(void) const
Iterator to Begin() of alphabet.
std::string TStr(const Transition &rTrans) const
Return pretty printable transition (eg for debugging)
std::string StateName(Idx index) const
State name lookup.
virtual void DotWrite(const std::string &rFileName) const
Writes generator to dot input format.
void Name(const std::string &rName)
Set the generator's name.
StateSet::Iterator StatesEnd(void) const
Iterator to End() of state set.
TransSet::Iterator TransRelEnd(void) const
Iterator to End() of transition relation.
Idx InsState(void)
Add new anonymous state to generator.
bool InsEvent(Idx index)
Add an existing event to alphabet by index.
std::string EventName(Idx index) const
Event name lookup.
EventSet::Iterator AlphabetEnd(void) const
Iterator to End() of alphabet.
Idx Size(void) const
Get generator size (number of states)
std::string SStr(Idx index) const
Return pretty printable state name for index (eg for debugging)
void InjectAlphabet(const EventSet &rNewalphabet)
Set mpAlphabet without consistency check.
virtual void Clear(void)
Clear all set.
Definition: cfl_baseset.h:1902
Iterator End(void) const
Iterator to the end of set.
Definition: cfl_baseset.h:1896
Iterator Begin(void) const
Iterator to the begin of set.
Definition: cfl_baseset.h:1891
const std::string & Name(void) const
Return name of TBaseSet.
Definition: cfl_baseset.h:1755
void ComputeBisimulation(const Generator &rGenOrig, map< Idx, Idx > &rMapStateToPartition)
Computation of the coarsest bisimulation relation for a specified generator.
Idx calcNaturalObserver(const MtcSystem &rGen, EventSet &rHighAlph)
Calculate a colored natural observer by extending a given high-level alphabet.
void ExtendHighAlphabet(const Generator &rGen, EventSet &rHighAlph, map< Idx, Idx > &rMapStateToPartition)
Extension of the high-level alphabet to achieve the Lm-observer property.
libFAUDES resides within the namespace faudes.
uint32_t Idx
Type definition for index type (allways 32bit)
void calcAbstAlphObs(MtcSystem &rGenObs, EventSet &rControllableEvents, EventSet &rHighAlph, EventSet &rNewHighAlph, map< Transition, Idx > &rMapChangedTrans)
Lm-observer computation.
void calculateDynamicSystemObs(const MtcSystem &rGen, EventSet &rHighAlph, Generator &rGenDyn)
Computation of the dynamic system for an Lm-observer.
void LocalAccessibleReach(const Generator &rLowGen, const EventSet &rHighAlph, Idx lowState, StateSet &rAccessibleReach)
Compute the accessible reach for a local automaton.
std::string ToStringInteger(Int number)
integer to string
Definition: cfl_helper.cpp:43
bool relabel(Generator &rGenRelabel, EventSet &rControllableEvents, EventSet &rHighAlph, map< Idx, Idx > &rMapStateToPartition, map< Transition, Transition > &rMapChangedTransReverse, map< Transition, Idx > &rMapChangedTrans, map< Idx, EventSet > &rMapRelabeledEvents)
Relabeling algorithm for the computation of an Lm-observer.
#define OP_DF(expr)
Definition: op_debug.h:31

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