diag_eventdiagnosis.cpp
Go to the documentation of this file.
1 /** @file diag_eventdiagnosis.cpp
2 Functions to check a system's event-diagnosability and computation of an event-diagnoser. Covers diagnosability with respect to failure events (diagnosability, I-diagnosability).
3 */
4 
5 #include "diag_eventdiagnosis.h"
6 
7 using namespace std;
8 
9 namespace faudes {
10 
11 
12 // IsEventDiagnosable()
13 bool IsEventDiagnosable(const System& rGen, const AttributeFailureTypeMap& rFailureTypeMap, string& rReportString) {
14  Diagnoser genGobs;
15  System genGd;
16  map<pair<Idx,Idx>,Idx> reverseCompositionMap;
17  map<pair<Idx,Idx>,Idx>::iterator rcmIt;
18  StateSet::Iterator stateIt;
20  EventSet::Iterator evIt;
21 
22  // reset report
23  rReportString.clear();
24 
25  FD_DD("IsEventDiagnosable()");
26  // TODO: throw exception, dont report
27  // check for indicator events (which should not exist)
28  for (ftIt = rFailureTypeMap.mFailureTypeMap.Begin(); ftIt != rFailureTypeMap.mFailureTypeMap.End(); ftIt++) {
29  if (!rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mIndicatorEvents.Empty()) {
30  FD_DD("IsEventDiagnosable(): Warning: Existing indicator events are ignored! If you want to check for I-diagnosability use IsIdiagnosable() instead.");
31  rReportString.append("IsEventDiagnosable(): Warning: Existing indicator events are ignored! If you want to check for I-diagnosability use IsIdiagnosable() instead.\n");
32  break;
33  }
34  }
35 
36  // check if assumptions are met
37  // TODO: convention: "Check" rather than "Meet"
38  if (!MeetsDiagnosabilityAssumptions(rGen, rFailureTypeMap, rReportString)) {
39  return false;
40  }
41 
42  // Implementation of Remark 2: Applying Algorithm 1 for each failure type on its own
43  for (ftIt = rFailureTypeMap.mFailureTypeMap.Begin(); ftIt != rFailureTypeMap.mFailureTypeMap.End(); ftIt++) {
44  FD_DD("Testing for failure type " + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) \
45  + " with failures " + rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mFailureEvents.ToString());
46 
47  // 3 Steps of Algorithm 1
48  // Step 1: Generate G_o
49  FD_DD("__Step 1__");
50  ComputeGobs(rGen, rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt), rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mFailureEvents, genGobs);
51  //genGobs.Write("tmp_Gobs_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".gen");
52  //genGobs.GraphWrite("tmp_Gobs_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".png");
53 
54  // Step 2: Generate G_d = G_o || G_o
55  // State names/attributes are not copied to new generator G_d
56  // but can be obtained via reverse composition map and the corresponding elements of G_o
57  FD_DD("__Step 2__");
58  ComputeGd(genGobs, reverseCompositionMap, genGd);
59  //genGd.Write("tmp_Gd_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".gen");
60  //genGd.GraphWrite("tmp_Gd_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".png");
61 
62  // Step 3: Check for cycles in G_d which contain states with different failure labels
63  FD_DD("__Step 3__");
64  if(ExistsViolatingCyclesInGd(genGd, genGobs, reverseCompositionMap, rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt), rReportString)) {
65  //genGd.Write("tmp_Gd_pruned_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".gen");
66  //genGd.GraphWrite("tmp_Gd_pruned_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".png");
67  return false;
68  } else {
69  //genGd.Write("tmp_Gd_pruned_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".gen");
70  //genGd.GraphWrite("tmp_Gd_pruned_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".png");
71  }
72 
73  }
74  return true;
75 }
76 
77 // rti function interface
78 bool IsEventDiagnosable(const System& rGen, const AttributeFailureTypeMap& rFailureTypeMap) {
79  std::string ignore;
80  return IsEventDiagnosable(rGen,rFailureTypeMap,ignore);
81 }
82 
83 
84 // IsIdiagnosable()
85 bool IsIndicatorEventDiagnosable(const System& rGen, const AttributeFailureTypeMap& rFailureTypeMap, string& rReportString) {
86  Diagnoser genGobs;
87  System genGd;
88  map<pair<Idx,Idx>,Idx> reverseCompositionMap;
89  map<pair<Idx,Idx>,Idx>::iterator rcmIt;
90  StateSet::Iterator stateIt;
92  EventSet::Iterator evIt;
93  rReportString.clear();
94 
95  FD_DD("IsIndicatorEventDiagnosable()");
96  // check for indicator events (which should exist)
97  for (ftIt = rFailureTypeMap.mFailureTypeMap.Begin(); ftIt != rFailureTypeMap.mFailureTypeMap.End(); ftIt++) {
98  if (rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mIndicatorEvents.Empty()) {
99  FD_DD("IsIndicatorEventDiagnosable(): Warning: There are no indicator events for failure type " << rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) << "!");
100  rReportString.append("IsIndicatorEventDiagnosable(): Warning: There are no indicator events for failure type " + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + "!\n");
101  }
102  }
103 
104  // check if assumptions are met
105  if (!MeetsDiagnosabilityAssumptions(rGen, rFailureTypeMap, rReportString)) {
106  return false;
107  }
108 
109  // Implementation of Remark 2: Applying Algorithm 1 for each failure type on its own
110  for (ftIt = rFailureTypeMap.mFailureTypeMap.Begin(); ftIt != rFailureTypeMap.mFailureTypeMap.End(); ftIt++) {
111  FD_DD("Testing for failure type " + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) \
112  + " with failures/indicators " + rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).ToString());
113 
114  // 3 Steps of Algorithm 1
115  // Step 1: Generate G_o
116  FD_DD("__Step 1__");
117  ComputeGobs(rGen, rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt), rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mFailureEvents, genGobs);
118  //genGobs.Write("tmp_I_Gobs_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".gen");
119  //genGobs.GraphWrite("tmp_I_Gobs_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".png");
120 
121  // Step 2: Generate G_d = G_o || G_o
122  // State names/attributes are not copied to new generator G_d
123  // but can be obtained via reverse composition map and the corresponding elements of G_o
124  FD_DD("__Step 2__");
125  ComputeGd(genGobs, reverseCompositionMap, genGd);
126  //genGd.Write("tmp_I_Gd_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".gen");
127  //genGd.GraphWrite("tmp_I_Gd_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".png");
128 
129  // Additionally for I-diagnosability: Remove all traces which do not contain a failure event followed by an indicator event
130  FD_DD("Removing all traces not containing an indicator event " + rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mIndicatorEvents.ToString());
131  TrimNonIndicatorTracesOfGd(genGd, genGobs, *ftIt, rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mIndicatorEvents, reverseCompositionMap);
132  //genGd.Write("tmp_I_Gd_iTraces_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".gen");
133  //genGd.GraphWrite("tmp_I_Gd_iTraces_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".png");
134 
135  // Step 3: Check for cycles in G_d which contain states with different failure labels
136  FD_DD("__Step 3__");
137  if(ExistsViolatingCyclesInGd(genGd, genGobs, reverseCompositionMap, rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt), rReportString)) {
138  //genGd.Write("tmp_I_Gd_pruned_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".gen");
139  //genGd.GraphWrite("tmp_I_Gd_pruned_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".png");
140  return false;
141  } else {
142  //genGd.Write("tmp_I_Gd_pruned_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".gen");
143  //genGd.GraphWrite("tmp_I_Gd_pruned_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".png");
144  }
145 
146  }
147  return true;
148 }
149 
150 
151 
152 // rti function interface
153 bool IsIndicatorEventDiagnosable(const System& rGen, const AttributeFailureTypeMap& rFailureTypeMap) {
154  std::string ignore;
155  return IsEventDiagnosable(rGen,rFailureTypeMap,ignore);
156 }
157 
158 
159 // MeetsDiagnosabilityAssumptions()
160 bool MeetsDiagnosabilityAssumptions(const System& rGen, const AttributeFailureTypeMap& rFailureTypeMap, string& rReportString) {
162  EventSet::Iterator evIt;
163 
164  // check if failure and indicator events are part of the generators alphabet
165  for (ftIt = rFailureTypeMap.mFailureTypeMap.Begin(); ftIt != rFailureTypeMap.mFailureTypeMap.End(); ftIt++) {
166  // check if all failures are valid events of generator
167  for (evIt = rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mFailureEvents.Begin(); evIt != rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mFailureEvents.End(); evIt++) {
168  if (!rGen.Alphabet().Exists(*evIt)) {
169  stringstream errstr;
170  errstr << "Failure " << rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mFailureEvents.SymbolicName(*evIt) << " is not in alphabet of generator!" << endl;
171  throw Exception("MeetsDiagnosabilityAssumptions()", errstr.str(), 302);
172  }
173  }
174  // check if all indicator events are valid events of generator
175  for (evIt = rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mIndicatorEvents.Begin(); evIt != rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mIndicatorEvents.End(); evIt++) {
176  if (!rGen.Alphabet().Exists(*evIt)) {
177  stringstream errstr;
178  errstr << "Indicator " << rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mIndicatorEvents.SymbolicName(*evIt) << " is not in alphabet of generator!" << endl;
179  throw Exception("MeetsDiagnosabilityAssumptions()", errstr.str(), 303);
180  }
181  }
182  }
183 
184  // Assumption A1: Liveness
185  if (!IsLive(rGen, rReportString)) {
186  FD_DD("MeetsDiagnosabilityAssumptions(): Generator is not live!");
187  rReportString.append("Generator is not live!\n");
188  return false;
189  }
190 
191  // Assumption A3: All failure events are unobservable
192  if (!FailuresUnobservable(rGen, rFailureTypeMap, rReportString)) {
193  FD_DD("MeetsDiagnosabilityAssumptions(): Not all failure events are unobservable!");
194  rReportString.append("Not all failure events are unobservable!\n");
195  return false;
196  }
197 
198  // Assumption A2: No cycles of unobservable events
199  if (CycleOfUnobsEvents(rGen, rReportString)) {
200  FD_DD("MeetsDiagnosabilityAssumptions(): Generator contains cycle of unobservable events!");
201  rReportString.append("Generator contains cycle of unobservable events!\n");
202  return false;
203  }
204 
205  // otherwise
206  return true;
207 }
208 
209 // ConvertParallelCompositionMap()
210 void ConvertParallelCompositionMap( const map<pair<Idx,Idx>,Idx>& rReverseCompositionMap,
211  map<Idx,pair<Idx,Idx> >& rCompositionMap) {
212  // invert rReverseCompositionMap (possible, as map is expected to be from parallel composition
213  // and thus must be bijective)
214  map<pair<Idx,Idx>,Idx>::const_iterator iter;
215 
216  FD_DD("ConvertParallelCompositionMap()");
217  rCompositionMap.clear();
218  for(iter = rReverseCompositionMap.begin(); iter != rReverseCompositionMap.end(); iter++) {
219  rCompositionMap.insert(make_pair(iter->second,iter->first));
220  }
221 }
222 
223 // IsLive()
224 // TODO: inefficient set of active vents; have method in Generator
225 bool IsLive(const System& rGen, string& rReport) {
226  StateSet states;
227  StateSet::Iterator it;
228  FD_DD("IsLive()");
229  states = rGen.States();
230  for (it = states.Begin(); it != states.End(); it++) {
231  if (rGen.ActiveEventSet(*it).Empty()) {
232  rReport.append("Missing transition at state " + ToStringInteger(*it) + " --> ");
233  return false;
234  }
235  }
236  return true;
237 }
238 
239 // CycleOfUnobsEvents()
240 // TODO: inefficient copy; have method in Generator
241 bool CycleOfUnobsEvents(const System& rGen, string& rReport) {
242  TransSet transitionsToDelete;
244  System genCopy;
245 
246  FD_DD("CycleOfUnobsEvents()");
247  transitionsToDelete.Clear();
248  // make a copy of generator
249  genCopy = rGen;
250  // parse through all its transitions and delete the observable ones
251  for (it = genCopy.TransRelBegin(); it != genCopy.TransRelEnd(); it++) {
252  if (genCopy.Observable(it->Ev)) {
253  transitionsToDelete.Insert(*it);
254  }
255  }
256  for (it = transitionsToDelete.Begin(); it != transitionsToDelete.End(); it++) {
257  FD_DD("delete " << it->X1 << " --" << genCopy.EventName(it->Ev) << "--> " << it->X2);
258  genCopy.ClrTransition(*it);
259  }
260  // check for cycles within the remaining unobservable events
261  return ExistsCycle(genCopy, rReport);
262 }
263 
264 // FailuresUnobservable()
265 bool FailuresUnobservable(const System& rGen, const AttributeFailureTypeMap& rFailureTypeMap, string& rReport) {
266  EventSet failures, unobsEvents;
267  EventSet::Iterator evIt;
268 
269  FD_DD("FailuresUnobservable()");
270  failures = rFailureTypeMap.AllFailureEvents();
271  unobsEvents = rGen.UnobservableEvents();
272  for (evIt = failures.Begin(); evIt != failures.End(); evIt++) {
273  if (!unobsEvents.Exists(*evIt)) {
274  FD_DD("FailuresUnobservable(): Failure event \"" << failures.SymbolicName(*evIt) << "\" is not unobservable in generator!");
275  rReport.append("Failure event \"" + failures.SymbolicName(*evIt) + "\" is observable in generator --> ");
276  return false;
277  }
278  }
279  return true;
280 }
281 
282 // ExistsCycle()
283 bool ExistsCycle(const System& rGen, string& rReport) {
284  StateSet todo, path;
285  StateSet::Iterator stateIt;
286 
287  FD_DD("ExistsCycle()");
288  todo = rGen.States();
289  path.Clear();
290  for (stateIt = rGen.InitStatesBegin(); stateIt != rGen.InitStatesEnd(); ++stateIt) {
291  FD_DD("Start cycle search at initial state");
292  if (ExistsCycleSearch(rGen, todo, *stateIt, path, rReport)) {
293  return true;
294  }
295  }
296  while (!todo.Empty()) {
297  FD_DD("Start cycle search at some state..");
298  if (ExistsCycleSearch(rGen, todo, *todo.Begin(), path, rReport)) {
299  return true;
300  }
301  }
302  return false;
303 }
304 
305 // ExistsCycleSearch()
306 bool ExistsCycleSearch(const System& rGen, StateSet& rTodo, Idx currState, StateSet statesOnPath, string& rReport) {
307  StateSet successors, newStatesOnPath;
308  StateSet::Iterator stateIt;
309 
310  FD_DD("ExistsCycleSearch() for State " << currState);
311  rTodo.Erase(currState);
312  statesOnPath.Insert(currState);
313 
314  successors = rGen.SuccessorStates(currState);
315  // parse through active state set of currState
316  for (stateIt = successors.Begin(); stateIt != successors.End(); stateIt++) {
317  if (statesOnPath.Exists(*stateIt)) {
318  FD_DD("Cycle found at state " << *stateIt);
319  rReport.append("Cycle found at state " + ToStringInteger(*stateIt) + " --> ");
320  return true;
321  }
322  // call ExistsCycleSearch() for next successor state and with updated state set newStatesOnPath
323  newStatesOnPath.Clear();
324  newStatesOnPath.InsertSet(statesOnPath);
325  newStatesOnPath.Insert(*stateIt);
326  if (ExistsCycleSearch(rGen, rTodo, *stateIt, newStatesOnPath, rReport)) {
327  return true;
328  }
329  }
330  return false;
331 }
332 
333 // CycleStartStates()
334 void CycleStartStates(const System& rGen, StateSet& rCycleOrigins) {
335  StateSet todo, path;
336 
337  FD_DD("ExistsCycle()");
338  rCycleOrigins.Clear();
339  todo = rGen.States();
340  if (!rGen.InitStatesEmpty()) {
341  FD_DD("Start cycle search at initial state");
342  path.Clear();
343  CycleStartStatesSearch(rGen, todo, rGen.InitState(), path, rCycleOrigins);
344  }
345  while (!todo.Empty()) {
346  FD_DD("Start cycle search at some state..");
347  path.Clear();
348  CycleStartStatesSearch(rGen, todo, *todo.Begin(), path, rCycleOrigins);
349  }
350  return;
351 }
352 
353 // CycleStartStatesSearch()
354 void CycleStartStatesSearch(const System& rGen, StateSet& rTodo, Idx currState, StateSet statesOnPath, StateSet& rCycleOriginStates) {
355  StateSet successors, newStatesOnPath;
356  StateSet::Iterator stateIt;
357 
358  FD_DD("CycleStartStatesSearch() for State " << currState);
359  rTodo.Erase(currState);
360  statesOnPath.Insert(currState);
361 
362  successors = rGen.SuccessorStates(currState);
363  // parse through active state set of currState
364  for (stateIt = successors.Begin(); stateIt != successors.End(); stateIt++) {
365  if (statesOnPath.Exists(*stateIt)) {
366  FD_DD("Cycle found at state " << *stateIt);
367  rCycleOriginStates.Insert(*stateIt);
368  return;
369  }
370  // call ExistsCycleSearch() for next successor state and with updated state set newStatesOnPath
371  newStatesOnPath.Clear();
372  newStatesOnPath.InsertSet(statesOnPath);
373  newStatesOnPath.Insert(*stateIt);
374  CycleStartStatesSearch(rGen, rTodo, *stateIt, newStatesOnPath, rCycleOriginStates);
375  }
376  return;
377 }
378 
379 // ExistsViolatingCyclesInGd()
380 bool ExistsViolatingCyclesInGd(System& rGd, const Diagnoser& rGobs, map<pair<Idx,Idx>,Idx>& rReverseCompositionMap, const string& rFailureType, string& rReportString) {
381  map<pair<Idx,Idx>,Idx>::iterator rcmIt;
382  const TaIndexSet<DiagLabelSet>* fLabel1;
383  const TaIndexSet<DiagLabelSet>* fLabel2;
386 
387  FD_DD("ExistsViolatingCyclesInGd()");
388  // Therefore parse through reverse composition map
389  for (rcmIt = rReverseCompositionMap.begin(); rcmIt != rReverseCompositionMap.end();) {
390  FD_DD("state " << rcmIt->second << " (" << rcmIt->first.first << "," << rcmIt->first.second << ")");
391  // if both states in G_o are equal or just contain the same failure label: delete corresponding state in G_d
392  if (rcmIt->first.first == rcmIt->first.second) {
393  FD_DD(" --> delete (same G_o state)");
394  rGd.DelState(rcmIt->second);
395  rReverseCompositionMap.erase(rcmIt++);
396  } else {
397  fLabel1 = rGobs.StateAttribute(rcmIt->first.first).DiagnoserStateMapp();
398  fLabel2 = rGobs.StateAttribute(rcmIt->first.second).DiagnoserStateMapp();
399  fL1Begin = fLabel1->Begin();
400  fL2Begin = fLabel2->Begin();
401  if (fLabel1->Attribute(*fL1Begin) == fLabel2->Attribute(*fL2Begin)) {
402  FD_DD(" --> delete (same failure label)");
403  rGd.DelState(rcmIt->second);
404  rReverseCompositionMap.erase(rcmIt++);
405  } else {
406  ++rcmIt;
407  }
408  }
409  FD_DD("");
410  }
411  // if there exists a cycle in the remainder graph the system rGen is not diagnosable
412  if (ExistsCycle(rGd,rReportString)) {
413  FD_DD("Detected cycle in G_d");
414  rReportString.append("While checking diagnosability for failure type " + rFailureType + ": " + \
415  "G_d contains a cycle of states with unequal failure labels, i.e. there exists an " + \
416  rFailureType + "-indeterminate cycle in the diagnoser.\n");
417  return true;
418  }
419  return false;
420 }
421 
422 // ComputeGobs()
423 void ComputeGobs(const System& rOrigGen, const string& rFailureType, const EventSet& rFailureEvents, Diagnoser& rGobs) {
424  AttributeFailureTypeMap singleFailureTypeMap;
425  singleFailureTypeMap.Clear();
426  singleFailureTypeMap.AddFailureTypeMapping(rFailureType, rFailureEvents);
427  ComputeGobs(rOrigGen, singleFailureTypeMap, rGobs);
428 }
429 
430 // ComputeGobs()
431 void ComputeGobs(const System& rOrigGen, const AttributeFailureTypeMap& rAttrFTMap, Diagnoser& rGobs) {
432  EventSet failureEvents;
433  EventSet gObservableEvents, gUnobservableEvents;
434  StateSet newGobsStates;
435  Idx currDState = 0;
436  Idx nextDState = 0;
437 
438  FD_DD("ComputeGobs()");
439  // check if FailureTypeMap is empty
440  if (rAttrFTMap.Empty()) {
441  FD_DD("WARNING - ComputeGobs(): failure type map is empty!");
442  }
443 
444  // clear Gobs
445  rGobs.Clear();
446  rGobs.ClearAttributes();
447 
448  // copy attribute failure type map to Gobs
449  rGobs.GlobalAttribute(rAttrFTMap);
450 
451  // get observable events of original generator
452  gObservableEvents = rOrigGen.ObservableEvents();
453  FD_DD("Observable events: " << gObservableEvents.ToString());
454 
455  // get unobservable events of original generator
456  gUnobservableEvents = rOrigGen.UnobservableEvents();
457  FD_DD("Unobservable events: " << gUnobservableEvents.ToString());
458 
459  // copy all failure events into one single EventSet
460  failureEvents = rGobs.GetAllFailureEvents();
461  FD_DD("Failure events: " << failureEvents.ToString());
462 
463  // create initial state of Gobs and its attribute with label "normal"
464  #ifdef FAUDES_CHECKED
465  if(rOrigGen.InitStatesSize() != 1) {
466  std::stringstream errstr;
467  errstr << "original generator has no unique initial state" << std::endl;
468  throw Exception("ComputeGobs()", errstr.str(), 301);
469  }
470  #endif
471  Idx gInitState = rOrigGen.InitState();
472  currDState = rGobs.InsInitState();
473  newGobsStates.Insert(currDState);
474  rGobs.InsStateLabelMapping(currDState,gInitState,DiagLabelSet::IndexOfLabelN());
475 
476  Idx gStateEstimate = 0;
477  Idx newState = 0;
478 
479  map<Idx,multimap<Idx,DiagLabelSet> > reachMap; // maps executable events to all reachable states and occuring relative failure types
480  map<Idx,multimap<Idx,DiagLabelSet> >::iterator it;
481 
482  multimap<Idx,DiagLabelSet>::iterator mmit, mmit2;
483 
484  pair<Idx,DiagLabelSet> reachMapPair;
485 
486  TransSet transitions;
487  DiagLabelSet oldLabel, newLabel, occFailureTypes;
488  DiagLabelSet::Iterator labelIt;
489  StateSet gObsStates;
490  StateSet::Iterator stateIt;
491  EventSet activeEvents;
492  AttributeDiagnoserState newAttr;
493  AttributeDiagnoserState currDStateAttr;
494  TaIndexSet<DiagLabelSet> currDStateMap;
495  TaIndexSet<DiagLabelSet>::Iterator currDStateMapIt;
496 
497  // parse through new Gobs states
498  while (!newGobsStates.Empty()) {
499  // set current Gobs state
500  currDState = *newGobsStates.Begin();
501 
502  currDStateAttr = rGobs.StateAttribute(currDState);
503  currDStateMap = currDStateAttr.DiagnoserStateMap();
504 
505  // parse through state estimates of current Gobs state
506  for(currDStateMapIt = currDStateMap.Begin(); currDStateMapIt != currDStateMap.End(); ++ currDStateMapIt){
507  gStateEstimate = *currDStateMapIt;
508 
509  // generate reachMap for current state estimate
510  ComputeReachability(rOrigGen, gUnobservableEvents, failureEvents, gStateEstimate, rAttrFTMap, reachMap);
511 
512  #ifdef FAUDES_DEBUG_DIAGNOSIS
513  FD_DD(endl << "reachMap: ");
514  for (it = reachMap.begin(); it != reachMap.end(); it++) {
515  //print reachMap for current event
516  FD_DD("_" << rOrigGen.EventName(it->first) << " ("<< it->second.size() << " state estimates)");
517  for (mmit = it->second.begin(); mmit != it->second.end(); mmit++) {
518  FD_DD(mmit->first << " " << mmit->second.ToString());
519  }
520  }
521  FD_DD("");
522  #endif
523 
524  // parse through reachMap (eventwise)
525  for (it = reachMap.begin(); it != reachMap.end(); it++) {
526  //print reachMap for current event
527  #ifdef FAUDES_DEBUG_DIAGNOSIS
528  FD_DD(endl << "_" << rOrigGen.EventName(it->first) << " ("<< it->second.size() << " state estimates)");
529  for (mmit = it->second.begin(); mmit != it->second.end(); mmit++) {
530  FD_DD(mmit->first << " " << mmit->second.ToString());
531  }
532  #endif
533 
534  // get label set of current state estimate
535  oldLabel = currDStateMap.Attribute(*currDStateMapIt);
536  FD_DD("old label: " << oldLabel.ToString());
537 
538  newState = 0;
539  // parse through state failure type map (for current event in reachMap)
540  for (mmit = it->second.begin(); mmit != it->second.end(); mmit++) {
541  newState = mmit->first;
542  FD_DD("new state: " << newState);
543  occFailureTypes = mmit->second;
544  FD_DD("failure types occurred: " << occFailureTypes.ToString());
545  LabelPropagation(oldLabel, occFailureTypes, newLabel);
546  FD_DD("new label: " << newLabel.ToString());
547  newAttr.Clear();
548  newAttr.AddStateLabelMap(newState,newLabel);
549 
550  // if newAttr equals any existing state attribute than we create a transition to this very state
551  gObsStates = rGobs.States();
552  stateIt = gObsStates.Begin();
553  while (stateIt != gObsStates.End()) {
554  if (newAttr == rGobs.StateAttribute(*stateIt)) {
555  FD_DD("realising as back- or self-loop to existing state " << *stateIt);
556  rGobs.InsEvent(it->first);
557  rGobs.SetTransition(currDState,it->first,*stateIt);
558  break;
559  }
560  stateIt++;
561  }
562  // if newAttribute is new to Gobs
563  if (stateIt == gObsStates.End()) {
564  // create new Gobs state and add it to new states
565  nextDState = rGobs.InsState();
566  FD_DD("Create new state " << nextDState << " and transition " << currDState << " --" << rOrigGen.EventName(it->first) << "--> " << nextDState);
567  newGobsStates.Insert(nextDState);
568  rGobs.InsEvent(it->first);
569  rGobs.SetTransition(currDState,it->first,nextDState);
570  rGobs.StateAttribute(nextDState, newAttr);
571 
572  FD_DD("Print Gobs label of state " << nextDState);
573  FD_DD(rGobs.StateAttributep(nextDState)->ToString());
574  }
575  }
576  }
577  }
578 
579  activeEvents = rGobs.ActiveEventSet(currDState);
580  transitions = rGobs.ActiveTransSet(currDState);
581 
582  // delete current Gobs state from new states
583  newGobsStates.Erase(currDState);
584  }
585 }
586 
587 // ComputeGd()
588 void ComputeGd(const Diagnoser& rGobs, map<pair<Idx,Idx>,Idx>& rReverseCompositionMap, System& rGd) {
589  string stateName;
590  map<pair<Idx,Idx>,Idx>::iterator rcmIt;
591  rReverseCompositionMap.clear();
592 
593  FD_DD("ComputeGd()");
594  FD_DD("Performing parallel compostion of G_o with itself ...");
595  Parallel(rGobs, rGobs, rReverseCompositionMap, rGd);
596  FD_DD("Writing G_d state names ...");
597  for (rcmIt = rReverseCompositionMap.begin(); rcmIt != rReverseCompositionMap.end(); rcmIt++) {
598  stateName = ToStringInteger(rcmIt->second) + "{" + \
599  rGobs.SAStr(rcmIt->first.first) + "'" + \
600  rGobs.SAStr(rcmIt->first.second) +"}";
601  rGd.StateName(rcmIt->second, stateName);
602  }
603 }
604 
605 // TrimNonIndicatorTracesOfGd()
606 void TrimNonIndicatorTracesOfGd(System& rGd, const Diagnoser& rGobs, const Idx rFailureType,
607  const EventSet& rIndicatorEvents, const map<pair<Idx,Idx>,Idx>& rReverseCompositionMap) {
608  StateSet statesDone;
609  map<Idx,pair<Idx,Idx> > CompositionMap;
610 
611  FD_DD("TrimNonIndicatorTracesOfGd()");
612  ConvertParallelCompositionMap(rReverseCompositionMap, CompositionMap);
613  statesDone.Clear();
614  TrimNonIndicatorTracesOfGdRecursive(rGd, rGobs, rFailureType, rIndicatorEvents, CompositionMap, rGd.InitState(), statesDone);
615 }
616 
617 // TrimNonIndicatorTracesOfGdRecursive()
618 void TrimNonIndicatorTracesOfGdRecursive(System& rGd, const Diagnoser& rGobs, const Idx rFailureType,
619  const EventSet& rIndicatorEvents, map<Idx,pair<Idx,Idx> >& rCompositionMap,
620  Idx state, StateSet& rStatesDone) {
621  TransSet trans, backTrans;
623  Idx nextState = 0;
624  const TaIndexSet<DiagLabelSet>* pDiagState1;
625  const TaIndexSet<DiagLabelSet>* pDiagState2;
626  map<Idx,pair<Idx,Idx> >::iterator compMapIt;
627  bool failureHasAlreadyOccurred = false;
628 
629  FD_DD("TrimNonIndicatorTracesOfGdRecursive() for state " + ToStringInteger(state));
630 
631  // return if this state has already been processed
632  if (rStatesDone.Exists(state)) {
633  return;
634  }
635  rStatesDone.Insert(state);
636  trans = rGd.ActiveTransSet(state);
637 
638  // if state has no successors than delete it
639  if (trans.Empty()) {
640  rGd.DelState(state);
641  FD_DD("removing state " << state);
642  return;
643  }
644 
645  // If there exists a self-loop of an indicator event (after the occurrence of a failure event), return.
646  // This needs to be checked because otherwise the following for-loop could cut parts of the future traces before noticing the self-loop.
647  for (it = trans.Begin(); it != trans.End(); it++) {
648  if (it->X1 == it->X2) {
649  if (rIndicatorEvents.Exists(it->Ev)) {
650  compMapIt = rCompositionMap.find(it->X2);
651  pDiagState1 = rGobs.StateAttribute(compMapIt->second.first).DiagnoserStateMapp();
652  pDiagState2 = rGobs.StateAttribute(compMapIt->second.second).DiagnoserStateMapp();
653  if (*(pDiagState1->Attribute(*(pDiagState1->Begin())).mDiagLabels.Begin()) == rFailureType) {
654  return;
655  }
656  if (*(pDiagState2->Attribute(*(pDiagState2->Begin())).mDiagLabels.Begin()) == rFailureType) {
657  return;
658  }
659  }
660  }
661  }
662 
663  // parse through transitions of active transition set
664  for (it = trans.Begin(); it != trans.End(); it++) {
665  nextState = it->X2;
666  failureHasAlreadyOccurred = false;
667 
668  // if event is an indicator: check if corresponding failure type has already occurred
669  // by checking if there exists a corresponding failure in the _next_ failure label in G_d
670  // (we use the _next_ label (and not the last one) to make sure not to miss out failures that occur immediately before the indicator event)
671  if (rIndicatorEvents.Exists(it->Ev)) {
672  compMapIt = rCompositionMap.find(nextState);
673  pDiagState1 = rGobs.StateAttribute(compMapIt->second.first).DiagnoserStateMapp();
674  pDiagState2 = rGobs.StateAttribute(compMapIt->second.second).DiagnoserStateMapp();
675  if (*(pDiagState1->Attribute(*(pDiagState1->Begin())).mDiagLabels.Begin()) == rFailureType) {
676  failureHasAlreadyOccurred = true;
677  }
678  if (*(pDiagState2->Attribute(*(pDiagState2->Begin())).mDiagLabels.Begin()) == rFailureType) {
679  failureHasAlreadyOccurred = true;
680  }
681  }
682 
683  // if transition event is not an indicator event or there did not occur a failure _before_ the indicator
684  if (!rIndicatorEvents.Exists(it->Ev) || !failureHasAlreadyOccurred) {
685  // remove transition
686  rGd.ClrTransition(*it);
687  FD_DD("removing transition " << it->X1 << "--" << rGd.EventName(it->Ev) << "-->" << it->X2 );
688  // remove state if it does not have any transitions left
689  if (rGd.ActiveTransSet(state).Empty()) {
690  rGd.DelState(state);
691  FD_DD("removing state " << state );
692  }
693  // if there do not exist any further transitions form other states into the next state: continue trimming at next state
694  backTrans = ActiveBackwardTransSet(rGd, nextState);
695  if (backTrans.Empty() || ((backTrans.Size() == 1) && (backTrans.Begin()->X2 == nextState))) {
696  TrimNonIndicatorTracesOfGdRecursive(rGd, rGobs, rFailureType, rIndicatorEvents, rCompositionMap, nextState, rStatesDone);
697  }
698  }
699  }
700 }
701 
702 // ComputeReachability()
703 void ComputeReachability(const System& rGen, const EventSet& rUnobsEvents, const EventSet& rFailures, Idx State,
704  const AttributeFailureTypeMap& rAttrFTMap, map<Idx,multimap<Idx,DiagLabelSet> >& rReachabilityMap) {
705  DiagLabelSet FTonPath;
706 
707  FD_DD("ComputeReachability() for state " << State << "...");
708  rReachabilityMap.clear();
709  FTonPath.Clear();
710  ComputeReachabilityRecursive(rGen, rUnobsEvents, rFailures, State, rAttrFTMap, rReachabilityMap, FTonPath);
711 
712  multimap<Idx,DiagLabelSet>::iterator mmLabelIt;
713  map<Idx,multimap<Idx,DiagLabelSet> >::iterator it;
714 
715  #ifdef FAUDES_DEBUG_DIAGNOSIS
716  FD_DD("rReachabilityMap: ");
717  for (it = rReachabilityMap.begin(); it != rReachabilityMap.end(); it++) {
718  // print rReachabilityMap for current event
719  FD_DD("_" << rGen.EventName(it->first) << " ("<< it->second.size() << " state estimates)");
720  for (mmLabelIt = it->second.begin(); mmLabelIt != it->second.end(); mmLabelIt++) {
721  FD_DD(mmLabelIt->first << " " << mmLabelIt->second.ToString());
722  }
723  }
724  FD_DD("");
725  #endif
726 }
727 
728 // ComputeReachabilityRecursive()
729 void ComputeReachabilityRecursive(const System& rGen, const EventSet& rUnobsEvents,
730  const EventSet& rFailures, Idx State, const AttributeFailureTypeMap& rAttrFTMap,
731  map<Idx,multimap<Idx,DiagLabelSet> >& rReachabilityMap, const DiagLabelSet FToccurred) {
732  TransSet trans;
733  TransSet::Iterator tIt;
734  EventSet tmpFailureSet;
735  EventSet::Iterator evIt;
736  multimap<Idx,DiagLabelSet> stateFailureTypeMap; // maps generator states onto occurred failure types (=labels), part of rReachabilityMap
737  multimap<Idx,DiagLabelSet>::iterator mmLabelIt;
738  map<Idx,multimap<Idx,DiagLabelSet> >::iterator it;
739  Idx failureType;
740  DiagLabelSet newFT;
741  bool mappingExists;
742 
743  trans = rGen.ActiveTransSet(State);
744 
745  FD_DD("ComputeReachabilityRecursive() for state " << State);
746  // parse through active transitions of current generator state
747  for (tIt = trans.Begin(); tIt != trans.End(); tIt++) {
748  FD_DD(tIt->X1 << "--" << rGen.EventName(tIt->Ev) << "-->" << tIt->X2 << " for " << FToccurred.ToString());
749  // if current event is unobservable
750  if (rUnobsEvents.Exists(tIt->Ev)) {
751  // if it is a failure as well add its failure type
752  if (rFailures.Exists(tIt->Ev)) {
753  FD_DD(rGen.EventName(tIt->Ev) << " is a failure");
754  newFT = FToccurred;
755  newFT.Erase(DiagLabelSet::IndexOfLabelN());
756  failureType = rAttrFTMap.FailureType(tIt->Ev);
757  newFT.Insert(failureType);
758  FD_DD("new failure path: " << newFT.ToString());
759  } else {
760  FD_DD(rGen.EventName(tIt->Ev) << " is unobservable but no failure");
761  newFT = FToccurred;
762  }
763  // call ComputeReachabilityRecursive for successor state
764  ComputeReachabilityRecursive(rGen, rUnobsEvents, rFailures, tIt->X2, rAttrFTMap, rReachabilityMap, newFT);
765  }
766  // if current event is observable add failure type path to rReachabilityMap
767  else {
768  FD_DD(rGen.EventName(tIt->Ev) << " is observable: add it to rReachabilityMap " << FToccurred.ToString());
769  // get old entry of rReachabilityMap if it exists
770  stateFailureTypeMap.clear();
771  if (rReachabilityMap.find(tIt->Ev) != rReachabilityMap.end()) {
772  stateFailureTypeMap = rReachabilityMap[tIt->Ev];
773  #ifdef FAUDES_DEBUG_DIAGNOSIS
774  FD_DD("old entry of rReachabilityMap for " << rGen.EventName(tIt->Ev));
775  for (mmLabelIt = stateFailureTypeMap.begin(); mmLabelIt != stateFailureTypeMap.end(); mmLabelIt++) {
776  FD_DD(mmLabelIt->first << " " << mmLabelIt->second.ToString());
777  }
778  #endif
779  }
780  // if no failure occurred add normal label
781  newFT = FToccurred;
782  if (newFT.Empty()) {
783  newFT.Insert(DiagLabelSet::IndexOfLabelRelN());
784  }
785  // check if new mapping does already exist
786  mappingExists = false;
787  for (mmLabelIt = stateFailureTypeMap.lower_bound(tIt->X2); mmLabelIt != stateFailureTypeMap.upper_bound(tIt->X2); mmLabelIt++) {
788  if (mmLabelIt->second == newFT) {
789  mappingExists = true;
790  }
791  }
792  // if new mapping does not yet exist: add it to rReachabilityMap
793  if (!mappingExists) {
794  stateFailureTypeMap.insert(pair<Idx,DiagLabelSet>(tIt->X2,newFT));
795  rReachabilityMap[tIt->Ev] = stateFailureTypeMap;
796  }
797  }
798  }
799 }
800 
801 // ActiveBackwardTransSet()
803  TransSet result;
804  TransSetX2EvX1 transByX2;
806 
807  rGen.TransRel(transByX2);
808  for (it = transByX2.BeginByX2(state); it != transByX2.EndByX2(state); it++) {
809  result.Insert(*it);
810  }
811  return result;
812 }
813 
814 
815 // EventDiagnoser()
816 void EventDiagnoser(const System& rOrigGen, const map<string,EventSet>& rFailureTypeMap, Diagnoser& rDiagGen) {
817  FD_DD("EventDiagnoser()");
819  attrFT.AddFailureTypeMap(rFailureTypeMap);
820  EventDiagnoser(rOrigGen, attrFT, rDiagGen);
821 }
822 
823 // EventDiagnoser()
824 void EventDiagnoser(const System& rOrigGen, const AttributeFailureTypeMap& rAttrFTMap, Diagnoser& rDiagGen) {
825  EventSet failureEvents;
826  EventSet gObservableEvents, gUnobservableEvents;
827  StateSet newDiagStates;
828  Idx currDState = 0;
829  Idx nextDState = 0;
830  string reportString;
831 
832  FD_DD("EventDiagnoser()");
833  // check if FailureTypeMap is empty
834  if (rAttrFTMap.Empty()) {
835  FD_DD( endl << "WARNING - EventDiagnoser(): failure type map is empty!" << endl);
836  }
837 
838  // Necessary assumption: No cycles of unobservable events
839  reportString.clear();
840  if (CycleOfUnobsEvents(rOrigGen,reportString)) {
841  FD_DD( "EventDiagnoser(): Generator contains cycle of unobservable events! Aborting..");
842  FD_DD(reportString);
843  return;
844  }
845 
846  // clear diagnoser
847  rDiagGen.Clear();
848  rDiagGen.ClearAttributes();
849 
850  // copy attribute failure type map to diagnoser
851  rDiagGen.GlobalAttribute(rAttrFTMap);
852 
853  // get observable events of original generator
854  gObservableEvents = rOrigGen.ObservableEvents();
855  FD_DD("Observable events: " << gObservableEvents.ToString());
856 
857  // get unobservable events of original generator
858  gUnobservableEvents = rOrigGen.UnobservableEvents();
859  FD_DD("Unobservable events: " << gUnobservableEvents.ToString());
860 
861  // copy all failure events into one single EventSet
862  failureEvents = rDiagGen.GetAllFailureEvents();
863  FD_DD("Failure events: " << failureEvents.ToString());
864 
865  // create initial state of diagnoser and its attribute with label "normal"
866  #ifdef FAUDES_CHECKED
867  if(rOrigGen.InitStatesSize() != 1) {
868  std::stringstream errstr;
869  errstr << "original generator has no unique initial state" << std::endl;
870  throw Exception("EventDiagnoser()", errstr.str(), 301);
871  }
872  #endif
873  Idx gInitState = rOrigGen.InitState();
874  currDState = rDiagGen.InsInitState();
875  newDiagStates.Insert(currDState);
876  rDiagGen.InsStateLabelMapping(currDState,gInitState,DiagLabelSet::IndexOfLabelN());
877 
878  Idx gStateEstimate = 0;
879  Idx newState = 0;
880 
881  map<Idx,multimap<Idx,DiagLabelSet> > reachMap; // maps executable events to all reachable states and occuring relative failure types
882  map<Idx,multimap<Idx,DiagLabelSet> > reachMapWholeState; // map for whole diagnoser state, contains propagated absolute failure type labels
883  map<Idx,multimap<Idx,DiagLabelSet> >::iterator it;
884 
885  multimap<Idx,DiagLabelSet> tmpPropagatedLabels;
886  multimap<Idx,DiagLabelSet> bufferPropLabels;
887  multimap<Idx,DiagLabelSet>::iterator mmit, mmit2;
888 
889  //pair<Idx,DiagLabelSet> stateLabelPair;
890  pair<Idx,DiagLabelSet> reachMapPair;
891 
892  TransSet transitions;
893  TransSet::Iterator transIt;
894  DiagLabelSet oldLabel, newLabel, occFailureTypes;
895  DiagLabelSet::Iterator labelIt;
896  StateSet diagStates;
897  StateSet::Iterator stateIt;
898  EventSet activeEvents;
899  AttributeDiagnoserState newAttr;
900  bool stateLabelExists = false;
901  AttributeDiagnoserState currDStateAttr;
902  TaIndexSet<DiagLabelSet> currDStateMap;
903  TaIndexSet<DiagLabelSet>::Iterator currDStateMapIt;
904 
905  // parse through new diagnoser states
906  while (!newDiagStates.Empty()) {
907  // set current diagnoser state
908  currDState = *newDiagStates.Begin();
909 
910  reachMapWholeState.clear();
911 
912  currDStateAttr = rDiagGen.StateAttribute(currDState);
913  currDStateMap = currDStateAttr.DiagnoserStateMap();
914 
915  // parse through state estimates of current diagnoser state
916  for(currDStateMapIt = currDStateMap.Begin(); currDStateMapIt != currDStateMap.End(); ++ currDStateMapIt){
917  gStateEstimate = *currDStateMapIt;
918  // generate reachMap for current state estimate
919  ComputeReachability(rOrigGen, gUnobservableEvents, failureEvents, gStateEstimate, rAttrFTMap, reachMap);
920  // parse through reachMap (eventwise), propagate label and copy it to reachMapWholeState
921  for (it = reachMap.begin(); it != reachMap.end(); it++) {
922  // get label set of current state estimate
923  oldLabel = currDStateMap.Attribute(*currDStateMapIt);
924  newState = 0;
925  tmpPropagatedLabels.clear();
926  // parse through state failure type mappings of state failure type map (for current event in reachMap)
927  for (mmit = it->second.begin(); mmit != it->second.end(); mmit++) {
928  newState = mmit->first;
929  occFailureTypes = mmit->second;
930  LabelPropagation(oldLabel, occFailureTypes, newLabel);
931  // check if this combination of state and label does already exist
932  stateLabelExists = false;
933  for (mmit2 = tmpPropagatedLabels.lower_bound(newState); mmit2 != tmpPropagatedLabels.upper_bound(newState); mmit2++) {
934  if (mmit2->second == newLabel) {
935  stateLabelExists = true;
936  }
937  }
938  // insert new state-label-pair if it does not exist yet
939  if (!stateLabelExists) {
940  tmpPropagatedLabels.insert(pair<Idx,DiagLabelSet>(newState,newLabel));
941  }
942  }
943 
944  // if event is already mapped: add new Labels to multimap and insert it afterwards
945  if (reachMapWholeState.find(it->first) != reachMapWholeState.end()) {
946  bufferPropLabels = reachMapWholeState[it->first];
947 
948  // parse throught tmpPropagatedLabels and check for every combination of state and label
949  // if it does already exist in bufferPropLabels
950  for (mmit = tmpPropagatedLabels.begin(); mmit != tmpPropagatedLabels.end(); mmit++) {
951  stateLabelExists = false;
952  for (mmit2 = bufferPropLabels.lower_bound(mmit->first); mmit2 != bufferPropLabels.upper_bound(mmit->first); mmit2++) {
953  if (mmit2->second == mmit->second) {
954  stateLabelExists = true;
955  }
956  }
957  // insert new state-label-pair if it does not exist yet
958  if (!stateLabelExists) {
959  bufferPropLabels.insert(pair<Idx,DiagLabelSet>(mmit->first,mmit->second));
960  }
961  }
962  reachMapWholeState[it->first] = bufferPropLabels;
963  }
964  // if not just insert the new labels
965  else {
966  reachMapWholeState[it->first] = tmpPropagatedLabels;
967  }
968  }
969  }
970  activeEvents = rDiagGen.ActiveEventSet(currDState);
971  transitions = rDiagGen.ActiveTransSet(currDState);
972 
973  for (it = reachMapWholeState.begin(); it != reachMapWholeState.end(); it++) {
974  LabelCorrection(it->second,newAttr);
975  // if newAttr equals any existing state attribute than create a transition to this very state
976  diagStates = rDiagGen.States();
977  stateIt = diagStates.Begin();
978  while (stateIt != diagStates.End()) {
979  if (newAttr == rDiagGen.StateAttribute(*stateIt)) {
980  // realising as back- or self-loop to existing state *stateIt
981  rDiagGen.InsEvent(it->first);
982  rDiagGen.SetTransition(currDState,it->first,*stateIt);
983  break;
984  }
985  stateIt++;
986  }
987  // if newAttr is new to diagnoser
988  if (stateIt == diagStates.End()) {
989  // if current event is executable from current diagnoser state
990  if (activeEvents.Exists(it->first)) {
991  // this event is executable from current diagnoser state
992  // find successor state nextDState
993  transIt = transitions.Begin();
994  while (transIt != transitions.End()) {
995  if (transIt->Ev == it->first) {
996  nextDState = transIt->X2;
997  break;
998  }
999  transIt++;
1000  }
1001  }
1002  // if event is not executable from current diagnoser state
1003  else {
1004  // this event is not yet executable from current diagnoser state: create new diagnoser state
1005  // creat new diagnoser state and add it to new states
1006  nextDState = rDiagGen.InsState();
1007  newDiagStates.Insert(nextDState);
1008  rDiagGen.InsEvent(it->first);
1009  rDiagGen.SetTransition(currDState,it->first,nextDState);
1010  }
1011  rDiagGen.StateAttribute(nextDState, newAttr);
1012  }
1013  }
1014  // delete current diagnoser state from new states
1015  newDiagStates.Erase(currDState);
1016  }
1017 }
1018 
1019 // LabelPropagation()
1020 void LabelPropagation(const DiagLabelSet& lastLabel, const DiagLabelSet& failureTypes, DiagLabelSet& newLabel) {
1021  FD_DD("LabelPropagation()");
1022  newLabel.Clear();
1023 
1024  // if no failure occurred
1025  if (failureTypes.Size() == 1 && failureTypes.Exists(DiagLabelSet::IndexOfLabelRelN())) {
1026  // if label = {"N"}
1027  if (lastLabel.Size() == 1 && lastLabel.Exists(DiagLabelSet::IndexOfLabelN())) {
1028  newLabel.Insert(DiagLabelSet::IndexOfLabelN());
1029  return;
1030  }
1031  // if label = {"A"}
1032  if (lastLabel.Size() == 1 && lastLabel.Exists(DiagLabelSet::IndexOfLabelA())) {
1033  newLabel.Insert(DiagLabelSet::IndexOfLabelA());
1034  return;
1035  }
1036  }
1037  // otherwise:
1038  newLabel.InsertSet(lastLabel);
1039  newLabel.InsertSet(failureTypes);
1040  newLabel.Erase(DiagLabelSet::IndexOfLabelN());
1041  newLabel.Erase(DiagLabelSet::IndexOfLabelA());
1042  newLabel.Erase(DiagLabelSet::IndexOfLabelRelN());
1043  return;
1044 }
1045 
1046 // LabelCorrection()
1047 void LabelCorrection(const multimap<Idx,DiagLabelSet>& mm, AttributeDiagnoserState& attr) {
1048  multimap<Idx,DiagLabelSet>::const_iterator mmit;
1049  multimap<Idx,DiagLabelSet>::const_iterator mmit_ub;
1050  DiagLabelSet label;
1051  Idx state;
1052 
1053  FD_DD("LabelCorrection()");
1054  attr.Clear();
1055  mmit = mm.begin();
1056  // parse through propagated labels
1057  while (mmit != mm.end()) {
1058  // if there is only one label for a particular state: no correction is needed and the label is copied to diagnoser state attribute
1059  if (mm.count(mmit->first) == 1) {
1060  attr.AddStateLabelMap(mmit->first,mmit->second);
1061  mmit++;
1062  }
1063  // if there are several labels: correct label before adding it to the diagnoser state attribute
1064  else {
1065  mmit_ub = mm.upper_bound(mmit->first);
1066  state = mmit->first;
1067 
1068  label = mmit->second;
1069  mmit++;
1070  for ( ; mmit != mmit_ub; mmit++) {
1071  label = label * mmit->second;
1072  }
1073  label.Insert(DiagLabelSet::IndexOfLabelA());
1074  attr.AddStateLabelMap(state,label);
1075  }
1076  }
1077 }
1078 
1079 
1080 } // namespace faudes
Implements state estimates for the current status of the generator.
virtual void Clear(void)
Delete the mDiagnoserStateMap.
const TaIndexSet< DiagLabelSet > & DiagnoserStateMap(void) const
Get mDiagnoserStateMap.
void AddStateLabelMap(Idx gstate, const DiagLabelSet &labels)
Add state estimates to mDiagnoserStateMap.
Partitions the failure and indicator events.
EventSet AllFailureEvents(void) const
Obtain all failure events in mFailureTypeMap.
TaNameSet< AttributeFailureEvents > mFailureTypeMap
Failure and indicator event partition.
void AddFailureTypeMap(const std::map< std::string, EventSet > &rFailureMap)
Inserts entire failure type map to mFailureTypeMap.
Idx AddFailureTypeMapping(const std::string &failureType, const EventSet &rfailureEvents)
Add a set of failure events to failure type map.
bool Empty(void) const
Test if mFailureTypeMap is empty.
void Clear(void)
Clears mFailureTypeMap.
Idx FailureType(Idx failureEvent) const
Returns failure type of failure event.
Implements the label representation for state estimates.
NameSet::Iterator Iterator
Convenience definition of NameSet::Iterator.
void Clear(void)
Clear mDiagLabels.
bool Insert(Idx index)
Add an element by index.
void InsertSet(const DiagLabelSet &rSet)
Insert elements of rSet.
bool Erase(Idx index)
Delete element by index.
bool Exists(Idx index) const
Test existence of index.
bool Empty(void) const
Check if mDiagLabels is empty.
Idx Size(void) const
Get size of mDiagLabels.
Faudes exception class.
Set of indices.
Definition: cfl_indexset.h:78
Idx Insert(void)
Insert new index to set.
Set of indices with symbolic names.
Definition: cfl_nameset.h:69
bool Exists(const Idx &rIndex) const
Test existence of index.
void SymbolicName(Idx index, const std::string &rName)
Set new name for existing index.
Iterator class for high-level api to TBaseSet.
Definition: cfl_baseset.h:387
Iterator Begin(void) const
Iterator to begin of set.
Iterator End(void) const
Iterator to end of set.
Iterator BeginByX2(Idx x2) const
Iterator to first Transition specified by successor state x2.
bool Insert(const Transition &rTransition)
Add a Transition.
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
Idx InsState(void)
Add new anonymous state to generator.
virtual void Clear(void)
Clear generator data.
bool InsEvent(Idx index)
Add an existing event to alphabet by index.
const TaStateSet< StateAttr > & States(void) const
Return reference to state set.
const TaEventSet< EventAttr > & Alphabet(void) const
Return const reference to alphabet.
bool SetTransition(Idx x1, Idx ev, Idx x2)
Add a transition to generator by indices.
const ATransSet & TransRel(void) const
Return reference to transition relation.
void GlobalAttribute(const GlobalAttr &rAttr)
Set global attribute.
void StateAttribute(Idx index, const StateAttr &rAttr)
Set attribute for existing state.
StateAttr * StateAttributep(Idx index)
State attribute pointer (to access Attribute methods) note: may insert explicit default attribute.
Set of indices with attributes.
Definition: cfl_indexset.h:316
const Attr & Attribute(const Idx &rElem) const
Definition: cfl_indexset.h:528
Set of indices with symbolic names and attributes.
Definition: cfl_nameset.h:564
Generator with controllability attributes.
EventSet UnobservableEvents(void) const
Get EventSet with unobservable events.
bool Observable(Idx index) const
Is event observable (by index)
EventSet ObservableEvents(void) const
Get EventSet with observable events.
Provides the structure and methods to build and handle diagnosers.
EventSet GetAllFailureEvents(void) const
Returns the all failure events of the failure partition.
void InsStateLabelMapping(Idx dStateIndex, Idx gStateIndex, Idx labelIndex)
Inserts a generator state estimate to a diagnoser state.
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
Write configuration data to a string.
Definition: cfl_types.cpp:169
StateSet::Iterator InitStatesBegin(void) const
Iterator to Begin() of mInitStates.
bool InitStatesEmpty(void) const
Check if set of initial states are empty.
EventSet ActiveEventSet(Idx x1) const
Return active event set at state x1.
TransSet::Iterator TransRelBegin(void) const
Iterator to Begin() of transition relation.
void ClrTransition(Idx x1, Idx ev, Idx x2)
Remove a transition by indices.
Idx InitStatesSize(void) const
Get number of initial states.
TransSet ActiveTransSet(Idx x1) const
Return active transition set at state x1.
std::string StateName(Idx index) const
State name lookup.
bool DelState(Idx index)
Delete a state from generator by index.
TransSet::Iterator TransRelEnd(void) const
Iterator to End() of transition relation.
Idx InitState(void) const
Return initial state.
Idx InsInitState(void)
Create new anonymous state and set as initial state.
StateSet::Iterator InitStatesEnd(void) const
Iterator to End() of mInitStates.
std::string EventName(Idx index) const
Event name lookup.
virtual void ClearAttributes(void)
Clear Attributes.
StateSet SuccessorStates(Idx x1) const
Return the successor states of state x1.
#define FD_DD(message)
Definition: diag_debug.h:13
Functions to check a system's diagnosability with respect to failure events (diagnosability and I-dia...
bool Empty(void) const
Test whether if the TBaseSet is Empty.
Definition: cfl_baseset.h:1824
bool Exists(const T &rElem) const
Test existence of element.
Definition: cfl_baseset.h:2115
virtual void Clear(void)
Clear all set.
Definition: cfl_baseset.h:1902
Iterator End(void) const
Iterator to the end of set.
Definition: cfl_baseset.h:1896
virtual void InsertSet(const TBaseSet &rOtherSet)
Insert elements given by rOtherSet.
Definition: cfl_baseset.h:1987
Iterator Begin(void) const
Iterator to the begin of set.
Definition: cfl_baseset.h:1891
virtual bool Erase(const T &rElem)
Erase element by reference.
Definition: cfl_baseset.h:2019
Idx Size(void) const
Get Size of TBaseSet.
Definition: cfl_baseset.h:1819
void EventDiagnoser(const System &rOrigGen, const AttributeFailureTypeMap &rAttrFTMap, Diagnoser &rDiagGen)
Compute a standard diagnoser from an input generator and a failure partition.
void Parallel(const Generator &rGen1, const Generator &rGen2, Generator &rResGen)
Parallel composition.
libFAUDES resides within the namespace faudes.
uint32_t Idx
Type definition for index type (allways 32bit)
void ConvertParallelCompositionMap(const map< pair< Idx, Idx >, Idx > &rReverseCompositionMap, map< Idx, pair< Idx, Idx > > &rCompositionMap)
bool ExistsViolatingCyclesInGd(System &rGd, const Diagnoser &rGobs, map< pair< Idx, Idx >, Idx > &rReverseCompositionMap, const string &rFailureType, string &rReportString)
bool FailuresUnobservable(const System &rGen, const AttributeFailureTypeMap &rFailureTypeMap, string &rReport)
void ComputeGd(const Diagnoser &rGobs, map< pair< Idx, Idx >, Idx > &rReverseCompositionMap, System &rGd)
bool IsEventDiagnosable(const System &rGen, const AttributeFailureTypeMap &rFailureTypeMap)
Function definition for run-time interface.
void ComputeGobs(const System &rOrigGen, const AttributeFailureTypeMap &rAttrFTMap, Diagnoser &rGobs)
Compute G_o for a given generator with a given failure partition (according to Jiang).
TransSet ActiveBackwardTransSet(const System &rGen, Idx state)
Obtain all transitions from other states into a given state of a generator.
bool ExistsCycleSearch(const System &rGen, StateSet &rTodo, Idx currState, StateSet statesOnPath, string &rReport)
bool IsIndicatorEventDiagnosable(const System &rGen, const AttributeFailureTypeMap &rFailureTypeMap)
Function definition for run-time interface.
bool ExistsCycle(const System &rGen, string &rReport)
void CycleStartStatesSearch(const System &rGen, StateSet &rTodo, Idx currState, StateSet statesOnPath, StateSet &rCycleOriginStates)
Auxiliary function for CycleStartStates().
void CycleStartStates(const System &rGen, StateSet &rCycleOrigins)
Find all start/end states of cycles of unobservable events in a generator.
void TrimNonIndicatorTracesOfGd(System &rGd, const Diagnoser &rGobs, const Idx rFailureType, const EventSet &rIndicatorEvents, const map< pair< Idx, Idx >, Idx > &rReverseCompositionMap)
bool IsLive(const System &rGen, string &rReport)
void ComputeReachability(const System &rGen, const EventSet &rUnobsEvents, const EventSet &rFailures, Idx State, const AttributeFailureTypeMap &rAttrFTMap, map< Idx, multimap< Idx, DiagLabelSet > > &rReachabilityMap)
std::string ToStringInteger(Int number)
integer to string
Definition: cfl_helper.cpp:43
void LabelPropagation(const DiagLabelSet &lastLabel, const DiagLabelSet &failureTypes, DiagLabelSet &newLabel)
Generate a new label.
void ComputeReachabilityRecursive(const System &rGen, const EventSet &rUnobsEvents, const EventSet &rFailures, Idx State, const AttributeFailureTypeMap &rAttrFTMap, map< Idx, multimap< Idx, DiagLabelSet > > &rReachabilityMap, const DiagLabelSet FToccurred)
bool CycleOfUnobsEvents(const System &rGen, string &rReport)
bool MeetsDiagnosabilityAssumptions(const System &rGen, const AttributeFailureTypeMap &rFailureTypeMap, string &rReportString)
void TrimNonIndicatorTracesOfGdRecursive(System &rGd, const Diagnoser &rGobs, const Idx rFailureType, const EventSet &rIndicatorEvents, map< Idx, pair< Idx, Idx > > &rCompositionMap, Idx state, StateSet &rStatesDone)
void LabelCorrection(const multimap< Idx, DiagLabelSet > &mm, AttributeDiagnoserState &attr)

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