libFAUDES

Sections

Index

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 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