diag_decentralizeddiagnosis.cppGo 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 |