mtc_observercomputation.cpp
Go to the documentation of this file.
1/** @file mtc_observercomputation.cpp
2
3Methods to compute natural projections that exhibit the obsrver property.
4The observer algorithm is elaborated in
5K. C. Wong and W. M. Wonham, "On the Computation of Observers in Discrete Event
6Systems," Discrete Event Dynamic Systems, vol. 14, no. 1, pp. 55-107, 2004.
7In addition, methods to compute natural projections that exhibit
8output control consistency (OCC) and local control consistency (LCC) are provided. See for example
9K. Schmidt and C. Breindl, "On Maximal Permissiveness of Hierarchical and Modular Supervisory
10Control Approaches for Discrete Event Systems," Workshop on Discrete Event Systems, 2008.
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
35using namespace std;
36
37namespace faudes{
38
39
40// calcNaturalObserver(rGen,rHighAlph)
41Idx 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)
60void 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)
71void 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)
94void 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)
138void 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;
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}
const std::string & Name(void) const
bool Exists(const Idx &rIndex) const
Iterator BeginByX2(Idx x2) const
Iterator EndByX2(Idx x2) const
const TaEventSet< EventAttr > & Alphabet(void) const
const ATransSet & TransRel(void) const
EventSet ControllableEvents(void) const
void SetControllable(Idx index)
std::string ColorName(Idx colorIndex) const
void Colors(ColorSet &rColors) const
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
StateSet::Iterator StatesBegin(void) const
const TransSet & TransRel(void) const
bool SetTransition(Idx x1, Idx ev, Idx x2)
TransSet::Iterator TransRelBegin(void) const
SymbolTable * EventSymbolTablep(void) const
EventSet::Iterator AlphabetBegin(void) const
std::string TStr(const Transition &rTrans) const
std::string StateName(Idx index) const
virtual void DotWrite(const std::string &rFileName) const
StateSet::Iterator StatesEnd(void) const
TransSet::Iterator TransRelEnd(void) const
bool InsEvent(Idx index)
std::string EventName(Idx index) const
EventSet::Iterator AlphabetEnd(void) const
Idx Size(void) const
std::string SStr(Idx index) const
void InjectAlphabet(const EventSet &rNewalphabet)
virtual void Clear(void)
Iterator End(void) const
Iterator Begin(void) const
void ComputeBisimulation(const Generator &rGenOrig, map< Idx, Idx > &rMapStateToPartition)
Int calcNaturalObserver(const Generator &rGen, EventSet &rHighAlph)
void calcAbstAlphObs(System &rGenObs, EventSet &rHighAlph, EventSet &rNewHighAlph, map< Idx, set< Idx > > &rMapRelabeledEvents)
void ExtendHighAlphabet(const Generator &rGen, EventSet &rHighAlph, map< Idx, Idx > &rMapStateToPartition)
uint32_t Idx
void LocalAccessibleReach(const Generator &rLowGen, const EventSet &rHighAlph, Idx lowState, StateSet &rAccessibleReach)
std::string ToStringInteger(Int number)
Definition cfl_utils.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)
void calculateDynamicSystemObs(const Generator &rGen, EventSet &rHighAlph, Generator &rGenDyn)
#define OP_DF(expr)
Definition op_debug.h:31

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