| |
libFAUDES
Sections
Index
|
diag_eventdiagnosis.cppGo to the documentation of this file.00001 /** @file diag_eventdiagnosis.cpp 00002 Functions to check a system's event-diagnosability and computation of an event-diagnoser. Covers diagnosability with respect to failure events (diagnosability, I-diagnosability). 00003 */ 00004 00005 #include "diag_eventdiagnosis.h" 00006 00007 using namespace std; 00008 00009 namespace faudes { 00010 00011 00012 // IsEventDiagnosable() 00013 bool IsEventDiagnosable(const cGenerator& rGen, const AttributeFailureTypeMap& rFailureTypeMap, string& rReportString) { 00014 diagGenerator genGobs; 00015 cGenerator genGd; 00016 map<pair<Idx,Idx>,Idx> reverseCompositionMap; 00017 map<pair<Idx,Idx>,Idx>::iterator rcmIt; 00018 StateSet::Iterator stateIt; 00019 TaNameSet<AttributeFailureEvents>::Iterator ftIt; 00020 EventSet::Iterator evIt; 00021 00022 // reset report 00023 rReportString.clear(); 00024 00025 FD_DD("IsEventDiagnosable()"); 00026 // TODO: throw exception, dont report 00027 // check for indicator events (which should not exist) 00028 for (ftIt = rFailureTypeMap.mFailureTypeMap.Begin(); ftIt != rFailureTypeMap.mFailureTypeMap.End(); ftIt++) { 00029 if (!rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mIndicatorEvents.Empty()) { 00030 FD_DD("IsEventDiagnosable(): Warning: Existing indicator events are ignored! If you want to check for I-diagnosability use IsIdiagnosable() instead."); 00031 rReportString.append("IsEventDiagnosable(): Warning: Existing indicator events are ignored! If you want to check for I-diagnosability use IsIdiagnosable() instead.\n"); 00032 break; 00033 } 00034 } 00035 00036 // check if assumptions are met 00037 // TODO: convention: "Check" rather than "Meet" 00038 if (!MeetsDiagnosabilityAssumptions(rGen, rFailureTypeMap, rReportString)) { 00039 return false; 00040 } 00041 00042 // Implementation of Remark 2: Applying Algorithm 1 for each failure type on its own 00043 for (ftIt = rFailureTypeMap.mFailureTypeMap.Begin(); ftIt != rFailureTypeMap.mFailureTypeMap.End(); ftIt++) { 00044 FD_DD("Testing for failure type " + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) \ 00045 + " with failures " + rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mFailureEvents.ToString()); 00046 00047 // 3 Steps of Algorithm 1 00048 // Step 1: Generate G_o 00049 FD_DD("__Step 1__"); 00050 ComputeGobs(rGen, rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt), rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mFailureEvents, genGobs); 00051 //genGobs.Write("tmp_Gobs_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".gen"); 00052 //genGobs.GraphWrite("tmp_Gobs_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".png"); 00053 00054 // Step 2: Generate G_d = G_o || G_o 00055 // State names/attributes are not copied to new generator G_d 00056 // but can be obtained via reverse composition map and the corresponding elements of G_o 00057 FD_DD("__Step 2__"); 00058 ComputeGd(genGobs, reverseCompositionMap, genGd); 00059 //genGd.Write("tmp_Gd_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".gen"); 00060 //genGd.GraphWrite("tmp_Gd_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".png"); 00061 00062 // Step 3: Check for cycles in G_d which contain states with different failure labels 00063 FD_DD("__Step 3__"); 00064 if(ExistsViolatingCyclesInGd(genGd, genGobs, reverseCompositionMap, rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt), rReportString)) { 00065 //genGd.Write("tmp_Gd_pruned_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".gen"); 00066 //genGd.GraphWrite("tmp_Gd_pruned_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".png"); 00067 return false; 00068 } else { 00069 //genGd.Write("tmp_Gd_pruned_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".gen"); 00070 //genGd.GraphWrite("tmp_Gd_pruned_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".png"); 00071 } 00072 00073 } 00074 return true; 00075 } 00076 00077 // rti function interface 00078 void IsEventDiagnosable(const cGenerator& rGen, const AttributeFailureTypeMap& rFailureTypeMap, bool& rRes, std::string& rReportString) { 00079 rRes=IsEventDiagnosable(rGen,rFailureTypeMap,rReportString); 00080 } 00081 00082 // rti function interface 00083 void IsEventDiagnosable(const cGenerator& rGen, const AttributeFailureTypeMap& rFailureTypeMap, bool& rRes) { 00084 std::string ignore; 00085 rRes=IsEventDiagnosable(rGen,rFailureTypeMap,ignore); 00086 } 00087 00088 00089 // IsIdiagnosable() 00090 bool IsIndicatorEventDiagnosable(const cGenerator& rGen, const AttributeFailureTypeMap& rFailureTypeMap, string& rReportString) { 00091 diagGenerator genGobs; 00092 cGenerator genGd; 00093 map<pair<Idx,Idx>,Idx> reverseCompositionMap; 00094 map<pair<Idx,Idx>,Idx>::iterator rcmIt; 00095 StateSet::Iterator stateIt; 00096 TaNameSet<AttributeFailureEvents>::Iterator ftIt; 00097 EventSet::Iterator evIt; 00098 rReportString.clear(); 00099 00100 FD_DD("IsIndicatorEventDiagnosable()"); 00101 // check for indicator events (which should exist) 00102 for (ftIt = rFailureTypeMap.mFailureTypeMap.Begin(); ftIt != rFailureTypeMap.mFailureTypeMap.End(); ftIt++) { 00103 if (rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mIndicatorEvents.Empty()) { 00104 FD_DD("IsIndicatorEventDiagnosable(): Warning: There are no indicator events for failure type " << rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) << "!"); 00105 rReportString.append("IsIndicatorEventDiagnosable(): Warning: There are no indicator events for failure type " + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + "!\n"); 00106 } 00107 } 00108 00109 // check if assumptions are met 00110 if (!MeetsDiagnosabilityAssumptions(rGen, rFailureTypeMap, rReportString)) { 00111 return false; 00112 } 00113 00114 // Implementation of Remark 2: Applying Algorithm 1 for each failure type on its own 00115 for (ftIt = rFailureTypeMap.mFailureTypeMap.Begin(); ftIt != rFailureTypeMap.mFailureTypeMap.End(); ftIt++) { 00116 FD_DD("Testing for failure type " + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) \ 00117 + " with failures/indicators " + rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).ToString()); 00118 00119 // 3 Steps of Algorithm 1 00120 // Step 1: Generate G_o 00121 FD_DD("__Step 1__"); 00122 ComputeGobs(rGen, rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt), rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mFailureEvents, genGobs); 00123 //genGobs.Write("tmp_I_Gobs_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".gen"); 00124 //genGobs.GraphWrite("tmp_I_Gobs_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".png"); 00125 00126 // Step 2: Generate G_d = G_o || G_o 00127 // State names/attributes are not copied to new generator G_d 00128 // but can be obtained via reverse composition map and the corresponding elements of G_o 00129 FD_DD("__Step 2__"); 00130 ComputeGd(genGobs, reverseCompositionMap, genGd); 00131 //genGd.Write("tmp_I_Gd_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".gen"); 00132 //genGd.GraphWrite("tmp_I_Gd_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".png"); 00133 00134 // Additionally for I-diagnosability: Remove all traces which do not contain a failure event followed by an indicator event 00135 FD_DD("Removing all traces not containing an indicator event " + rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mIndicatorEvents.ToString()); 00136 TrimNonIndicatorTracesOfGd(genGd, genGobs, *ftIt, rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mIndicatorEvents, reverseCompositionMap); 00137 //genGd.Write("tmp_I_Gd_iTraces_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".gen"); 00138 //genGd.GraphWrite("tmp_I_Gd_iTraces_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".png"); 00139 00140 // Step 3: Check for cycles in G_d which contain states with different failure labels 00141 FD_DD("__Step 3__"); 00142 if(ExistsViolatingCyclesInGd(genGd, genGobs, reverseCompositionMap, rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt), rReportString)) { 00143 //genGd.Write("tmp_I_Gd_pruned_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".gen"); 00144 //genGd.GraphWrite("tmp_I_Gd_pruned_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".png"); 00145 return false; 00146 } else { 00147 //genGd.Write("tmp_I_Gd_pruned_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".gen"); 00148 //genGd.GraphWrite("tmp_I_Gd_pruned_" + rFailureTypeMap.mFailureTypeMap.SymbolicName(*ftIt) + ".png"); 00149 } 00150 00151 } 00152 return true; 00153 } 00154 00155 00156 // rti function interface 00157 void IsIndicatorEventDiagnosable(const cGenerator& rGen, const AttributeFailureTypeMap& rFailureTypeMap, bool& rRes, std::string& rReportString) { 00158 rRes=IsEventDiagnosable(rGen,rFailureTypeMap,rReportString); 00159 } 00160 00161 // rti function interface 00162 void IsIndicatorEventDiagnosable(const cGenerator& rGen, const AttributeFailureTypeMap& rFailureTypeMap, bool& rRes) { 00163 std::string ignore; 00164 rRes=IsEventDiagnosable(rGen,rFailureTypeMap,ignore); 00165 } 00166 00167 00168 // MeetsDiagnosabilityAssumptions() 00169 bool MeetsDiagnosabilityAssumptions(const cGenerator& rGen, const AttributeFailureTypeMap& rFailureTypeMap, string& rReportString) { 00170 TaNameSet<AttributeFailureEvents>::Iterator ftIt; 00171 EventSet::Iterator evIt; 00172 00173 // check if failure and indicator events are part of the generators alphabet 00174 for (ftIt = rFailureTypeMap.mFailureTypeMap.Begin(); ftIt != rFailureTypeMap.mFailureTypeMap.End(); ftIt++) { 00175 // check if all failures are valid events of generator 00176 for (evIt = rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mFailureEvents.Begin(); evIt != rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mFailureEvents.End(); evIt++) { 00177 if (!rGen.Alphabet().Exists(*evIt)) { 00178 stringstream errstr; 00179 errstr << "Failure " << rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mFailureEvents.SymbolicName(*evIt) << " is not in alphabet of generator!" << endl; 00180 throw Exception("MeetsDiagnosabilityAssumptions()", errstr.str(), 302); 00181 } 00182 } 00183 // check if all indicator events are valid events of generator 00184 for (evIt = rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mIndicatorEvents.Begin(); evIt != rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mIndicatorEvents.End(); evIt++) { 00185 if (!rGen.Alphabet().Exists(*evIt)) { 00186 stringstream errstr; 00187 errstr << "Indicator " << rFailureTypeMap.mFailureTypeMap.Attribute(*ftIt).mIndicatorEvents.SymbolicName(*evIt) << " is not in alphabet of generator!" << endl; 00188 throw Exception("MeetsDiagnosabilityAssumptions()", errstr.str(), 303); 00189 } 00190 } 00191 } 00192 00193 // Assumption A1: Liveness 00194 if (!IsLive(rGen, rReportString)) { 00195 FD_DD("MeetsDiagnosabilityAssumptions(): Generator is not live!"); 00196 rReportString.append("Generator is not live!\n"); 00197 return false; 00198 } 00199 00200 // Assumption A3: All failure events are unobservable 00201 if (!FailuresUnobservable(rGen, rFailureTypeMap, rReportString)) { 00202 FD_DD("MeetsDiagnosabilityAssumptions(): Not all failure events are unobservable!"); 00203 rReportString.append("Not all failure events are unobservable!\n"); 00204 return false; 00205 } 00206 00207 // Assumption A2: No cycles of unobservable events 00208 if (CycleOfUnobsEvents(rGen, rReportString)) { 00209 FD_DD("MeetsDiagnosabilityAssumptions(): Generator contains cycle of unobservable events!"); 00210 rReportString.append("Generator contains cycle of unobservable events!\n"); 00211 return false; 00212 } 00213 00214 // otherwise 00215 return true; 00216 } 00217 00218 // ConvertParallelCompositionMap() 00219 void ConvertParallelCompositionMap( const map<pair<Idx,Idx>,Idx>& rReverseCompositionMap, 00220 map<Idx,pair<Idx,Idx> >& rCompositionMap) { 00221 // invert rReverseCompositionMap (possible, as map is expected to be from parallel composition 00222 // and thus must be bijective) 00223 map<pair<Idx,Idx>,Idx>::const_iterator iter; 00224 00225 FD_DD("ConvertParallelCompositionMap()"); 00226 rCompositionMap.clear(); 00227 for(iter = rReverseCompositionMap.begin(); iter != rReverseCompositionMap.end(); iter++) { 00228 rCompositionMap.insert(make_pair(iter->second,iter->first)); 00229 } 00230 } 00231 00232 // IsLive() 00233 // TODO: inefficient set of active vents; have method in vGenerator 00234 bool IsLive(const cGenerator& rGen, string& rReport) { 00235 StateSet states; 00236 StateSet::Iterator it; 00237 FD_DD("IsLive()"); 00238 states = rGen.States(); 00239 for (it = states.Begin(); it != states.End(); it++) { 00240 if (rGen.ActiveEventSet(*it).Empty()) { 00241 rReport.append("Missing transition at state " + ToStringInteger(*it) + " --> "); 00242 return false; 00243 } 00244 } 00245 return true; 00246 } 00247 00248 // CycleOfUnobsEvents() 00249 // TODO: inefficient copy; have method in vGenerator 00250 bool CycleOfUnobsEvents(const cGenerator& rGen, string& rReport) { 00251 TransSet transitionsToDelete; 00252 TransSet::Iterator it; 00253 cGenerator genCopy; 00254 00255 FD_DD("CycleOfUnobsEvents()"); 00256 transitionsToDelete.Clear(); 00257 // make a copy of generator 00258 genCopy = rGen; 00259 // parse through all its transitions and delete the observable ones 00260 for (it = genCopy.TransRelBegin(); it != genCopy.TransRelEnd(); it++) { 00261 if (genCopy.Observable(it->Ev)) { 00262 transitionsToDelete.Insert(*it); 00263 } 00264 } 00265 for (it = transitionsToDelete.Begin(); it != transitionsToDelete.End(); it++) { 00266 FD_DD("delete " << it->X1 << " --" << genCopy.EventName(it->Ev) << "--> " << it->X2); 00267 genCopy.ClrTransition(*it); 00268 } 00269 // check for cycles within the remaining unobservable events 00270 return ExistsCycle(genCopy, rReport); 00271 } 00272 00273 // FailuresUnobservable() 00274 bool FailuresUnobservable(const cGenerator& rGen, const AttributeFailureTypeMap& rFailureTypeMap, string& rReport) { 00275 EventSet failures, unobsEvents; 00276 EventSet::Iterator evIt; 00277 00278 FD_DD("FailuresUnobservable()"); 00279 failures = rFailureTypeMap.AllFailureEvents(); 00280 unobsEvents = rGen.UnobservableEvents(); 00281 for (evIt = failures.Begin(); evIt != failures.End(); evIt++) { 00282 if (!unobsEvents.Exists(*evIt)) { 00283 FD_DD("FailuresUnobservable(): Failure event \"" << failures.SymbolicName(*evIt) << "\" is not unobservable in generator!"); 00284 rReport.append("Failure event \"" + failures.SymbolicName(*evIt) + "\" is observable in generator --> "); 00285 return false; 00286 } 00287 } 00288 return true; 00289 } 00290 00291 // ExistsCycle() 00292 bool ExistsCycle(const cGenerator& rGen, string& rReport) { 00293 StateSet todo, path; 00294 StateSet::Iterator stateIt; 00295 00296 FD_DD("ExistsCycle()"); 00297 todo = rGen.States(); 00298 path.Clear(); 00299 for (stateIt = rGen.InitStatesBegin(); stateIt != rGen.InitStatesEnd(); ++stateIt) { 00300 FD_DD("Start cycle search at initial state"); 00301 if (ExistsCycleSearch(rGen, todo, *stateIt, path, rReport)) { 00302 return true; 00303 } 00304 } 00305 while (!todo.Empty()) { 00306 FD_DD("Start cycle search at some state.."); 00307 if (ExistsCycleSearch(rGen, todo, *todo.Begin(), path, rReport)) { 00308 return true; 00309 } 00310 } 00311 return false; 00312 } 00313 00314 // ExistsCycleSearch() 00315 bool ExistsCycleSearch(const cGenerator& rGen, StateSet& rTodo, Idx currState, StateSet statesOnPath, string& rReport) { 00316 StateSet successors, newStatesOnPath; 00317 StateSet::Iterator stateIt; 00318 00319 FD_DD("ExistsCycleSearch() for State " << currState); 00320 rTodo.Erase(currState); 00321 statesOnPath.Insert(currState); 00322 00323 successors = rGen.TransRelStateSpace(currState); 00324 // parse through active state set of currState 00325 for (stateIt = successors.Begin(); stateIt != successors.End(); stateIt++) { 00326 if (statesOnPath.Exists(*stateIt)) { 00327 FD_DD("Cycle found at state " << *stateIt); 00328 rReport.append("Cycle found at state " + ToStringInteger(*stateIt) + " --> "); 00329 return true; 00330 } 00331 // call ExistsCycleSearch() for next successor state and with updated state set newStatesOnPath 00332 newStatesOnPath.Clear(); 00333 newStatesOnPath.InsertSet(statesOnPath); 00334 newStatesOnPath.Insert(*stateIt); 00335 if (ExistsCycleSearch(rGen, rTodo, *stateIt, newStatesOnPath, rReport)) { 00336 return true; 00337 } 00338 } 00339 return false; 00340 } 00341 00342 // CycleStartStates() 00343 void CycleStartStates(const cGenerator& rGen, StateSet& rCycleOrigins) { 00344 StateSet todo, path; 00345 00346 FD_DD("ExistsCycle()"); 00347 rCycleOrigins.Clear(); 00348 todo = rGen.States(); 00349 if (!rGen.InitStatesEmpty()) { 00350 FD_DD("Start cycle search at initial state"); 00351 path.Clear(); 00352 CycleStartStatesSearch(rGen, todo, rGen.InitState(), path, rCycleOrigins); 00353 } 00354 while (!todo.Empty()) { 00355 FD_DD("Start cycle search at some state.."); 00356 path.Clear(); 00357 CycleStartStatesSearch(rGen, todo, *todo.Begin(), path, rCycleOrigins); 00358 } 00359 return; 00360 } 00361 00362 // CycleStartStatesSearch() 00363 void CycleStartStatesSearch(const cGenerator& rGen, StateSet& rTodo, Idx currState, StateSet statesOnPath, StateSet& rCycleOriginStates) { 00364 StateSet successors, newStatesOnPath; 00365 StateSet::Iterator stateIt; 00366 00367 FD_DD("CycleStartStatesSearch() for State " << currState); 00368 rTodo.Erase(currState); 00369 statesOnPath.Insert(currState); 00370 00371 successors = rGen.TransRelStateSpace(currState); 00372 // parse through active state set of currState 00373 for (stateIt = successors.Begin(); stateIt != successors.End(); stateIt++) { 00374 if (statesOnPath.Exists(*stateIt)) { 00375 FD_DD("Cycle found at state " << *stateIt); 00376 rCycleOriginStates.Insert(*stateIt); 00377 return; 00378 } 00379 // call ExistsCycleSearch() for next successor state and with updated state set newStatesOnPath 00380 newStatesOnPath.Clear(); 00381 newStatesOnPath.InsertSet(statesOnPath); 00382 newStatesOnPath.Insert(*stateIt); 00383 CycleStartStatesSearch(rGen, rTodo, *stateIt, newStatesOnPath, rCycleOriginStates); 00384 } 00385 return; 00386 } 00387 00388 // ExistsViolatingCyclesInGd() 00389 bool ExistsViolatingCyclesInGd(cGenerator& rGd, const diagGenerator& rGobs, map<pair<Idx,Idx>,Idx>& rReverseCompositionMap, const string& rFailureType, string& rReportString) { 00390 map<pair<Idx,Idx>,Idx>::iterator rcmIt; 00391 const TaIndexSet<DiagLabelSet>* fLabel1; 00392 const TaIndexSet<DiagLabelSet>* fLabel2; 00393 TaIndexSet<DiagLabelSet>::Iterator fL1Begin; 00394 TaIndexSet<DiagLabelSet>::Iterator fL2Begin; 00395 00396 FD_DD("ExistsViolatingCyclesInGd()"); 00397 // Therefore parse through reverse composition map 00398 for (rcmIt = rReverseCompositionMap.begin(); rcmIt != rReverseCompositionMap.end();) { 00399 FD_DD("state " << rcmIt->second << " (" << rcmIt->first.first << "," << rcmIt->first.second << ")"); 00400 // if both states in G_o are equal or just contain the same failure label: delete corresponding state in G_d 00401 if (rcmIt->first.first == rcmIt->first.second) { 00402 FD_DD(" --> delete (same G_o state)"); 00403 rGd.DelState(rcmIt->second); 00404 rReverseCompositionMap.erase(rcmIt++); 00405 } else { 00406 fLabel1 = rGobs.StateAttribute(rcmIt->first.first).DiagnoserStateMapp(); 00407 fLabel2 = rGobs.StateAttribute(rcmIt->first.second).DiagnoserStateMapp(); 00408 fL1Begin = fLabel1->Begin(); 00409 fL2Begin = fLabel2->Begin(); 00410 if (fLabel1->Attribute(*fL1Begin) == fLabel2->Attribute(*fL2Begin)) { 00411 FD_DD(" --> delete (same failure label)"); 00412 rGd.DelState(rcmIt->second); 00413 rReverseCompositionMap.erase(rcmIt++); 00414 } else { 00415 ++rcmIt; 00416 } 00417 } 00418 FD_DD(""); 00419 } 00420 // if there exists a cycle in the remainder graph the system rGen is not diagnosable 00421 if (ExistsCycle(rGd,rReportString)) { 00422 FD_DD("Detected cycle in G_d"); 00423 rReportString.append("While checking diagnosability for failure type " + rFailureType + ": " + \ 00424 "G_d contains a cycle of states with unequal failure labels, i.e. there exists an " + \ 00425 rFailureType + "-indeterminate cycle in the diagnoser.\n"); 00426 return true; 00427 } 00428 return false; 00429 } 00430 00431 // ComputeGobs() 00432 void ComputeGobs(const cGenerator& rOrigGen, const string& rFailureType, const EventSet& rFailureEvents, diagGenerator& rGobs) { 00433 AttributeFailureTypeMap singleFailureTypeMap; 00434 singleFailureTypeMap.Clear(); 00435 singleFailureTypeMap.AddFailureTypeMapping(rFailureType, rFailureEvents); 00436 ComputeGobs(rOrigGen, singleFailureTypeMap, rGobs); 00437 } 00438 00439 // ComputeGobs() 00440 void ComputeGobs(const cGenerator& rOrigGen, const AttributeFailureTypeMap& rAttrFTMap, diagGenerator& rGobs) { 00441 EventSet failureEvents; 00442 EventSet gObservableEvents, gUnobservableEvents; 00443 StateSet newGobsStates; 00444 Idx currDState = 0; 00445 Idx nextDState = 0; 00446 00447 FD_DD("ComputeGobs()"); 00448 // check if FailureTypeMap is empty 00449 if (rAttrFTMap.Empty()) { 00450 FD_DD("WARNING - ComputeGobs(): failure type map is empty!"); 00451 } 00452 00453 // clear Gobs 00454 rGobs.Clear(); 00455 rGobs.ClearAttributes(); 00456 00457 // copy attribute failure type map to Gobs 00458 rGobs.GlobalAttribute(rAttrFTMap); 00459 00460 // get observable events of original generator 00461 gObservableEvents = rOrigGen.ObservableEvents(); 00462 FD_DD("Observable events: " << gObservableEvents.ToString()); 00463 00464 // get unobservable events of original generator 00465 gUnobservableEvents = rOrigGen.UnobservableEvents(); 00466 FD_DD("Unobservable events: " << gUnobservableEvents.ToString()); 00467 00468 // copy all failure events into one single EventSet 00469 failureEvents = rGobs.GetAllFailureEvents(); 00470 FD_DD("Failure events: " << failureEvents.ToString()); 00471 00472 // create initial state of Gobs and its attribute with label "normal" 00473 #ifdef FAUDES_CHECKED 00474 if(rOrigGen.InitStatesSize() != 1) { 00475 std::stringstream errstr; 00476 errstr << "original generator has no unique initial state" << std::endl; 00477 throw Exception("ComputeGobs()", errstr.str(), 301); 00478 } 00479 #endif 00480 Idx gInitState = rOrigGen.InitState(); 00481 currDState = rGobs.InsInitState(); 00482 newGobsStates.Insert(currDState); 00483 rGobs.InsStateLabelMapping(currDState,gInitState,DiagLabelSet::IndexOfLabelN()); 00484 00485 Idx gStateEstimate = 0; 00486 Idx newState = 0; 00487 00488 map<Idx,multimap<Idx,DiagLabelSet> > reachMap; // maps executable events to all reachable states and occuring relative failure types 00489 map<Idx,multimap<Idx,DiagLabelSet> >::iterator it; 00490 00491 multimap<Idx,DiagLabelSet>::iterator mmit, mmit2; 00492 00493 pair<Idx,DiagLabelSet> reachMapPair; 00494 00495 TransSet transitions; 00496 DiagLabelSet oldLabel, newLabel, occFailureTypes; 00497 DiagLabelSet::Iterator labelIt; 00498 StateSet gObsStates; 00499 StateSet::Iterator stateIt; 00500 EventSet activeEvents; 00501 AttributeDiagnoserState newAttr; 00502 AttributeDiagnoserState currDStateAttr; 00503 TaIndexSet<DiagLabelSet> currDStateMap; 00504 TaIndexSet<DiagLabelSet>::Iterator currDStateMapIt; 00505 00506 // parse through new Gobs states 00507 while (!newGobsStates.Empty()) { 00508 // set current Gobs state 00509 currDState = *newGobsStates.Begin(); 00510 00511 currDStateAttr = rGobs.StateAttribute(currDState); 00512 currDStateMap = currDStateAttr.DiagnoserStateMap(); 00513 00514 // parse through state estimates of current Gobs state 00515 for(currDStateMapIt = currDStateMap.Begin(); currDStateMapIt != currDStateMap.End(); ++ currDStateMapIt){ 00516 gStateEstimate = *currDStateMapIt; 00517 00518 // generate reachMap for current state estimate 00519 ComputeReachability(rOrigGen, gUnobservableEvents, failureEvents, gStateEstimate, rAttrFTMap, reachMap); 00520 00521 #ifdef FAUDES_DEBUG_DIAGNOSIS 00522 FD_DD(endl << "reachMap: "); 00523 for (it = reachMap.begin(); it != reachMap.end(); it++) { 00524 //print reachMap for current event 00525 FD_DD("_" << rOrigGen.EventName(it->first) << " ("<< it->second.size() << " state estimates)"); 00526 for (mmit = it->second.begin(); mmit != it->second.end(); mmit++) { 00527 FD_DD(mmit->first << " " << mmit->second.ToString()); 00528 } 00529 } 00530 FD_DD(""); 00531 #endif 00532 00533 // parse through reachMap (eventwise) 00534 for (it = reachMap.begin(); it != reachMap.end(); it++) { 00535 //print reachMap for current event 00536 #ifdef FAUDES_DEBUG_DIAGNOSIS 00537 FD_DD(endl << "_" << rOrigGen.EventName(it->first) << " ("<< it->second.size() << " state estimates)"); 00538 for (mmit = it->second.begin(); mmit != it->second.end(); mmit++) { 00539 FD_DD(mmit->first << " " << mmit->second.ToString()); 00540 } 00541 #endif 00542 00543 // get label set of current state estimate 00544 oldLabel = currDStateMap.Attribute(*currDStateMapIt); 00545 FD_DD("old label: " << oldLabel.ToString()); 00546 00547 newState = 0; 00548 // parse through state failure type map (for current event in reachMap) 00549 for (mmit = it->second.begin(); mmit != it->second.end(); mmit++) { 00550 newState = mmit->first; 00551 FD_DD("new state: " << newState); 00552 occFailureTypes = mmit->second; 00553 FD_DD("failure types occurred: " << occFailureTypes.ToString()); 00554 LabelPropagation(oldLabel, occFailureTypes, newLabel); 00555 FD_DD("new label: " << newLabel.ToString()); 00556 newAttr.Clear(); 00557 newAttr.AddStateLabelMap(newState,newLabel); 00558 00559 // if newAttr equals any existing state attribute than we create a transition to this very state 00560 gObsStates = rGobs.States(); 00561 stateIt = gObsStates.Begin(); 00562 while (stateIt != gObsStates.End()) { 00563 if (newAttr == rGobs.StateAttribute(*stateIt)) { 00564 FD_DD("realising as back- or self-loop to existing state " << *stateIt); 00565 rGobs.InsEvent(it->first); 00566 rGobs.SetTransition(currDState,it->first,*stateIt); 00567 break; 00568 } 00569 stateIt++; 00570 } 00571 // if newAttribute is new to Gobs 00572 if (stateIt == gObsStates.End()) { 00573 // create new Gobs state and add it to new states 00574 nextDState = rGobs.InsState(); 00575 FD_DD("Create new state " << nextDState << " and transition " << currDState << " --" << rOrigGen.EventName(it->first) << "--> " << nextDState); 00576 newGobsStates.Insert(nextDState); 00577 rGobs.InsEvent(it->first); 00578 rGobs.SetTransition(currDState,it->first,nextDState); 00579 rGobs.StateAttribute(nextDState, newAttr); 00580 00581 FD_DD("Print Gobs label of state " << nextDState); 00582 FD_DD(rGobs.StateAttributep(nextDState)->ToString()); 00583 } 00584 } 00585 } 00586 } 00587 00588 activeEvents = rGobs.ActiveEventSet(currDState); 00589 transitions = rGobs.ActiveTransSet(currDState); 00590 00591 // delete current Gobs state from new states 00592 newGobsStates.Erase(currDState); 00593 } 00594 } 00595 00596 // ComputeGd() 00597 void ComputeGd(const diagGenerator& rGobs, map<pair<Idx,Idx>,Idx>& rReverseCompositionMap, cGenerator& rGd) { 00598 string stateName; 00599 map<pair<Idx,Idx>,Idx>::iterator rcmIt; 00600 rReverseCompositionMap.clear(); 00601 00602 FD_DD("ComputeGd()"); 00603 FD_DD("Performing parallel compostion of G_o with itself ..."); 00604 Parallel(rGobs, rGobs, rReverseCompositionMap, rGd); 00605 FD_DD("Writing G_d state names ..."); 00606 for (rcmIt = rReverseCompositionMap.begin(); rcmIt != rReverseCompositionMap.end(); rcmIt++) { 00607 stateName = ToStringInteger(rcmIt->second) + "{" + \ 00608 rGobs.SAStr(rcmIt->first.first) + "'" + \ 00609 rGobs.SAStr(rcmIt->first.second) +"}"; 00610 rGd.StateName(rcmIt->second, stateName); 00611 } 00612 } 00613 00614 // TrimNonIndicatorTracesOfGd() 00615 void TrimNonIndicatorTracesOfGd(cGenerator& rGd, const diagGenerator& rGobs, const Idx rFailureType, 00616 const EventSet& rIndicatorEvents, const map<pair<Idx,Idx>,Idx>& rReverseCompositionMap) { 00617 StateSet statesDone; 00618 map<Idx,pair<Idx,Idx> > CompositionMap; 00619 00620 FD_DD("TrimNonIndicatorTracesOfGd()"); 00621 ConvertParallelCompositionMap(rReverseCompositionMap, CompositionMap); 00622 statesDone.Clear(); 00623 TrimNonIndicatorTracesOfGdRecursive(rGd, rGobs, rFailureType, rIndicatorEvents, CompositionMap, rGd.InitState(), statesDone); 00624 } 00625 00626 // TrimNonIndicatorTracesOfGdRecursive() 00627 void TrimNonIndicatorTracesOfGdRecursive(cGenerator& rGd, const diagGenerator& rGobs, const Idx rFailureType, 00628 const EventSet& rIndicatorEvents, map<Idx,pair<Idx,Idx> >& rCompositionMap, 00629 Idx state, StateSet& rStatesDone) { 00630 TransSet trans, backTrans; 00631 TransSet::Iterator it; 00632 Idx nextState = 0; 00633 const TaIndexSet<DiagLabelSet>* pDiagState1; 00634 const TaIndexSet<DiagLabelSet>* pDiagState2; 00635 map<Idx,pair<Idx,Idx> >::iterator compMapIt; 00636 bool failureHasAlreadyOccurred = false; 00637 00638 FD_DD("TrimNonIndicatorTracesOfGdRecursive() for state " + ToStringInteger(state)); 00639 00640 // return if this state has already been processed 00641 if (rStatesDone.Exists(state)) { 00642 return; 00643 } 00644 rStatesDone.Insert(state); 00645 trans = rGd.ActiveTransSet(state); 00646 00647 // if state has no successors than delete it 00648 if (trans.Empty()) { 00649 rGd.DelState(state); 00650 FD_DD("removing state " << state); 00651 return; 00652 } 00653 00654 // If there exists a self-loop of an indicator event (after the occurrence of a failure event), return. 00655 // This needs to be checked because otherwise the following for-loop could cut parts of the future traces before noticing the self-loop. 00656 for (it = trans.Begin(); it != trans.End(); it++) { 00657 if (it->X1 == it->X2) { 00658 if (rIndicatorEvents.Exists(it->Ev)) { 00659 compMapIt = rCompositionMap.find(it->X2); 00660 pDiagState1 = rGobs.StateAttribute(compMapIt->second.first).DiagnoserStateMapp(); 00661 pDiagState2 = rGobs.StateAttribute(compMapIt->second.second).DiagnoserStateMapp(); 00662 if (*(pDiagState1->Attribute(*(pDiagState1->Begin())).mDiagLabels.Begin()) == rFailureType) { 00663 return; 00664 } 00665 if (*(pDiagState2->Attribute(*(pDiagState2->Begin())).mDiagLabels.Begin()) == rFailureType) { 00666 return; 00667 } 00668 } 00669 } 00670 } 00671 00672 // parse through transitions of active transition set 00673 for (it = trans.Begin(); it != trans.End(); it++) { 00674 nextState = it->X2; 00675 failureHasAlreadyOccurred = false; 00676 00677 // if event is an indicator: check if corresponding failure type has already occurred 00678 // by checking if there exists a corresponding failure in the _next_ failure label in G_d 00679 // (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) 00680 if (rIndicatorEvents.Exists(it->Ev)) { 00681 compMapIt = rCompositionMap.find(nextState); 00682 pDiagState1 = rGobs.StateAttribute(compMapIt->second.first).DiagnoserStateMapp(); 00683 pDiagState2 = rGobs.StateAttribute(compMapIt->second.second).DiagnoserStateMapp(); 00684 if (*(pDiagState1->Attribute(*(pDiagState1->Begin())).mDiagLabels.Begin()) == rFailureType) { 00685 failureHasAlreadyOccurred = true; 00686 } 00687 if (*(pDiagState2->Attribute(*(pDiagState2->Begin())).mDiagLabels.Begin()) == rFailureType) { 00688 failureHasAlreadyOccurred = true; 00689 } 00690 } 00691 00692 // if transition event is not an indicator event or there did not occur a failure _before_ the indicator 00693 if (!rIndicatorEvents.Exists(it->Ev) || !failureHasAlreadyOccurred) { 00694 // remove transition 00695 rGd.ClrTransition(*it); 00696 FD_DD("removing transition " << it->X1 << "--" << rGd.EventName(it->Ev) << "-->" << it->X2 ); 00697 // remove state if it does not have any transitions left 00698 if (rGd.ActiveTransSet(state).Empty()) { 00699 rGd.DelState(state); 00700 FD_DD("removing state " << state ); 00701 } 00702 // if there do not exist any further transitions form other states into the next state: continue trimming at next state 00703 backTrans = ActiveBackwardTransSet(rGd, nextState); 00704 if (backTrans.Empty() || ((backTrans.Size() == 1) && (backTrans.Begin()->X2 == nextState))) { 00705 TrimNonIndicatorTracesOfGdRecursive(rGd, rGobs, rFailureType, rIndicatorEvents, rCompositionMap, nextState, rStatesDone); 00706 } 00707 } 00708 } 00709 } 00710 00711 // ComputeReachability() 00712 void ComputeReachability(const cGenerator& rGen, const EventSet& rUnobsEvents, const EventSet& rFailures, Idx State, 00713 const AttributeFailureTypeMap& rAttrFTMap, map<Idx,multimap<Idx,DiagLabelSet> >& rReachabilityMap) { 00714 DiagLabelSet FTonPath; 00715 00716 FD_DD("ComputeReachability() for state " << State << "..."); 00717 rReachabilityMap.clear(); 00718 FTonPath.Clear(); 00719 ComputeReachabilityRecursive(rGen, rUnobsEvents, rFailures, State, rAttrFTMap, rReachabilityMap, FTonPath); 00720 00721 multimap<Idx,DiagLabelSet>::iterator mmLabelIt; 00722 map<Idx,multimap<Idx,DiagLabelSet> >::iterator it; 00723 00724 #ifdef FAUDES_DEBUG_DIAGNOSIS 00725 FD_DD("rReachabilityMap: "); 00726 for (it = rReachabilityMap.begin(); it != rReachabilityMap.end(); it++) { 00727 // print rReachabilityMap for current event 00728 FD_DD("_" << rGen.EventName(it->first) << " ("<< it->second.size() << " state estimates)"); 00729 for (mmLabelIt = it->second.begin(); mmLabelIt != it->second.end(); mmLabelIt++) { 00730 FD_DD(mmLabelIt->first << " " << mmLabelIt->second.ToString()); 00731 } 00732 } 00733 FD_DD(""); 00734 #endif 00735 } 00736 00737 // ComputeReachabilityRecursive() 00738 void ComputeReachabilityRecursive(const cGenerator& rGen, const EventSet& rUnobsEvents, 00739 const EventSet& rFailures, Idx State, const AttributeFailureTypeMap& rAttrFTMap, 00740 map<Idx,multimap<Idx,DiagLabelSet> >& rReachabilityMap, const DiagLabelSet FToccurred) { 00741 TransSet trans; 00742 TransSet::Iterator tIt; 00743 EventSet tmpFailureSet; 00744 EventSet::Iterator evIt; 00745 multimap<Idx,DiagLabelSet> stateFailureTypeMap; // maps generator states onto occurred failure types (=labels), part of rReachabilityMap 00746 multimap<Idx,DiagLabelSet>::iterator mmLabelIt; 00747 map<Idx,multimap<Idx,DiagLabelSet> >::iterator it; 00748 Idx failureType; 00749 DiagLabelSet newFT; 00750 bool mappingExists; 00751 00752 trans = rGen.ActiveTransSet(State); 00753 00754 FD_DD("ComputeReachabilityRecursive() for state " << State); 00755 // parse through active transitions of current generator state 00756 for (tIt = trans.Begin(); tIt != trans.End(); tIt++) { 00757 FD_DD(tIt->X1 << "--" << rGen.EventName(tIt->Ev) << "-->" << tIt->X2 << " for " << FToccurred.ToString()); 00758 // if current event is unobservable 00759 if (rUnobsEvents.Exists(tIt->Ev)) { 00760 // if it is a failure as well add its failure type 00761 if (rFailures.Exists(tIt->Ev)) { 00762 FD_DD(rGen.EventName(tIt->Ev) << " is a failure"); 00763 newFT = FToccurred; 00764 newFT.Erase(DiagLabelSet::IndexOfLabelN()); 00765 failureType = rAttrFTMap.FailureType(tIt->Ev); 00766 newFT.Insert(failureType); 00767 FD_DD("new failure path: " << newFT.ToString()); 00768 } else { 00769 FD_DD(rGen.EventName(tIt->Ev) << " is unobservable but no failure"); 00770 newFT = FToccurred; 00771 } 00772 // call ComputeReachabilityRecursive for successor state 00773 ComputeReachabilityRecursive(rGen, rUnobsEvents, rFailures, tIt->X2, rAttrFTMap, rReachabilityMap, newFT); 00774 } 00775 // if current event is observable add failure type path to rReachabilityMap 00776 else { 00777 FD_DD(rGen.EventName(tIt->Ev) << " is observable: add it to rReachabilityMap " << FToccurred.ToString()); 00778 // get old entry of rReachabilityMap if it exists 00779 stateFailureTypeMap.clear(); 00780 if (rReachabilityMap.find(tIt->Ev) != rReachabilityMap.end()) { 00781 stateFailureTypeMap = rReachabilityMap[tIt->Ev]; 00782 #ifdef FAUDES_DEBUG_DIAGNOSIS 00783 FD_DD("old entry of rReachabilityMap for " << rGen.EventName(tIt->Ev)); 00784 for (mmLabelIt = stateFailureTypeMap.begin(); mmLabelIt != stateFailureTypeMap.end(); mmLabelIt++) { 00785 FD_DD(mmLabelIt->first << " " << mmLabelIt->second.ToString()); 00786 } 00787 #endif 00788 } 00789 // if no failure occurred add normal label 00790 newFT = FToccurred; 00791 if (newFT.Empty()) { 00792 newFT.Insert(DiagLabelSet::IndexOfLabelRelN()); 00793 } 00794 // check if new mapping does already exist 00795 mappingExists = false; 00796 for (mmLabelIt = stateFailureTypeMap.lower_bound(tIt->X2); mmLabelIt != stateFailureTypeMap.upper_bound(tIt->X2); mmLabelIt++) { 00797 if (mmLabelIt->second == newFT) { 00798 mappingExists = true; 00799 } 00800 } 00801 // if new mapping does not yet exist: add it to rReachabilityMap 00802 if (!mappingExists) { 00803 stateFailureTypeMap.insert(pair<Idx,DiagLabelSet>(tIt->X2,newFT)); 00804 rReachabilityMap[tIt->Ev] = stateFailureTypeMap; 00805 } 00806 } 00807 } 00808 } 00809 00810 // ActiveBackwardTransSet() 00811 TransSet ActiveBackwardTransSet(const cGenerator& rGen, Idx state) { 00812 TransSet result; 00813 TransSetX2EvX1 transByX2; 00814 TransSetX2EvX1::Iterator it; 00815 00816 rGen.TransRel(transByX2); 00817 for (it = transByX2.BeginByX2(state); it != transByX2.EndByX2(state); it++) { 00818 result.Insert(*it); 00819 } 00820 return result; 00821 } 00822 00823 00824 // ComputeEventDiagnoser() 00825 void ComputeEventDiagnoser(const cGenerator& rOrigGen, const map<string,EventSet>& rFailureTypeMap, diagGenerator& rDiagGen) { 00826 FD_DD("ComputeEventDiagnoser()"); 00827 AttributeFailureTypeMap attrFT; 00828 attrFT.AddFailureTypeMap(rFailureTypeMap); 00829 ComputeEventDiagnoser(rOrigGen, attrFT, rDiagGen); 00830 } 00831 00832 // ComputeEventDiagnoser() 00833 void ComputeEventDiagnoser(const cGenerator& rOrigGen, const AttributeFailureTypeMap& rAttrFTMap, diagGenerator& rDiagGen) { 00834 EventSet failureEvents; 00835 EventSet gObservableEvents, gUnobservableEvents; 00836 StateSet newDiagStates; 00837 Idx currDState = 0; 00838 Idx nextDState = 0; 00839 string reportString; 00840 00841 FD_DD("ComputeEventDiagnoser()"); 00842 // check if FailureTypeMap is empty 00843 if (rAttrFTMap.Empty()) { 00844 FD_DD( endl << "WARNING - ComputeEventDiagnoser(): failure type map is empty!" << endl); 00845 } 00846 00847 // Necessary assumption: No cycles of unobservable events 00848 reportString.clear(); 00849 if (CycleOfUnobsEvents(rOrigGen,reportString)) { 00850 FD_DD( "ComputeEventDiagnoser(): Generator contains cycle of unobservable events! Aborting.."); 00851 FD_DD(reportString); 00852 return; 00853 } 00854 00855 // clear diagnoser 00856 rDiagGen.Clear(); 00857 rDiagGen.ClearAttributes(); 00858 00859 // copy attribute failure type map to diagnoser 00860 rDiagGen.GlobalAttribute(rAttrFTMap); 00861 00862 // get observable events of original generator 00863 gObservableEvents = rOrigGen.ObservableEvents(); 00864 FD_DD("Observable events: " << gObservableEvents.ToString()); 00865 00866 // get unobservable events of original generator 00867 gUnobservableEvents = rOrigGen.UnobservableEvents(); 00868 FD_DD("Unobservable events: " << gUnobservableEvents.ToString()); 00869 00870 // copy all failure events into one single EventSet 00871 failureEvents = rDiagGen.GetAllFailureEvents(); 00872 FD_DD("Failure events: " << failureEvents.ToString()); 00873 00874 // create initial state of diagnoser and its attribute with label "normal" 00875 #ifdef FAUDES_CHECKED 00876 if(rOrigGen.InitStatesSize() != 1) { 00877 std::stringstream errstr; 00878 errstr << "original generator has no unique initial state" << std::endl; 00879 throw Exception("ComputeEventDiagnoser()", errstr.str(), 301); 00880 } 00881 #endif 00882 Idx gInitState = rOrigGen.InitState(); 00883 currDState = rDiagGen.InsInitState(); 00884 newDiagStates.Insert(currDState); 00885 rDiagGen.InsStateLabelMapping(currDState,gInitState,DiagLabelSet::IndexOfLabelN()); 00886 00887 Idx gStateEstimate = 0; 00888 Idx newState = 0; 00889 00890 map<Idx,multimap<Idx,DiagLabelSet> > reachMap; // maps executable events to all reachable states and occuring relative failure types 00891 map<Idx,multimap<Idx,DiagLabelSet> > reachMapWholeState; // map for whole diagnoser state, contains propagated absolute failure type labels 00892 map<Idx,multimap<Idx,DiagLabelSet> >::iterator it; 00893 00894 multimap<Idx,DiagLabelSet> tmpPropagatedLabels; 00895 multimap<Idx,DiagLabelSet> bufferPropLabels; 00896 multimap<Idx,DiagLabelSet>::iterator mmit, mmit2; 00897 00898 //pair<Idx,DiagLabelSet> stateLabelPair; 00899 pair<Idx,DiagLabelSet> reachMapPair; 00900 00901 TransSet transitions; 00902 TransSet::Iterator transIt; 00903 DiagLabelSet oldLabel, newLabel, occFailureTypes; 00904 DiagLabelSet::Iterator labelIt; 00905 StateSet diagStates; 00906 StateSet::Iterator stateIt; 00907 EventSet activeEvents; 00908 AttributeDiagnoserState newAttr; 00909 bool stateLabelExists = false; 00910 AttributeDiagnoserState currDStateAttr; 00911 TaIndexSet<DiagLabelSet> currDStateMap; 00912 TaIndexSet<DiagLabelSet>::Iterator currDStateMapIt; 00913 00914 // parse through new diagnoser states 00915 while (!newDiagStates.Empty()) { 00916 // set current diagnoser state 00917 currDState = *newDiagStates.Begin(); 00918 00919 reachMapWholeState.clear(); 00920 00921 currDStateAttr = rDiagGen.StateAttribute(currDState); 00922 currDStateMap = currDStateAttr.DiagnoserStateMap(); 00923 00924 // parse through state estimates of current diagnoser state 00925 for(currDStateMapIt = currDStateMap.Begin(); currDStateMapIt != currDStateMap.End(); ++ currDStateMapIt){ 00926 gStateEstimate = *currDStateMapIt; 00927 // generate reachMap for current state estimate 00928 ComputeReachability(rOrigGen, gUnobservableEvents, failureEvents, gStateEstimate, rAttrFTMap, reachMap); 00929 // parse through reachMap (eventwise), propagate label and copy it to reachMapWholeState 00930 for (it = reachMap.begin(); it != reachMap.end(); it++) { 00931 // get label set of current state estimate 00932 oldLabel = currDStateMap.Attribute(*currDStateMapIt); 00933 newState = 0; 00934 tmpPropagatedLabels.clear(); 00935 // parse through state failure type mappings of state failure type map (for current event in reachMap) 00936 for (mmit = it->second.begin(); mmit != it->second.end(); mmit++) { 00937 newState = mmit->first; 00938 occFailureTypes = mmit->second; 00939 LabelPropagation(oldLabel, occFailureTypes, newLabel); 00940 // check if this combination of state and label does already exist 00941 stateLabelExists = false; 00942 for (mmit2 = tmpPropagatedLabels.lower_bound(newState); mmit2 != tmpPropagatedLabels.upper_bound(newState); mmit2++) { 00943 if (mmit2->second == newLabel) { 00944 stateLabelExists = true; 00945 } 00946 } 00947 // insert new state-label-pair if it does not exist yet 00948 if (!stateLabelExists) { 00949 tmpPropagatedLabels.insert(pair<Idx,DiagLabelSet>(newState,newLabel)); 00950 } 00951 } 00952 00953 // if event is already mapped: add new Labels to multimap and insert it afterwards 00954 if (reachMapWholeState.find(it->first) != reachMapWholeState.end()) { 00955 bufferPropLabels = reachMapWholeState[it->first]; 00956 00957 // parse throught tmpPropagatedLabels and check for every combination of state and label 00958 // if it does already exist in bufferPropLabels 00959 for (mmit = tmpPropagatedLabels.begin(); mmit != tmpPropagatedLabels.end(); mmit++) { 00960 stateLabelExists = false; 00961 for (mmit2 = bufferPropLabels.lower_bound(mmit->first); mmit2 != bufferPropLabels.upper_bound(mmit->first); mmit2++) { 00962 if (mmit2->second == mmit->second) { 00963 stateLabelExists = true; 00964 } 00965 } 00966 // insert new state-label-pair if it does not exist yet 00967 if (!stateLabelExists) { 00968 bufferPropLabels.insert(pair<Idx,DiagLabelSet>(mmit->first,mmit->second)); 00969 } 00970 } 00971 reachMapWholeState[it->first] = bufferPropLabels; 00972 } 00973 // if not just insert the new labels 00974 else { 00975 reachMapWholeState[it->first] = tmpPropagatedLabels; 00976 } 00977 } 00978 } 00979 activeEvents = rDiagGen.ActiveEventSet(currDState); 00980 transitions = rDiagGen.ActiveTransSet(currDState); 00981 00982 for (it = reachMapWholeState.begin(); it != reachMapWholeState.end(); it++) { 00983 LabelCorrection(it->second,newAttr); 00984 // if newAttr equals any existing state attribute than create a transition to this very state 00985 diagStates = rDiagGen.States(); 00986 stateIt = diagStates.Begin(); 00987 while (stateIt != diagStates.End()) { 00988 if (newAttr == rDiagGen.StateAttribute(*stateIt)) { 00989 // realising as back- or self-loop to existing state *stateIt 00990 rDiagGen.InsEvent(it->first); 00991 rDiagGen.SetTransition(currDState,it->first,*stateIt); 00992 break; 00993 } 00994 stateIt++; 00995 } 00996 // if newAttr is new to diagnoser 00997 if (stateIt == diagStates.End()) { 00998 // if current event is executable from current diagnoser state 00999 if (activeEvents.Exists(it->first)) { 01000 // this event is executable from current diagnoser state 01001 // find successor state nextDState 01002 transIt = transitions.Begin(); 01003 while (transIt != transitions.End()) { 01004 if (transIt->Ev == it->first) { 01005 nextDState = transIt->X2; 01006 break; 01007 } 01008 transIt++; 01009 } 01010 } 01011 // if event is not executable from current diagnoser state 01012 else { 01013 // this event is not yet executable from current diagnoser state: create new diagnoser state 01014 // creat new diagnoser state and add it to new states 01015 nextDState = rDiagGen.InsState(); 01016 newDiagStates.Insert(nextDState); 01017 rDiagGen.InsEvent(it->first); 01018 rDiagGen.SetTransition(currDState,it->first,nextDState); 01019 } 01020 rDiagGen.StateAttribute(nextDState, newAttr); 01021 } 01022 } 01023 // delete current diagnoser state from new states 01024 newDiagStates.Erase(currDState); 01025 } 01026 } 01027 01028 // LabelPropagation() 01029 void LabelPropagation(const DiagLabelSet& lastLabel, const DiagLabelSet& failureTypes, DiagLabelSet& newLabel) { 01030 FD_DD("LabelPropagation()"); 01031 newLabel.Clear(); 01032 01033 // if no failure occurred 01034 if (failureTypes.Size() == 1 && failureTypes.Exists(DiagLabelSet::IndexOfLabelRelN())) { 01035 // if label = {"N"} 01036 if (lastLabel.Size() == 1 && lastLabel.Exists(DiagLabelSet::IndexOfLabelN())) { 01037 newLabel.Insert(DiagLabelSet::IndexOfLabelN()); 01038 return; 01039 } 01040 // if label = {"A"} 01041 if (lastLabel.Size() == 1 && lastLabel.Exists(DiagLabelSet::IndexOfLabelA())) { 01042 newLabel.Insert(DiagLabelSet::IndexOfLabelA()); 01043 return; 01044 } 01045 } 01046 // otherwise: 01047 newLabel.InsertSet(lastLabel); 01048 newLabel.InsertSet(failureTypes); 01049 newLabel.Erase(DiagLabelSet::IndexOfLabelN()); 01050 newLabel.Erase(DiagLabelSet::IndexOfLabelA()); 01051 newLabel.Erase(DiagLabelSet::IndexOfLabelRelN()); 01052 return; 01053 } 01054 01055 // LabelCorrection() 01056 void LabelCorrection(const multimap<Idx,DiagLabelSet>& mm, AttributeDiagnoserState& attr) { 01057 multimap<Idx,DiagLabelSet>::const_iterator mmit; 01058 multimap<Idx,DiagLabelSet>::const_iterator mmit_ub; 01059 DiagLabelSet label; 01060 Idx state; 01061 01062 FD_DD("LabelCorrection()"); 01063 attr.Clear(); 01064 mmit = mm.begin(); 01065 // parse through propagated labels 01066 while (mmit != mm.end()) { 01067 // if there is only one label for a particular state: no correction is needed and the label is copied to diagnoser state attribute 01068 if (mm.count(mmit->first) == 1) { 01069 attr.AddStateLabelMap(mmit->first,mmit->second); 01070 mmit++; 01071 } 01072 // if there are several labels: correct label before adding it to the diagnoser state attribute 01073 else { 01074 mmit_ub = mm.upper_bound(mmit->first); 01075 state = mmit->first; 01076 01077 label = mmit->second; 01078 mmit++; 01079 for ( ; mmit != mmit_ub; mmit++) { 01080 label = label * mmit->second; 01081 } 01082 label.Insert(DiagLabelSet::IndexOfLabelA()); 01083 attr.AddStateLabelMap(state,label); 01084 } 01085 } 01086 } 01087 01088 01089 } // namespace faudes |
libFAUDES 2.14g --- 2009-12-3 --- c++ source docu by doxygen 1.5.6