diag_eventdiagnosis.cpp

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

libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen