hio_functions.cppGo to the documentation of this file.00001 /** @file hio_functions.cpp Algorithms for hierarchical discrete event systems with inputs and outputs */ 00002 00003 /* Hierarchical IO Systems Plug-In for FAU Discrete Event Systems Library (libfaudes) 00004 00005 Copyright (C) 2006 Sebastian Perk 00006 Copyright (C) 2006 Thomas Moor 00007 Copyright (C) 2006 Klaus Schmidt 00008 00009 */ 00010 00011 // note: deterministic generators only 00012 00013 // todo: exceptions on invalid input data if FAUDES_CHECKED 00014 // todo: files eg: normal. cycles. hiotest. hiosynth. 00015 // todo: implement routines that check hio properties 00016 // todo: only use statenames if statenamesenabled (eg HioFreeInput) 00017 00018 // todo: other todos below 00019 00020 #include "hio_functions.h" 00021 #include "syn_include.h" 00022 00023 00024 namespace faudes { 00025 00026 00027 // This is Sebastian'y version of SupNorm with a special 00028 // marking of the result. It also uses a different order 00029 // of arguments 00030 00031 // SupNormSP(rL,rOAlph,rK,rResult) 00032 bool SupNormSP( 00033 Generator& rL, 00034 const EventSet& rOAlph, 00035 const Generator& rK, 00036 Generator& rResult) 00037 { 00038 FD_DF("SupNorm(" << rK.Name() << "," << rL.Name() << "," << rOAlph.Name() << ")"); 00039 00040 NormalityConsistencyCheck(rL,rOAlph,rK); 00041 00042 // prepare result 00043 rResult.Clear(); 00044 00045 //extract overall alphabet: 00046 EventSet allevents; 00047 allevents=rL.Alphabet(); 00048 00049 //extract alphabet of rK: 00050 EventSet Kevents=rK.Alphabet(); 00051 00052 // record name and marked states of rL 00053 std::string rLname=rL.Name(); 00054 StateSet rLmarked=rL.MarkedStates(); 00055 00056 // involved operations from cfl_regular.h operate on the marked 00057 // languages -> turn generated languages into marked langs 00058 rL.InjectMarkedStates(rL.States()); 00059 Generator prK=rK; 00060 prK.InjectMarkedStates(prK.States()); 00061 rResult = prK; 00062 00063 // calculate "L-K" (ToDo: use LanguageDifference): 00064 LanguageComplement(rResult); 00065 FD_DF("SupNorm: size of complement(K): "<<rResult.Size()<<",marked: "<<rResult.MarkedStatesSize()); 00066 Generator tempgen; 00067 LanguageIntersection(rL, rResult, tempgen); 00068 rResult.Clear(); 00069 FD_DF("SupNorm: sizeof L U complement(K)=L-K: "<<tempgen.Size()); 00070 00071 // calculate Pinv(P(L-K)): 00072 Project(tempgen,rOAlph,rResult); 00073 tempgen.Clear(); 00074 FD_DF("SupNorm: sizeof p(L-K): "<< rResult.Size()); 00075 InvProject(rResult,allevents); 00076 FD_DF("SupNorm: sizeof pinv(p(L-K)): "<<rResult.Size()); 00077 00078 // FD_DF("SupNorm: sizeof pinv(p(L-K)): "<<rResult.Size()); 00079 00080 //calculate remaining set difference -> supnorm(K) 00081 LanguageComplement(rResult); 00082 LanguageIntersection(prK, rResult, tempgen); 00083 rResult=tempgen; 00084 tempgen.Clear(); 00085 FD_DF("SupNorm: sizeof K - pinv(p(L-K)) (result): "<<rResult.Size()); 00086 00087 // language MARKED by rResult is the result -> remove blocking states, mark all remaining states. 00088 rResult.Trim(); 00089 rResult.InjectMarkedStates(rResult.States()); 00090 00091 // restore original rL 00092 rL.Name(rLname); 00093 rL.InjectMarkedStates(rLmarked); 00094 00095 return !( rResult.InitStatesEmpty() ); 00096 } 00097 00098 00099 00100 00101 00102 00103 // CompleteSynth(rPlant,rCAlph,rSpec,rClosedLoop) 00104 bool CompleteSynth( 00105 const Generator& rPlant, 00106 const EventSet rCAlph, 00107 const Generator& rSpec, 00108 Generator& rClosedLoop) { 00109 FD_DF("CompleteSynth(" << rPlant.Name() << "," << rSpec.Name()<< ")"); 00110 00111 // prepare result 00112 rClosedLoop.Clear(); 00113 00114 //check for trivial result 00115 if(rSpec.InitStatesEmpty()){ 00116 FD_DF("CompleteSynth::empty language specification: empty closed loop."); 00117 rClosedLoop.Name("CompeleteSynth("+rPlant.Name()+", "+rSpec.Name()+")"); 00118 return false; 00119 } 00120 00121 // spec as candidate for closed loop 00122 Generator ClosedLoopCand=rSpec; 00123 00124 // iterate supcon and dead end elimination 00125 while(true) { 00126 // try std synthesis 00127 FD_DF("CompleteSynth:: spec size " << ClosedLoopCand.Size()); 00128 00129 // try SupCon 00130 SupConClosed(rPlant, rCAlph, ClosedLoopCand, rClosedLoop); 00131 //std::cout<<std::endl<<"CompleteSynth:: current result after SupCon: tmp_ContLoop.gen"; 00132 FD_DF("CompleteSynth: size of current result after SupCon: "<<rClosedLoop.Size()); 00133 //std::cout<<" (Size: "<<rClosedLoop.Size()<<")."; 00134 00135 //check for empty result 00136 if(rClosedLoop.InitStatesEmpty()) { 00137 FD_DF("CompleteSynth:: failed: empty language result."); 00138 rClosedLoop.StateNamesEnabled(false); 00139 rClosedLoop.Name("CompeleteSynth("+rPlant.Name()+", "+rSpec.Name()+")"); 00140 return false; 00141 } 00142 00143 FD_DF("CompleteSynth:: candidate size " << rClosedLoop.Size()); 00144 00145 // find dead ends and return success if no dead end found 00146 StateSet dead_ends=rClosedLoop.TerminalStates(rClosedLoop.AccessibleSet()); 00147 if(dead_ends.Empty()) { 00148 rClosedLoop.StateNamesEnabled(false); 00149 FD_DF("CompleteSynth:: done"); 00150 rClosedLoop.Name("CompeleteSynth("+rPlant.Name()+", "+rSpec.Name()+")"); 00151 return true; 00152 } 00153 00154 // report to console 00155 FD_DF("CompleteSynth:: eliminating following " << dead_ends.Size() << " dead ends"); 00156 FD_DF(rClosedLoop.StateSetToString(dead_ends)); 00157 00158 // eliminate dead ends. 00159 rClosedLoop.DelStates(dead_ends); 00160 // becomes new candidate for SupCon 00161 ClosedLoopCand=rClosedLoop; 00162 00163 //std::cout<<std::endl<<"CompleteSynth:: current result after Complete: tmp_CompleteLoop.gen"; 00164 FD_DF("CompleteSynth:: size of result after removing dead ends: "<<rClosedLoop.Size()); 00165 //std::cout<<" (Size: "<<rClosedLoop.Size()<<")."; 00166 00167 //check for empty result 00168 if(rClosedLoop.InitStatesEmpty()) { 00169 FD_DF("CompleteSynth:: failed: empty language result."); 00170 rClosedLoop.Name("CompeleteSynth("+rPlant.Name()+", "+rSpec.Name()+")"); 00171 return false; 00172 } 00173 rClosedLoop.Clear(); 00174 } 00175 } 00176 00177 // NormalCompleteSynth(rPlant,rCAlph,rOAlph,rSpec,rClosedLoop) 00178 bool NormalCompleteSynth( 00179 Generator& rPlant, 00180 const EventSet& rCAlph, 00181 const EventSet& rOAlph, 00182 const Generator& rSpec, 00183 Generator& rClosedLoop) 00184 { 00185 FD_DF("NormalCompleteSynth(" << rPlant.Name() << "," << rSpec.Name()<< ")"); 00186 00187 // prepare result 00188 rClosedLoop.Clear(); 00189 00190 // spec as candidate for closed loop 00191 Generator Spec=rSpec; 00192 00193 while(true) { 00194 00195 // try CompleteSynth and check for empty result: 00196 if(!CompleteSynth(rPlant,rCAlph,Spec,rClosedLoop)) { 00197 FD_DF("NormalCompleteSynth:: failed: empty result after CompleteSynth()."); 00198 std::cout<<std::endl<<"NormalCompleteSynth:: failed: empty result after CompleteSynth()."; 00199 rClosedLoop.Name("NormalCompleteSynth(" + rPlant.Name() + "," + rSpec.Name()+ ")"); 00200 return false; 00201 } 00202 00203 // check for normality and return on success 00204 if(IsNormal(rPlant,rOAlph,rClosedLoop)) { 00205 FD_DF("NormalCompleteSynth:: candidate supervisor is normal. success."); 00206 rClosedLoop.Name("NormalCompleteSynth(" + rPlant.Name() + "," + rSpec.Name()+ ")"); 00207 return true; 00208 } 00209 00210 // supremal normal sublanguage of rClosedLoop as new spec 00211 // return false on empty result 00212 FD_DF("NormalCompleteSynth:: candidate supervisor not normal. running SupNorm"); 00213 if(!SupNormSP(rPlant, rOAlph, rClosedLoop, Spec)) { 00214 FD_DF("NormalCompleteSynth:: failed: empty result after SupNorm()."); 00215 std::cout<<std::endl<<"NormalCompleteSynth:: failed: empty result after SupNorm()."; 00216 rClosedLoop.Clear(); 00217 rClosedLoop.Name("NormalCompleteSynth(" + rPlant.Name() + "," + rSpec.Name()+ ")"); 00218 return false; 00219 } 00220 00221 Spec.StateNamesEnabled(false); 00222 //std::cout<<std::endl<<"NormalCompleteSynth:: current result after SupNorm():"; 00223 //std::cout<<" Size: "<<Spec.Size()<<"."; 00224 FD_DF("NormalCompleteSynth:: size of result after SupNorm(): "<<Spec.Size()); 00225 } 00226 } 00227 00228 00229 // NormalCompleteSynthNB(rPlant,rCAlph,rOAlph,rSpec,rClosedLoop) 00230 bool NormalCompleteSynthNB( 00231 Generator& rPlant, 00232 const EventSet& rCAlph, 00233 const EventSet& rOAlph, 00234 const Generator& rSpec, 00235 Generator& rClosedLoop) 00236 { 00237 FD_DF("NormalCompleteSynth(" << rPlant.Name() << "," << rSpec.Name()<< ")"); 00238 00239 // prepare result 00240 rClosedLoop.Clear(); 00241 00242 // spec as candidate for closed loop 00243 Generator Spec=rSpec; 00244 while(true) { 00245 00246 // try NormalCompleteSynth and check for empty result: 00247 if(!NormalCompleteSynth(rPlant,rCAlph,rOAlph,Spec,rClosedLoop)) { 00248 FD_DF("NormalCompleteSynthNB:: failed: empty result after NormalCompleteSynth()."); 00249 std::cout<<std::endl<<"NormalCompleteSynthNB:: failed: empty result after NormalCompleteSynth()."; 00250 rClosedLoop.Name("NormalCompleteSynthNB(" + rPlant.Name() + "," + rSpec.Name()+ ")"); 00251 return false; 00252 } 00253 00254 // check for coaccessibility and return on success 00255 if(rClosedLoop.IsTrim()) { 00256 FD_DF("NormalCompleteSynthNB:: candidate supervisor is trim. success."); 00257 rClosedLoop.Name("NormalCompleteSynthNB(" + rPlant.Name() + "," + rSpec.Name()+ ")"); 00258 return true; 00259 } 00260 00261 // supremal nonblocking sublanguage of rClosedLoop as new Spec 00262 // return false on empty result 00263 FD_DF("NormalCompleteSynthNB:: candidate supervisor not Trim. running Trim()"); 00264 Spec=rClosedLoop; 00265 if(!Spec.Trim()) { 00266 FD_DF("NormalCompleteSynthNB:: failed: empty result after Trim()."); 00267 std::cout<<std::endl<<"NormalCompleteSynthNB:: failed: empty result after Trim()."; 00268 rClosedLoop.Clear(); 00269 rClosedLoop.Name("NormalCompleteSynthNB(" + rPlant.Name() + "," + rSpec.Name()+ ")"); 00270 return false; 00271 } 00272 //std::cout<<std::endl<<"NormalCompleteSynthNB:: current result after Trim():"; 00273 //std::cout<<" Size: "<<Spec.Size()<<"."; 00274 FD_DF("NormalCompleteSynthNB:: size of result after Trim():"<<Spec.Size()); 00275 } 00276 } 00277 00278 00279 // HioSortCL(const EventSet& rYc,rUc,rYp,rUP,rYe,rUe) 00280 Generator HioSortCL( 00281 const EventSet& rYc, 00282 const EventSet& rUc, 00283 const EventSet& rYp, 00284 const EventSet& rUp, 00285 const EventSet& rYe, 00286 const EventSet& rUe) 00287 { 00288 FD_DF("HioSortCL(...)"); 00289 00290 #ifdef FAUDES_CHECKED 00291 // check for nonempty sets 00292 if (rYc.Empty()||rUc.Empty()||rYp.Empty()||rUp.Empty()||rYe.Empty()||rUe.Empty()){ 00293 std::stringstream errstr; 00294 errstr << "At least one empty parameter."; 00295 throw Exception("HioSortCL", errstr.str(), 0); 00296 } 00297 #endif 00298 00299 // create resulting alphabet while checking for disjoint sets 00300 EventSet alphabet,errevents; 00301 // initialize with rYc 00302 alphabet.SetUnion(rYc); 00303 // insert remaining events one by one and check if new 00304 EventSet::Iterator evit; 00305 // rUc 00306 for (evit = rUc.Begin(); evit != rUc.End(); ++evit) { 00307 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 00308 } 00309 // rYp 00310 for (evit = rYp.Begin(); evit != rYp.End(); ++evit) { 00311 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 00312 } 00313 // rUp 00314 for (evit = rUp.Begin(); evit != rUp.End(); ++evit) { 00315 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 00316 } 00317 // rYe 00318 for (evit = rYe.Begin(); evit != rYe.End(); ++evit) { 00319 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 00320 } 00321 // rUe 00322 for (evit = rUe.Begin(); evit != rUe.End(); ++evit) { 00323 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 00324 } 00325 00326 #ifdef FAUDES_CHECKED 00327 // throw exception on non disjoint alphabets 00328 if (!errevents.Empty()){ 00329 std::stringstream errstr; 00330 errstr << "Non-disjoint parameters; ambiguous events:\n" <<errevents.ToString(); 00331 throw Exception("HioSortCL", errstr.str(), 0); 00332 } 00333 #endif 00334 00335 // create result 00336 Generator ResGen; 00337 00338 ResGen.Name("HioSortCL("+rYc.Name()+","+rUc.Name()+","+rYp.Name()+","+rUp.Name()+","+rYe.Name()+","+rUe.Name()+")"); 00339 00340 ResGen.InjectAlphabet(alphabet); 00341 alphabet.Clear(); 00342 00343 // 5 marked states with initial state 1: 00344 ResGen.InsInitState("Yp_or_Ye"); 00345 ResGen.SetMarkedState("Yp_or_Ye"); 00346 ResGen.InsMarkedState("Yc_or_Up"); 00347 ResGen.InsMarkedState("Uc"); 00348 ResGen.InsMarkedState("Up"); 00349 ResGen.InsMarkedState("Ue"); 00350 00351 // set transitions according to desired ioSorting structure: 00352 // all Yp-events lead from state 1 to state 2: 00353 for (evit = rYp.Begin(); evit != rYp.End(); ++evit) { 00354 ResGen.SetTransition("Yp_or_Ye",rYp.SymbolicName(*evit),"Yc_or_Up"); 00355 } 00356 // all Yc-events lead from state 2 to state 3: 00357 for (evit = rYc.Begin(); evit != rYc.End(); ++evit) { 00358 ResGen.SetTransition("Yc_or_Up",rYc.SymbolicName(*evit),"Uc"); 00359 } 00360 // all Uc-events lead from state 3 to state 4: 00361 for (evit = rUc.Begin(); evit != rUc.End(); ++evit) { 00362 ResGen.SetTransition("Uc",rUc.SymbolicName(*evit),"Up"); 00363 } 00364 // all Up-events lead from state 2 and 4 to state 1: 00365 for (evit = rUp.Begin(); evit != rUp.End(); ++evit) { 00366 ResGen.SetTransition("Yc_or_Up",rUp.SymbolicName(*evit),"Yp_or_Ye"); 00367 ResGen.SetTransition("Up",rUp.SymbolicName(*evit),"Yp_or_Ye"); 00368 } 00369 // all Ye-events lead from state 1 to state 5: 00370 for (evit = rYe.Begin(); evit != rYe.End(); ++evit) { 00371 ResGen.SetTransition("Yp_or_Ye",rYe.SymbolicName(*evit),"Ue"); 00372 } 00373 // all Ue-events lead from state 5 to state 1: 00374 for (evit = rUe.Begin(); evit != rUe.End(); ++evit) { 00375 ResGen.SetTransition("Ue",rUe.SymbolicName(*evit),"Yp_or_Ye"); 00376 } 00377 return ResGen; 00378 } 00379 00380 // HioFreeInput(rGen,rInput,rOutput,rResGen,rErrState1,rErrState2,rErrState1Idx,rErrState2Idx) 00381 void HioFreeInput( 00382 const Generator& rGen, 00383 const EventSet& rInput, 00384 const EventSet& rOutput, 00385 Generator& rResGen, 00386 const std::string& rErrState1, 00387 const std::string& rErrState2, 00388 Idx& rErrState1Idx, 00389 Idx& rErrState2Idx) { 00390 FD_DF("HioFreeInput( [generator] " << rGen.Name() << ")"); 00391 00392 Generator* pResGen = &rResGen; 00393 if(&rResGen== &rGen) { 00394 pResGen= rResGen.New(); 00395 } 00396 00397 #ifdef FAUDES_CHECKED 00398 // exception on empty Input-alphabet or non-disjoint Input and Output 00399 if(rInput.Empty() || !((rInput*rOutput).Empty())) { 00400 std::stringstream errstr; 00401 errstr << "Empty Input-alphabet or non-disjoint Input and Output.\n"; 00402 errstr << "Input: "<< rInput.ToString()<<"\n"; 00403 errstr << "Output: "<< rOutput.ToString()<<"\n"; 00404 errstr << "Input*Output: "<< (rInput*rOutput).ToString()<<"\n"; 00405 throw Exception("HioFreeInput", errstr.str(), 0); 00406 } 00407 #endif 00408 00409 // check for enabled state names: 00410 bool StateNamesEnabled = pResGen->StateNamesEnabled(); 00411 // Warning on inconsistency with error-state names 00412 if(!StateNamesEnabled && (!rErrState1.empty()||!rErrState2.empty())) { 00413 FD_WARN("HioFreeInput: state names disabled in rResGen: error state names ignored."); 00414 } 00415 00416 // prepare result, preserve StateNamesEnabled of rGen 00417 *pResGen=rGen; 00418 pResGen->StateNamesEnabled(StateNamesEnabled); 00419 pResGen->Name("HioFreeInput("+rGen.Name()+")"); 00420 00421 //create first error state, where inserted Input-events shall lead to: 00422 std::string errstate1; 00423 if(StateNamesEnabled) { 00424 errstate1=pResGen->UniqueStateName(rErrState1); 00425 rErrState1Idx=pResGen->InsMarkedState(errstate1); 00426 } 00427 else { 00428 rErrState1Idx=pResGen->InsMarkedState(); 00429 } 00430 00431 //find Input-states 00432 StateSet::Iterator sit=pResGen->StatesBegin(); 00433 EventSet::Iterator evit; 00434 bool InputInserted = false; 00435 for(;sit!=pResGen->StatesEnd();sit++){ 00436 EventSet disabledInput; 00437 disabledInput = rInput - pResGen->ActiveEventSet(*sit); 00438 //if at least one Input-event is enabled AND at least one Input-event is disabled: 00439 //insert missing Input-transitions to error state 00440 if( (disabledInput!=rInput) && !disabledInput.Empty()) { 00441 FD_DF("HioFreeInput: " << *sit << " disabledInput: " << disabledInput.ToString()); 00442 InputInserted = true; 00443 for (evit = disabledInput.Begin(); evit != disabledInput.End(); ++evit) { 00444 pResGen->SetTransition(*sit,*evit,rErrState1Idx); 00445 } 00446 } 00447 }//for-loop through states 00448 00449 //insert err_Input-state and connect both err-states with Input-Output-loop in case missing Input-events were inserted: 00450 if(InputInserted) { 00451 if(StateNamesEnabled) { 00452 FD_DF("HioFreeInput(...): inserted error state 1: " << errstate1 << " with Idx: " << rErrState1Idx); 00453 } 00454 else { 00455 FD_DF("HioFreeInput(...): inserted error state 1 with Idx: " << rErrState1Idx); 00456 } 00457 if(!rOutput.Empty()) { // this 'if' and the 'if' before are seperated because of the 'else' below ! 00458 //create second error state 00459 std::string errstate2; 00460 if(StateNamesEnabled) { 00461 errstate2=pResGen->UniqueStateName(rErrState2); 00462 rErrState2Idx=pResGen->InsMarkedState(errstate2); 00463 FD_DF("HioFreeInput(...): inserted error state 2: " << errstate2); 00464 } 00465 else { 00466 rErrState2Idx=pResGen->InsMarkedState(); 00467 FD_DF("HioFreeInput(...): inserted error state 2 with Idx: " << rErrState2Idx); 00468 } 00469 00470 //insert Input-events: 00471 for (evit = rInput.Begin(); evit != rInput.End(); ++evit) { 00472 pResGen->SetTransition(rErrState2Idx,*evit,rErrState1Idx); 00473 } 00474 //insert output-events: 00475 for (evit = rOutput.Begin(); evit != rOutput.End(); ++evit) { 00476 pResGen->SetTransition(rErrState1Idx,*evit,rErrState2Idx); 00477 } 00478 } 00479 } 00480 //else delete err_Output-state 00481 else { 00482 pResGen->DelState(rErrState1Idx); 00483 } 00484 // if necessary, move pResGen to rResGen 00485 if(pResGen != &rResGen) { 00486 pResGen->Move(rResGen); 00487 delete pResGen; 00488 } 00489 } 00490 00491 // HioFreeInput(rGen,rInput,rOutput,rResGen,rErrState1,rErrState2) 00492 void HioFreeInput( 00493 const Generator& rGen, 00494 const EventSet& rInput, 00495 const EventSet& rOutput, 00496 Generator& rResGen, 00497 const std::string& rErrState1, 00498 const std::string& rErrState2) { 00499 Idx errstate1,errstate2; 00500 HioFreeInput(rGen,rInput,rOutput,rResGen,rErrState1,rErrState2,errstate1,errstate2); 00501 } 00502 00503 // HioFreeInput(rGen,rInput,rOutput,rResGen) 00504 void HioFreeInput( 00505 const Generator& rGen, 00506 const EventSet& rInput, 00507 const EventSet& rOutput, 00508 Generator& rResGen) 00509 { 00510 //Call HioFreeInput with empty names for error states 00511 std::string ErrState1,ErrState2; 00512 HioFreeInput(rGen,rInput,rOutput,rResGen,ErrState1,ErrState2); 00513 } 00514 00515 // HioFreeInput(HioPlant,HioPlant) 00516 void HioFreeInput( 00517 const HioPlant& rPlant, 00518 HioPlant& rResPlant) 00519 { 00520 00521 FD_DF("HioFreeInput( [plant] " << rPlant.Name() << ")"); 00522 00523 // Call HioFreeInput with certain names for error state, 00524 // set Err-flag 00525 Idx errstateUp,errstateUe,errstate2; 00526 std::string ErrState1,ErrState2; 00527 00528 EventSet NoOutput,uP,uE,yP,yE; 00529 uP=rPlant.UpEvents(); 00530 uE=rPlant.UeEvents(); 00531 yP=rPlant.YpEvents(); 00532 yE=rPlant.YeEvents(); 00533 00534 ErrState1="UpError"; 00535 HioFreeInput(rPlant,uP,NoOutput,rResPlant,ErrState1,ErrState2,errstateUp,errstate2); 00536 00537 ErrState1="UeError"; 00538 HioFreeInput(rResPlant,uE,NoOutput,rResPlant,ErrState1,ErrState2,errstateUe,errstate2); 00539 00540 // set HioStateFlag Err 00541 if(rResPlant.ExistsState(errstateUp)) rResPlant.SetErr(errstateUp); 00542 if(rResPlant.ExistsState(errstateUe)) rResPlant.SetErr(errstateUe); 00543 00544 // restore event attributes 00545 rResPlant.SetYp(yP); 00546 rResPlant.SetUp(uP); 00547 rResPlant.SetYe(yE); 00548 rResPlant.SetUe(uE); 00549 00550 } 00551 00552 // HioFreeInput(HioController,HioController) 00553 void HioFreeInput( 00554 const HioController& rController, 00555 HioController& rResController) 00556 { 00557 FD_DF("HioFreeInput( [controller] " << rController.Name() << ")"); 00558 00559 HioController* pResController = &rResController; 00560 if(&rResController== &rController) { 00561 pResController=rResController.New(); 00562 } 00563 00564 // check for enabled state names: 00565 bool StateNamesEnabled = pResController->StateNamesEnabled(); 00566 00567 // prepare error state names 00568 std::string errStr1, errStr2; 00569 00570 // prepare error state indeces 00571 Idx errIdx1, errIdx2; 00572 00573 // prepare result, preserve StateNamesEnabled of rGen 00574 pResController->Assign(rController); 00575 //*pResController=rController; // didn't work (should work ... check!!) 00576 //pResController=&rController; // didn't work (cannot work anyway) 00577 pResController->StateNamesEnabled(StateNamesEnabled); 00578 pResController->Name("HioFreeInput("+rController.Name()+")"); 00579 00580 // figure input alphabets 00581 EventSet UcEvents = rController.UcEvents(); 00582 EventSet YpEvents = rController.YpEvents(); 00583 EventSet YcEvents = rController.YcEvents(); 00584 EventSet UpEvents = rController.UpEvents(); 00585 00586 //create first error state, where inserted Uc- or Yp-events shall lead to: 00587 if(StateNamesEnabled) { 00588 errStr1=pResController->UniqueStateName("UcYpError"); 00589 errIdx1=pResController->InsMarkedState(errStr1); 00590 } 00591 else { 00592 errIdx1=pResController->InsMarkedState(); 00593 } 00594 // set HioStateFlag Err 00595 pResController->SetErr(errIdx1); 00596 00597 // set state attribute QUp 00598 pResController->SetQUp(errIdx1); 00599 00600 //find Input-states 00601 StateSet::Iterator sit=pResController->StatesBegin(); 00602 EventSet::Iterator evit; 00603 bool InputInserted = false; 00604 for(;sit!=pResController->StatesEnd();sit++){ 00605 EventSet disabledInput, active; 00606 active = pResController->ActiveEventSet(*sit); 00607 // first treat Uc-events 00608 disabledInput = UcEvents - active; 00609 //if at least one Input-event is enabled AND at least one Input-event is disabled: 00610 //insert missing Input-transitions to error state 00611 if( (disabledInput!=UcEvents) && !disabledInput.Empty()) { 00612 // FD_DF("HioFreeInput: " << *sit << " disabledInput: " << disabledInput.ToString()); 00613 InputInserted = true; 00614 for (evit = disabledInput.Begin(); evit != disabledInput.End(); ++evit) { 00615 pResController->SetTransition(*sit,*evit,errIdx1); 00616 } 00617 } 00618 // then treat Yp-events 00619 disabledInput = YpEvents - active; 00620 //if at least one Input-event is enabled AND at least one Input-event is disabled: 00621 //insert missing Input-transitions to error state 00622 if( (disabledInput!=YpEvents) && !disabledInput.Empty()) { 00623 // FD_DF("HioFreeInput: " << *sit << " disabledInput: " << disabledInput.ToString()); 00624 InputInserted = true; 00625 for (evit = disabledInput.Begin(); evit != disabledInput.End(); ++evit) { 00626 pResController->SetTransition(*sit,*evit,errIdx1); 00627 } 00628 } 00629 }//for-loop through states 00630 00631 //insert err_Input-state and connect both err-states with Input-Output-loop in case missing Input-events were inserted: 00632 if(InputInserted) { 00633 //create second error state 00634 std::string errstate2; 00635 if(StateNamesEnabled) { 00636 FD_DF("HioFreeInput(...): inserted error state 1: " << errStr1); 00637 errStr2=pResController->UniqueStateName("ErrorQYp"); 00638 errIdx2=pResController->InsMarkedState(errStr2); 00639 FD_DF("HioFreeInput(...): inserted error state 2: " << errStr2); 00640 } 00641 else { 00642 FD_DF("HioFreeInput(...): inserted error state 1 with Idx: " << errIdx1); 00643 errIdx2=pResController->InsMarkedState(); 00644 FD_DF("HioFreeInput(...): inserted error state 2 with Idx: " << errIdx2); 00645 } 00646 00647 // set HioStateFlag Err 00648 pResController->SetErr(errIdx2); 00649 // set HioStateFlag QYp 00650 pResController->SetQYp(errIdx2); 00651 00652 //insert Up-events: 00653 for (evit = UpEvents.Begin(); evit != UpEvents.End(); ++evit) { 00654 pResController->SetTransition(errIdx1,*evit,errIdx2); 00655 } 00656 //insert Yp-events: 00657 for (evit = YpEvents.Begin(); evit != YpEvents.End(); ++evit) { 00658 pResController->SetTransition(errIdx2,*evit,errIdx1); 00659 } 00660 } 00661 00662 //else delete error-state 1 00663 else { 00664 pResController->DelState(errIdx1); 00665 } 00666 00667 // if necessary, move pResGen to rResGen 00668 if(pResController != &rResController) { 00669 pResController->Move(rResController); 00670 delete pResController; 00671 } 00672 // restore event attributes 00673 rResController.SetYc(YcEvents); 00674 rResController.SetUc(UcEvents); 00675 rResController.SetYp(YpEvents); 00676 rResController.SetUp(UpEvents); 00677 } 00678 00679 // HioFreeInput(HioEnvironment,HioEnvironment) 00680 void HioFreeInput( 00681 const HioEnvironment& rEnvironment, 00682 HioEnvironment& rResEnvironment) 00683 { 00684 FD_DF("HioFreeInput( [environment] " << rEnvironment.Name() << ")"); 00685 00686 HioEnvironment* pResEnvironment = &rResEnvironment; 00687 if(&rResEnvironment== &rEnvironment) { 00688 pResEnvironment=rResEnvironment.New(); 00689 } 00690 00691 // check for enabled state names: 00692 bool StateNamesEnabled = pResEnvironment->StateNamesEnabled(); 00693 00694 // prepare error state names 00695 std::string errStr1, errStr2; 00696 00697 // prepare error state indeces 00698 Idx errIdx1, errIdx2; 00699 00700 // prepare result, preserve StateNamesEnabled of rGen 00701 pResEnvironment->Assign(rEnvironment); 00702 //*pResEnvironment=rEnvironment; // didn't work 00703 //pResEnvironment=&rEnvironment; // didn't work 00704 pResEnvironment->StateNamesEnabled(StateNamesEnabled); 00705 pResEnvironment->Name("HioFreeInput("+rEnvironment.Name()+")"); 00706 00707 // figure alphabets 00708 EventSet UlEvents = rEnvironment.UlEvents(); 00709 EventSet YeEvents = rEnvironment.YeEvents(); 00710 EventSet YlEvents = rEnvironment.YlEvents(); 00711 EventSet UeEvents = rEnvironment.UeEvents(); 00712 00713 //create first error state, where inserted Uc- or Yp-events shall lead to: 00714 if(StateNamesEnabled) { 00715 errStr1=pResEnvironment->UniqueStateName("UlYeError"); 00716 errIdx1=pResEnvironment->InsMarkedState(errStr1); 00717 } 00718 else { 00719 errIdx1=pResEnvironment->InsMarkedState(); 00720 } 00721 00722 // set HioStateFlag Err 00723 pResEnvironment->SetErr(errIdx1); 00724 // set HioStateFlag QUe 00725 pResEnvironment->SetQUe(errIdx1); 00726 00727 //find Input-states 00728 StateSet::Iterator sit=pResEnvironment->StatesBegin(); 00729 EventSet::Iterator evit; 00730 bool InputInserted = false; 00731 for(;sit!=pResEnvironment->StatesEnd();sit++){ 00732 EventSet disabledInput, active; 00733 active = pResEnvironment->ActiveEventSet(*sit); 00734 // first treat Uc-events 00735 disabledInput = UlEvents - active; 00736 //if at least one Input-event is enabled AND at least one Input-event is disabled: 00737 //insert missing Input-transitions to error state 00738 if( (disabledInput!=UlEvents) && !disabledInput.Empty()) { 00739 // FD_DF("HioFreeInput: " << *sit << " disabledInput: " << disabledInput.ToString()); 00740 InputInserted = true; 00741 for (evit = disabledInput.Begin(); evit != disabledInput.End(); ++evit) { 00742 pResEnvironment->SetTransition(*sit,*evit,errIdx1); 00743 } 00744 } 00745 // then treat Yp-events 00746 disabledInput = YeEvents - active; 00747 //if at least one Input-event is enabled AND at least one Input-event is disabled: 00748 //insert missing Input-transitions to error state 00749 if( (disabledInput!=YeEvents) && !disabledInput.Empty()) { 00750 // FD_DF("HioFreeInput: " << *sit << " disabledInput: " << disabledInput.ToString()); 00751 InputInserted = true; 00752 for (evit = disabledInput.Begin(); evit != disabledInput.End(); ++evit) { 00753 pResEnvironment->SetTransition(*sit,*evit,errIdx1); 00754 } 00755 } 00756 }//for-loop through states 00757 00758 //insert err_Input-state and connect both err-states with Input-Output-loop in case missing Input-events were inserted: 00759 if(InputInserted) { 00760 //create second error state 00761 std::string errstate2; 00762 if(StateNamesEnabled) { 00763 FD_DF("HioFreeInput(...): inserted error state 1: " << errStr1); 00764 errStr2=pResEnvironment->UniqueStateName("ErrorQYe"); 00765 errIdx2=pResEnvironment->InsMarkedState(errStr2); 00766 FD_DF("HioFreeInput(...): inserted error state 2: " << errStr2); 00767 } 00768 else { 00769 FD_DF("HioFreeInput(...): inserted error state 1 with Idx: " << errIdx1); 00770 errIdx2=pResEnvironment->InsMarkedState(); 00771 FD_DF("HioFreeInput(...): inserted error state 2 with Idx: " << errIdx2); 00772 } 00773 00774 // set HioStateFlag Err 00775 pResEnvironment->SetErr(errIdx2); 00776 // set state attribute QYe 00777 pResEnvironment->SetQYe(errIdx2); 00778 00779 //insert Ue-events: 00780 for (evit = UeEvents.Begin(); evit != UeEvents.End(); ++evit) { 00781 pResEnvironment->SetTransition(errIdx1,*evit,errIdx2); 00782 } 00783 //insert Ye-events: 00784 for (evit = YeEvents.Begin(); evit != YeEvents.End(); ++evit) { 00785 pResEnvironment->SetTransition(errIdx2,*evit,errIdx1); 00786 } 00787 } 00788 00789 //else delete error-state 1 00790 else { 00791 pResEnvironment->DelState(errIdx1); 00792 } 00793 // if necessary, move pResGen to rResGen 00794 if(pResEnvironment != &rResEnvironment) { 00795 pResEnvironment->Move(rResEnvironment); 00796 delete pResEnvironment; 00797 } 00798 // restore event attributes 00799 rResEnvironment.SetYl(YlEvents); 00800 rResEnvironment.SetUl(UlEvents); 00801 rResEnvironment.SetYe(YeEvents); 00802 rResEnvironment.SetUe(UeEvents); 00803 } 00804 00805 // HioFreeInput(HioConstraint,HioConstraint) 00806 void HioFreeInput( 00807 const HioConstraint& rConstraint, 00808 HioConstraint& rResConstraint) 00809 { 00810 // Call HioFreeInput with certain names for error states, 00811 // set Err-flags 00812 Idx errstate1,errstate2; 00813 std::string ErrState1="Y-Error"; 00814 std::string ErrState2="ErrorQY"; 00815 EventSet y,u; 00816 y=rConstraint.YEvents(); 00817 u=rConstraint.UEvents(); 00818 HioFreeInput(rConstraint,y,u,rResConstraint,ErrState1,ErrState2,errstate1,errstate2); 00819 // set HioStateFlag Err 00820 rResConstraint.SetErr(errstate1); 00821 rResConstraint.SetErr(errstate2); 00822 // restore event attributes 00823 rResConstraint.SetY(y); 00824 rResConstraint.SetU(u); 00825 } 00826 00827 // HioFreeInput(HioPlant) 00828 void HioFreeInput(HioPlant& rPlant) { 00829 FD_DF("HioFreeInput( [single arg plant] " << rPlant.Name() << ")"); 00830 HioFreeInput(rPlant,rPlant); 00831 } 00832 00833 // HioFreeInput(HioController) 00834 void HioFreeInput(HioController& rController) { 00835 HioFreeInput(rController,rController); 00836 } 00837 00838 // HioFreeInput(HioEnvironment) 00839 void HioFreeInput(HioEnvironment& rEnvironment) { 00840 HioFreeInput(rEnvironment,rEnvironment); 00841 } 00842 00843 // HioFreeInput(HioConstraint) 00844 void HioFreeInput(HioConstraint& rConstraint) { 00845 HioFreeInput(rConstraint,rConstraint); 00846 } 00847 00848 00849 00850 //********************************************************** 00851 //******************** Completeness ************************ 00852 //********************************************************** 00853 00854 00855 00856 //********************************************************** 00857 //******************** I/O-shuffle ************************ 00858 //********************************************************** 00859 00860 //******************** current version: marked parameters + marking of alternation ************************ 00861 00862 // MarkHioShuffle(rGen1,rGen2,rMapOrigToResult,rShuffle) 00863 void MarkHioShuffle(const Generator& rGen1,const Generator& rGen2, 00864 const std::map< std::pair<Idx,Idx>, Idx >& rMapOrigToResult, 00865 Generator& rShuffle) { 00866 00867 // invert mapOrigToResult (possible, as map is expected to be from parallel composition and thus must be bijective) 00868 std::map< Idx, std::pair<Idx,Idx> > mapResultToOrig; 00869 std::map< std::pair<Idx,Idx>, Idx >::const_iterator iter; 00870 for( iter = rMapOrigToResult.begin(); iter != rMapOrigToResult.end(); ++iter ) { 00871 mapResultToOrig.insert(std::make_pair( iter->second, iter->first )); 00872 } 00873 00874 // (I) duplicate all non-marked states, whose corresponding state in rGen1 or rGen2 is marked. 00875 StateSet nonmarked=rShuffle.States()-rShuffle.MarkedStates(); 00876 StateSet::Iterator sit; 00877 std::map< Idx, Idx > rGen1Clones,rGen2Clones; 00878 for(sit = nonmarked.Begin(); sit != nonmarked.End(); sit ++) { 00879 // marked in rGen1? 00880 if(rGen1.ExistsMarkedState(mapResultToOrig[*sit].first)) { 00881 rGen1Clones[*sit]=rShuffle.InsMarkedState(); 00882 } 00883 // marked in rGen2? 00884 if(rGen2.ExistsMarkedState(mapResultToOrig[*sit].first)) { 00885 rGen2Clones[*sit]=rShuffle.InsMarkedState(); 00886 } 00887 } 00888 00889 // (II) MOVE HEAD OF rGen1-transitions whose X2 has a rGen1-clone, and head of rGen2-transitions whose 00890 // X2 has a rGen2-clone 00891 TransSet TransToClear, TransToSet; 00892 TransSet::Iterator tit=rShuffle.TransRelBegin(); 00893 TransSet::Iterator tit_end=rShuffle.TransRelEnd(); 00894 std::map<Idx,Idx>::iterator cloneit; 00895 bool x1hasGen1Clone,x1hasGen2Clone, x2hasClone; 00896 for(;tit!=tit_end;tit++) { 00897 00898 x1hasGen1Clone=false; 00899 x1hasGen2Clone=false; 00900 x2hasClone=false; 00901 00902 //################################################## 00903 // CASE (I) - X2 has clone: move head of transition, also duplicate transition if X1 has clone 00904 //################################################## 00905 00906 // preliminarily check if X1 has clone 00907 cloneit=rGen1Clones.find(tit->X1); 00908 if(cloneit!=rGen1Clones.end()) x1hasGen1Clone=true; 00909 cloneit=rGen2Clones.find(tit->X1); 00910 if(cloneit!=rGen2Clones.end()) x1hasGen2Clone=true; 00911 00912 00913 // distinguish rGen1-events and rGen2-events 00914 if(rGen1.Alphabet().Exists(tit->Ev)) { 00915 // exists rGen1-clone? 00916 cloneit=rGen1Clones.find(tit->X2); 00917 if(cloneit!=rGen1Clones.end()) { 00918 x2hasClone=true; 00919 // move head to clone: delete original trans, insert moved trans 00920 TransToClear.Insert(*tit); 00921 TransToSet.Insert(tit->X1,tit->Ev,rGen1Clones[tit->X2]); 00922 // if X1 has a clone make copy starting from clone of X1 00923 if(x1hasGen1Clone) { 00924 TransToSet.Insert(rGen1Clones[tit->X1],tit->Ev,rGen1Clones[tit->X2]); 00925 } 00926 if(x1hasGen2Clone) { 00927 TransToSet.Insert(rGen2Clones[tit->X1],tit->Ev,rGen1Clones[tit->X2]); 00928 } 00929 } 00930 } 00931 00932 // else, tit is rGen2-transition 00933 else { 00934 // exists rGen2-clone? 00935 cloneit=rGen2Clones.find(tit->X2); 00936 if(cloneit!=rGen2Clones.end()) { 00937 x2hasClone=true; 00938 // move head to clone: delete original trans, insert moved trans 00939 TransToClear.Insert(*tit); 00940 TransToSet.Insert(tit->X1,tit->Ev,cloneit->second); 00941 // if X1 has a clone make copy starting from clone of X1 00942 if(x1hasGen1Clone) { 00943 TransToSet.Insert(rGen1Clones[tit->X1],tit->Ev,rGen2Clones[tit->X2]); 00944 } 00945 if(x1hasGen2Clone) { 00946 TransToSet.Insert(rGen2Clones[tit->X1],tit->Ev,rGen2Clones[tit->X2]); 00947 } 00948 } 00949 } 00950 00951 //################################################### 00952 // CASE (II) - (only) X1 has clone: duplicate transition (see Case I for case also X2 has clone) 00953 //################################################### 00954 00955 if( (x1hasGen1Clone||x1hasGen2Clone) && !x2hasClone ) { 00956 if(x1hasGen1Clone) TransToSet.Insert(rGen1Clones[tit->X1],tit->Ev,tit->X2); 00957 if(x1hasGen2Clone) TransToSet.Insert(rGen2Clones[tit->X1],tit->Ev,tit->X2); 00958 } 00959 } 00960 00961 // clear invalid transitions 00962 tit=TransToClear.Begin(); 00963 tit_end=TransToClear.End(); 00964 for(;tit!=tit_end;tit++) rShuffle.ClrTransition(*tit); 00965 00966 // set updated transitions 00967 tit=TransToSet.Begin(); 00968 tit_end=TransToSet.End(); 00969 for(;tit!=tit_end;tit++) rShuffle.SetTransition(*tit); 00970 00971 // cosmetics 00972 rShuffle.Accessible(); 00973 return; 00974 } 00975 00976 // MarkAlternationAB(Aset,Bset,AltAB) 00977 void MarkAlternationAB( 00978 const EventSet rAset, 00979 const EventSet rBset, 00980 Generator& rAltAB) 00981 { 00982 FD_DF("MarkAlternationAB()"); 00983 00984 #ifdef FAUDES_CHECKED 00985 // validate parameters 00986 if (rAset.Empty()){ 00987 std::stringstream errstr; 00988 errstr << "Empty parameter rAset."; 00989 throw Exception("CheapAltAnB", errstr.str(), 0); 00990 } 00991 if (rBset.Empty()){ 00992 std::stringstream errstr; 00993 errstr << "Empty parameter rBset."; 00994 throw Exception("CheapAltAnB", errstr.str(), 0); 00995 } 00996 #endif 00997 00998 rAltAB.Clear(); 00999 rAltAB.InjectAlphabet(rAset+rBset); 01000 01001 Idx s1,s2,s3,s4,s5; 01002 01003 s1=rAltAB.InsInitState(); 01004 rAltAB.SetMarkedState(s1); 01005 s2=rAltAB.InsMarkedState(); 01006 s3=rAltAB.InsMarkedState(); 01007 s4=rAltAB.InsState(); 01008 s5=rAltAB.InsState(); 01009 EventSet::Iterator evit=rAset.Begin(); 01010 EventSet::Iterator evit_end=rAset.End(); 01011 for(;evit!=evit_end;++evit) { 01012 rAltAB.SetTransition(s1,*evit,s2); 01013 rAltAB.SetTransition(s2,*evit,s4); 01014 rAltAB.SetTransition(s3,*evit,s2); 01015 rAltAB.SetTransition(s4,*evit,s4); 01016 rAltAB.SetTransition(s5,*evit,s2); 01017 } 01018 evit=rBset.Begin(); 01019 evit_end=rBset.End(); 01020 for(;evit!=evit_end;++evit) { 01021 rAltAB.SetTransition(s1,*evit,s3); 01022 rAltAB.SetTransition(s2,*evit,s3); 01023 rAltAB.SetTransition(s3,*evit,s5); 01024 rAltAB.SetTransition(s4,*evit,s3); 01025 rAltAB.SetTransition(s5,*evit,s5); 01026 } 01027 } 01028 01029 // HioShuffleUnchecked(rPlantA,rPlantB,rYp,rUp,rYe,rUe,rIOShuffAB) 01030 void HioShuffleUnchecked( 01031 const Generator& rPlantA, 01032 const Generator& rPlantB, 01033 const EventSet& rYp, 01034 const EventSet& rUp, 01035 const EventSet& rYe, 01036 const EventSet& rUe, 01037 Generator& rIOShuffAB) 01038 { 01039 FD_DF("HioShuffle()"); 01040 01041 //Extract alphabets: 01042 EventSet A,B,SigmaP; 01043 A = rPlantA.Alphabet(); 01044 B = rPlantB.Alphabet(); 01045 01046 // parallel composition of plantA and plantB (i.e. shuffle as there are no shared events) 01047 Generator parallel1, parallel2; 01048 std::map< std::pair<Idx,Idx>, Idx > MapOrigToResult; 01049 Parallel(rPlantA,rPlantB,MapOrigToResult,parallel1); 01050 MarkHioShuffle(rPlantA,rPlantB,MapOrigToResult,parallel1); 01051 01052 // restrict to event pairs [(SigA SigA)*+(SigB SigB)*]*, which results 01053 // in correct I/O sorting L_IO. 01054 Generator EventPairs; // generator of above sorting language 01055 EventPairs.InjectAlphabet(A + B); 01056 Idx state1,state2,state3; 01057 state1=EventPairs.InsInitState("1"); 01058 EventPairs.SetMarkedState(state1); 01059 state2=EventPairs.InsMarkedState("2"); 01060 state3=EventPairs.InsMarkedState("3"); 01061 EventSet::Iterator evit; 01062 for (evit = A.Begin(); evit != A.End(); ++evit) { 01063 EventPairs.SetTransition(state1,*evit,state2); 01064 EventPairs.SetTransition(state2,*evit,state1); 01065 } 01066 for (evit = B.Begin(); evit != B.End(); ++evit) { 01067 EventPairs.SetTransition(state1,*evit,state3); 01068 EventPairs.SetTransition(state3,*evit,state1); 01069 } 01070 Parallel(parallel1,EventPairs,parallel2); 01071 parallel1 = parallel2; 01072 01073 // //##################################################################################### 01074 // //##################################################################################### 01075 // //##################################################################################### 01076 // //restrict to IO-sorting structure with forced alternation: 01077 // 01078 // // Old Vers before Dez 4 2006: Alternation of whole alphabets 01079 // A = rPlantA.Alphabet(); 01080 // B = rPlantB.Alphabet(); 01081 // 01082 // 01083 //// // New Vers: Alternation of YP Events only 01084 //// // -> currently leads to normality problems during superposed controller synthesis 01085 //// SigmaP.SetUnion(rYp); 01086 //// SigmaP.SetUnion(rUp); 01087 //// A.SetIntersection(SigmaP); 01088 //// B.SetIntersection(SigmaP); 01089 // 01090 // 01091 // 01092 // Generator AltAB; 01093 // A.Name("A"); 01094 // B.Name("B"); 01095 // CheapAltAB(A,B,Depth,AltAB); 01096 // // Alt_AB.Write("tmp_Alternation_AB.gen"); 01097 // Parallel(parallel2, AltAB, parallel1); 01098 // //parallel2.Write("tmp_IOS3.gen"); 01099 // 01100 // 01101 // 01102 01103 01104 // bugfix to resolve normality problem: whenever plant A 01105 // can send a yp-event and at the same time plant B can 01106 // send a ye-event, then let the ye-event be sent first: 01107 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 01108 //*** Environment-first policy: If, in some state both, Yp- and Ye events are 01109 //*** active, then cancel all Yp-transitions in this state, as environment has 01110 //*** to be updated first. 01111 01112 FD_DF("------ HioShuffle with Environment-First-Policy! -----"); 01113 01114 // loop all states 01115 StateSet::Iterator sit = parallel1.StatesBegin(); 01116 StateSet::Iterator sit_end = parallel1.StatesEnd(); 01117 01118 for(; sit != sit_end; sit++) 01119 { 01120 // figure active Yp-events and active Ye-events 01121 //std::cout << "End: " << *sit_end <<"...done: " << *sit << std::endl; 01122 EventSet ActiveYe; 01123 EventSet ActiveYp = parallel1.TransRel().ActiveEvents(*sit); 01124 ActiveYe=ActiveYp; 01125 ActiveYe.SetIntersection(rYe); 01126 ActiveYp.SetIntersection(rYp); 01127 if (!(ActiveYe.Empty())&& !(ActiveYp.Empty())) 01128 { 01129 TransSet TransToClear; 01130 TransSet::Iterator tit=parallel1.TransRelBegin(*sit); 01131 TransSet::Iterator tit_end=parallel1.TransRelEnd(*sit); 01132 for(;tit!=tit_end;tit++) 01133 { 01134 //std::cout << "finding Yp-events to delete... "; 01135 if(ActiveYp.Exists(tit->Ev)) 01136 { 01137 TransToClear.Insert(*tit); 01138 } 01139 } 01140 tit=TransToClear.Begin(); 01141 tit_end=TransToClear.End(); 01142 for(;tit!=tit_end;tit++) 01143 { 01144 //std::cout<<" ...deleting" <<std::endl; 01145 parallel1.ClrTransition(*tit); 01146 } 01147 } 01148 } 01149 01150 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 01151 01152 01153 01154 //~ //// 01155 //~ // //##################################################################################### 01156 //~ // //##################################################################################### 01157 //~ // //##################################################################################### 01158 01159 01160 // Insert Error Behaviour, i.e. make UP and UE free in (YP,UP)-port of result: 01161 // free UP: 01162 HioFreeInput(parallel1, rUp, rYp, parallel2, "errYp_Ye", "errUp"); 01163 //parallel1.Write("tmp_IOS4.gen"); 01164 // free UE: 01165 HioFreeInput(parallel2, rUe, rYe, parallel1, "errYp_Ye", "errUe"); 01166 //parallel2.Write("tmp_IOS5.gen"); 01167 01168 // Mark Alternation of YP-events 01169 A.SetIntersection(rYp); 01170 B.SetIntersection(rYp); 01171 MarkAlternationAB(A,B,parallel2); 01172 Parallel(parallel2,parallel1,parallel1); 01173 01174 rIOShuffAB = parallel1; 01175 rIOShuffAB.Name("HioShuffle("+rPlantA.Name()+rPlantB.Name()+")"); 01176 return; 01177 } 01178 01179 01180 // HioShuffle(rPlantA,rPlantB,rYp,rUp,rYe,rUe,rIOShuffAB) 01181 void HioShuffle( 01182 const Generator& rPlantA, 01183 const Generator& rPlantB, 01184 const EventSet& rYp, 01185 const EventSet& rUp, 01186 const EventSet& rYe, 01187 const EventSet& rUe, 01188 Generator& rIOShuffAB) 01189 { 01190 rIOShuffAB.Clear(); 01191 #ifdef FAUDES_CHECKED 01192 // exception on empty alphabets 01193 if (rYp.Empty()){ 01194 std::stringstream errstr; 01195 errstr << "Empty Yp alphabet\n"; 01196 throw Exception("HioShuffle", errstr.str(), 0); 01197 } 01198 if (rUp.Empty()){ 01199 std::stringstream errstr; 01200 errstr << "Empty Up alphabet\n"; 01201 throw Exception("HioShuffle", errstr.str(), 0); 01202 } 01203 if (rYe.Empty()){ 01204 std::stringstream errstr; 01205 errstr << "Empty Ye alphabet\n"; 01206 throw Exception("HioShuffle", errstr.str(), 0); 01207 } 01208 if (rUe.Empty()){ 01209 std::stringstream errstr; 01210 errstr << "Empty Ue alphabet\n"; 01211 throw Exception("HioShuffle", errstr.str(), 0); 01212 } 01213 01214 // create resulting alphabet while checking for disjoint sets 01215 EventSet alphabet,alphabetA,alphabetB,errevents; 01216 alphabetA=rPlantA.Alphabet(); 01217 alphabetB=rPlantB.Alphabet(); 01218 // initialize with rYp 01219 alphabet.SetUnion(rYp); 01220 // insert remaining events one by one and check if new 01221 EventSet::Iterator evit; 01222 // rUp 01223 for (evit = rUp.Begin(); evit != rUp.End(); ++evit) { 01224 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 01225 } 01226 // rYe 01227 for (evit = rYe.Begin(); evit != rYe.End(); ++evit) { 01228 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 01229 } 01230 // rUe 01231 for (evit = rUe.Begin(); evit != rUe.End(); ++evit) { 01232 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 01233 } 01234 // throw exception on non disjoint alphabets 01235 if (!errevents.Empty()){ 01236 std::stringstream errstr; 01237 errstr << "Non-disjoint parameters; ambiguous events:\n" <<errevents.ToString(); 01238 throw Exception("HioShuffle", errstr.str(), 0); 01239 } 01240 01241 // check alphabet match with plant A and B-alphabets: 01242 // The union of plant A and B alphabets need not equal but must be included in the union of EventSet parameters. 01243 01244 errevents=alphabetA+alphabetB-alphabet; 01245 if (!errevents.Empty()){ 01246 std::stringstream errstr; 01247 errstr << "Plant A- or plant B-events missing in Yp,Up,Ye or Ue:\n" <<errevents.ToString(); 01248 throw Exception("HioShuffle", errstr.str(), 0); 01249 } 01250 01251 // plant A and plant B must be in HioPlantForm 01252 HioPlant hioPlantA=HioPlant(rPlantA,rYp*alphabetA,rUp*alphabetA,rYe*alphabetA,rUe*alphabetA); 01253 std::string report; 01254 if(!IsHioPlantForm(hioPlantA,report)){ 01255 std::stringstream errstr; 01256 errstr << "plant A not in HioPlantForm:\n" << report; 01257 throw Exception("HioShuffle", errstr.str(), 0); 01258 } 01259 01260 HioPlant hioPlantB=HioPlant(rPlantB,rYp*alphabetB,rUp*alphabetB,rYe*alphabetB,rUe*alphabetB); 01261 report.clear(); 01262 if(!IsHioPlantForm(hioPlantB,report)){ 01263 std::stringstream errstr; 01264 errstr << "plant B not in HioPlantForm:\n" << report; 01265 throw Exception("HioShuffle", errstr.str(), 0); 01266 } 01267 #endif 01268 01269 // compute I/O-shuffle 01270 HioShuffleUnchecked(rPlantA, rPlantB, rYp, rUp, rYe, rUe, rIOShuffAB); 01271 01272 } 01273 01274 void HioShuffle( 01275 const HioPlant& rPlantA, 01276 const HioPlant& rPlantB, 01277 HioPlant& rIOShuffAB) { 01278 01279 //prepare result 01280 rIOShuffAB.Clear(); 01281 01282 EventSet yp = rPlantA.YpEvents()+rPlantB.YpEvents(); 01283 EventSet up = rPlantA.UpEvents()+rPlantB.UpEvents(); 01284 EventSet ye = rPlantA.YeEvents()+rPlantB.YeEvents(); 01285 EventSet ue = rPlantA.UeEvents()+rPlantB.UeEvents(); 01286 01287 // compute I/O-shuffle 01288 HioShuffle(rPlantA, rPlantB, yp, up, ye, ue, rIOShuffAB); 01289 01290 // set event and state attributes 01291 rIOShuffAB.SetYp(yp); 01292 rIOShuffAB.SetUp(up); 01293 rIOShuffAB.SetYe(ye); 01294 rIOShuffAB.SetUe(ue); 01295 01296 IsHioPlantForm(rIOShuffAB); 01297 } 01298 //******************** old version: no marking, forced alternation ************************ 01299 01300 // CheapAltAnB(rAset,rBset,Depth,rAltAnB) 01301 void CheapAltAnB( 01302 const EventSet rAset, 01303 const EventSet rBset, 01304 const int Depth, 01305 Generator& rAltAnB) 01306 { 01307 FD_DF("CheapAltAnB()"); 01308 01309 // validate parameters 01310 if (Depth<1){ 01311 std::stringstream errstr; 01312 errstr << "Parameter Depth must be 1 or greater."; 01313 throw Exception("CheapAltAnB", errstr.str(), 0); 01314 } 01315 #ifdef FAUDES_CHECKED 01316 if (rAset.Empty()){ 01317 std::stringstream errstr; 01318 errstr << "Empty parameter rAset."; 01319 throw Exception("CheapAltAnB", errstr.str(), 0); 01320 } 01321 if (rBset.Empty()){ 01322 std::stringstream errstr; 01323 errstr << "Empty parameter rBset."; 01324 throw Exception("CheapAltAnB", errstr.str(), 0); 01325 } 01326 #endif 01327 01328 // prepare result 01329 rAltAnB.Clear(); 01330 rAltAnB.Name("CheapAltAnB(" + rAset.Name() + "," + rBset.Name() + "," + ToStringInteger(Depth) + ")"); 01331 01332 // create initial state 01333 Idx init = rAltAnB.InsInitState("alt_"+rAset.Name()+"_init"); 01334 rAltAnB.SetMarkedState(init); 01335 01336 Idx last = init; 01337 rAltAnB.InjectAlphabet(rAset + rBset); 01338 01339 // selfloop initial state with Bset: 01340 EventSet::Iterator evit; 01341 for (evit = rBset.Begin(); evit != rBset.End(); ++evit) { 01342 rAltAnB.SetTransition(last,*evit,last); 01343 } 01344 01345 //create n concatenated pathes A->|a|A->|b| and transitions B from |b| to initial state. 01346 for (int i=0; i!=Depth; ++i) { 01347 Idx a = rAltAnB.InsMarkedState("alt_"+rAset.Name()+"_U"+ToStringInteger(i+1)); 01348 Idx b = rAltAnB.InsMarkedState("alt_"+rAset.Name()+"_Y"+ToStringInteger(i+2)); 01349 //connect last,a and b with A-transitions. 01350 for (evit = rAset.Begin(); evit != rAset.End(); ++evit) { 01351 rAltAnB.SetTransition(last,*evit,a); 01352 rAltAnB.SetTransition(a,*evit,b); 01353 } 01354 //insert B-transitions from b to init 01355 for (evit = rBset.Begin(); evit != rBset.End(); ++evit) { 01356 rAltAnB.SetTransition(b,*evit,init); 01357 } 01358 last = b; 01359 } 01360 } 01361 01362 // CheapAltAB(rAset,rBset,Depth,rAltAnB) 01363 void CheapAltAB( 01364 const EventSet rAset, 01365 const EventSet rBset, 01366 const int Depth, 01367 Generator& rAltAB) 01368 { 01369 FD_DF("CheapAltAB()"); 01370 // prepare result 01371 rAltAB.Clear(); 01372 01373 Generator AnB, BnA; 01374 CheapAltAnB(rAset,rBset,Depth,AnB); 01375 CheapAltAnB(rBset,rAset,Depth,BnA); 01376 Parallel(AnB,BnA,rAltAB); 01377 rAltAB.Name("CheapAltAB("+rAset.Name()+","+rBset.Name()+","+ToStringInteger(Depth)+")"); 01378 } 01379 01380 // HioShuffleTU(rPlantA,rPlantB,rYp,rUp,rYe,rUe,Depth,rIOShuffAB) 01381 void HioShuffleTU( 01382 const Generator& rPlantA, 01383 const Generator& rPlantB, 01384 const EventSet& rUp, 01385 const EventSet& rYp, 01386 const EventSet& rYe, 01387 const EventSet& rUe, 01388 const int Depth, 01389 Generator& rIOShuffAB) 01390 { 01391 FD_DF("HioShuffle()"); 01392 01393 //Extract alphabets: 01394 EventSet A,B,SigmaP; 01395 A = rPlantA.Alphabet(); 01396 B = rPlantB.Alphabet(); 01397 01398 // parallel composition of plantA and plantB (i.e. shuffle as there are no shared events) 01399 Generator parallel1, parallel2; 01400 Parallel(rPlantA,rPlantB,parallel1); 01401 01402 // restrict to event pairs [(SigA SigA)*+(SigB SigB)*]*, which results 01403 // in correct I/O sorting L_IO. 01404 Generator EventPairs; // generator of above sorting language 01405 EventPairs.InjectAlphabet(A + B); 01406 Idx state1,state2,state3; 01407 state1=EventPairs.InsInitState("1"); 01408 EventPairs.SetMarkedState(state1); 01409 state2=EventPairs.InsMarkedState("2"); 01410 state3=EventPairs.InsMarkedState("3"); 01411 EventSet::Iterator evit; 01412 for (evit = A.Begin(); evit != A.End(); ++evit) { 01413 EventPairs.SetTransition(state1,*evit,state2); 01414 EventPairs.SetTransition(state2,*evit,state1); 01415 } 01416 for (evit = B.Begin(); evit != B.End(); ++evit) { 01417 EventPairs.SetTransition(state1,*evit,state3); 01418 EventPairs.SetTransition(state3,*evit,state1); 01419 } 01420 Parallel(parallel1,EventPairs,parallel2); 01421 01422 //restrict to IO-sorting structure with forced alternation: 01423 01424 //////// // Old Vers before Dez 4 2006: Alternation of whole alphabets 01425 //////// A = rPlantA.Alphabet(); 01426 //////// B = rPlantB.Alphabet(); 01427 ////// 01428 ////// // New Vers: Alternation of YP Events only 01429 ////// // -> currently leads to normality problems during superposed controller synthesis 01430 ////// SigmaP.SetUnion(rYp); 01431 ////// SigmaP.SetUnion(rUp); 01432 ////// A.SetIntersection(SigmaP); 01433 ////// B.SetIntersection(SigmaP); 01434 ////// 01435 ////// 01436 ////// Generator AltAB; 01437 ////// A.Name("A"); 01438 ////// B.Name("B"); 01439 ////// CheapAltAB(A,B,Depth,AltAB); 01440 ////// // Alt_AB.Write("tmp_Alternation_AB.gen"); 01441 ////// Parallel(parallel2, AltAB, parallel1); 01442 ////// //parallel2.Write("tmp_IOS3.gen"); 01443 01444 // Old Vers before Dez 4 2006: Alternation of whole alphabets 01445 EventSet Ap, Bp, Ae, Be, SigmaE; 01446 01447 Ap = rPlantA.Alphabet(); 01448 Bp = rPlantB.Alphabet(); 01449 01450 Ae = rPlantA.Alphabet(); 01451 Be = rPlantB.Alphabet(); 01452 01453 01454 01455 //************************************************************************* 01456 //// New Vers: Alternation of YP Events only 01457 //// -> currently leads to normality problems during superposed controller synthesis 01458 SigmaP.SetUnion(rYp); 01459 SigmaP.SetUnion(rUp); 01460 Ap.SetIntersection(SigmaP); 01461 Bp.SetIntersection(SigmaP); 01462 01463 SigmaE.SetUnion(rYe); 01464 SigmaE.SetUnion(rUe); 01465 Ae.SetIntersection(SigmaE); 01466 Be.SetIntersection(SigmaE); 01467 01468 01469 //************************************************************************* 01470 Generator AltAB; 01471 Ap.Name("A"); 01472 Bp.Name("B"); 01473 CheapAltAB(Ap,Bp,Depth,AltAB); 01474 // Alt_AB.Write("tmp_Alternation_AB.gen"); 01475 Parallel(parallel2, AltAB, parallel1); 01476 01477 /* // bugfix to resolve normality problem: whenever plant A 01478 * // can send a yp-event and at the same time plant B can 01479 * // send a ye-event, then let the ye-event be sent first: 01480 * //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 01481 * // Environment-first policy: If, in some state both, Yp- and Ye events are 01482 * // active, then cancel all Yp-transitions in this state, as environment has 01483 * // to be updated first. 01484 * 01485 * // loop all states 01486 * StateSet::Iterator sit = parallel1.StatesBegin(); 01487 * StateSet::Iterator sit_end = parallel1.StatesEnd(); 01488 * 01489 * for(; sit != sit_end; sit++) 01490 * { 01491 * // figure active Yp-events and active Ye-events 01492 * //std::cout << "End: " << *sit_end <<"...done: " << *sit << std::endl; 01493 * EventSet ActiveYe; 01494 * EventSet ActiveYp = parallel1.TransRel().ActiveEvents(*sit); 01495 * ActiveYe=ActiveYp; 01496 * ActiveYe.SetIntersection(rYe); 01497 * ActiveYp.SetIntersection(rYp); 01498 * if (!(ActiveYe.Empty())&& !(ActiveYp.Empty())) 01499 * { 01500 * TransSet TransToClear; 01501 * TransSet::Iterator tit=parallel1.TransRelBegin(*sit); 01502 * TransSet::Iterator tit_end=parallel1.TransRelEnd(*sit); 01503 * for(;tit!=tit_end;tit++) 01504 * { 01505 * //std::cout << "finding Yp-events to delete... "; 01506 * if(ActiveYp.Exists(tit->Ev)) 01507 * { 01508 * TransToClear.Insert(*tit); 01509 * } 01510 * } 01511 * tit=TransToClear.Begin(); 01512 * tit_end=TransToClear.End(); 01513 * for(;tit!=tit_end;tit++) 01514 * { 01515 * //std::cout<<" ...deleting" <<std::endl; 01516 * parallel1.ClrTransition(*tit); 01517 * } 01518 * } 01519 * } 01520 * 01521 * //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 01522 * 01523 */ 01524 01525 01526 // Insert Error Behaviour, i.e. make UP and UE free in (YP,UP)-port of result: 01527 // free UP: 01528 HioFreeInput(parallel1, rUp, rYp, parallel2, "errYp_Ye", "errUp"); 01529 //parallel1.Write("tmp_IOS4.gen"); 01530 // free UE: 01531 HioFreeInput(parallel2, rUe, rYe, parallel1, "errYp_Ye", "errUe"); 01532 //parallel2.Write("tmp_IOS5.gen"); 01533 01534 rIOShuffAB = parallel1; 01535 } 01536 01537 //********************************************************** 01538 //******************** Cycles ************************ 01539 //********************************************************** 01540 01541 01542 // ***Search for strongly connected ycless components (SCC)*** 01543 // This function partitions the stateset of a generator into equivalent classes 01544 // such that states x1 and x2 are equivalent iff there is a ycless path from x1 01545 // to x2 AND a ycless path from x2 to x1. 01546 // This function implements the algorithm based on a depth first search 01547 // presented in: 01548 // -Aho, Hopcroft, Ullman: The Design and Analysis of Computer Algorithms- 01549 // 01550 // Most of the comments in this function have been literally taken from 01551 // this book! 01552 // 01553 // Parameters (an api with generator and Yc-events as input and SCCs as output 01554 // is provided right below this method.) 01555 // -state: State, from which the current recursion is started. 01556 // -rcount: denotes the current depth of the recursion. 01557 // -Yc: set of Yc-events 01558 // -UnMarkedOnly: if set true, being unmarked is an additional condition for equivalence of states 01559 // -NewStates: Set of states that up to now were not found by the depth first search 01560 // -STACK: stack of state indeces 01561 // -StackStates: set of states whose indeces are on STACK. 01562 // -DFN: map assigning to each state its Depth-First Number 01563 // -LOWLINK: map assigning to each state its LOWLINK Number 01564 // -SCCset: result - the set of strongly connected components 01565 // -UnMarkedSCCset: result - the set of strongly connected components consisting exclusively of marked states 01566 // -Roots: result - the set of states that each are root of some SCC. 01567 // 01568 // ToDo: handle exceptions. 01569 // 01570 01571 void SearchYclessScc( 01572 const Idx state, 01573 int& rcount, // why is this a ref? 01574 const Generator& rGen, 01575 const EventSet& rYc, 01576 const bool UnMarkedOnly, 01577 StateSet& rNewStates, 01578 std::stack<Idx>& rSTACK, 01579 StateSet& rStackStates, 01580 std::map<const Idx, int>& rDFN, 01581 std::map<const Idx, int>& rLOWLINK, 01582 std::set<StateSet>& rSccSet, 01583 StateSet& rRoots) 01584 { 01585 FD_DF("SerchYclessScc: -- search from state "<< state << "--"); 01586 01587 // mark state "old"; 01588 rNewStates.Erase(state); 01589 01590 // DFNUMBER[state] <- count; 01591 rDFN[state]=rcount; 01592 01593 // count <- count+1; 01594 rcount++; 01595 01596 // LOWLINK[v] <- DFNUMBER[v]; 01597 rLOWLINK[state]=rDFN[state]; 01598 //cout<<"count: "<<rcount<<" state: "<<state<<" DFN: "<<rDFN[state]<<endl; 01599 01600 // push state on STACK; 01601 rSTACK.push(state); 01602 rStackStates.Insert(state); 01603 01604 //<<create set "L[state]" of successor states of state, without states reached via a Yc-event: 01605 StateSet SuccStates = StateSet(); 01606 TransSet::Iterator it = rGen.TransRelBegin(state); 01607 TransSet::Iterator it_end = rGen.TransRelEnd(state); 01608 for (; it != it_end; ++it) { 01609 if(!rYc.Exists(it->Ev)||(UnMarkedOnly &! rGen.ExistsMarkedState(it->X2))) 01610 { 01611 SuccStates.Insert(it->X2); 01612 } 01613 } 01614 01615 // for each vertex *sit on L[state] do 01616 StateSet::Iterator sit = SuccStates.Begin(); 01617 StateSet::Iterator sit_end = SuccStates.End(); 01618 for (; sit != sit_end; ++sit) 01619 { 01620 // if *sit is marked "new" then 01621 if(rNewStates.Exists(*sit)) 01622 {// begin 01623 01624 // SearchC(*sit); 01625 SearchYclessScc(*sit, rcount, rGen, rYc, UnMarkedOnly, rNewStates, rSTACK, rStackStates, rDFN, rLOWLINK, rSccSet, rRoots); 01626 // LOWLINK[state] <- MIN(LOWLINK[state],LOWLINK[*sit]); 01627 if(rLOWLINK[*sit]<rLOWLINK[state]) 01628 { 01629 rLOWLINK[state]=rLOWLINK[*sit]; 01630 } 01631 }//end 01632 01633 else 01634 { 01635 // if DFNUMBER[*sit]<DFNUMBER[state] and [*sit] is on STACK then 01636 if((rDFN[*sit]<rDFN[state])&&(rStackStates.Exists(*sit))) 01637 { 01638 // LOWLINK[state]<-MIN(DFNUMBER[*sit],LOWLINK[state]); 01639 if(rDFN[*sit]<rLOWLINK[state]) 01640 { 01641 rLOWLINK[state]=rDFN[*sit]; 01642 } 01643 } 01644 } 01645 }//end for 01646 // if LOWLINK[state]=DFNUMBER[state] (i.e. state is root of a SCC) then 01647 if((rLOWLINK[state]==rDFN[state])) 01648 { 01649 // per def., each state in a graph is element of a SCC, thus: 01650 // check if size of SCC is>1 or (else) SCC contains (non-{epsilon,yc}-)selfloops 01651 // to avoid print of trivial SCCs 01652 bool realscc=rSTACK.top()!=state; //size of SCC>1 ? if not, check for selfloops: 01653 if(!realscc) 01654 { 01655 TransSet::Iterator it = rGen.TransRelBegin(state); 01656 TransSet::Iterator it_end = rGen.TransRelEnd(state); 01657 for (; it != it_end; ++it) 01658 { 01659 if((it->X2==state)&&(!rYc.Exists(it->Ev))) 01660 { 01661 realscc=true; //at least one yc-less selfloop found -> SCC is nontrivial 01662 break; 01663 } 01664 } 01665 } 01666 01667 //~ if(realscc) // be aware: "else" statement is NOT correct at this point, as realscc-value is changed in the above if-clause 01668 //~ { 01669 //~ // cout<<endl<<"found ycless SCC with root "<<state<<", consisting of the following states:"<<endl<<"begin"<<endl; 01670 //~ rRoots.Insert(state); 01671 //~ } 01672 01673 //create SCC 01674 StateSet Scc; 01675 bool purelyUnMarked=true; 01676 // begin 01677 // repeat 01678 while(true) 01679 {// begin 01680 // pop x from top of STACK and print x; 01681 Idx top=rSTACK.top(); 01682 if(realscc) // things outside the "if(realscc)"-clause have to be done in any case! 01683 { 01684 // cout<<top; 01685 Scc.Insert(top); 01686 if(rGen.ExistsMarkedState(top)) purelyUnMarked=false; 01687 } 01688 rStackStates.Erase(top); 01689 rSTACK.pop(); 01690 01691 // until x=state; 01692 if(top==state) 01693 { 01694 // print "end of SCC", insert SCC into SCCset; 01695 if(realscc) 01696 { 01697 // cout<<endl<<"end"<<endl; 01698 if(!purelyUnMarked || UnMarkedOnly) 01699 { 01700 rSccSet.insert(Scc); 01701 rRoots.Insert(state); 01702 } 01703 } 01704 //system("pause"); 01705 break; 01706 } 01707 // cout<<", "<<endl; 01708 } //end while 01709 } // end if 01710 } 01711 01712 // YclessScc(Generator,Yc-events, SccSet, Roots) 01713 // -> api using SearchYclessScc() from above. 01714 bool YclessScc( 01715 const Generator& rGen, 01716 const EventSet& rYc, 01717 std::set<StateSet>& rSccSet, 01718 StateSet& rRoots) 01719 { 01720 FD_DF("YclessScc(" << rGen.Name() << ")"); 01721 01722 // inititalize results: 01723 rRoots.Clear(); 01724 rSccSet.clear(); 01725 // initialize counter for depthfirstnumbers(DFN): 01726 int count=1; 01727 01728 // initialize stack of states (state indeces): 01729 std::stack<Idx> STACK; 01730 // due to lack of STACK-iterator: initialize set of states that are on STACK: 01731 StateSet StackStates = StateSet(); 01732 01733 // initialize set of states to be examined: 01734 StateSet NewStates=rGen.AccessibleSet(); 01735 01736 // initialize map of state indeces to their DFN: 01737 std::map<const Idx, int> DFN; 01738 // initialize map of state indeces to their LOWLINK: 01739 std::map<const Idx, int> LOWLINK; 01740 01741 // figure initial state: 01742 Idx InitState = *rGen.InitStatesBegin(); 01743 // start recursive depth-first search for Scc's: 01744 while(!NewStates.Empty()) { 01745 // the following 'if' isn't necessary, but provokes search begin at initial state of rGen 01746 if(NewStates.Exists(InitState)) { 01747 SearchYclessScc(InitState, count, rGen, rYc, false, NewStates, STACK, StackStates, DFN, LOWLINK, rSccSet, rRoots); 01748 } else { 01749 SearchYclessScc(*NewStates.Begin(), count, rGen, rYc, false, NewStates, STACK, StackStates, DFN, LOWLINK, rSccSet, rRoots); 01750 } 01751 } 01752 01753 return !rSccSet.empty(); 01754 } 01755 01756 // YclessUnMarkedScc(Generator,Yc-events, SccSet, Roots) 01757 // -> api using SearchYclessScc() from above. 01758 bool YclessUnmarkedScc( 01759 const Generator& rGen, 01760 const EventSet& rYc, 01761 std::set<StateSet>& rSccSet, 01762 StateSet& rRoots) 01763 { 01764 FD_DF("YclessScc(" << rGen.Name() << ")"); 01765 01766 // inititalize results: 01767 rRoots.Clear(); 01768 rSccSet.clear(); 01769 // initialize counter for depthfirstnumbers(DFN): 01770 int count=1; 01771 01772 // initialize stack of states (state indeces): 01773 std::stack<Idx> STACK; 01774 // due to lack of STACK-iterator: initialize set of states that are on STACK: 01775 StateSet StackStates = StateSet(); 01776 01777 // initialize set of states to be examined: 01778 StateSet NewStates=rGen.AccessibleSet()-rGen.MarkedStates(); 01779 01780 // initialize map of state indeces to their DFN: 01781 std::map<const Idx, int> DFN; 01782 // initialize map of state indeces to their LOWLINK: 01783 std::map<const Idx, int> LOWLINK; 01784 01785 // figure initial state: 01786 Idx InitState = *rGen.InitStatesBegin(); 01787 // start recursive depth-first search for Scc's: 01788 while(!NewStates.Empty()) { 01789 // the following 'if' isn't necessary, but provokes search begin at initial state of rGen 01790 if(NewStates.Exists(InitState)) { 01791 SearchYclessScc(InitState, count, rGen, rYc, true, NewStates, STACK, StackStates, DFN, LOWLINK, rSccSet, rRoots); 01792 } else { 01793 SearchYclessScc(*NewStates.Begin(), count, rGen, rYc, true, NewStates, STACK, StackStates, DFN, LOWLINK, rSccSet, rRoots); 01794 } 01795 } 01796 01797 return !rSccSet.empty(); 01798 } 01799 01800 01801 // YclessScc(rGen,rYc,rSccSet) 01802 // -> api using YclessScc() from above. 01803 bool YclessScc( 01804 const Generator& rGen, 01805 const EventSet& rYc, 01806 std::set<StateSet>& rSccSet) 01807 { 01808 FD_DF("YclessScc(" << rGen.Name() << ")"); 01809 01810 // inititalize result: 01811 rSccSet.clear(); 01812 01813 StateSet Roots; 01814 return YclessScc(rGen,rYc,rSccSet,Roots); 01815 } 01816 01817 // IsYcLive(rGen,rYc) 01818 bool IsYcLive( 01819 const Generator& rGen, 01820 const EventSet& rYc) 01821 { 01822 FD_DF("IsYcLive(" << rGen.Name() << ")"); 01823 01824 std::set<StateSet> rSccSet; 01825 01826 // Generator is YcLive if no YcLessScc is found 01827 YclessScc(rGen,rYc,rSccSet); 01828 return rSccSet.size()==0; 01829 } 01830 01831 // WriteStateSets(rStateSets) 01832 // Write set of StateSet's to console. 01833 void WriteStateSets( 01834 const std::set<StateSet>& rStateSets) 01835 { 01836 FD_DF("WriteStateSets()"); 01837 std::cout<<std::endl; 01838 if(rStateSets.empty()) { 01839 std::cout<<"WriteStateSets: Set of state sets is empty."<<std::endl; 01840 FD_DF("WriteStateSets: Set of state sets is empty."); 01841 return; 01842 } 01843 std::cout<<">WriteStateSets: Set of state sets begin:"<< std::endl; 01844 std::set<StateSet>::iterator StateSetit = rStateSets.begin(); 01845 std::set<StateSet>::iterator StateSetit_end = rStateSets.end(); 01846 for (; StateSetit != StateSetit_end; ++StateSetit) { 01847 std::cout<<std::endl<<" >> State set begin:"<< std::endl; 01848 StateSet::Iterator sit = StateSetit->Begin(); 01849 StateSet::Iterator sit_end = StateSetit->End(); 01850 for (; sit != sit_end; ++sit) { 01851 std::cout<<" >> "<<*sit<<std::endl; 01852 } 01853 std::cout<<" >> State set end."<< std::endl; 01854 } 01855 std::cout<<std::endl<<">WriteStateSets: Set of state sets end."<<std::endl; 01856 } 01857 01858 // WriteStateSets(rGen,rStateSets) 01859 // Write set of StateSet's to console. 01860 // Use rGen for symbolic state names 01861 void WriteStateSets( 01862 const Generator& rGen, 01863 const std::set<StateSet>& rStateSets) 01864 { 01865 FD_DF("WriteStateSets()"); 01866 std::cout<<std::endl; 01867 if(rStateSets.empty()) { 01868 std::cout<<"WriteStateSets: Set of state sets is empty."<<std::endl; 01869 FD_DF("WriteStateSets: Set of state sets is empty."); 01870 return; 01871 } 01872 std::cout<<">WriteStateSets: Set of state sets begin:"<< std::endl; 01873 std::set<StateSet>::iterator StateSetit = rStateSets.begin(); 01874 std::set<StateSet>::iterator StateSetit_end = rStateSets.end(); 01875 for (; StateSetit != StateSetit_end; ++StateSetit) { 01876 std::cout<<std::endl<<" >> State set begin:"<< std::endl; 01877 std::cout<<" "<<rGen.StateSetToString(*StateSetit)<<std::endl; 01878 std::cout<<" >> State set end."<< std::endl; 01879 } 01880 std::cout<<std::endl<<">WriteStateSets: Set of state sets end."<<std::endl; 01881 } 01882 01883 // SccEntries(rGen,rSccSet,rEntryStates,rEntryTransSet) 01884 void SccEntries( 01885 const Generator& rGen, 01886 const std::set<StateSet>& rSccSet, 01887 StateSet& rEntryStates, 01888 TransSetX2EvX1& rEntryTransSet) { 01889 01890 FD_DF("SccEntries(...)"); 01891 01892 // prepare results: 01893 rEntryStates.Clear(); 01894 rEntryTransSet.Clear(); 01895 01896 //extract all transitions sorted by target state X2 01897 TransSetX2EvX1 trel; 01898 rGen.TransRel(trel); 01899 FD_DF("SccEntries: Entry states of all SCCs:"); 01900 01901 //loop through all SCCs: 01902 std::set<StateSet>::iterator sccit = rSccSet.begin(); 01903 std::set<StateSet>::iterator sccit_end = rSccSet.end(); 01904 for (int i=0; sccit != sccit_end; ++sccit, i++) { 01905 FD_DF("SccEntries: SCC " << i << " begin:"); 01906 //loop through all states: 01907 StateSet::Iterator sit = sccit->Begin(); 01908 StateSet::Iterator sit_end = sccit->End(); 01909 for (; sit != sit_end; ++sit) { 01910 //check if sit is initial state: 01911 if(rGen.ExistsInitState(*sit)) { 01912 rEntryStates.Insert(*sit); 01913 } 01914 //loop through all transitions with target state X2=sit: 01915 TransSetX2EvX1::Iterator tit=trel.BeginByX2(*sit); 01916 TransSetX2EvX1::Iterator tit_end=trel.EndByX2(*sit); 01917 for(;tit!=tit_end;tit++) { 01918 //if sit is successor of a state X1 that is element of a SCC different 01919 //from the current SCC "StateSetit" and if sit has not been added to 01920 //rEntryStates up to now, then add sit to EntryStates: 01921 if(!sccit->Exists(tit->X1)) { 01922 // insert entry transition: 01923 rEntryTransSet.Insert(*tit); 01924 // if new, insert entry state: 01925 if(!rEntryStates.Exists(*sit)) { 01926 // Perk: check if Insert returns false anyway if element already 01927 // existed before. if so, then write: 01928 // if(rEntryStates.Insert(*sit)) FD_DF("SccEntries: Entry state:" <<*sit); 01929 FD_DF("SccEntries: Entry state:" <<*sit); 01930 rEntryStates.Insert(*sit); 01931 } 01932 } 01933 } 01934 } 01935 FD_DF("SccEntries: SCC " << i << " end:"); 01936 } 01937 FD_DF("SccEntries: done"); 01938 } 01939 01940 // CloneScc(rGen,rScc,rSccSet,rEntryState,rEntryStates,rEntryTransSet) 01941 void CloneScc( 01942 Generator& rGen, 01943 const StateSet& rScc, 01944 std::set<StateSet>& rSccSet, 01945 const Idx EntryState, 01946 StateSet& rEntryStates, 01947 TransSetX2EvX1& rEntryTransSet) 01948 { 01949 FD_DF("CloneScc(...)"); 01950 // initialize map from original SCC-states to their clones: 01951 std::map<const Idx, Idx> clone; 01952 // initialize clone-SCC: 01953 StateSet CloneScc; 01954 // clone SCC-states: 01955 StateSet::Iterator sit=rScc.Begin(); 01956 StateSet::Iterator sit_end=rScc.End(); 01957 for(;sit!=sit_end;sit++) { 01958 // if sit is marked, also mark its clone 01959 if(rGen.ExistsMarkedState(*sit)) { 01960 clone[*sit]=rGen.InsMarkedState(); 01961 CloneScc.Insert(clone[*sit]); 01962 // cout<<"marked state "<<clone[*sit]<<" of "<<*sit<<" inserted."; 01963 } 01964 // or else insert unmarked state 01965 else { 01966 clone[*sit]=rGen.InsState(); 01967 CloneScc.Insert(clone[*sit]); 01968 // cout<<"unmarked state "<<clone[*sit]<<" of "<<*sit<<" inserted."; 01969 } 01970 } 01971 // add clone of SCC to set of all SCCs: 01972 rSccSet.insert(CloneScc); 01973 // clone all transitions: 01974 sit=rScc.Begin(); 01975 for(;sit!=sit_end;sit++) { 01976 TransSet::Iterator tit=rGen.TransRelBegin(*sit); 01977 TransSet::Iterator tit_end=rGen.TransRelEnd(*sit); 01978 for(;tit!=tit_end;tit++) { 01979 // clone all transitions within SCC: 01980 if(rScc.Exists(tit->X2)) { 01981 rGen.SetTransition(clone[*sit],tit->Ev,clone[tit->X2]); 01982 } 01983 //...and transitions leaving the SC: 01984 else { 01985 rGen.SetTransition(clone[*sit],tit->Ev,tit->X2); 01986 //**** added 06.09.2007: 01987 // If this cloned transition leads to an entry state of 01988 // some other SCC, then it is a new entry transition: 01989 if(rEntryStates.Exists(tit->X2)) { 01990 rEntryTransSet.Insert(clone[*sit],tit->Ev,tit->X2); 01991 } 01992 //**** 01993 } 01994 } 01995 } 01996 // move the head of all entry transitions leading to EntryState to the clone of EntryState: 01997 TransSet TransToClear, EntryTransToInsert; 01998 TransSetX2EvX1::Iterator tit=rEntryTransSet.BeginByX2(EntryState); 01999 TransSetX2EvX1::Iterator tit_end=rEntryTransSet.EndByX2(EntryState); 02000 for(;tit!=tit_end;tit++) { 02001 // cout<<endl<<"Moving entryTransition "<<"("<<tit->X1<<","<<rGen.EventName(tit->Ev)<<","<<tit->X2<<")"; 02002 // cout<<" to target state "<<clone[EntryState]; 02003 rGen.SetTransition(tit->X1,tit->Ev,clone[EntryState]); 02004 //prebook new moved transition to be inserted in rEntryTransSet: 02005 EntryTransToInsert.Insert(tit->X1,tit->Ev,clone[EntryState]); 02006 //prebook transitions to former entry state to clear in rGen and rEntryTransSet: 02007 TransToClear.Insert(*tit); 02008 } 02009 //clear former transitions in rGen and rEntryTransSet: 02010 TransSet::Iterator tit2=TransToClear.Begin(); 02011 TransSet::Iterator tit2_end=TransToClear.End(); 02012 for(;tit2!=tit2_end;tit2++) { 02013 rGen.ClrTransition(*tit2); 02014 //erase transitions to former entry state from rEntryTransSet: 02015 rEntryTransSet.Erase(*tit2); 02016 } 02017 // update rEntryTransSet with new moved entry transitions: 02018 TransSet::Iterator tit3=EntryTransToInsert.Begin(); 02019 TransSet::Iterator tit3_end=EntryTransToInsert.End(); 02020 for(;tit3!=tit3_end;tit3++) { 02021 //insert new moved transitions in rEntryTransSet: 02022 rEntryTransSet.Insert(*tit3); 02023 } 02024 //update rEntryStateSet: 02025 rEntryStates.Erase(EntryState); // erase former ambiguous entry state 02026 rEntryStates.Insert(clone[EntryState]); // insert unique entry state of cloned SCC 02027 } 02028 02029 // CloneUnMarkedScc(rGen,rScc,rSccSet,rEntryState,rEntryStates,rEntryTransSet) 02030 void CloneUnMarkedScc( 02031 Generator& rGen, 02032 const StateSet& rScc, 02033 const Idx EntryState, 02034 const StateSet& rEntryStates, 02035 TransSetX2EvX1& rEntryTransSet) 02036 { 02037 FD_DF("CloneUnMarkedScc(...)"); 02038 // initialize map from original SCC-states to their clones: 02039 std::map<const Idx, Idx> clone; 02040 // initialize clone-SCC: 02041 StateSet CloneScc; 02042 // clone all SCC-states but EntryState: 02043 StateSet::Iterator sit=rScc.Begin(); 02044 StateSet::Iterator sit_end=rScc.End(); 02045 for(;sit!=sit_end;sit++) { 02046 if(*sit != EntryState) { 02047 clone[*sit]=rGen.InsState(); 02048 CloneScc.Insert(clone[*sit]); 02049 } 02050 else clone[*sit]=*sit; // entry state is not cloned 02051 02052 } 02053 02054 //*** Think about this: 02055 // // add clone of SCC to set of all SCCs: 02056 // rSccSet.insert(CloneScc); 02057 //*** 02058 02059 // clone all transitions: 02060 TransSet TransToClear; 02061 sit=rScc.Begin(); 02062 bool isEntryState=false; 02063 TransSet::Iterator tit,tit_end; 02064 for(;sit!=sit_end;sit++) { 02065 isEntryState=(*sit==EntryState); 02066 tit=rGen.TransRelBegin(*sit); 02067 tit_end=rGen.TransRelEnd(*sit); 02068 for(;tit!=tit_end;tit++) { 02069 // clone all transitions within SCC: 02070 if(rScc.Exists(tit->X2)) { 02071 rGen.SetTransition(clone[*sit],tit->Ev,clone[tit->X2]); 02072 // if transition starts at entry state, only keep the clone transition 02073 if(isEntryState) { 02074 // prebook this transition to be cleared 02075 TransToClear.Insert(*tit); 02076 } 02077 } 02078 //...and transitions leaving the SCC: 02079 else { 02080 rGen.SetTransition(clone[*sit],tit->Ev,tit->X2); 02081 //**** added 06.09.2007: 02082 // If this cloned transition leads to an entry state of 02083 // some other SCC, then it is a new entry transition: 02084 if(rEntryStates.Exists(tit->X2)) { 02085 rEntryTransSet.Insert(clone[*sit],tit->Ev,tit->X2); 02086 } 02087 //**** 02088 } 02089 } 02090 } 02091 02092 // clear prebooked transitions 02093 tit=TransToClear.Begin(); 02094 tit_end=TransToClear.End(); 02095 for(;tit!=tit_end;tit++) { 02096 rGen.ClrTransition(*tit); 02097 } 02098 02099 } 02100 //============================ 02101 02102 02103 02104 // YcAcyclic(rGen,rYc,rResGen) 02105 void YcAcyclic( 02106 const Generator& rGen, 02107 const EventSet& rYc, 02108 Generator& rResGen) 02109 { 02110 FD_DF("YcAcyclic: Statesize before: "<<rGen.Size()<<" - starting..."); 02111 // initialize set of ycless strongly connected components (SCCs): 02112 std::set<StateSet> SccSet,UnMarkedSccSet; 02113 // initialize set of all states that are member or root or entry state of some SCC: 02114 StateSet Scc,Roots,EntryStates,notRoots,UnMarkedRoots; 02115 // initialize set of transitions that enter some SCC from a different SCC, 02116 // sorted by target states X2 (which are entry states): 02117 TransSetX2EvX1 EntryTransSet; 02118 // take rGen as first candidate: 02119 rResGen=rGen; 02120 // counter for below while loop: 02121 // int i=0; 02122 02123 while(true) { 02124 //++i; 02125 // check for SCCs and return if there are none -> ResGen is the result. 02126 // cout<<endl<<"Round "<<i<<": Searching for remaining Yc-less SCCs..."; 02127 if(!YclessScc(rResGen,rYc,SccSet,Roots)) { 02128 //time_t *t2; 02129 //time(t2); 02130 //cout<<"...finished in "<<difftime(*t2, *t1)<<" seconds."; 02131 //rResGen.DotWrite("tmp_YcAcyclic_res"); 02132 FD_DF("YcAcyclic: Statesize of result: "<<rResGen.Size()); 02133 // cout<<". Statemin..."; 02134 // Generator tmp; 02135 // StateMin(rResGen,tmp); 02136 // cout<<"done. New Statesize:"<<tmp.Size(); 02137 // tmp.ClrStateNames(); 02138 // rResGen=tmp; 02139 // tmp.Clear(); 02140 //rResGen.Write("tmp_YcAcyclic.gen"); 02141 return; 02142 } 02143 //cout<<endl<<"...found "<<SCCset.size()<<" Yc-less SCCs: computing entry states..."; 02144 // cout<<"Found following Yc-less SCCs:"<<endl; 02145 // WriteStateSets(SCCset); 02146 // system("pause"); 02147 // else figure entry states and entry transitions of the SCCs 02148 SccEntries(rResGen,SccSet,EntryStates,EntryTransSet); 02149 02150 // root states are kept as entry states of the original SCCs, for all other 02151 // entry states clone SCCs: 02152 notRoots=EntryStates - Roots; 02153 //cout<<"...found "<<notRoots.Size()<<" entry states that are not roots. Start cloning SCCs..."<<endl; 02154 // cout<<endl<<"EntryStates before cloning:"<<endl; 02155 // EntryStates.DWrite(); 02156 // cout<<endl<<"Roots before cloning:"<<endl; 02157 // Roots.DWrite(); 02158 // cout<<endl<<"notRoots before cloning:"<<endl; 02159 // notRoots.DWrite(); 02160 02161 StateSet::Iterator sit=notRoots.Begin(); 02162 StateSet::Iterator sit_end=notRoots.End(); 02163 for(;sit!=sit_end;sit++) 02164 { 02165 // figure SCC with entry state sit: 02166 std::set<StateSet>::iterator sccit = SccSet.begin(); 02167 std::set<StateSet>::iterator sccit_end = SccSet.end(); 02168 for (; sccit != sccit_end; ++sccit) 02169 { 02170 if(sccit->Exists(*sit)) 02171 { 02172 Scc=*sccit; 02173 break; 02174 } 02175 } 02176 // clone this SCC (and add clone to SCCset): 02177 // cout<<"cloning SCCC:"<<endl; 02178 // SCC.DWrite(); 02179 CloneScc(rResGen,Scc,SccSet,*sit,EntryStates,EntryTransSet); 02180 // cout<<endl<<"New set of SCCs:"<<endl; 02181 // WriteStateSets(SccSet); 02182 } 02183 //cout<<endl<<"...done. Identifying unique entry states..."; 02184 // rResGen.Write("tmp_YcAcyclic_step.gen"); 02185 // rResGen.DotWrite("tmp_YcAcyclic_step"); 02186 // ++i; 02187 // cout<<endl<<"Printed intermediate result "<<i<<"."<<endl; 02188 // system("pause"); 02189 02190 // Now, all SCCs have one unique entry state. 02191 // If some SCC contains a sub-SCC that a) includes the entry 02192 // state of the whole SCC and b) consists of only unmarked 02193 // states, then this sub-SCC has to be copied to resolve the 02194 // ambiguity. 02195 if( !( ((rResGen.States()-rResGen.MarkedStates())*EntryStates).Empty() ) ) { 02196 // find possible unmarked sub-SCCs including EntryState 02197 YclessUnmarkedScc(rResGen,rYc,UnMarkedSccSet,UnMarkedRoots); 02198 std::set<StateSet>::iterator sccit = UnMarkedSccSet.begin(); 02199 std::set<StateSet>::iterator sccit_end = UnMarkedSccSet.end(); 02200 for (; sccit != sccit_end; ++sccit) { 02201 // check if this unmarked sub-SCC includes an EntryState; if so: clone it 02202 if( !( ((*sccit)*EntryStates).Empty() ) ) { 02203 Idx EntryState=*(((*sccit)*EntryStates).Begin()); 02204 CloneUnMarkedScc(rResGen,*sccit,EntryState,EntryStates,EntryTransSet); 02205 } 02206 } 02207 } 02208 02209 02210 02211 //"Back transitions" leading 02212 // from a SCC to its own entry state have to be cancelled, 02213 // if they are not Yc-transitions: 02214 02215 // 2) loop through all SCCs and find Ycless back transitions: 02216 TransSet TransToClear; 02217 std::set<StateSet>::iterator sccit = SccSet.begin(); 02218 std::set<StateSet>::iterator sccit_end = SccSet.end(); 02219 //cout<<endl<<"Determining non-yc-backtransitions..."; 02220 for (; sccit != sccit_end; ++sccit) 02221 { 02222 //loop through all states: 02223 StateSet::Iterator sit = sccit->Begin(); 02224 StateSet::Iterator sit_end = sccit->End(); 02225 for (; sit != sit_end; ++sit) 02226 { 02227 //cout<<endl<<"looping state "<<*sit<<endl; 02228 // loop through all transitions: 02229 TransSet::Iterator tit=rResGen.TransRelBegin(*sit); 02230 TransSet::Iterator tit_end=rResGen.TransRelEnd(*sit); 02231 for(;tit!=tit_end;tit++) 02232 { 02233 // Check if tit leads back to entry state of current SCC 02234 // and if it is not a Yc-transition: 02235 if(sccit->Exists(tit->X2) && EntryStates.Exists(tit->X2) 02236 &&!rYc.Exists(tit->Ev)) 02237 { 02238 //cout<<" - Trans to clear: "<<tit->Ev<<endl; 02239 TransToClear.Insert(*tit); 02240 } 02241 } 02242 } 02243 } 02244 //cout<<endl<<"...found "<<TransToClear.Size()<<" transitions. Deleting these transitions..."; 02245 // 3) Clear back transitions: 02246 TransSet::Iterator tit=TransToClear.Begin(); 02247 TransSet::Iterator tit_end=TransToClear.End(); 02248 for(;tit!=tit_end;tit++) 02249 { 02250 //cout<<"clearing transition ("<<tit->X1<<","<<rResGen.EventName(tit->Ev)<<","<<tit->X2<<")"<<endl; 02251 rResGen.ClrTransition(*tit); 02252 } 02253 02254 // ++i; 02255 // rResGen.Write("tmp_YcAcyclic_step.gen"); 02256 // rResGen.DotWrite("tmp_YcAcyclic_step"); 02257 // cout<<endl<<"Printed intermediate result "<<i<<"."<<endl; 02258 // system("pause"); 02259 // cout<<endl<<"...transitions deletetd, next round!"; 02260 // cout<<endl<<"state size of current intermediate result: "<<rResGen.Size(); 02261 //cout<<endl<<". Press enter to start statemin."<<endl; 02262 //string anykey; 02263 //getline( cin, anykey ); 02264 02265 // cout<<". Statemin..."; 02266 // Generator tmp; 02267 // StateMin(rResGen,tmp); 02268 // cout<<"done. New Statesize:"<<tmp.Size(); 02269 // rResGen=tmp; 02270 // tmp.Clear(); 02271 02272 // system("pause"); 02273 } //end while(true): resulting generator might contain SCCs within the 02274 // SCCs that have been "broken" in this step -> continue while-loop. 02275 } 02276 02277 //********************************************************** 02278 //******************** hio synthesis ************************ 02279 //********************************************************** 02280 02281 // ConstrSynth_Beta(rPlant,rYp,rUp,rOpConstr) 02282 void ConstrSynth_Beta( 02283 Generator& rPlant, 02284 const EventSet& rYp, 02285 const EventSet& rUp, 02286 const Generator& rLocConstr, 02287 Generator& rOpConstraint) { 02288 02289 FD_DF("ConstrSynth_Beta(...)"); 02290 02291 // helper 02292 Generator tmpGen; 02293 EventSet sigmap=rYp+rUp; 02294 02295 //prepare rsult: 02296 rOpConstraint.Clear(); 02297 02298 // respect optional local constraints 02299 Parallel(rPlant,rLocConstr,rOpConstraint); 02300 02301 // calculate YpAcyclic sublanguage: 02302 YcAcyclic(rOpConstraint,rYp,tmpGen); 02303 rOpConstraint.Clear(); 02304 02305 // compute normal, complete, controllable and nonblocking sublanguage 02306 // note: tmpGen has role of spec 02307 NormalCompleteSynthNB(rPlant,rUp,sigmap,tmpGen,rOpConstraint); 02308 tmpGen.Clear(); 02309 02310 // project to P-Alphabet 02311 Project(rOpConstraint,sigmap,tmpGen); 02312 rOpConstraint.Clear(); 02313 02314 // minimize state space 02315 StateMin(tmpGen,tmpGen); 02316 tmpGen.StateNamesEnabled(false); 02317 02318 // eneable symbolic state names for error states 02319 tmpGen.StateNamesEnabled(true); 02320 rOpConstraint.StateNamesEnabled(true); 02321 // make YP free in OpConstr 02322 HioFreeInput(tmpGen, rYp, rUp, rOpConstraint, "errUp","errYp"); 02323 02324 rOpConstraint.Name("ConstrSynth_Beta("+rPlant.Name()+")"); 02325 02326 return; 02327 } 02328 02329 // HioSynthUnchecked(rPlant,rSpec,rConstr,rLocConstr,rYc,rUc,rYp,rUp,rYel,rUel,rController) 02330 void HioSynthUnchecked( 02331 const Generator& rPlant, 02332 const Generator& rSpec, 02333 const Generator& rExtConstr, 02334 const Generator& rLocConstr, 02335 const EventSet& rYc, 02336 const EventSet& rUc, 02337 const EventSet& rYp, 02338 const EventSet& rUp, 02339 const EventSet& rYel, 02340 const EventSet& rUel, 02341 Generator& rController) 02342 { 02343 FD_DF("HioSynth(...)"); 02344 //prepare rsult: 02345 rController.Clear(); 02346 //make copy of plant, spec for modifications 02347 Generator plant,spec; 02348 plant = rPlant; 02349 spec = rSpec; 02350 02351 //create necessary eventsets: 02352 EventSet sigmacp; 02353 sigmacp.SetUnion(rUc + rYc + rUp + rYp); 02354 EventSet sigmace; 02355 sigmace.SetUnion(rUc + rYc + rUel + rYel); 02356 02357 EventSet allsigma; 02358 allsigma.SetUnion(rPlant.Alphabet()); 02359 allsigma.SetUnion(rSpec.Alphabet()); 02360 02361 EventSet controllable, wait; 02362 controllable.SetUnion(rUp); 02363 controllable.SetUnion(rYc); 02364 02365 //make alphabets of plant and spec match: 02366 InvProject(plant,allsigma); 02367 InvProject(spec,allsigma); 02368 02369 // FD_DF("******************** actual plant: composition with external constraints"); 02370 02371 // generate plant under constraint: 02372 Parallel(plant,rExtConstr,plant); 02373 //plant.Write("tmp_cplant.gen"); 02374 02375 //FD_DF("******************** mininmal hio structure, composition with plant"); 02376 Generator minhio; 02377 minhio = HioSortCL(rYc,rUc,rYp,rUp,rYel,rUel); 02378 //minhio.Write("tmp_minhio.gen"); 02379 02380 // generate plant in hio structure: 02381 Parallel(plant,minhio,plant); 02382 plant.StateNamesEnabled(false); 02383 //plant.Write("tmp_hiocplant.gen"); 02384 02385 //FD_DF("******************** composition plant-specification: tmp_plantspec.gen "); 02386 02387 // composition of plant, I/O sorting, constraint and specification: 02388 Generator plantspec; 02389 Parallel(plant,spec,plantspec); 02390 //plantspec.Write("tmp_plantspec.gen"); 02391 plantspec.StateNamesEnabled(false); 02392 FD_DF("Size of plantspec: "<<plantspec.Size()<<" - Statemin..."); 02393 StateMin(plantspec,plantspec); 02394 FD_DF("done. New Statesize: "<<plantspec.Size()<<"."); 02395 plantspec.StateNamesEnabled(false); 02396 //plantspec.Write("results/tmp_plantspec.gen"); 02397 FD_DF("******************** computing YcAcyclic(plantspec):"); 02398 02399 // calculate YcAcyclic sublanguage of plantspec: 02400 Generator yclifeplantspec; 02401 YcAcyclic(plantspec,rYc,yclifeplantspec); 02402 yclifeplantspec.StateNamesEnabled(false); 02403 //yclifeplantspec.Write("tmp_YcAcyclic.gen"); 02404 02405 //FD_DF("******************** actual spec: composition yclifeplantspec||minhio||locconstr (tmp_actualspec.gen)"); 02406 //generate plantspec with closed-loop I/O sorting: 02407 Parallel(yclifeplantspec,minhio,plantspec); 02408 yclifeplantspec.Clear(); 02409 //add local constraints to plantspec: the result is the actual spec for synthesis 02410 Parallel(plantspec,rLocConstr,plantspec); 02411 plantspec.StateNamesEnabled(false); 02412 plantspec.Name("actualspec"); 02413 //plantspec.Write("tmp_actualspec.gen"); 02414 02415 //FD_DF("******************** closed loop synthesis: tmp_closedloop.gen/.dot"); 02416 02417 // compute normal, complete and controllable sublangugae of actualspec w.r.t. plant under constraints (cplant): 02418 Generator loop; 02419 NormalCompleteSynthNB(plant,controllable,sigmacp,plantspec,loop); 02420 plantspec.Clear(); 02421 //loop.Write("tmp_closedloop.gen"); 02422 02423 FD_DF("size of closed loop before StateMin: "<<loop.Size()<<", starting StateMin..."); 02424 StateMin(loop,loop); 02425 FD_DF("...size of closed loop after StateMin (tmp_closedloop.gen): "<<loop.Size()); 02426 //std::cout<<"ClosedLoop.IsTrim: "<<loop.IsTrim(); 02427 loop.StateNamesEnabled(false); 02428 // loop.Write("tmp_closedloop.gen"); 02429 FD_DF("********* IsYcLive(closed loop): "<<IsYcLive(loop,rYc)); 02430 plant.Clear(); 02431 02432 //calculate external closedloop: 02433 FD_DF("******************** external closed loop: tmp_extloop.gen"); 02434 Generator extloop; 02435 Project(loop,sigmace,extloop); 02436 FD_DF("size of external closed loop: "<<extloop.Size()); 02437 02438 // // recheck if specification is met: 02439 // if(LanguageInclusion(extloop,rSpec)) { 02440 // FD_DF("External closed loop meets specification."); 02441 // } // Perk: change below to LanguageInclusion with reverse order of parameters 02442 // // and move into above bracket. 02443 // if(LanguageEquality(extloop,rSpec)) { 02444 // FD_DF("External closed loop EQUALS specification."); 02445 // } 02446 02447 extloop.StateNamesEnabled(false); 02448 //extloop.Write("tmp_extloop.gen"); 02449 02450 FD_DF("******************** project closed loop: tmp_controller.gen"); 02451 02452 Generator controller; 02453 Project(loop,sigmacp,controller); 02454 loop.Clear(); 02455 controller.StateNamesEnabled(false); 02456 //controller.Write("tmp_controller.gen"); 02457 02458 // extend to io-controller: result 02459 HioFreeInput(controller, rYp, rUp, rController, "errUp","errYp"); 02460 controller.Clear(); 02461 FD_DF("size of marked IO controller: "<<rController.Size()<<". PrefixClosure, StateMin..."); 02462 02463 // the following procedure erases all marking information to reduce the result's state space! This step is unproblematic as long as the specification 02464 // is a prefix-closed system, because then, all marking information comes from the plant and is restored in the closed loop. Otherwise, care has to be taken 02465 // wether this step is correct or should be omitted . 02466 if(!(rSpec.AccessibleSet()<=rSpec.MarkedStates())) { 02467 FD_WARN("Careful: marking information of the specification has been erased from the resulting controller."); 02468 } 02469 PrefixClosure(rController); 02470 StateMin(rController,rController); 02471 FD_DF("...size of prefix-closed IO controller after StateMin: "<<rController.Size()); 02472 rController.StateNamesEnabled(false); 02473 rController.Name("HioSynth("+rPlant.Name()+","+rSpec.Name()+")"); 02474 FD_DF("IO controller synthesis done. ******************** " ); 02475 } 02476 02477 // HioSynth(rPlant,rSpec,rConstr,rLocConstr,rYc,rUc,rYp,rUp,rYel,rUel,rController) 02478 void HioSynth( 02479 const Generator& rPlant, 02480 const Generator& rSpec, 02481 const Generator& rExtConstr, 02482 const Generator& rLocConstr, 02483 const EventSet& rYc, 02484 const EventSet& rUc, 02485 const EventSet& rYp, 02486 const EventSet& rUp, 02487 const EventSet& rYel, 02488 const EventSet& rUel, 02489 Generator& rController) 02490 { 02491 02492 rController.Clear(); 02493 02494 #ifdef FAUDES_CHECKED 02495 // exception on empty alphabets 02496 if (rYc.Empty()){ 02497 std::stringstream errstr; 02498 errstr << "Empty Yc alphabet\n"; 02499 throw Exception("HioSynth", errstr.str(), 0); 02500 } 02501 if (rUc.Empty()){ 02502 std::stringstream errstr; 02503 errstr << "Empty Uc alphabet\n"; 02504 throw Exception("HioSynth", errstr.str(), 0); 02505 } 02506 if (rYp.Empty()){ 02507 std::stringstream errstr; 02508 errstr << "Empty Yp alphabet\n"; 02509 throw Exception("HioSynth", errstr.str(), 0); 02510 } 02511 if (rUp.Empty()){ 02512 std::stringstream errstr; 02513 errstr << "Empty Up alphabet\n"; 02514 throw Exception("HioSynth", errstr.str(), 0); 02515 } 02516 if (rYel.Empty()){ 02517 std::stringstream errstr; 02518 errstr << "Empty Ye alphabet\n"; 02519 throw Exception("HioSynth", errstr.str(), 0); 02520 } 02521 if (rUel.Empty()){ 02522 std::stringstream errstr; 02523 errstr << "Empty Ue alphabet\n"; 02524 throw Exception("HioSynth", errstr.str(), 0); 02525 } 02526 02527 // create resulting alphabet while checking for disjoint sets 02528 EventSet alphabet,errevents; 02529 // initialize with rYc 02530 alphabet.SetUnion(rYc); 02531 // insert remaining events one by one and check if new 02532 EventSet::Iterator evit; 02533 // rUc 02534 for (evit = rUc.Begin(); evit != rUc.End(); ++evit) { 02535 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 02536 } 02537 // rYp 02538 for (evit = rYp.Begin(); evit != rYp.End(); ++evit) { 02539 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 02540 } 02541 // rUp 02542 for (evit = rUp.Begin(); evit != rUp.End(); ++evit) { 02543 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 02544 } 02545 // rYe 02546 for (evit = rYel.Begin(); evit != rYel.End(); ++evit) { 02547 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 02548 } 02549 // rUe 02550 for (evit = rUel.Begin(); evit != rUel.End(); ++evit) { 02551 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 02552 } 02553 // throw exception on non disjoint alphabets 02554 if (!errevents.Empty()){ 02555 std::stringstream errstr; 02556 errstr << "Non-disjoint parameters; ambiguous events:\n" <<errevents.ToString(); 02557 throw Exception("HioSynth", errstr.str(), 0); 02558 } 02559 // check alphabet matches: 02560 EventSet plantEvents, specEvents; 02561 plantEvents=rPlant.Alphabet(); 02562 specEvents=rSpec.Alphabet(); 02563 // plant and spec must share environment alphabet 02564 if (!(plantEvents*specEvents==rYel+rUel)){ 02565 std::stringstream errstr; 02566 errstr << "Alphabet mismatch between plant and spec:\n"; 02567 errstr << "plant: " << plantEvents.ToString() << "\n"; 02568 errstr << "spec: " << specEvents.ToString() << "\n"; 02569 errstr << "Yel+Uel: " << (rYel+rUel).ToString() << "\n"; 02570 throw Exception("HioSynth", errstr.str(), 0); 02571 } 02572 // ExtConstr must relate to spec alphabet 02573 if (!(rExtConstr.Alphabet()<=specEvents)){ 02574 std::stringstream errstr; 02575 errstr << "Alphabet mismatch between external constraints and spec.\n"; 02576 throw Exception("HioSynth", errstr.str(), 0); 02577 } 02578 // LocConstr must relate to plant alphabet 02579 if (!(rLocConstr.Alphabet()<=plantEvents)){ 02580 std::stringstream errstr; 02581 errstr << "Alphabet mismatch between internal constraints and plant.\n"; 02582 throw Exception("HioSynth", errstr.str(), 0); 02583 } 02584 02585 // check I/O plant form of spec (note: plant may be composed group and thus need not be in I/o plant form) 02586 HioPlant spec(rSpec,rYc,rUc,rYel,rUel); 02587 std::string report; 02588 if(!IsHioPlantForm(spec,report)){ 02589 std::stringstream errstr; 02590 errstr << "Spec not in HioPlantForm:\n" << report; 02591 throw Exception("HioSynth", errstr.str(), 0); 02592 } 02593 report.clear(); 02594 #endif 02595 02596 // do hio synthesis 02597 HioSynthUnchecked(rPlant,rSpec,rExtConstr,rLocConstr,rYc,rUc,rYp,rUp,rYel,rUel,rController); 02598 } 02599 02600 // HioSynthMonolithic(rPlant,rSpec,rSc,rSp,rSe,rController) 02601 void HioSynthMonolithic( 02602 const HioPlant& rPlant, 02603 const HioPlant& rSpec, 02604 const HioConstraint& rSc, 02605 const HioConstraint& rSp, 02606 const HioConstraint& rSe, 02607 HioController& rController) { 02608 02609 rController.Clear(); 02610 02611 #ifdef FAUDES_CHECKED 02612 // check I/O plant form of rPlant (further parameter checks in HioSynth()) 02613 // tmp non-const copy of const rPlant 02614 HioPlant plant=rPlant; 02615 std::string report; 02616 if(!IsHioPlantForm(plant,report)){ 02617 std::stringstream errstr; 02618 errstr << "Plant not in HioPlantForm:\n" << report; 02619 throw Exception("HioSynthMonolithic", errstr.str(), 0); 02620 } 02621 plant.Clear(); 02622 report.clear(); 02623 #endif 02624 02625 // extract alphabets 02626 EventSet yc,uc,yp,up,ye,ue; 02627 yc=rSpec.YpEvents(); 02628 uc=rSpec.UpEvents(); 02629 yp=rPlant.YpEvents(); 02630 up=rPlant.UpEvents(); 02631 ye=rSpec.YeEvents(); 02632 ue=rSpec.UeEvents(); 02633 02634 // generator for composed external constraints 02635 Generator extConstr; 02636 Parallel(rSc,rSe,extConstr); 02637 02638 // run HioSynth procedure 02639 HioSynth(rPlant,rSpec,extConstr,rSp,yc,uc,yp,up,ye,ue,rController); 02640 02641 // set event and state attributes 02642 rController.SetYc(yc); 02643 rController.SetUc(uc); 02644 rController.SetYp(yp); 02645 rController.SetUp(up); 02646 02647 IsHioControllerForm(rController); 02648 } 02649 02650 void HioSynthHierarchical( 02651 const HioPlant& rHioShuffle, 02652 const HioEnvironment& rEnvironment, 02653 const HioPlant& rSpec, 02654 const Generator& rIntConstr, 02655 const HioConstraint& rSc, 02656 const HioConstraint& rSl, 02657 HioController& rController) { 02658 02659 rController.Clear(); 02660 02661 #ifdef FAUDES_CHECKED 02662 // check I/O plant form of rPlant (further parameter checks in HioSynth()) 02663 // tmp non-const copy of const rPlant 02664 HioPlant plant=rHioShuffle; 02665 std::string report; 02666 if(!IsHioPlantForm(plant,report)){ 02667 std::stringstream errstr; 02668 errstr << "HioShuffle not in HioPlantForm:\n" << report; 02669 throw Exception("HioSynthHierarchical", errstr.str(), 0); 02670 } 02671 plant.Clear(); 02672 report.clear(); 02673 02674 // check I/O environment form 02675 // tmp non-const copy of const rEnvironment 02676 HioEnvironment env=rEnvironment; 02677 if(!IsHioEnvironmentForm(env,report)){ 02678 std::stringstream errstr; 02679 errstr << "Environment not in HioEnvironmentForm:\n" << report; 02680 throw Exception("HioSynthHierarchical", errstr.str(), 0); 02681 } 02682 env.Clear(); 02683 report.clear(); 02684 02685 // check for matching alphabets between ioshuffle, environment and spec 02686 if (!(rHioShuffle.EEvents()==rEnvironment.EEvents())){ 02687 std::stringstream errstr; 02688 errstr << "Alphabet mismatch between I/O-shuffle and environment.\n"; 02689 throw Exception("HioSynthHierarchical", errstr.str(), 0); 02690 } 02691 // check for matching alphabets between ioshuffle, environment and spec 02692 if (!(rSpec.EEvents()==rEnvironment.LEvents())){ 02693 std::stringstream errstr; 02694 errstr << "Alphabet mismatch between specification and environment.\n"; 02695 throw Exception("HioSynthHierarchical", errstr.str(), 0); 02696 } 02697 02698 //(further parameter checks in HioSynth()) 02699 02700 #endif 02701 // compose ioshuffle and environment 02702 Generator ioShuffParEnv; 02703 Parallel(rHioShuffle,rEnvironment,ioShuffParEnv); 02704 02705 // extract alphabets 02706 EventSet yc,uc,yp,up,ye,ue; 02707 yc=rSpec.YpEvents(); 02708 uc=rSpec.UpEvents(); 02709 yp=rHioShuffle.YpEvents(); 02710 up=rHioShuffle.UpEvents(); 02711 ye=rSpec.YeEvents(); 02712 ue=rSpec.UeEvents(); 02713 02714 // generator for composed external constraints 02715 Generator extConstr; 02716 Parallel(rSc,rSl,extConstr); 02717 02718 // run HioSynth procedure 02719 HioSynth(ioShuffParEnv,rSpec,extConstr,rIntConstr,yc,uc,yp,up,ye,ue,rController); 02720 02721 // set event and state attributes 02722 rController.SetYc(yc); 02723 rController.SetUc(uc); 02724 rController.SetYp(yp); 02725 rController.SetUp(up); 02726 02727 IsHioControllerForm(rController); 02728 } 02729 02730 // end of hio_functions - below just archive 02731 02732 //###################################################### 02733 //############ Special versions for HioModule - will soon be obsolete 02734 02735 //HioShuffle_Musunoi() - Version with hio-parameters 02736 void HioShuffle_Musunoi( 02737 const HioPlant& rPlantA, 02738 const HioPlant& rPlantB, 02739 int depth, 02740 Generator& rIOShuffAB) 02741 { 02742 FD_DF("HioShuffle()_Musunoi"); 02743 02744 //Extract alphabets: 02745 EventSet A,B,SigmaP, Yp, Up, Ye, Ue; 02746 Yp = rPlantA.YpEvents()+rPlantB.YpEvents(); 02747 Ye = rPlantA.YeEvents()+rPlantB.YeEvents(); 02748 Up = rPlantA.UpEvents()+rPlantB.UpEvents(); 02749 Ue = rPlantA.UeEvents()+rPlantB.UeEvents(); 02750 A = rPlantA.Alphabet(); 02751 B = rPlantB.Alphabet(); 02752 02753 02754 // parallel composition of plantA and plantB (i.e. shuffle as there are no shared events) 02755 Generator parallel1, parallel2; 02756 Parallel(rPlantA,rPlantB,parallel1); 02757 02758 // restrict to event pairs [(SigA SigA)*+(SigB SigB)*]*, which results 02759 // in correct I/O sorting L_IO. 02760 Generator EventPairs; // generator of above sorting language 02761 EventPairs.InjectAlphabet(A + B); 02762 Idx state1,state2,state3; 02763 state1=EventPairs.InsInitState("1"); 02764 EventPairs.SetMarkedState(state1); 02765 state2=EventPairs.InsMarkedState("2"); 02766 state3=EventPairs.InsMarkedState("3"); 02767 EventSet::Iterator evit; 02768 for (evit = A.Begin(); evit != A.End(); ++evit) { 02769 EventPairs.SetTransition(state1,*evit,state2); 02770 EventPairs.SetTransition(state2,*evit,state1); 02771 } 02772 for (evit = B.Begin(); evit != B.End(); ++evit) { 02773 EventPairs.SetTransition(state1,*evit,state3); 02774 EventPairs.SetTransition(state3,*evit,state1); 02775 } 02776 Parallel(parallel1,EventPairs,parallel2); 02777 02778 //restrict to IO-sorting structure with forced alternation: 02779 02780 // Old Vers before Dez 4 2006: + of whole alphabets 02781 EventSet Ap, Bp, Ae, Be, SigmaE; 02782 02783 Ap = rPlantA.Alphabet(); 02784 Bp = rPlantB.Alphabet(); 02785 02786 Ae = rPlantA.Alphabet(); 02787 Be = rPlantB.Alphabet(); 02788 02789 02790 02791 //************************************************************************* 02792 //// New Vers: Alternation of YP Events only 02793 //// -> currently leads to normality problems during superposed controller synthesis 02794 SigmaP.SetUnion(Yp); 02795 SigmaP.SetUnion(Up); 02796 Ap.SetIntersection(SigmaP); 02797 Bp.SetIntersection(SigmaP); 02798 02799 SigmaE.SetUnion(Ye); 02800 SigmaE.SetUnion(Ue); 02801 Ae.SetIntersection(SigmaE); 02802 Be.SetIntersection(SigmaE); 02803 02804 02805 //************************************************************************* 02806 Generator AltAB; 02807 Ap.Name("A"); 02808 Bp.Name("B"); 02809 CheapAltAB(Ap,Bp,depth,AltAB); 02810 // Alt_AB.Write("tmp_Alternation_AB.gen"); 02811 Parallel(parallel2, AltAB, parallel1); 02812 //parallel2.Write("tmp_IOS3.gen"); 02813 02814 02815 02816 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 02817 //*** Environment-first policy: If, in some state both, Yp- and Ye events are 02818 //*** active, then cancel all Yp-transitions in this state, as environment has 02819 //*** to be updated first. 02820 02821 // loop all states 02822 StateSet::Iterator sit = parallel1.StatesBegin(); 02823 StateSet::Iterator sit_end = parallel1.StatesEnd(); 02824 02825 for(; sit != sit_end; sit++) 02826 { 02827 // figure active Yp-events and active Ye-events 02828 //std::cout << "End: " << *sit_end <<"...done: " << *sit << std::endl; 02829 EventSet ActiveYe; 02830 EventSet ActiveYp = parallel1.TransRel().ActiveEvents(*sit); 02831 ActiveYe=ActiveYp; 02832 ActiveYe.SetIntersection(Ye); 02833 ActiveYp.SetIntersection(Yp); 02834 02835 if (!(ActiveYe.Empty())&& !(ActiveYp.Empty())) 02836 { 02837 TransSet TransToClear; 02838 TransSet::Iterator tit=parallel1.TransRelBegin(*sit); 02839 TransSet::Iterator tit_end=parallel1.TransRelEnd(*sit); 02840 for(;tit!=tit_end;tit++) 02841 { 02842 //std::cout << "finding Yp-events to delete... "; 02843 if(ActiveYp.Exists(tit->Ev)) 02844 { 02845 TransToClear.Insert(*tit); 02846 } 02847 } 02848 tit=TransToClear.Begin(); 02849 tit_end=TransToClear.End(); 02850 for(;tit!=tit_end;tit++) 02851 { 02852 //std::cout<<" ...deleting" <<std::endl; 02853 parallel1.ClrTransition(*tit); 02854 } 02855 } 02856 } 02857 02858 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 02859 02860 02861 02862 // Insert Error Behaviour, i.e. make UP and UE free in (YP,UP)-port of result: 02863 // free UP: 02864 02865 HioFreeInput(parallel1, Up, Yp, parallel2, "errYp_Ye", "errUp"); 02866 //parallel1.Write("tmp_IOS4.gen"); 02867 // free UE: 02868 HioFreeInput(parallel2, Ue, Ye, parallel1, "errYp_Ye", "errUe"); 02869 //parallel2.Write("tmp_IOS5.gen"); 02870 02871 rIOShuffAB = parallel1; 02872 } 02873 02874 // HioSynth_Musunoi() 02875 void HioSynth_Musunoi(const Generator& rPlant, const HioPlant& rSpec, 02876 const Generator& rConstr, const Generator& rLocConstr, 02877 const EventSet& rYp, const EventSet& rUp, 02878 Generator& rController) 02879 { 02880 EventSet rYc, rUc, rYe, rUe; 02881 rYc = (rSpec.YpEvents()); 02882 rUc = (rSpec.UpEvents()); 02883 rYe = (rSpec.YeEvents()); 02884 rUe = (rSpec.UeEvents()); 02885 02886 02887 //make copy of plant, spec, constr and alphabets 02888 Generator plant,spec,constr,locconstr; 02889 plant = rPlant; 02890 spec = rSpec; 02891 constr = rConstr; 02892 locconstr = rLocConstr; 02893 02894 EventSet yc,uc,yp,up,ye,ue; 02895 yc = rYc; 02896 uc = rUc; 02897 yp = rYp; 02898 up = rUp; 02899 ye = rYe; 02900 ue = rUe; 02901 02902 //create necessary eventsets: 02903 EventSet sigmacp; 02904 sigmacp.SetUnion(rUc + rYc + rUp + rYp); 02905 EventSet sigmace; 02906 sigmace.SetUnion(rUc + rYc + rUe + rYe); 02907 02908 EventSet allsigma; 02909 allsigma.SetUnion(rPlant.Alphabet()); 02910 allsigma.SetUnion(rSpec.Alphabet()); 02911 02912 EventSet controllable; 02913 controllable.SetUnion(up); 02914 controllable.SetUnion(yc); 02915 02916 //make alphabets of plant and spec match: 02917 InvProject(plant,allsigma); 02918 InvProject(spec,allsigma); 02919 02920 FD_DF("******************** actual plant: composition with environment constraint: tmp_cplant.gen "); 02921 02922 // generate plant under constraint: 02923 Generator cplant; 02924 Parallel(plant,constr,cplant); 02925 //cplant.Write("tmp_cplant.gen"); 02926 02927 FD_DF("******************** mininmal hio structure: tmp_minhio.gen, composition with plant: tmp_hioplant.gen "); 02928 Generator minhio; 02929 minhio = HioSortCL(yc,uc,yp,up,ye,ue); 02930 //minhio.Write("tmp_minhio.gen"); 02931 02932 // generate plant in hio structure: 02933 Generator hiocplant; 02934 Parallel(cplant,minhio,hiocplant); 02935 //hiocplant.Write("tmp_hiocplant.gen"); 02936 02937 FD_DF("******************** composition plant-specification: tmp_plantspec.gen "); 02938 02939 // composition of plant, I/O sorting, constraint and specification: 02940 Generator plantspec,plantspecMin; 02941 Parallel(hiocplant,spec,plantspec); 02942 //plantspec.Write("tmp_plantspec.gen"); 02943 plantspec.StateNamesEnabled(false); 02944 // plantspec.DotWrite("tmp_plantspec"); 02945 FD_DF("Size of plantspec: "<<plantspec.Size()<<" - Statemin..."); 02946 //string anykey; 02947 //getline(cin,anykey); 02948 StateMin(plantspec,plantspecMin); 02949 FD_DF("done. New Statesize: "<<plantspecMin.Size()<<"."); 02950 plantspec=plantspecMin; 02951 plantspecMin.Clear(); 02952 plantspec.StateNamesEnabled(false); 02953 FD_DF("******************** computing YcAcyclic(plantspec):"); 02954 02955 // calculate YcAcyclic sublanguage of plantspec: 02956 Generator yclifeplantspec; 02957 YcAcyclic(plantspec,yc,yclifeplantspec); 02958 Generator yclifeplantspecMin; 02959 //cout <<endl<< " StateMin(yclifeplantspec)..." << endl; 02960 //StateMin(yclifeplantspec,yclifeplantspecMin); 02961 //cout<<endl<<"Statesize of yclifeplantspec after StateMin (tmp_YcAcyclic_Min.gen): "<<yclifeplantspecMin.Size(); 02962 yclifeplantspecMin=yclifeplantspec; 02963 yclifeplantspecMin.StateNamesEnabled(false); 02964 //yclifeplantspecMin.Write("tmp_YcAcyclic_Min.gen"); 02965 02966 FD_DF("******************** actual spec: composition yclifeplantspec||minhio||locconstr (tmp_actualspec.gen)"); 02967 //generate plantspec with closed-loop I/O sorting: 02968 Parallel(yclifeplantspecMin,minhio,plantspec); 02969 02970 //add local constraints to plantspec: the result is the actual spec for synthesis 02971 Generator actualspec; 02972 Parallel(plantspec,locconstr,actualspec); 02973 //actualspec.Write("tmp_actualspec.gen"); 02974 02975 FD_DF("******************** closed loop synthesis: tmp_closedloop.gen/.dot"); 02976 02977 //std::cout<<"Starting NormalCompleteSynth...."; 02978 FD_DF("Starting NormalCompleteSynth...."); 02979 02980 // compute normal, complete and controllable sublangugae of actualspec w.r.t. plant under constraints (cplant): 02981 Generator loop; 02982 NormalCompleteSynth(hiocplant,controllable,yc+uc+yp+up,actualspec,loop); 02983 //loop.Write("tmp_closedloop.gen"); 02984 //loop.DotWrite("tmp_closedloop"); 02985 02986 FD_DF("size of closed loop before StateMin: "<<loop.Size()<<", starting StateMin..."); 02987 02988 //std::cout<<"Starting NormalCompleteSynth....done... starting StateMin"; 02989 FD_DF("Starting NormalCompleteSynth....done... starting StateMin"); 02990 02991 Generator minloop; 02992 StateMin(loop,minloop); 02993 FD_DF("...size of closed loop after StateMin (tmp_closedloop.gen): "<<minloop.Size()); 02994 //minloop=loop; 02995 minloop.StateNamesEnabled(false); 02996 //minloop.Write("tmp_closedloop.gen"); 02997 // test: recheck for YCless SCCs: 02998 Generator minlooptest; 02999 minlooptest=minloop; 03000 std::set<StateSet> SccSet; 03001 YclessScc(minlooptest,yc,SccSet); 03002 FD_DF(""); 03003 FD_DF("*********number of Yc-less strongly connencted components in closed loop (should be zero): " 03004 <<SccSet.size()); 03005 03006 // minloop.DotWrite("tmp_minclosedloop"); 03007 03008 //calculate external closedloop: 03009 FD_DF("******************** external closed loop: tmp_extloop.gen/.dot"); 03010 Generator extloop; 03011 Project(minloop,sigmace,extloop); 03012 FD_DF("size of external closed loop: "<<extloop.Size());; 03013 03014 // recheck if specification is met: 03015 if(LanguageInclusion(extloop,rSpec)) { 03016 FD_DF("External closed loop meets specification."); 03017 } 03018 if(LanguageEquality(extloop,rSpec)) { 03019 FD_DF("External closed loop EQUALS specification."); 03020 } 03021 03022 extloop.StateNamesEnabled(false); 03023 //extloop.Write("tmp_extloop.gen"); 03024 //extloop.DotWrite("tmp_extloop"); 03025 03026 FD_DF("******************** project closed loop: tmp_controller.gen/.dot "); 03027 03028 Generator controller; 03029 Project(minloop,sigmacp,controller); 03030 controller.StateNamesEnabled(false); 03031 //controller.Write("tmp_controller.gen"); 03032 // controller.DotWrite("tmp_controller"); 03033 03034 FD_DF("******************** extend to IO controller: tmp_IOcontroller.gen/.dot "); 03035 03036 // extend to io-controller 03037 Generator HioController, minIOcontroller; 03038 HioFreeInput(controller, yp, up, HioController, "errUp","errYp"); 03039 //HioController.Write("tmp_IOcontroller.gen"); 03040 // HioController.DotWrite("tmp_IOcontroller"); 03041 FD_DF("size of IO controller: "<<HioController.Size()<<", StateMin..."); 03042 StateMin(HioController,minIOcontroller); 03043 FD_DF("...size of IO controller after StateMin: "<<minIOcontroller.Size()); 03044 minIOcontroller.StateNamesEnabled(false); 03045 //minIOcontroller.Write("tmp_IOcontroller.gen"); 03046 03047 // RESULT: 03048 rController = minIOcontroller; 03049 03050 ////******************************************************************* 03051 // // uncomment this, if you use complete_synth, instead of 03052 // // normal_complete_synth, for controller design: 03053 03054 //cout <<endl<< "******************** checking normality... " << endl; 03055 // 03056 //if(!isnormal(minloop,hiocplant,sigmacp)) 03057 // { 03058 // cout<<endl<<"isnormal says: false! :("<<endl; 03059 // } 03060 //else 03061 // { 03062 // cout<<endl<<"isnormal says: true! :)"<<endl; 03063 // } 03064 ////******************************************************************* 03065 03066 FD_DF("IO controller synthesis done. ******************** " ); 03067 } 03068 03069 }//namespace faudes libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen |