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