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
const TaIndexSet< DiagLabelSet > & DiagnoserStateMap(void) const
void AddStateLabelMap(Idx gstate, const DiagLabelSet &labels)
TaNameSet< AttributeFailureEvents > mFailureTypeMap
void AddFailureTypeMap(const std::map< std::string, EventSet > &rFailureMap)
Idx AddFailureTypeMapping(const std::string &failureType, const EventSet &rfailureEvents)
Idx FailureType(Idx failureEvent) const
NameSet::Iterator Iterator
void InsertSet(const DiagLabelSet &rSet)
bool Exists(Idx index) const
bool Empty(void) const
bool Exists(const Idx &rIndex) const
void SymbolicName(Idx index, const std::string &rName)
Iterator Begin(void) const
Iterator End(void) const
Iterator BeginByX2(Idx x2) const
bool Insert(const Transition &rTransition)
Iterator EndByX2(Idx x2) const
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
Definition: cfl_transset.h:273
virtual void Clear(void)
bool InsEvent(Idx index)
const TaStateSet< StateAttr > & States(void) const
const TaEventSet< EventAttr > & Alphabet(void) const
bool SetTransition(Idx x1, Idx ev, Idx x2)
const ATransSet & TransRel(void) const
void GlobalAttribute(const GlobalAttr &rAttr)
void StateAttribute(Idx index, const StateAttr &rAttr)
StateAttr * StateAttributep(Idx index)
const Attr & Attribute(const Idx &rElem) const
Definition: cfl_indexset.h:535
EventSet UnobservableEvents(void) const
bool Observable(Idx index) const
EventSet ObservableEvents(void) const
EventSet GetAllFailureEvents(void) const
void InsStateLabelMapping(Idx dStateIndex, Idx gStateIndex, Idx labelIndex)
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
Definition: cfl_types.cpp:170
StateSet::Iterator InitStatesBegin(void) const
bool InitStatesEmpty(void) const
EventSet ActiveEventSet(Idx x1) const
TransSet::Iterator TransRelBegin(void) const
void ClrTransition(Idx x1, Idx ev, Idx x2)
Idx InitStatesSize(void) const
TransSet ActiveTransSet(Idx x1) const
std::string StateName(Idx index) const
bool DelState(Idx index)
TransSet::Iterator TransRelEnd(void) const
Idx InitState(void) const
StateSet::Iterator InitStatesEnd(void) const
std::string EventName(Idx index) const
virtual void ClearAttributes(void)
StateSet SuccessorStates(Idx x1) const
#define FD_DD(message)
Definition: diag_debug.h:13
bool Empty(void) const
Definition: cfl_baseset.h:1841
bool Exists(const T &rElem) const
Definition: cfl_baseset.h:2132
virtual void Clear(void)
Definition: cfl_baseset.h:1919
Iterator End(void) const
Definition: cfl_baseset.h:1913
virtual void InsertSet(const TBaseSet &rOtherSet)
Definition: cfl_baseset.h:2004
Iterator Begin(void) const
Definition: cfl_baseset.h:1908
virtual bool Erase(const T &rElem)
Definition: cfl_baseset.h:2036
Idx Size(void) const
Definition: cfl_baseset.h:1836
void EventDiagnoser(const System &rOrigGen, const AttributeFailureTypeMap &rAttrFTMap, Diagnoser &rDiagGen)
void Parallel(const Generator &rGen1, const Generator &rGen2, Generator &rResGen)
uint32_t Idx
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)
void ComputeGobs(const System &rOrigGen, const AttributeFailureTypeMap &rAttrFTMap, Diagnoser &rGobs)
TransSet ActiveBackwardTransSet(const System &rGen, Idx state)
bool ExistsCycleSearch(const System &rGen, StateSet &rTodo, Idx currState, StateSet statesOnPath, string &rReport)
bool IsIndicatorEventDiagnosable(const System &rGen, const AttributeFailureTypeMap &rFailureTypeMap)
bool ExistsCycle(const System &rGen, string &rReport)
void CycleStartStatesSearch(const System &rGen, StateSet &rTodo, Idx currState, StateSet statesOnPath, StateSet &rCycleOriginStates)
void CycleStartStates(const System &rGen, StateSet &rCycleOrigins)
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)
Definition: cfl_utils.cpp:43
void LabelPropagation(const DiagLabelSet &lastLabel, const DiagLabelSet &failureTypes, DiagLabelSet &newLabel)
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.33c --- 2025.05.15 --- c++ api documentaion by doxygen