libFAUDES

Sections

Index

diag_languagediagnosis.cpp

Go to the documentation of this file.
00001 /** @file diag_languagediagnosis.cpp
00002 Functions to check a system's language-diagnosability and compute a language-diagnoser. 
00003 
00004 (c) 2009, Tobias Barthel, Thomas Moor, Klaus Schmidt.
00005 */
00006 
00007 #include "diag_languagediagnosis.h"
00008 
00009 using namespace std;
00010 
00011 namespace faudes {
00012 
00013 
00014 ///////////////////////////////////////////////////////////////////////////////
00015 // Functions for specification framework
00016 ///////////////////////////////////////////////////////////////////////////////
00017 
00018 
00019 // rti function interface
00020 void IsLanguageDiagnosable(const cGenerator& rGen, const cGenerator& rSpec, bool& rRes, std::string& rReportString) {
00021   rRes=IsLanguageDiagnosable(rGen,rSpec,rReportString);
00022 }
00023 
00024 // rti function interface
00025 void IsLanguageDiagnosable(const cGenerator& rGen, const cGenerator& rSpec, bool& rRes) {
00026   std::string ignore;
00027   rRes=IsLanguageDiagnosable(rGen,rSpec,ignore);
00028 }
00029 
00030 
00031 // ComputeGobs()
00032 void ComputeGobs(const cGenerator& rGenMarkedNonSpecBehaviour, diagGenerator& rGobs) {
00033   EventSet gObservableEvents, gUnobservableEvents;
00034   StateSet newGobsStates;
00035   Idx currDState = 0;
00036   Idx nextDState = 0;
00037   Idx gStateEstimate = 0;
00038   Idx newState = 0;
00039   map<Idx,multimap<Idx,DiagLabelSet> > reachMap;   // maps executable events to all reachable states and occuring relative failure types
00040   map<Idx,multimap<Idx,DiagLabelSet> >::iterator it;
00041   multimap<Idx,DiagLabelSet>::iterator mmit, mmit2;
00042   pair<Idx,DiagLabelSet> reachMapPair;  
00043   TransSet transitions;
00044   DiagLabelSet oldLabel, newLabel, occFailureTypes;
00045   DiagLabelSet::Iterator labelIt;
00046   StateSet gObsStates;
00047   StateSet::Iterator stateIt, initStateIt;
00048   EventSet activeEvents;
00049   AttributeDiagnoserState newAttr;
00050   const TaIndexSet<DiagLabelSet>* pDiagState;
00051   
00052   FD_DD("ComputeGobs()");
00053   
00054   // clear Gobs
00055   rGobs.Clear();
00056   rGobs.ClearAttributes();
00057   
00058   // get observable events of original generator
00059   gObservableEvents = rGenMarkedNonSpecBehaviour.ObservableEvents();
00060   FD_DD( "Observable events: " << gObservableEvents.ToString() );
00061   
00062   // get unobservable events of original generator
00063   gUnobservableEvents = rGenMarkedNonSpecBehaviour.UnobservableEvents();
00064   FD_DD( "Unobservable events: " << gUnobservableEvents.ToString() );
00065 
00066   // parse through init states of rGenMarkedNonSpecBehaviour
00067   for (initStateIt = rGenMarkedNonSpecBehaviour.InitStatesBegin(); initStateIt != rGenMarkedNonSpecBehaviour.InitStatesEnd(); initStateIt++) {
00068     newGobsStates.Clear();
00069     newLabel.Clear();
00070     newAttr.Clear();
00071         
00072     // create newAttr with state index of current initial state of rGenMarkedNonSpecBehaviour and label "N"
00073     newLabel.Insert(DiagLabelSet::IndexOfLabelN());
00074     newAttr.AddStateLabelMap(*initStateIt,newLabel);
00075 
00076     // if newAttr equals any existing state attribute then use this state and make it an initial state
00077     gObsStates = rGobs.States();
00078     stateIt = gObsStates.Begin();
00079     while (stateIt != gObsStates.End()) {
00080       if (newAttr == rGobs.StateAttribute(*stateIt)) {
00081         FD_DD("Statelabel " << *initStateIt << "N already exists at state " << *stateIt << " --> make it init state.");
00082         rGobs.SetInitState(*stateIt);
00083         break;
00084       }
00085       stateIt++;
00086     }
00087     // if newAttribute is new to Gobs
00088     if (stateIt == gObsStates.End()) {
00089       // create new initial state of Gobs and its attribute with label "normal"
00090       currDState = rGobs.InsInitState();
00091       rGobs.StateAttribute(currDState, newAttr);
00092       newGobsStates.Insert(currDState);
00093     }
00094     
00095     // parse through new Gobs states
00096     while (!newGobsStates.Empty()) {
00097       // set current Gobs state
00098       currDState = *newGobsStates.Begin();
00099       
00100       // get unique state estimate and unique failure label from Gobs
00101       pDiagState = rGobs.StateAttribute(currDState).DiagnoserStateMapp();
00102       gStateEstimate = *(pDiagState->Begin());
00103       oldLabel = pDiagState->Attribute(*(pDiagState->Begin()));
00104 
00105       //  generate reachMap for current state estimate
00106       ComputeReachability(rGenMarkedNonSpecBehaviour, gUnobservableEvents, gStateEstimate, reachMap);
00107 
00108 
00109 #ifdef FAUDES_DEBUG_DIAGNOSIS
00110       FD_DD("reachMap: ");
00111       for (it = reachMap.begin(); it != reachMap.end(); it++) {
00112         //print reachMap for current event
00113         FD_DD("_" << rGenMarkedNonSpecBehaviour.EventName(it->first) << " ("<< it->second.size() << " state estimates)");
00114         for (mmit = it->second.begin(); mmit != it->second.end(); mmit++) {
00115           FD_DD(mmit->first << " " << mmit->second.ToString());
00116         }
00117       }
00118 #endif
00119       
00120       // parse through reachMap (eventwise)
00121       for (it = reachMap.begin(); it != reachMap.end(); it++) {
00122 #ifdef FAUDES_DEBUG_DIAGNOSIS
00123         // print reachMap for current event
00124         FD_DD("Parsing reachMap: " << "_" << rGenMarkedNonSpecBehaviour.EventName(it->first));
00125         for (mmit = it->second.begin(); mmit != it->second.end(); mmit++) {
00126           FD_DD(mmit->first << " " << mmit->second.ToString());
00127         }
00128         #endif
00129         
00130         FD_DD("old label: " << oldLabel.ToString());
00131         
00132         newState = 0;
00133         // parse through state failure type map (for current event in reachMap)
00134         for (mmit = it->second.begin(); mmit != it->second.end(); mmit++) {
00135           newState = mmit->first;
00136           FD_DD("new state: " << newState);
00137           occFailureTypes = mmit->second;
00138           FD_DD("failure types occurred: " << occFailureTypes.ToString());
00139           LabelPropagation(oldLabel, occFailureTypes, newLabel);
00140           FD_DD("new label: " << newLabel.ToString());
00141           newAttr.Clear();
00142           newAttr.AddStateLabelMap(newState,newLabel);
00143 
00144           // if newAttr equals any existing state attribute then we create a transition to this very state
00145           gObsStates = rGobs.States();
00146           stateIt = gObsStates.Begin();
00147           while (stateIt != gObsStates.End()) {
00148             if (newAttr == rGobs.StateAttribute(*stateIt)) {
00149               FD_DD("realising as back- or self-loop to existing state " << *stateIt);
00150               if (!rGobs.ExistsTransition(currDState,it->first,*stateIt)) {
00151                 if (!rGobs.ExistsEvent(it->first)) {
00152                   rGobs.InsEvent(it->first);
00153                 }
00154                 rGobs.SetTransition(currDState,it->first,*stateIt);
00155               }
00156               break;
00157             }
00158             stateIt++;
00159           }
00160           // if newAttribute is new to Gobs
00161           if (stateIt == gObsStates.End()) {
00162             // create new Gobs state and add it to new states
00163             nextDState = rGobs.InsState();
00164             FD_DD("Create new state " << nextDState << " and transition "  << currDState << " --" << rGenMarkedNonSpecBehaviour.EventName(it->first) << "--> " << nextDState);
00165             newGobsStates.Insert(nextDState);
00166             rGobs.InsEvent(it->first);
00167             rGobs.SetTransition(currDState,it->first,nextDState);
00168             
00169             //rGobs.InsStateLabelMap(nextDState,newState,newLabel);
00170             rGobs.StateAttribute(nextDState, newAttr);
00171           }
00172         }
00173       }
00174       
00175       activeEvents = rGobs.ActiveEventSet(currDState);
00176       transitions = rGobs.ActiveTransSet(currDState);
00177 
00178       // delete current Gobs state from new states
00179       newGobsStates.Erase(currDState);  
00180     }
00181   }
00182 }
00183 
00184 // ComputeReachability()
00185 void ComputeReachability(const cGenerator& rGen, const EventSet& rUnobsEvents, Idx State, 
00186                 map<Idx,multimap<Idx,DiagLabelSet> >& rReachabilityMap) {
00187                 
00188   FD_DD("ComputeReachability() for state " << State << "...");
00189   StateSet doneStates;
00190   
00191   doneStates.Clear();
00192   rReachabilityMap.clear();
00193   ComputeReachabilityRecursive(rGen, rUnobsEvents, State, doneStates, rReachabilityMap);
00194   FD_DD("ComputeReachability for state " << State << ": done");
00195   
00196   #ifdef FAUDES_DEBUG_DIAGNOSIS
00197   map<Idx,multimap<Idx,DiagLabelSet> >::iterator it;
00198   multimap<Idx,DiagLabelSet>::iterator mmLabelIt;
00199   FD_DD("rReachabilityMap: ");
00200   for (it = rReachabilityMap.begin(); it != rReachabilityMap.end(); it++) {
00201     // print rReachabilityMap for current event
00202     FD_DD("_" << rGen.EventName(it->first) << " ("<< it->second.size() << " state estimates)");
00203     for (mmLabelIt = it->second.begin(); mmLabelIt != it->second.end(); mmLabelIt++) {
00204       FD_DD(mmLabelIt->first << " " << mmLabelIt->second.ToString());
00205     }
00206   }
00207   FD_DD("");
00208   #endif
00209 }
00210 
00211 // ComputeReachabilityRecursive()
00212 void ComputeReachabilityRecursive(const cGenerator& rGen, const EventSet& rUnobsEvents, Idx State, StateSet done, 
00213                     map<Idx,multimap<Idx,DiagLabelSet> >& rReachabilityMap) {
00214   TransSet trans;
00215   TransSet::Iterator tIt;
00216   EventSet tmpFailureSet;
00217   EventSet::Iterator evIt;
00218   multimap<Idx,DiagLabelSet> stateFailureTypeMap; // maps generator states onto occurred failures types (=labels), part of rReachabilityMap
00219   multimap<Idx,DiagLabelSet>::iterator mmLabelIt;
00220   map<Idx,multimap<Idx,DiagLabelSet> >::iterator it;
00221   DiagLabelSet newFT;
00222   bool mappingExists;
00223   
00224   if (done.Exists(State)) {
00225     FD_DD( "State " << State << " has already been processed." );
00226     return;
00227   }
00228   trans = rGen.ActiveTransSet(State);
00229   
00230   FD_DD("ComputeReachabilityRecursive() for state " << State << ": Events in ActiveTransSet: ");  
00231   // parse through active transitions of current generator state
00232   for (tIt = trans.Begin(); tIt != trans.End(); tIt++) {
00233     FD_DD(tIt->X1 << "--" << rGen.EventName(tIt->Ev) << "-->" << tIt->X2);
00234     // if current event is unobservable
00235     if (rUnobsEvents.Exists(tIt->Ev)) {
00236       // call ComputeReachabilityRecursive for successor state
00237       done.Insert(tIt->X1);
00238       ComputeReachabilityRecursive(rGen, rUnobsEvents, tIt->X2, done, rReachabilityMap);
00239     }
00240     // if current event is observable add failure (spec violation) to rReachabilityMap
00241     else {
00242       FD_DD(rGen.EventName(tIt->Ev) << " is observable: add it to rReachabilityMap ");
00243       // get old entry of rReachabilityMap if it exists
00244       stateFailureTypeMap.clear();
00245       if (rReachabilityMap.find(tIt->Ev) != rReachabilityMap.end()) {
00246         stateFailureTypeMap = rReachabilityMap[tIt->Ev];
00247 #ifdef FAUDES_DEBUG_DIAGNOSIS
00248         FD_DD("old entry of rReachabilityMap for " << rGen.EventName(tIt->Ev));
00249         for (mmLabelIt = stateFailureTypeMap.begin(); mmLabelIt != stateFailureTypeMap.end(); mmLabelIt++) {
00250           FD_DD(mmLabelIt->first << " " << mmLabelIt->second.ToString());
00251         }
00252 #endif        
00253       }
00254       newFT.Clear();
00255       // if successor state is marked: add failure label
00256       if (rGen.ExistsMarkedState(tIt->X2)) {
00257         newFT.Insert(DiagLabelSet::IndexOfLabelSpecViolated());
00258       }
00259       // if no failure occurred add normal label
00260       if (newFT.Empty()) {
00261         newFT.Insert(DiagLabelSet::IndexOfLabelRelN());
00262       }
00263       // check if new mapping does already exist
00264       mappingExists = false;
00265       for (mmLabelIt = stateFailureTypeMap.lower_bound(tIt->X2); mmLabelIt != stateFailureTypeMap.upper_bound(tIt->X2); mmLabelIt++) {
00266         if (mmLabelIt->second == newFT) {
00267           mappingExists = true;
00268         }
00269       }
00270       // if new mapping does not yet exist: add it to rReachabilityMap
00271       if (!mappingExists) {
00272         stateFailureTypeMap.insert(pair<Idx,DiagLabelSet>(tIt->X2,newFT));
00273         rReachabilityMap[tIt->Ev] = stateFailureTypeMap;
00274       }
00275     }
00276   }
00277 }
00278 
00279 // ComputeLanguageDiagnoser()
00280 void ComputeLanguageDiagnoser(const cGenerator& rGen, const cGenerator& rSpec, diagGenerator& rDiagGen) {
00281   cGenerator genMarkedNonSpecBehaviour, specComplement;
00282   diagGenerator genGobs;
00283   
00284   FD_DD("ComputeLanguageDiagnoser()");
00285 
00286   // copy const arguments
00287   cGenerator gen = rGen;
00288   cGenerator spec = rSpec;
00289 
00290   // prepare result
00291   rDiagGen.Clear();
00292   
00293   // mark all states in generator and specification
00294   StateSet::Iterator sit;
00295   for (sit = gen.StatesBegin(); sit != gen.StatesEnd(); sit++) 
00296     gen.SetMarkedState(*sit);
00297   for (sit = spec.StatesBegin(); sit != spec.StatesEnd(); sit++) 
00298     spec.SetMarkedState(*sit);
00299   
00300   // lift spec  to same alphabet (insert missing events)
00301   EventSet diffEventsGenAndSpec = gen.Alphabet() - spec.Alphabet();
00302   FD_DD("diffEventsGenAndSpec: " << diffEventsGenAndSpec.ToString() );
00303   spec.InsEvents(diffEventsGenAndSpec);  
00304 
00305   // figure failure behaviour Gtilde=  Closure(G) ^ Complement(Closure(Specification))
00306   // technical note: to obtain a diagnoser that refers to  G state indicees, we use the reverse
00307   // composition map to track the correspondance to the original state space.
00308   specComplement = spec;
00309   LanguageComplement(specComplement);  
00310   std::map< std::pair<Idx,Idx>, Idx> rcmap;
00311   Parallel(gen, specComplement, rcmap, genMarkedNonSpecBehaviour);
00312   std::map<Idx, Idx> gen1cmap;
00313   CompositionMap1(rcmap,gen1cmap);
00314   rcmap.clear();
00315 
00316   genMarkedNonSpecBehaviour.ClrObservable(gen.UnobservableEvents());
00317 #ifdef FAUDES_DEBUG_DIAGNOSIS
00318   genMarkedNonSpecBehaviour.GraphWrite("tmp_wrtb_Gtilde_spec.png");
00319   genMarkedNonSpecBehaviour.Write("tmp_wrtb_Gtilde_spec.gen");
00320 #endif
00321   
00322   // bail out trivial case "no failures"
00323   if (genMarkedNonSpecBehaviour.MarkedStatesEmpty()) {
00324     rDiagGen.InjectAlphabet(gen.ObservableEvents());
00325     Idx dstate = rDiagGen.InsInitState();
00326     // TODO: loop over all possible states
00327     rDiagGen.InsStateLabelMapping(dstate,rGen.InitState(),DiagLabelSet::IndexOfLabelN());
00328     SelfLoop(rDiagGen,gen.ObservableEvents());
00329     return;
00330   }
00331 
00332   // compute the observer, i.e. non-deterministic basis for diagnoser  
00333   ComputeGobs(genMarkedNonSpecBehaviour, genGobs);
00334 
00335 #ifdef FAUDES_DEBUG_DIAGNOSIS
00336   genGobs.GraphWrite("tmp_wrtb_gobs.png");
00337 #endif
00338  
00339 
00340   // post process
00341   // We construct a deterministic diagnoser from the non-deterministic GObs by
00342   // parsing the transition structure of GObs and merging possible diagnosis 
00343   // labels.
00344 
00345   // have all observable events
00346   rDiagGen.InjectAlphabet(gen.ObservableEvents());
00347 
00348 
00349   // create initial state of diagnoser and its attribute with label "normal"
00350 #ifdef FAUDES_CHECKED
00351   if(genGobs.InitStatesSize() != 1) {    
00352     std::stringstream errstr;
00353     errstr << "Diagnosis: Internal Error: Go must have one initial state only" << std::endl;
00354     throw Exception("ComputeLanguageDiagnoser()", errstr.str(), 301);
00355   }
00356 #endif
00357   Idx gInitState = genGobs.InitState();
00358   Idx dInitState = rDiagGen.InsInitState();
00359   rDiagGen.InsStateLabelMapping(dInitState,gInitState,DiagLabelSet::IndexOfLabelN());
00360 
00361   // track state correspondence (map diagnoser states to genObs states)
00362   std::multimap<Idx,Idx> dgmap; 
00363   dgmap.insert(std::pair<Idx,Idx>(dInitState,gInitState));
00364 
00365   // loop variables  
00366   EventSet activeEvents;
00367   AttributeDiagnoserState newDAttr;
00368 
00369   // parse through gObsStates states
00370   StateSet dStates;
00371   dStates.Insert(dInitState);
00372   while (!dStates.Empty()) {
00373     // set current diagnoser state 
00374     Idx dstate = *dStates.Begin(); 
00375     // prepare reachmap: ev -> gSuccessors
00376     std::multimap<Idx,Idx> gSuccessors;
00377     // iterate over corresponding genObs States  
00378     std::multimap<Idx,Idx>::iterator gsit= dgmap.lower_bound(dstate);    
00379     std::multimap<Idx,Idx>::iterator gsit_end= dgmap.upper_bound(dstate);
00380     for(;gsit!=gsit_end; gsit++) {    
00381       Idx gState = gsit->second;
00382       // iterate over all successors
00383       TransSet::Iterator tit= genGobs.TransRelBegin(gState);
00384       TransSet::Iterator tit_end= genGobs.TransRelEnd(gState);
00385       for(; tit!=tit_end; tit++)  
00386   gSuccessors.insert(std::pair<Idx,Idx>(tit->Ev,tit->X2)); 
00387     }
00388     // per event, accumulate estimates
00389     gsit= gSuccessors.begin();
00390     gsit_end= gSuccessors.end();
00391     std::multimap<Idx,Idx>::iterator gsit_beg= gsit;
00392     newDAttr.Clear();
00393     while(gsit!=gsit_end) {
00394       Idx ev= gsit->first;
00395       // TODO: need merge method for diagnoser estimates
00396       const AttributeDiagnoserState sestimate= genGobs.StateAttribute(gsit->second);
00397       StateSet::Iterator lit=sestimate.DiagnoserStateMap().Begin();
00398       StateSet::Iterator lit_end=sestimate.DiagnoserStateMap().End();
00399       for(; lit!=lit_end; lit++) {
00400         //newDAttr.AddStateLabelMap(*lit, sestimate.DiagnoserStateMap().Attribute(*lit)); 
00401         newDAttr.AddStateLabelMap(gen1cmap[*lit], sestimate.DiagnoserStateMap().Attribute(*lit)); 
00402       }
00403       // increment 
00404       gsit++;
00405       // sense new event to set label
00406       bool nextev=false;
00407       if(gsit== gsit_end) nextev=true;
00408       if(gsit!= gsit_end) if(gsit->first!=ev) nextev=true;
00409       if(!nextev) continue;
00410       // insert new diag state set attribute
00411       // case 1: attribute exists, so use the corresponding diagnoser state
00412       // note: rather hold a map rather than to iterate over all attributes
00413       StateSet::Iterator sit= rDiagGen.StatesBegin();
00414       StateSet::Iterator sit_end= rDiagGen.StatesEnd();
00415       for(; sit!=sit_end; sit++) {
00416         if(!(newDAttr == rDiagGen.StateAttribute(*sit))) continue; 
00417         FD_DD("ComputeLanguageDiagnoser(): insert diag transition " << rDiagGen.TStr(Transition(dstate,ev,*sit)));
00418         rDiagGen.SetTransition(dstate,ev,*sit); 
00419         break;
00420       }
00421       // case 2: attribute does not exist, so insert new diagnoser state
00422       if(sit==sit_end) {
00423         // insert new dstate
00424         Idx newDState=rDiagGen.InsState();
00425         dStates.Insert(newDState);
00426         rDiagGen.StateAttribute(newDState,newDAttr);
00427         FD_DD("ComputeLanguageDiagnoser(): insert state with attr " << newDAttr.Str());
00428         // track corresponding gstates
00429         std::multimap<Idx,Idx>::iterator gesit= gsit_beg;
00430         for(;gesit!=gsit;gesit++) {
00431           FD_DD("ComputeLanguageDiagnoser(): corresponding gstate " << gesit->second);
00432     dgmap.insert(std::pair<Idx,Idx>(newDState,gesit->second));          
00433         }
00434         // insert transition
00435         FD_DD("ComputeLanguageDiagnoser(): insert diag transition " << rDiagGen.TStr(Transition(dstate,ev,newDState)));
00436         rDiagGen.SetTransition(dstate,ev,newDState);
00437       }
00438       // initialise per event variables in multimap loop
00439       gsit_beg=gsit;
00440       newDAttr.Clear();
00441     }
00442     // delete current state from todo list
00443     dStates.Erase(dstate);
00444   }
00445 
00446 #ifdef FAUDES_DEBUG_DIAGNOSIS
00447   rDiagGen.GraphWrite("tmp_wrtb_diag.png");
00448 #endif    
00449 }
00450 
00451 
00452 // IsLanguageDiagnosable
00453 bool IsLanguageDiagnosable(const cGenerator& rGen, const cGenerator rSpec, std::string& rReportString){
00454   FD_DD("IsLanguageDiagnosable()");
00455   EventSet obsEvents = rGen.ObservableEvents();
00456 #ifdef FAUDES_DEBUG_DIAGNOSIS
00457   obsEvents.DWrite();
00458 #endif
00459   Generator verifier; // Graph for diagnosability verification
00460   Idx nullEvent = verifier.InsEvent("nullEvent"); // event that corresponds to the value 0
00461   Idx negEvent = verifier.InsEvent("negEvent"); // event that corresponds to the value -1 
00462   //Generator verifierTest; // verifier with eeent information
00463   //verifierTest.InjectAlphabet(rGen.Alphabet() ); // FIXME remove this. 
00464   //verifierTest.InsEvent(nullEvent);
00465   map<Idx, VerifierState> stateToVerifierMap;
00466   map<VerifierState, Idx> verifierToStateMap;
00467   stack<pair<Idx, VerifierState> > waitingStates;
00468   StateSet doneStates;
00469   // initialize the algorithm 
00470   EventSet fullAlphabet = rGen.Alphabet();
00471   EventSet::Iterator eIt, eEndIt;
00472   eEndIt = fullAlphabet.End();
00473   Idx newState = verifier.InsInitState();
00474   //verifierTest.InsInitState(newState);
00475   VerifierState newVerifierState = VerifierState(rSpec.InitState(), rSpec.InitState(), rGen.InitState(),NORMAL);
00476   stateToVerifierMap[newState] = newVerifierState;
00477   verifierToStateMap[newVerifierState ] = newState;
00478   waitingStates.push(make_pair(newState, newVerifierState) );
00479   // extend the verifier graph until no new nodes can be added
00480   pair<Idx, VerifierState> currentState;
00481   Idx blockingState; // = verifier.InsMarkedState();
00482   TransSet::Iterator tIt;
00483   map<VerifierState, Idx>::const_iterator vsIt;
00484   Idx X2;
00485   bool block = false; // set to true if the BLOCK state is reachable  
00486   FD_DD("Main loop");
00487   while(waitingStates.empty() == false){
00488     // take the first element from the stack
00489     currentState = waitingStates.top();
00490     waitingStates.pop();
00491     doneStates.Insert(currentState.first);
00492     FD_DD("currentState: " + ToStringInteger(currentState.first) + " VerifierState: (" + rSpec.StateName(currentState.second.mSpec1State) + "," + rSpec.StateName(currentState.second.mSpec2State) + "," + rGen.StateName(currentState.second.mPlantState) + "," + ToStringInteger(currentState.second.mLabel) + ")");
00493     // go over all possible events
00494     eIt = fullAlphabet.Begin();
00495     for(; eIt != eEndIt; eIt++){
00496       // if the event is not observable, the specification and the plant can evolve independently
00497       if(obsEvents.Exists(*eIt) == false){
00498         tIt = rSpec.TransRelBegin(currentState.second.mSpec1State,*eIt);
00499         // transition in Spec1 exists
00500         if(tIt != rSpec.TransRelEnd(currentState.second.mSpec1State,*eIt) ){
00501           if(currentState.second.mLabel == NORMAL ){ // transition in spec1 from normal state
00502             newVerifierState = VerifierState(tIt->X2, currentState.second.mSpec2State, currentState.second.mPlantState, NORMAL);
00503           }
00504           else // transition in spec1 from confused state
00505             newVerifierState = VerifierState(tIt->X2, currentState.second.mSpec2State, currentState.second.mPlantState, CONFUSED);
00506           // check if the new VerifierState already exist snd insert new transitions (rule 1 and 4)
00507           vsIt = verifierToStateMap.find(newVerifierState);
00508           // a new state is inserted into the verifier
00509           if(vsIt == verifierToStateMap.end() ){
00510             newState = verifier.InsState();
00511             //verifierTest.InsState(newState);
00512             verifier.SetTransition(currentState.first,nullEvent,newState);
00513             //verifierTest.SetTransition(currentState.first,*eIt,newState);
00514             verifierToStateMap[newVerifierState] = newState;
00515             stateToVerifierMap[newState] = newVerifierState;
00516             if(doneStates.Exists(newState) == false)
00517               waitingStates.push(make_pair(newState,newVerifierState) );
00518           }
00519           // a transition to the existing state is added
00520           else{
00521             //verifierTest.SetTransition(currentState.first,*eIt,vsIt->second);
00522             verifier.SetTransition(currentState.first,nullEvent,vsIt->second);
00523             
00524           }
00525         }
00526         tIt = rGen.TransRelBegin(currentState.second.mPlantState,*eIt);
00527         // transition in plant exists
00528         if(tIt != rGen.TransRelEnd(currentState.second.mPlantState,*eIt) ){
00529           X2 = tIt->X2;
00530           if(currentState.second.mLabel == CONFUSED)
00531             newVerifierState = VerifierState(currentState.second.mSpec1State, currentState.second.mSpec2State, X2, CONFUSED);
00532           else{ // current state is NORMAL
00533             tIt = rSpec.TransRelBegin(currentState.second.mSpec2State,*eIt); 
00534             if(tIt == rSpec.TransRelEnd(currentState.second.mSpec2State,*eIt) ){ // violation of the specification
00535               newVerifierState = VerifierState(currentState.second.mSpec1State, currentState.second.mSpec2State, X2, CONFUSED);
00536             }
00537             else{ // correct behavior
00538               newVerifierState = VerifierState(currentState.second.mSpec1State, tIt->X2, X2, NORMAL);
00539             }
00540           }
00541           // check if a new state has to be inserted into the verifier a
00542           vsIt = verifierToStateMap.find(newVerifierState);
00543           // a new state is inserted into the verifier
00544           if(vsIt == verifierToStateMap.end() ){
00545             newState = verifier.InsState();
00546             //verifierTest.InsState(newState);
00547             verifierToStateMap[newVerifierState] = newState;
00548             stateToVerifierMap[newState] = newVerifierState;
00549             if(doneStates.Exists(newState) == false)
00550               waitingStates.push(make_pair(newState,newVerifierState) );
00551           }
00552           else  
00553             newState = vsIt->second;
00554           // new transition in the verifier
00555           if(newVerifierState.mLabel == NORMAL || (currentState.second.mLabel == CONFUSED && newVerifierState.mPlantState == currentState.second.mPlantState) ){ // normal behavior or confused behavior extended in the specification (rule 3 or 4)
00556             //verifierTest.SetTransition(currentState.first,*eIt,newState);
00557             verifier.SetTransition(currentState.first,nullEvent,newState);
00558           }
00559           else{ // faulty behavior extended in the plant (rule 5)
00560             //verifierTest.SetTransition(currentState.first,*eIt,newState);
00561             verifier.SetTransition(currentState.first,negEvent,newState);
00562           }
00563         }
00564       }// (obsEvents.Exists(*eIt) == false)
00565       else{
00566         TransSet::Iterator plantIt, specIt;
00567         Idx eventIdx;
00568         tIt = rSpec.TransRelBegin(currentState.second.mSpec1State, *eIt);
00569         plantIt= rGen.TransRelBegin(currentState.second.mPlantState, *eIt);
00570         specIt = rSpec.TransRelBegin(currentState.second.mSpec2State, *eIt);
00571         if(tIt != rSpec.TransRelEnd(currentState.second.mSpec1State, *eIt) && plantIt != rGen.TransRelEnd(currentState.second.mPlantState, *eIt) ){ // event occurs in the potentially confused specification and in the plant
00572           if(currentState.second.mLabel == NORMAL && specIt != rSpec.TransRelEnd(currentState.second.mSpec2State, *eIt) ){ // no confusion (rule 6)
00573             newVerifierState = VerifierState(tIt->X2, specIt->X2, plantIt->X2, NORMAL);
00574             eventIdx = nullEvent;
00575           }
00576           else if(currentState.second.mLabel == NORMAL){// faulty behavior occurs (rule 7)
00577             newVerifierState = VerifierState(tIt->X2, currentState.second.mSpec2State, plantIt->X2, CONFUSED);
00578             eventIdx = negEvent;
00579           }
00580           else{ // there is already confusion (rule 8)
00581             newVerifierState = VerifierState(tIt->X2, currentState.second.mSpec2State, plantIt->X2, CONFUSED);
00582             eventIdx = negEvent;
00583           }
00584           // check if a new state has to be inserted into the verifier a
00585           vsIt = verifierToStateMap.find(newVerifierState);
00586           // a new state is inserted into the verifier
00587           if(vsIt == verifierToStateMap.end() ){
00588             newState = verifier.InsState();
00589             //verifierTest.InsState(newState);
00590             verifierToStateMap[newVerifierState] = newState;
00591             stateToVerifierMap[newState] = newVerifierState;
00592             if(doneStates.Exists(newState) == false)
00593               waitingStates.push(make_pair(newState,newVerifierState) );
00594           }
00595           else  
00596             newState = vsIt->second;    
00597 
00598           // update the verifier
00599           //verifierTest.SetTransition(currentState.first,*eIt,newState);
00600           verifier.SetTransition(currentState.first,eventIdx,newState);
00601         }
00602       }
00603     }
00604     // check if the Block state is reachable 
00605     if(rGen.TransRelBegin(currentState.second.mPlantState) == rGen.TransRelEnd(currentState.second.mPlantState) && currentState.second.mLabel == CONFUSED){
00606       blockingState = verifier.InsMarkedState();
00607       verifier.SetTransition(currentState.first,nullEvent,blockingState);
00608       //verifierTest.InsMarkedState(blockingState);
00609       //verifierTest.SetTransition(currentState.first,nullEvent,blockingState);
00610       FD_DD("Blocking State Reachable");
00611       block = true;
00612     }
00613   }
00614   #ifdef FAUDES_DEBUG_DIAGNOSIS
00615   verifier.GraphWrite("data/verifier.png");
00616   #endif 
00617   //verifierTest.GraphWrite("data/verifierTest.png");
00618   // Seach for cycles with "-1"-transitions (negEvent) in the verifier
00619   list<StateSet> sccList;
00620   StateSet rootSet;
00621   // compute the strongly connected components in the verifier
00622   ComputeScc(verifier,sccList,rootSet);
00623   // Check if there is a "-1"-transition in any of the SCCs
00624   list<StateSet>::const_iterator sccIt, sccEndIt;
00625   sccIt = sccList.begin();
00626   sccEndIt = sccList.end();
00627   StateSet::Iterator stIt, stEndIt;
00628   bool existsCycle = false;
00629   for( ; sccIt != sccEndIt; sccIt++){
00630 #ifdef FAUDES_DEBUG_DIAGNOSIS
00631     sccIt->Write();
00632 #endif
00633     stIt = sccIt->Begin();
00634     stEndIt = sccIt->End();
00635     for(; stIt != stEndIt; stIt++){// check all states in the SCC
00636       tIt = verifier.TransRelBegin(*stIt, negEvent);
00637       if(tIt != verifier.TransRelEnd(*stIt, negEvent) && sccIt->Exists(tIt->X2) ){ // there is a transition with negEvent within the SCC
00638         FD_DD("Confused Cycle Found");
00639         existsCycle = true;
00640         break;
00641       }
00642     }
00643     if(existsCycle == true)
00644       break;
00645   }
00646   if(block == true || existsCycle == true)
00647     return false;
00648   else
00649     return true;
00650 }
00651 
00652 //IsLoopPreservingObserver()
00653 bool IsLoopPreservingObserver(const cGenerator& rGen, const EventSet& rHighAlph){
00654   cGenerator genCopy;
00655   TransSet::Iterator tit;
00656   string report;
00657   FD_DD("IsLoopPreservingObserver()");
00658   genCopy = rGen;
00659   genCopy.InjectMarkedStates(genCopy.States() );
00660   // Verify if the observer condition is fulfilled
00661   if(IsObs(genCopy,rHighAlph)  == false){ 
00662     FD_DD("Observer Condition violated");
00663     return false;
00664   }
00665   FD_DD("Observer Condition fulfilled");
00666   // Verify if there are loops with abstracted events
00667   // delete all transitions that do not belong to local high-alphabet
00668   for (tit = genCopy.TransRelBegin(); tit != genCopy.TransRelEnd();) {
00669     if (rHighAlph.Exists(tit->Ev)) 
00670       tit=genCopy.ClrTransition(tit);    
00671     else 
00672       ++tit;
00673   }
00674   // search for cycles in remainder automaton
00675   std::list<StateSet> sccList;
00676   StateSet sccRoots;
00677   ComputeScc(genCopy,sccList,sccRoots);
00678   std::list<StateSet>::const_iterator sIt = sccList.begin();
00679   for( ; sIt != sccList.end(); sIt++){
00680     if(sIt->Size() > 1){
00681       #ifdef FAUDES_DEBUG_DIAGNOSIS
00682       cout << "Bad states that form a cycle with abstracted events: " << endl;
00683       StateSet::Iterator stIt = sIt->Begin();
00684       for(; stIt != sIt->End(); stIt++)
00685         cout << *stIt << " ";
00686       cout << endl;
00687       #endif
00688       return false;
00689     }
00690   }
00691   return true;
00692 }
00693 
00694 //IsLoopPreservingObserver()
00695 void IsLoopPreservingObserver(const cGenerator& rGen, const EventSet& rHighAlph, bool& rRes){
00696   rRes = IsLoopPreservingObserver(rGen,rHighAlph);
00697 }
00698 
00699 void ComputeLoopPreservingObserver(const cGenerator& rGen, const EventSet& rInitialHighAlph, EventSet& rHighAlph){
00700   // Verify if the projection with the given initial alphabet is already a loop-preserving observer
00701   rHighAlph = rInitialHighAlph;
00702         rHighAlph.Name("HiAlph");
00703   FD_DD("ComputeLoopPreservingObserver()");
00704   if(IsLoopPreservingObserver(rGen,rHighAlph) == true)
00705     return;
00706     
00707   // check all combinations of events from the difference set 
00708   EventSet diffSet = rGen.Alphabet() - rHighAlph;
00709   EventSet::Iterator eIt = diffSet.Begin();
00710   std::vector<Idx> diffVector;
00711   for( ; eIt != diffSet.End(); eIt++) // ordered list of events in the diffSet
00712     diffVector.push_back(*eIt);
00713     
00714   for(Idx numberEvents = 1; numberEvents <= diffVector.size(); numberEvents++){// number events that are chosen in this step
00715     FD_DD("numberEvents: " + ToStringInteger(numberEvents));
00716     Idx currentNumberEvents = 1; // number of events under investigation
00717     Idx currentLocation = 0; // start position for the search for new events
00718     EventSet chosenEvents;
00719     if(rec_ComputeLoopPreservingObserver(rGen,rInitialHighAlph,rHighAlph,diffVector,numberEvents,currentNumberEvents,currentLocation,chosenEvents) == true)
00720       break;
00721   }
00722         // fix name
00723         rHighAlph.Name("HiAlph");
00724 }
00725 
00726 // rec_ComputeLoopPreservingObserver(rGen,
00727 bool rec_ComputeLoopPreservingObserver(const cGenerator& rGen, const EventSet& rInitialHighAlph, EventSet& rHighAlph, const std::vector<Idx>& rDiffVector, Idx numberEvents, Idx currentNumberEvents, Idx currentLocation, EventSet chosenEvents){
00728   FD_DD("rec_ComputeLoopPreservingObserver()");
00729   bool valid;
00730   for(Idx i = currentLocation; i < rDiffVector.size(); i++){
00731     FD_DD("currentNumberEvents: " + ToStringInteger(currentNumberEvents) + "currentLocation: " + ToStringInteger(i) + " event: " + SymbolTable::GlobalEventSymbolTablep()->Symbol(rDiffVector[i]));
00732     chosenEvents.Insert(rDiffVector[i]);
00733     rHighAlph = rInitialHighAlph + chosenEvents;
00734     if(currentNumberEvents == numberEvents){// enough events found
00735       valid = IsLoopPreservingObserver(rGen,rHighAlph);
00736       if(valid == true){
00737         return true;
00738       }
00739     }
00740     else if(rDiffVector.size() - 1 - i < numberEvents - currentNumberEvents){ // not enough events left to find numberEvents 
00741       return false;
00742     }
00743     else{// go to the next level to add events
00744       FD_DD("currentLevel: " + ToStringInteger(i));
00745       valid = rec_ComputeLoopPreservingObserver(rGen,rInitialHighAlph,rHighAlph,rDiffVector,numberEvents,currentNumberEvents + 1,i + 1, chosenEvents);
00746       if(valid == true){
00747         return true;
00748       }
00749     }
00750     chosenEvents.Erase(rDiffVector[i]);
00751   }
00752   return false;
00753 }
00754 
00755 } // namespace faudes

libFAUDES 2.14g --- 2009-12-3 --- c++ source docu by doxygen 1.5.6