diag_decentralizeddiagnosis.cpp

Go to the documentation of this file.
00001 /** @file diag_decentralizeddiagnosis.cpp Functions to test decentralized diagnosability and compute diagnosers.
00002 */
00003 
00004 /*
00005 
00006 Copyright Tobias Barthel, Klaus Schmidt, Thomas Moor
00007 
00008 */
00009 
00010 #include "diag_decentralizeddiagnosis.h"
00011 
00012 
00013 using namespace std;
00014 
00015 namespace faudes {
00016 
00017 ///////////////////////////////////////////////////////////////////////////////
00018 // Functions for decentralized diagnosability (co-diagnosability)
00019 ///////////////////////////////////////////////////////////////////////////////
00020 
00021 
00022 
00023 // IsCoDiagnosable()
00024 bool IsCoDiagnosable(const System& rGen, const Generator& rSpec, const vector<const EventSet*>& rAlphabets, std::string& rReportString) {
00025   
00026   FD_DD("IsCoDiagnosable()");
00027 
00028   // clear report
00029   rReportString.clear();
00030   EventSet obsEvents = rGen.ObservableEvents();
00031 #ifdef FAUDES_DEBUG_DIAGNOSIS
00032   obsEvents.DWrite();
00033 #endif
00034   Generator verifier; // Graph for co-diagnosability verification
00035   Idx nullEvent = verifier.InsEvent("nullEvent"); // event that corresponds to the value 0
00036   Idx negEvent = verifier.InsEvent("negEvent"); // event that corresponds to the value -1 
00037   Generator verifierTest; // verifier with eeent information
00038   verifierTest.InjectAlphabet(rGen.Alphabet() ); // FIXME remove this. 
00039   verifierTest.InsEvent(nullEvent);
00040   map<Idx, CoVerifierState> stateToVerifierMap;
00041   map<CoVerifierState, Idx> verifierToStateMap;
00042   stack<pair<Idx, CoVerifierState> > waitingStates;
00043   StateSet doneStates;
00044   // initialize the algorithm 
00045   EventSet fullAlphabet = rGen.Alphabet();
00046   EventSet::Iterator eIt, eEndIt;
00047   eEndIt = fullAlphabet.End();
00048   Idx newState = verifier.InsInitState();
00049   verifierTest.InsInitState(newState);
00050   CoVerifierState newVerifierState = CoVerifierState(rAlphabets.size(), rSpec.InitState(), rGen.InitState(),NORMAL);
00051   for(Idx i = 0; i < rAlphabets.size(); i++) // all decentralized versions of the specification are initialized
00052     newVerifierState.mSpec1State[i] = rSpec.InitState();
00053     
00054   stateToVerifierMap[newState] = newVerifierState;
00055   verifierToStateMap[newVerifierState ] = newState;
00056   waitingStates.push(make_pair(newState, newVerifierState) );
00057   // extend the verifier graph until no new nodes can be added
00058   pair<Idx, CoVerifierState> currentState;
00059   Idx blockingState; // = verifier.InsMarkedState();
00060   TransSet::Iterator tIt;
00061   map<CoVerifierState, Idx>::const_iterator vsIt;
00062   Idx X2;
00063   bool block = false; // set to true if the BLOCK state is reachable  
00064   FD_DD("Main loop");
00065   while(waitingStates.empty() == false){
00066     // take the first element from the stack
00067     currentState = waitingStates.top();
00068     waitingStates.pop();
00069     doneStates.Insert(currentState.first);
00070     #ifdef FAUDES_DEBUG_DIAGNOSIS
00071     std::cout << "currentState: " << ToStringInteger(currentState.first) <<  " VerifierState: (";
00072     for(unsigned k = 0; k < currentState.second.mSpec1State.size(); k++)
00073       cout << rSpec.StateName(currentState.second.mSpec1State.at(k)) << " ";
00074     cout << rSpec.StateName(currentState.second.mSpec2State) << " " << rGen.StateName(currentState.second.mPlantState) << " " << currentState.second.mLabel << ")" << endl;
00075     #endif
00076     // go over all possible events
00077     eIt = fullAlphabet.Begin();
00078     for(; eIt != eEndIt; eIt++){
00079       // if the event is not observable, the specifications and the plant can evolve independently
00080       if(obsEvents.Exists(*eIt) == false){
00081         for(Idx i = 0; i < rAlphabets.size(); i++){
00082           tIt = rSpec.TransRelBegin(currentState.second.mSpec1State.at(i),*eIt);
00083           // transition in decentralized version of Spec for component i exists
00084           if(tIt != rSpec.TransRelEnd(currentState.second.mSpec1State.at(i),*eIt) ){
00085             newVerifierState = CoVerifierState(rAlphabets.size(), currentState.second.mSpec2State, currentState.second.mPlantState, NORMAL);
00086             for(Idx j = 0; j < rAlphabets.size(); j++){ // determine new verifier state
00087               if(j == i)
00088                 newVerifierState.mSpec1State[j] = tIt->X2;
00089               else
00090                 newVerifierState.mSpec1State[j] = currentState.second.mSpec1State.at(j);
00091             }
00092             if(currentState.second.mLabel == CONFUSED ) // transition in spec1 from normal state// transition in spec1 from confused state
00093               newVerifierState.mLabel = CONFUSED;
00094             // check if the new VerifierState already exist snd insert new transitions (rule 1 and 4)
00095 
00096             vsIt = verifierToStateMap.find(newVerifierState);
00097             // a new state is inserted into the verifier
00098             if(vsIt == verifierToStateMap.end() ){
00099       
00100               newState = verifier.InsState();
00101               verifierTest.InsState(newState);
00102               verifier.SetTransition(currentState.first,nullEvent,newState);
00103               verifierTest.SetTransition(currentState.first,*eIt,newState);
00104               verifierToStateMap[newVerifierState] = newState;
00105               stateToVerifierMap[newState] = newVerifierState;
00106               if(doneStates.Exists(newState) == false)
00107                 waitingStates.push(make_pair(newState,newVerifierState) );
00108             }
00109             // a transition to the existing state is added
00110             else{
00111               verifierTest.SetTransition(currentState.first,*eIt,vsIt->second);
00112               verifier.SetTransition(currentState.first,nullEvent,vsIt->second);
00113               
00114             }
00115           }
00116         }// for(Idx i = 0...
00117         tIt = rGen.TransRelBegin(currentState.second.mPlantState,*eIt);
00118         // transition in plant exists
00119         if(tIt != rGen.TransRelEnd(currentState.second.mPlantState,*eIt) ){
00120           X2 = tIt->X2;
00121           newVerifierState = CoVerifierState(rAlphabets.size(), currentState.second.mSpec2State, X2, NORMAL); // prepare the new verifier state
00122           newVerifierState.mSpec1State = currentState.second.mSpec1State;
00123           if(currentState.second.mLabel == CONFUSED)
00124             newVerifierState.mLabel = CONFUSED;
00125           else{ // current state is NORMAL
00126             tIt = rSpec.TransRelBegin(currentState.second.mSpec2State,*eIt); 
00127             if(tIt == rSpec.TransRelEnd(currentState.second.mSpec2State,*eIt) ){ // violation of the specification
00128               newVerifierState.mLabel = CONFUSED;
00129             }
00130             else{ // correct behavior
00131               newVerifierState.mSpec2State = tIt->X2;
00132             }
00133           }
00134           // check if a new state has to be inserted into the verifier
00135           vsIt = verifierToStateMap.find(newVerifierState);
00136           // a new state is inserted into the verifier
00137           if(vsIt == verifierToStateMap.end() ){
00138             newState = verifier.InsState();
00139             verifierTest.InsState(newState);
00140             verifierToStateMap[newVerifierState] = newState;
00141             stateToVerifierMap[newState] = newVerifierState;
00142             if(doneStates.Exists(newState) == false)
00143               waitingStates.push(make_pair(newState,newVerifierState) );
00144           }
00145           else  
00146             newState = vsIt->second;
00147           // new transition in the verifier
00148           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)
00149             verifierTest.SetTransition(currentState.first,*eIt,newState);
00150             verifier.SetTransition(currentState.first,nullEvent,newState);
00151           }
00152           else{ // faulty behavior extended in the plant (rule 5)
00153             verifierTest.SetTransition(currentState.first,*eIt,newState);
00154             verifier.SetTransition(currentState.first,negEvent,newState);
00155           }
00156         }
00157       }// (obsEvents.Exists(*eIt) == false)
00158       else{
00159         CoVerifierState unobsVerifierState; // new verifier state in case of unobservable events
00160         bool allSpecsParticipate = true; // indicates if the plant can proceed together with all specs that have the current event
00161         TransSet::Iterator plantIt, specIt;
00162         plantIt= rGen.TransRelBegin(currentState.second.mPlantState, *eIt);
00163         specIt = rSpec.TransRelBegin(currentState.second.mSpec2State, *eIt);
00164         if(plantIt != rGen.TransRelEnd(currentState.second.mPlantState, *eIt) ){// there plant has a transition with *eIt
00165           // the new state is confused 
00166           if(specIt == rSpec.TransRelEnd(currentState.second.mSpec2State, *eIt) || currentState.second.mLabel == CONFUSED){
00167             newVerifierState = CoVerifierState(rAlphabets.size(), currentState.second.mSpec2State, plantIt->X2, CONFUSED);
00168           }
00169           else{// the new state is normal (spec follows plant)
00170             newVerifierState = CoVerifierState(rAlphabets.size(), specIt->X2, plantIt->X2, NORMAL);
00171           }
00172           // the state only exists if all specifications that observe *eIt can follow
00173           for(unsigned int i = 0; i < rAlphabets.size(); i++){
00174             if(rAlphabets.at(i)->Exists(*eIt) == true){ // check if transition exists
00175               tIt = rSpec.TransRelBegin(currentState.second.mSpec1State.at(i), *eIt);
00176               if(tIt == rSpec.TransRelEnd(currentState.second.mSpec1State.at(i), *eIt) ){
00177                 allSpecsParticipate = false; // this subsystem can detect that there is a deviationfrom the specification
00178                 break;
00179               }
00180               else{ // execute the transition in the respective specification
00181                 newVerifierState.mSpec1State[i] = tIt->X2;
00182               }
00183             }
00184             else
00185               newVerifierState.mSpec1State[i] = currentState.second.mSpec1State.at(i);
00186           }
00187           if(allSpecsParticipate == true){ // a new state has to be inserted in the verifier
00188             // check if a new state has to be inserted into the verifier
00189             vsIt = verifierToStateMap.find(newVerifierState);
00190             // a new state is inserted into the verifier
00191             if(vsIt == verifierToStateMap.end() ){
00192               newState = verifier.InsState();
00193               verifierTest.InsState(newState);
00194               verifierToStateMap[newVerifierState] = newState;
00195               stateToVerifierMap[newState] = newVerifierState;
00196               if(doneStates.Exists(newState) == false)
00197                 waitingStates.push(make_pair(newState,newVerifierState) );
00198             }
00199             else  
00200               newState = vsIt->second;
00201             // new transition in the verifier
00202             if(newVerifierState.mLabel == NORMAL){ // normal behavior 
00203               verifierTest.SetTransition(currentState.first,*eIt,newState);
00204               verifier.SetTransition(currentState.first,nullEvent,newState);
00205             }
00206             else{ // faulty behavior extended in the plant and unnoticed by the specification
00207               verifierTest.SetTransition(currentState.first,*eIt,newState);
00208               verifier.SetTransition(currentState.first,negEvent,newState);
00209             }           
00210           }
00211         }
00212         // go through all specifications and execute locally unobservable transitions
00213         for(unsigned int i = 0; i < rAlphabets.size(); i++){
00214           if(rAlphabets.at(i)->Exists(*eIt) == false){
00215             tIt = rSpec.TransRelBegin(currentState.second.mSpec1State.at(i), *eIt);
00216             if(tIt != rSpec.TransRelEnd(currentState.second.mSpec1State.at(i), *eIt) ){
00217               newVerifierState = currentState.second;
00218               newVerifierState.mSpec1State[i] = tIt->X2;
00219               // check if a new state has to be inserted into the verifier
00220               vsIt = verifierToStateMap.find(newVerifierState);
00221               // a new state is inserted into the verifier
00222               if(vsIt == verifierToStateMap.end() ){
00223                 newState = verifier.InsState();
00224                 verifierTest.InsState(newState);
00225                 verifierToStateMap[newVerifierState] = newState;
00226                 stateToVerifierMap[newState] = newVerifierState;
00227                 if(doneStates.Exists(newState) == false)
00228                   waitingStates.push(make_pair(newState,newVerifierState) );
00229               }
00230               else  
00231                 newState = vsIt->second;
00232 
00233               verifierTest.SetTransition(currentState.first,*eIt,newState);
00234               verifier.SetTransition(currentState.first,nullEvent,newState);
00235             }
00236           }
00237         }
00238       }
00239     }// for(; *eIt ...)
00240     // check if the Block state is reachable 
00241     if(rGen.TransRelBegin(currentState.second.mPlantState) == rGen.TransRelEnd(currentState.second.mPlantState) && currentState.second.mLabel == CONFUSED){
00242       blockingState = verifier.InsMarkedState();
00243       verifier.SetTransition(currentState.first,nullEvent,blockingState);
00244       verifierTest.InsMarkedState(blockingState);
00245       verifierTest.SetTransition(currentState.first,nullEvent,blockingState);
00246       FD_DD("Blocking State Reachable");
00247       block = true;
00248     }
00249   } // while(waiting...)
00250   #ifdef FAUDES_DEBUG_DIAGNOSIS
00251   if(verifier.Size() < 200){
00252     verifier.GraphWrite("data/verifier.png");
00253     verifierTest.GraphWrite("data/verifierTest.png");
00254   }
00255   #endif 
00256   //verifierTest.GraphWrite("data/verifierTest.png");
00257   // Seach for cycles with "-1"-transitions (negEvent) in the verifier
00258   list<StateSet> sccList;
00259   StateSet rootSet;
00260   // compute the strongly connected components in the verifier
00261   ComputeScc(verifier,sccList,rootSet);
00262   // Check if there is a "-1"-transition in any of the SCCs
00263   list<StateSet>::const_iterator sccIt, sccEndIt;
00264   sccIt = sccList.begin();
00265   sccEndIt = sccList.end();
00266   StateSet::Iterator stIt, stEndIt;
00267   bool existsCycle = false;
00268   for( ; sccIt != sccEndIt; sccIt++){
00269 #ifdef FAUDES_DEBUG_DIAGNOSIS
00270     sccIt->Write();
00271 #endif
00272     stIt = sccIt->Begin();
00273     stEndIt = sccIt->End();
00274     for(; stIt != stEndIt; stIt++){// check all states in the SCC
00275       tIt = verifier.TransRelBegin(*stIt, negEvent);
00276       if(tIt != verifier.TransRelEnd(*stIt, negEvent) && sccIt->Exists(tIt->X2) ){ // there is a transition with negEvent within the SCC
00277         FD_DD("Confused Cycle Found");
00278         existsCycle = true;
00279         break;
00280       }
00281     }
00282     if(existsCycle == true)
00283       break;
00284   }
00285   if(block == true || existsCycle == true)
00286     return false;
00287   else
00288     return true;
00289 }
00290 
00291 
00292 // DecentralizedDiagnoser(rGsubs, rKsubs, rDiagsubs, rReportString)
00293 bool DecentralizedDiagnoser(const System& rGen, const Generator& rSpec, const std::vector<const EventSet*>& rAlphabets, std::vector<Diagnoser*>& rDiags, std::string& rReportString){
00294   
00295   FD_DD("DecentralizedDiagnoser()");
00296   System copyGen = rGen;
00297   rDiags.clear();
00298   Diagnoser *newGen;
00299   // clear report
00300   rReportString.clear();
00301   // Verify Codiagnosability
00302   bool diagnosable = IsCoDiagnosable(rGen,rSpec,rAlphabets,rReportString);
00303   // Compute diagnoser for each local site
00304   for(unsigned int i = 0; i < rAlphabets.size(); i++){
00305     // modify observable events of copyGen according to the local observation
00306     copyGen.ClrObservable(copyGen.Alphabet() );
00307     copyGen.SetObservable(*rAlphabets.at(i) );
00308     newGen = new Diagnoser;
00309     rDiags.push_back(newGen );
00310     LanguageDiagnoser(copyGen,rSpec,*rDiags[i]);
00311   }
00312 
00313   return diagnosable;
00314 }
00315 
00316 // DecentralizedDiagnoser(rGsubs, rKsubs, rDiagsubs, rReportString)
00317 void DecentralizedModularDiagnoser(const std::vector<const System*>& rGens, const Generator& rSpec, std::vector<Diagnoser*>& rDiags, std::string& rReportString){
00318   Generator projSpec;
00319   Diagnoser *newGen;
00320   // clear report
00321   rReportString.clear();
00322   // Compute diagnoser for each local site
00323   for(unsigned int i = 0; i < rGens.size(); i++){
00324     // generate local versioin of the specification
00325     Project(rSpec,rGens.at(i)->Alphabet(),projSpec);
00326     newGen = new Diagnoser;
00327     rDiags.push_back(newGen);
00328     LanguageDiagnoser(*rGens.at(i),projSpec,*rDiags[i]);
00329   }
00330 }
00331 
00332 ///////////////////////////////////////////////////////////////////////////////
00333 // RTI wrapper
00334 ///////////////////////////////////////////////////////////////////////////////
00335 
00336 // IsCoDiagnosable()
00337 bool IsCoDiagnosable(const System& rGen, const Generator& rSpec, const EventSetVector& rAlphabets){
00338   std::string ignore;
00339   // reorganize as std vector
00340   std::vector<const EventSet*> alphabets;
00341   Idx i; 
00342 
00343   for(i = 0; i < rAlphabets.Size(); ++i) 
00344     alphabets.push_back(&rAlphabets.At(i));
00345   return IsCoDiagnosable(rGen, rSpec, alphabets, ignore);
00346 }
00347 
00348 // DecentralizedDiagnoser()
00349 bool DecentralizedDiagnoser(const System& rGen, const Generator& rSpec, const EventSetVector& rAlphabets, GeneratorVector& rDiags){
00350   std::string ignore;
00351   // reorganize as std vector
00352   std::vector<const EventSet*> alphabets;
00353   std::vector<Diagnoser*> diags;
00354   Idx i; 
00355 
00356   for(i = 0; i < rAlphabets.Size(); ++i) 
00357     alphabets.push_back(&rAlphabets.At(i));
00358 
00359   bool ok = DecentralizedDiagnoser(rGen,rSpec,alphabets,diags,ignore);
00360   for(i = 0; i < rAlphabets.Size(); ++i)
00361   rDiags.Append(diags.at(i) );
00362   rDiags.TakeOwnership();
00363   
00364   return ok;
00365 }
00366 
00367 void DecentralizedModularDiagnoser(const SystemVector& rGens, const Generator& rSpec, GeneratorVector& rDiags){
00368   std::string ignore;
00369   // reorganize as std vector
00370   std::vector<const System*> generators;
00371   std::vector<Diagnoser*> diags;
00372   Idx i; 
00373 
00374   for(i = 0; i < rGens.Size(); ++i) 
00375     generators.push_back(&rGens.At(i));
00376 
00377   DecentralizedModularDiagnoser(generators,rSpec,diags,ignore);
00378   for(i = 0; i < rGens.Size(); ++i)
00379   rDiags.Append(diags.at(i) );
00380   rDiags.TakeOwnership();
00381 }
00382 
00383 
00384 
00385 } // namespace faudes

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