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