| |
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 FreeInput) 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 // IoSortCL(const EventSet& rYc,rUc,rYp,rUP,rYe,rUe) 00203 Generator IoSortCL( 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("IoSortCL(...)"); 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("IoSortCL", 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("IoSortCL", errstr.str(), 0); 00255 } 00256 #endif 00257 00258 // create result 00259 Generator ResGen; 00260 00261 ResGen.Name("IoSortCL("+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 // FreeInput(rGen,rInput,rOutput,rResGen,rErrState1,rErrState2,rErrState1Idx,rErrState2Idx) 00304 void FreeInput( 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("FreeInput( [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("FreeInput", 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("FreeInput: 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("FreeInput("+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("FreeInput: " << *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("FreeInput(...): inserted error state 1: " << errstate1 << " with Idx: " << rErrState1Idx); 00376 } 00377 else { 00378 FD_DF("FreeInput(...): 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("FreeInput(...): inserted error state 2: " << errstate2); 00387 } 00388 else { 00389 rErrState2Idx=pResGen->InsMarkedState(); 00390 FD_DF("FreeInput(...): 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 // FreeInput(rGen,rInput,rOutput,rResGen,rErrState1,rErrState2) 00415 void FreeInput( 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 FreeInput(rGen,rInput,rOutput,rResGen,rErrState1,rErrState2,errstate1,errstate2); 00424 } 00425 00426 // FreeInput(rGen,rInput,rOutput,rResGen) 00427 void FreeInput( 00428 const Generator& rGen, 00429 const EventSet& rInput, 00430 const EventSet& rOutput, 00431 Generator& rResGen) 00432 { 00433 //Call FreeInput with empty names for error states 00434 std::string ErrState1,ErrState2; 00435 FreeInput(rGen,rInput,rOutput,rResGen,ErrState1,ErrState2); 00436 } 00437 00438 // FreeInput(HioPlant,HioPlant) 00439 void FreeInput( 00440 const HioPlant& rPlant, 00441 HioPlant& rResPlant) 00442 { 00443 00444 FD_DF("FreeInput( [plant] " << rPlant.Name() << ")"); 00445 00446 // Call FreeInput 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 FreeInput(rPlant,uP,NoOutput,rResPlant,ErrState1,ErrState2,errstateUp,errstate2); 00459 00460 ErrState1="UeError"; 00461 FreeInput(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 // FreeInput(HioController,HioController) 00476 void FreeInput( 00477 const HioController& rController, 00478 HioController& rResController) 00479 { 00480 FD_DF("FreeInput( [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("FreeInput("+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("FreeInput: " << *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("FreeInput: " << *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("FreeInput(...): inserted error state 1: " << errStr1); 00560 errStr2=pResController->UniqueStateName("ErrorQYp"); 00561 errIdx2=pResController->InsMarkedState(errStr2); 00562 FD_DF("FreeInput(...): inserted error state 2: " << errStr2); 00563 } 00564 else { 00565 FD_DF("FreeInput(...): inserted error state 1 with Idx: " << errIdx1); 00566 errIdx2=pResController->InsMarkedState(); 00567 FD_DF("FreeInput(...): 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 // FreeInput(HioEnvironment,HioEnvironment) 00603 void FreeInput( 00604 const HioEnvironment& rEnvironment, 00605 HioEnvironment& rResEnvironment) 00606 { 00607 FD_DF("FreeInput( [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("FreeInput("+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("FreeInput: " << *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("FreeInput: " << *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("FreeInput(...): inserted error state 1: " << errStr1); 00687 errStr2=pResEnvironment->UniqueStateName("ErrorQYe"); 00688 errIdx2=pResEnvironment->InsMarkedState(errStr2); 00689 FD_DF("FreeInput(...): inserted error state 2: " << errStr2); 00690 } 00691 else { 00692 FD_DF("FreeInput(...): inserted error state 1 with Idx: " << errIdx1); 00693 errIdx2=pResEnvironment->InsMarkedState(); 00694 FD_DF("FreeInput(...): 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 // FreeInput(HioConstraint,HioConstraint) 00729 void FreeInput( 00730 const HioConstraint& rConstraint, 00731 HioConstraint& rResConstraint) 00732 { 00733 // Call FreeInput 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 FreeInput(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 // FreeInput(HioPlant) 00751 void FreeInput(HioPlant& rPlant) { 00752 FD_DF("FreeInput( [single arg plant] " << rPlant.Name() << ")"); 00753 FreeInput(rPlant,rPlant); 00754 } 00755 00756 // FreeInput(HioController) 00757 void FreeInput(HioController& rController) { 00758 FreeInput(rController,rController); 00759 } 00760 00761 // FreeInput(HioEnvironment) 00762 void FreeInput(HioEnvironment& rEnvironment) { 00763 FreeInput(rEnvironment,rEnvironment); 00764 } 00765 00766 // FreeInput(HioConstraint) 00767 void FreeInput(HioConstraint& rConstraint) { 00768 FreeInput(rConstraint,rConstraint); 00769 } 00770 00771 00772 00773 //********************************************************** 00774 //******************** Completeness ************************ 00775 //********************************************************** 00776 00777 00778 00779 bool SupConComplete( 00780 const Generator& rPlant, 00781 const EventSet rCAlph, 00782 const Generator& rSpec, 00783 Generator& rResGen) 00784 { 00785 FD_DF("SupConComplete(" << rPlant.Name() << "," << rSpec.Name()<< ")"); 00786 00787 // exceptions on invalid parameters 00788 ControlProblemConsistencyCheck(rPlant,rCAlph,rSpec); 00789 00790 // prepare result 00791 rResGen.Clear(); 00792 rResGen.Name("SupConComplete("+rPlant.Name()+", "+rSpec.Name()+")"); 00793 00794 //check for trivial result 00795 if(rSpec.InitStatesEmpty()){ 00796 FD_DF("SupConComplete: empty language specification - empty result."); 00797 return false; 00798 } 00799 00800 // spec as candidate 00801 rResGen=rSpec; 00802 00803 // initialize set of bad states 00804 StateSet uncontrollable,dead,bad; 00805 00806 // ALGORITHM: iteratively remove uncontrollable and dead states 00807 while(true) { 00808 // check controllability and completeness, collect bad states 00809 dead=rResGen.TerminalStates(rResGen.AccessibleSet()); 00810 if (IsControllable(rPlant, rCAlph, rResGen, uncontrollable)&& dead.Empty()) { 00811 FD_DF("SupConComplete: success."); 00812 return true; 00813 } 00814 bad = uncontrollable + dead; 00815 dead.Clear(); 00816 uncontrollable.Clear(); 00817 FD_DF("SupConComplete: deleting bad states: " << bad.ToString()); 00818 // remove bad states 00819 StateSet::Iterator sit; 00820 for(sit = bad.Begin(); sit != bad.End(); sit ++){ 00821 rResGen.DelState(*sit); 00822 } 00823 00824 // return false if candidate is empty 00825 if(rResGen.InitStatesEmpty()) { 00826 FD_DF("SupConComplete: failed. empty language result."); 00827 return false; 00828 } 00829 } 00830 00831 } 00832 00833 //********************************************************** 00834 //******************** I/O-shuffle ************************ 00835 //********************************************************** 00836 00837 //******************** current version: marked parameters + marking of alternation ************************ 00838 00839 // MarkIoShuffle(rGen1,rGen2,rMapOrigToResult,rShuffle) 00840 void MarkIoShuffle(const vGenerator& rGen1,const vGenerator& rGen2, 00841 const std::map< std::pair<Idx,Idx>, Idx >& rMapOrigToResult, 00842 vGenerator& rShuffle) { 00843 00844 // invert mapOrigToResult (possible, as map is expected to be from parallel composition and thus must be bijective) 00845 std::map< Idx, std::pair<Idx,Idx> > mapResultToOrig; 00846 std::map< std::pair<Idx,Idx>, Idx >::const_iterator iter; 00847 for( iter = rMapOrigToResult.begin(); iter != rMapOrigToResult.end(); ++iter ) { 00848 mapResultToOrig.insert(std::make_pair( iter->second, iter->first )); 00849 } 00850 00851 // (I) duplicate all non-marked states, whose corresponding state in rGen1 or rGen2 is marked. 00852 StateSet nonmarked=rShuffle.States()-rShuffle.MarkedStates(); 00853 StateSet::Iterator sit; 00854 std::map< Idx, Idx > rGen1Clones,rGen2Clones; 00855 for(sit = nonmarked.Begin(); sit != nonmarked.End(); sit ++) { 00856 // marked in rGen1? 00857 if(rGen1.ExistsMarkedState(mapResultToOrig[*sit].first)) { 00858 rGen1Clones[*sit]=rShuffle.InsMarkedState(); 00859 } 00860 // marked in rGen2? 00861 if(rGen2.ExistsMarkedState(mapResultToOrig[*sit].first)) { 00862 rGen2Clones[*sit]=rShuffle.InsMarkedState(); 00863 } 00864 } 00865 00866 // (II) MOVE HEAD OF rGen1-transitions whose X2 has a rGen1-clone, and head of rGen2-transitions whose 00867 // X2 has a rGen2-clone 00868 TransSet TransToClear, TransToSet; 00869 TransSet::Iterator tit=rShuffle.TransRelBegin(); 00870 TransSet::Iterator tit_end=rShuffle.TransRelEnd(); 00871 std::map<Idx,Idx>::iterator cloneit; 00872 bool x1hasGen1Clone,x1hasGen2Clone, x2hasClone; 00873 for(;tit!=tit_end;tit++) { 00874 00875 x1hasGen1Clone=false; 00876 x1hasGen2Clone=false; 00877 x2hasClone=false; 00878 00879 //################################################## 00880 // CASE (I) - X2 has clone: move head of transition, also duplicate transition if X1 has clone 00881 //################################################## 00882 00883 // preliminarily check if X1 has clone 00884 cloneit=rGen1Clones.find(tit->X1); 00885 if(cloneit!=rGen1Clones.end()) x1hasGen1Clone=true; 00886 cloneit=rGen2Clones.find(tit->X1); 00887 if(cloneit!=rGen2Clones.end()) x1hasGen2Clone=true; 00888 00889 00890 // distinguish rGen1-events and rGen2-events 00891 if(rGen1.Alphabet().Exists(tit->Ev)) { 00892 // exists rGen1-clone? 00893 cloneit=rGen1Clones.find(tit->X2); 00894 if(cloneit!=rGen1Clones.end()) { 00895 x2hasClone=true; 00896 // move head to clone: delete original trans, insert moved trans 00897 TransToClear.Insert(*tit); 00898 TransToSet.Insert(tit->X1,tit->Ev,rGen1Clones[tit->X2]); 00899 // if X1 has a clone make copy starting from clone of X1 00900 if(x1hasGen1Clone) { 00901 TransToSet.Insert(rGen1Clones[tit->X1],tit->Ev,rGen1Clones[tit->X2]); 00902 } 00903 if(x1hasGen2Clone) { 00904 TransToSet.Insert(rGen2Clones[tit->X1],tit->Ev,rGen1Clones[tit->X2]); 00905 } 00906 } 00907 } 00908 00909 // else, tit is rGen2-transition 00910 else { 00911 // exists rGen2-clone? 00912 cloneit=rGen2Clones.find(tit->X2); 00913 if(cloneit!=rGen2Clones.end()) { 00914 x2hasClone=true; 00915 // move head to clone: delete original trans, insert moved trans 00916 TransToClear.Insert(*tit); 00917 TransToSet.Insert(tit->X1,tit->Ev,cloneit->second); 00918 // if X1 has a clone make copy starting from clone of X1 00919 if(x1hasGen1Clone) { 00920 TransToSet.Insert(rGen1Clones[tit->X1],tit->Ev,rGen2Clones[tit->X2]); 00921 } 00922 if(x1hasGen2Clone) { 00923 TransToSet.Insert(rGen2Clones[tit->X1],tit->Ev,rGen2Clones[tit->X2]); 00924 } 00925 } 00926 } 00927 00928 //################################################### 00929 // CASE (II) - (only) X1 has clone: duplicate transition (see Case I for case also X2 has clone) 00930 //################################################### 00931 00932 if( (x1hasGen1Clone||x1hasGen2Clone) && !x2hasClone ) { 00933 if(x1hasGen1Clone) TransToSet.Insert(rGen1Clones[tit->X1],tit->Ev,tit->X2); 00934 if(x1hasGen2Clone) TransToSet.Insert(rGen2Clones[tit->X1],tit->Ev,tit->X2); 00935 } 00936 } 00937 00938 // clear invalid transitions 00939 tit=TransToClear.Begin(); 00940 tit_end=TransToClear.End(); 00941 for(;tit!=tit_end;tit++) rShuffle.ClrTransition(*tit); 00942 00943 // set updated transitions 00944 tit=TransToSet.Begin(); 00945 tit_end=TransToSet.End(); 00946 for(;tit!=tit_end;tit++) rShuffle.SetTransition(*tit); 00947 00948 // cosmetics 00949 rShuffle.Accessible(); 00950 return; 00951 } 00952 00953 // MarkAlternationAB(Aset,Bset,AltAB) 00954 void MarkAlternationAB( 00955 const EventSet rAset, 00956 const EventSet rBset, 00957 Generator& rAltAB) 00958 { 00959 FD_DF("MarkAlternationAB()"); 00960 00961 #ifdef FAUDES_CHECKED 00962 // validate parameters 00963 if (rAset.Empty()){ 00964 std::stringstream errstr; 00965 errstr << "Empty parameter rAset."; 00966 throw Exception("CheapAltAnB", errstr.str(), 0); 00967 } 00968 if (rBset.Empty()){ 00969 std::stringstream errstr; 00970 errstr << "Empty parameter rBset."; 00971 throw Exception("CheapAltAnB", errstr.str(), 0); 00972 } 00973 #endif 00974 00975 rAltAB.Clear(); 00976 rAltAB.InjectAlphabet(rAset+rBset); 00977 00978 Idx s1,s2,s3,s4,s5; 00979 00980 s1=rAltAB.InsInitState(); 00981 rAltAB.SetMarkedState(s1); 00982 s2=rAltAB.InsMarkedState(); 00983 s3=rAltAB.InsMarkedState(); 00984 s4=rAltAB.InsState(); 00985 s5=rAltAB.InsState(); 00986 EventSet::Iterator evit=rAset.Begin(); 00987 EventSet::Iterator evit_end=rAset.End(); 00988 for(;evit!=evit_end;++evit) { 00989 rAltAB.SetTransition(s1,*evit,s2); 00990 rAltAB.SetTransition(s2,*evit,s4); 00991 rAltAB.SetTransition(s3,*evit,s2); 00992 rAltAB.SetTransition(s4,*evit,s4); 00993 rAltAB.SetTransition(s5,*evit,s2); 00994 } 00995 evit=rBset.Begin(); 00996 evit_end=rBset.End(); 00997 for(;evit!=evit_end;++evit) { 00998 rAltAB.SetTransition(s1,*evit,s3); 00999 rAltAB.SetTransition(s2,*evit,s3); 01000 rAltAB.SetTransition(s3,*evit,s5); 01001 rAltAB.SetTransition(s4,*evit,s3); 01002 rAltAB.SetTransition(s5,*evit,s5); 01003 } 01004 } 01005 01006 // IoShuffleUnchecked(rPlantA,rPlantB,rYp,rUp,rYe,rUe,rIOShuffAB) 01007 void IoShuffleUnchecked( 01008 const Generator& rPlantA, 01009 const Generator& rPlantB, 01010 const EventSet& rYp, 01011 const EventSet& rUp, 01012 const EventSet& rYe, 01013 const EventSet& rUe, 01014 Generator& rIOShuffAB) 01015 { 01016 FD_DF("IoShuffle()"); 01017 01018 //Extract alphabets: 01019 EventSet A,B,SigmaP; 01020 A = rPlantA.Alphabet(); 01021 B = rPlantB.Alphabet(); 01022 01023 // parallel composition of plantA and plantB (i.e. shuffle as there are no shared events) 01024 Generator parallel1, parallel2; 01025 std::map< std::pair<Idx,Idx>, Idx > MapOrigToResult; 01026 Parallel(rPlantA,rPlantB,MapOrigToResult,parallel1); 01027 MarkIoShuffle(rPlantA,rPlantB,MapOrigToResult,parallel1); 01028 01029 // restrict to event pairs [(SigA SigA)*+(SigB SigB)*]*, which results 01030 // in correct I/O sorting L_IO. 01031 Generator EventPairs; // generator of above sorting language 01032 EventPairs.InjectAlphabet(A + B); 01033 Idx state1,state2,state3; 01034 state1=EventPairs.InsInitState("1"); 01035 EventPairs.SetMarkedState(state1); 01036 state2=EventPairs.InsMarkedState("2"); 01037 state3=EventPairs.InsMarkedState("3"); 01038 EventSet::Iterator evit; 01039 for (evit = A.Begin(); evit != A.End(); ++evit) { 01040 EventPairs.SetTransition(state1,*evit,state2); 01041 EventPairs.SetTransition(state2,*evit,state1); 01042 } 01043 for (evit = B.Begin(); evit != B.End(); ++evit) { 01044 EventPairs.SetTransition(state1,*evit,state3); 01045 EventPairs.SetTransition(state3,*evit,state1); 01046 } 01047 Parallel(parallel1,EventPairs,parallel2); 01048 parallel1 = parallel2; 01049 01050 // //##################################################################################### 01051 // //##################################################################################### 01052 // //##################################################################################### 01053 // //restrict to IO-sorting structure with forced alternation: 01054 // 01055 // // Old Vers before Dez 4 2006: Alternation of whole alphabets 01056 // A = rPlantA.Alphabet(); 01057 // B = rPlantB.Alphabet(); 01058 // 01059 // 01060 //// // New Vers: Alternation of YP Events only 01061 //// // -> currently leads to normality problems during superposed controller synthesis 01062 //// SigmaP.SetUnion(rYp); 01063 //// SigmaP.SetUnion(rUp); 01064 //// A.SetIntersection(SigmaP); 01065 //// B.SetIntersection(SigmaP); 01066 // 01067 // 01068 // 01069 // Generator AltAB; 01070 // A.Name("A"); 01071 // B.Name("B"); 01072 // CheapAltAB(A,B,Depth,AltAB); 01073 // // Alt_AB.Write("tmp_Alternation_AB.gen"); 01074 // Parallel(parallel2, AltAB, parallel1); 01075 // //parallel2.Write("tmp_IOS3.gen"); 01076 // 01077 // 01078 // 01079 01080 01081 // bugfix to resolve normality problem: whenever plant A 01082 // can send a yp-event and at the same time plant B can 01083 // send a ye-event, then let the ye-event be sent first: 01084 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 01085 //*** Environment-first policy: If, in some state both, Yp- and Ye events are 01086 //*** active, then cancel all Yp-transitions in this state, as environment has 01087 //*** to be updated first. 01088 01089 FD_DF("------ IoShuffle with Environment-First-Policy! -----"); 01090 01091 // loop all states 01092 StateSet::Iterator sit = parallel1.StatesBegin(); 01093 StateSet::Iterator sit_end = parallel1.StatesEnd(); 01094 01095 for(; sit != sit_end; sit++) 01096 { 01097 // figure active Yp-events and active Ye-events 01098 //std::cout << "End: " << *sit_end <<"...done: " << *sit << std::endl; 01099 EventSet ActiveYe; 01100 EventSet ActiveYp = parallel1.TransRel().ActiveEvents(*sit); 01101 ActiveYe=ActiveYp; 01102 ActiveYe.SetIntersection(rYe); 01103 ActiveYp.SetIntersection(rYp); 01104 if (!(ActiveYe.Empty())&& !(ActiveYp.Empty())) 01105 { 01106 TransSet TransToClear; 01107 TransSet::Iterator tit=parallel1.TransRelBegin(*sit); 01108 TransSet::Iterator tit_end=parallel1.TransRelEnd(*sit); 01109 for(;tit!=tit_end;tit++) 01110 { 01111 //std::cout << "finding Yp-events to delete... "; 01112 if(ActiveYp.Exists(tit->Ev)) 01113 { 01114 TransToClear.Insert(*tit); 01115 } 01116 } 01117 tit=TransToClear.Begin(); 01118 tit_end=TransToClear.End(); 01119 for(;tit!=tit_end;tit++) 01120 { 01121 //std::cout<<" ...deleting" <<std::endl; 01122 parallel1.ClrTransition(*tit); 01123 } 01124 } 01125 } 01126 01127 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 01128 01129 01130 01131 //~ //// 01132 //~ // //##################################################################################### 01133 //~ // //##################################################################################### 01134 //~ // //##################################################################################### 01135 01136 01137 // Insert Error Behaviour, i.e. make UP and UE free in (YP,UP)-port of result: 01138 // free UP: 01139 FreeInput(parallel1, rUp, rYp, parallel2, "errYp_Ye", "errUp"); 01140 //parallel1.Write("tmp_IOS4.gen"); 01141 // free UE: 01142 FreeInput(parallel2, rUe, rYe, parallel1, "errYp_Ye", "errUe"); 01143 //parallel2.Write("tmp_IOS5.gen"); 01144 01145 // Mark Alternation of YP-events 01146 A.SetIntersection(rYp); 01147 B.SetIntersection(rYp); 01148 MarkAlternationAB(A,B,parallel2); 01149 Parallel(parallel2,parallel1,parallel1); 01150 01151 rIOShuffAB = parallel1; 01152 rIOShuffAB.Name("IoShuffle("+rPlantA.Name()+rPlantB.Name()+")"); 01153 return; 01154 } 01155 01156 01157 // IoShuffle(rPlantA,rPlantB,rYp,rUp,rYe,rUe,rIOShuffAB) 01158 void IoShuffle( 01159 const Generator& rPlantA, 01160 const Generator& rPlantB, 01161 const EventSet& rYp, 01162 const EventSet& rUp, 01163 const EventSet& rYe, 01164 const EventSet& rUe, 01165 Generator& rIOShuffAB) 01166 { 01167 rIOShuffAB.Clear(); 01168 #ifdef FAUDES_CHECKED 01169 // exception on empty alphabets 01170 if (rYp.Empty()){ 01171 std::stringstream errstr; 01172 errstr << "Empty Yp alphabet\n"; 01173 throw Exception("IoShuffle", errstr.str(), 0); 01174 } 01175 if (rUp.Empty()){ 01176 std::stringstream errstr; 01177 errstr << "Empty Up alphabet\n"; 01178 throw Exception("IoShuffle", errstr.str(), 0); 01179 } 01180 if (rYe.Empty()){ 01181 std::stringstream errstr; 01182 errstr << "Empty Ye alphabet\n"; 01183 throw Exception("IoShuffle", errstr.str(), 0); 01184 } 01185 if (rUe.Empty()){ 01186 std::stringstream errstr; 01187 errstr << "Empty Ue alphabet\n"; 01188 throw Exception("IoShuffle", errstr.str(), 0); 01189 } 01190 01191 // create resulting alphabet while checking for disjoint sets 01192 EventSet alphabet,alphabetA,alphabetB,errevents; 01193 alphabetA=rPlantA.Alphabet(); 01194 alphabetB=rPlantB.Alphabet(); 01195 // initialize with rYp 01196 alphabet.SetUnion(rYp); 01197 // insert remaining events one by one and check if new 01198 EventSet::Iterator evit; 01199 // rUp 01200 for (evit = rUp.Begin(); evit != rUp.End(); ++evit) { 01201 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 01202 } 01203 // rYe 01204 for (evit = rYe.Begin(); evit != rYe.End(); ++evit) { 01205 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 01206 } 01207 // rUe 01208 for (evit = rUe.Begin(); evit != rUe.End(); ++evit) { 01209 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 01210 } 01211 // throw exception on non disjoint alphabets 01212 if (!errevents.Empty()){ 01213 std::stringstream errstr; 01214 errstr << "Non-disjoint parameters; ambiguous events:\n" <<errevents.ToString(); 01215 throw Exception("IoShuffle", errstr.str(), 0); 01216 } 01217 01218 // check alphabet match with plant A and B-alphabets: 01219 // The union of plant A and B alphabets need not equal but must be included in the union of EventSet parameters. 01220 01221 errevents=alphabetA+alphabetB-alphabet; 01222 if (!errevents.Empty()){ 01223 std::stringstream errstr; 01224 errstr << "Plant A- or plant B-events missing in Yp,Up,Ye or Ue:\n" <<errevents.ToString(); 01225 throw Exception("IoShuffle", errstr.str(), 0); 01226 } 01227 01228 // plant A and plant B must be in IoPlantForm 01229 HioPlant hioPlantA=HioPlant(rPlantA,rYp*alphabetA,rUp*alphabetA,rYe*alphabetA,rUe*alphabetA); 01230 std::string report; 01231 if(!IsIoPlantForm(hioPlantA,report)){ 01232 std::stringstream errstr; 01233 errstr << "plant A not in IoPlantForm:\n" << report; 01234 throw Exception("IoShuffle", errstr.str(), 0); 01235 } 01236 01237 HioPlant hioPlantB=HioPlant(rPlantB,rYp*alphabetB,rUp*alphabetB,rYe*alphabetB,rUe*alphabetB); 01238 report.clear(); 01239 if(!IsIoPlantForm(hioPlantB,report)){ 01240 std::stringstream errstr; 01241 errstr << "plant B not in IoPlantForm:\n" << report; 01242 throw Exception("IoShuffle", errstr.str(), 0); 01243 } 01244 #endif 01245 01246 // compute I/O-shuffle 01247 IoShuffleUnchecked(rPlantA, rPlantB, rYp, rUp, rYe, rUe, rIOShuffAB); 01248 01249 } 01250 01251 void IoShuffle( 01252 const HioPlant& rPlantA, 01253 const HioPlant& rPlantB, 01254 HioPlant& rIOShuffAB) { 01255 01256 //prepare result 01257 rIOShuffAB.Clear(); 01258 01259 EventSet yp = rPlantA.YpEvents()+rPlantB.YpEvents(); 01260 EventSet up = rPlantA.UpEvents()+rPlantB.UpEvents(); 01261 EventSet ye = rPlantA.YeEvents()+rPlantB.YeEvents(); 01262 EventSet ue = rPlantA.UeEvents()+rPlantB.UeEvents(); 01263 01264 // compute I/O-shuffle 01265 IoShuffle(rPlantA, rPlantB, yp, up, ye, ue, rIOShuffAB); 01266 01267 // set event and state attributes 01268 rIOShuffAB.SetYp(yp); 01269 rIOShuffAB.SetUp(up); 01270 rIOShuffAB.SetYe(ye); 01271 rIOShuffAB.SetUe(ue); 01272 01273 IsIoPlantForm(rIOShuffAB); 01274 } 01275 //******************** old version: no marking, forced alternation ************************ 01276 01277 // CheapAltAnB(rAset,rBset,Depth,rAltAnB) 01278 void CheapAltAnB( 01279 const EventSet rAset, 01280 const EventSet rBset, 01281 const int Depth, 01282 Generator& rAltAnB) 01283 { 01284 FD_DF("CheapAltAnB()"); 01285 01286 // validate parameters 01287 if (Depth<1){ 01288 std::stringstream errstr; 01289 errstr << "Parameter Depth must be 1 or greater."; 01290 throw Exception("CheapAltAnB", errstr.str(), 0); 01291 } 01292 #ifdef FAUDES_CHECKED 01293 if (rAset.Empty()){ 01294 std::stringstream errstr; 01295 errstr << "Empty parameter rAset."; 01296 throw Exception("CheapAltAnB", errstr.str(), 0); 01297 } 01298 if (rBset.Empty()){ 01299 std::stringstream errstr; 01300 errstr << "Empty parameter rBset."; 01301 throw Exception("CheapAltAnB", errstr.str(), 0); 01302 } 01303 #endif 01304 01305 // prepare result 01306 rAltAnB.Clear(); 01307 rAltAnB.Name("CheapAltAnB(" + rAset.Name() + "," + rBset.Name() + "," + ToStringInteger(Depth) + ")"); 01308 01309 // create initial state 01310 Idx init = rAltAnB.InsInitState("alt_"+rAset.Name()+"_init"); 01311 rAltAnB.SetMarkedState(init); 01312 01313 Idx last = init; 01314 rAltAnB.InjectAlphabet(rAset + rBset); 01315 01316 // selfloop initial state with Bset: 01317 EventSet::Iterator evit; 01318 for (evit = rBset.Begin(); evit != rBset.End(); ++evit) { 01319 rAltAnB.SetTransition(last,*evit,last); 01320 } 01321 01322 //create n concatenated pathes A->|a|A->|b| and transitions B from |b| to initial state. 01323 for (int i=0; i!=Depth; ++i) { 01324 Idx a = rAltAnB.InsMarkedState("alt_"+rAset.Name()+"_U"+ToStringInteger(i+1)); 01325 Idx b = rAltAnB.InsMarkedState("alt_"+rAset.Name()+"_Y"+ToStringInteger(i+2)); 01326 //connect last,a and b with A-transitions. 01327 for (evit = rAset.Begin(); evit != rAset.End(); ++evit) { 01328 rAltAnB.SetTransition(last,*evit,a); 01329 rAltAnB.SetTransition(a,*evit,b); 01330 } 01331 //insert B-transitions from b to init 01332 for (evit = rBset.Begin(); evit != rBset.End(); ++evit) { 01333 rAltAnB.SetTransition(b,*evit,init); 01334 } 01335 last = b; 01336 } 01337 } 01338 01339 // CheapAltAB(rAset,rBset,Depth,rAltAnB) 01340 void CheapAltAB( 01341 const EventSet rAset, 01342 const EventSet rBset, 01343 const int Depth, 01344 Generator& rAltAB) 01345 { 01346 FD_DF("CheapAltAB()"); 01347 // prepare result 01348 rAltAB.Clear(); 01349 01350 Generator AnB, BnA; 01351 CheapAltAnB(rAset,rBset,Depth,AnB); 01352 CheapAltAnB(rBset,rAset,Depth,BnA); 01353 Parallel(AnB,BnA,rAltAB); 01354 rAltAB.Name("CheapAltAB("+rAset.Name()+","+rBset.Name()+","+ToStringInteger(Depth)+")"); 01355 } 01356 01357 // IoShuffleTU(rPlantA,rPlantB,rYp,rUp,rYe,rUe,Depth,rIOShuffAB) 01358 void IoShuffleTU( 01359 const Generator& rPlantA, 01360 const Generator& rPlantB, 01361 const EventSet& rUp, 01362 const EventSet& rYp, 01363 const EventSet& rYe, 01364 const EventSet& rUe, 01365 const int Depth, 01366 Generator& rIOShuffAB) 01367 { 01368 FD_DF("IoShuffle()"); 01369 01370 //Extract alphabets: 01371 EventSet A,B,SigmaP; 01372 A = rPlantA.Alphabet(); 01373 B = rPlantB.Alphabet(); 01374 01375 // parallel composition of plantA and plantB (i.e. shuffle as there are no shared events) 01376 Generator parallel1, parallel2; 01377 Parallel(rPlantA,rPlantB,parallel1); 01378 01379 // restrict to event pairs [(SigA SigA)*+(SigB SigB)*]*, which results 01380 // in correct I/O sorting L_IO. 01381 Generator EventPairs; // generator of above sorting language 01382 EventPairs.InjectAlphabet(A + B); 01383 Idx state1,state2,state3; 01384 state1=EventPairs.InsInitState("1"); 01385 EventPairs.SetMarkedState(state1); 01386 state2=EventPairs.InsMarkedState("2"); 01387 state3=EventPairs.InsMarkedState("3"); 01388 EventSet::Iterator evit; 01389 for (evit = A.Begin(); evit != A.End(); ++evit) { 01390 EventPairs.SetTransition(state1,*evit,state2); 01391 EventPairs.SetTransition(state2,*evit,state1); 01392 } 01393 for (evit = B.Begin(); evit != B.End(); ++evit) { 01394 EventPairs.SetTransition(state1,*evit,state3); 01395 EventPairs.SetTransition(state3,*evit,state1); 01396 } 01397 Parallel(parallel1,EventPairs,parallel2); 01398 01399 //restrict to IO-sorting structure with forced alternation: 01400 01401 //////// // Old Vers before Dez 4 2006: Alternation of whole alphabets 01402 //////// A = rPlantA.Alphabet(); 01403 //////// B = rPlantB.Alphabet(); 01404 ////// 01405 ////// // New Vers: Alternation of YP Events only 01406 ////// // -> currently leads to normality problems during superposed controller synthesis 01407 ////// SigmaP.SetUnion(rYp); 01408 ////// SigmaP.SetUnion(rUp); 01409 ////// A.SetIntersection(SigmaP); 01410 ////// B.SetIntersection(SigmaP); 01411 ////// 01412 ////// 01413 ////// Generator AltAB; 01414 ////// A.Name("A"); 01415 ////// B.Name("B"); 01416 ////// CheapAltAB(A,B,Depth,AltAB); 01417 ////// // Alt_AB.Write("tmp_Alternation_AB.gen"); 01418 ////// Parallel(parallel2, AltAB, parallel1); 01419 ////// //parallel2.Write("tmp_IOS3.gen"); 01420 01421 // Old Vers before Dez 4 2006: Alternation of whole alphabets 01422 EventSet Ap, Bp, Ae, Be, SigmaE; 01423 01424 Ap = rPlantA.Alphabet(); 01425 Bp = rPlantB.Alphabet(); 01426 01427 Ae = rPlantA.Alphabet(); 01428 Be = rPlantB.Alphabet(); 01429 01430 01431 01432 //************************************************************************* 01433 //// New Vers: Alternation of YP Events only 01434 //// -> currently leads to normality problems during superposed controller synthesis 01435 SigmaP.SetUnion(rYp); 01436 SigmaP.SetUnion(rUp); 01437 Ap.SetIntersection(SigmaP); 01438 Bp.SetIntersection(SigmaP); 01439 01440 SigmaE.SetUnion(rYe); 01441 SigmaE.SetUnion(rUe); 01442 Ae.SetIntersection(SigmaE); 01443 Be.SetIntersection(SigmaE); 01444 01445 01446 //************************************************************************* 01447 Generator AltAB; 01448 Ap.Name("A"); 01449 Bp.Name("B"); 01450 CheapAltAB(Ap,Bp,Depth,AltAB); 01451 // Alt_AB.Write("tmp_Alternation_AB.gen"); 01452 Parallel(parallel2, AltAB, parallel1); 01453 01454 /* // bugfix to resolve normality problem: whenever plant A 01455 * // can send a yp-event and at the same time plant B can 01456 * // send a ye-event, then let the ye-event be sent first: 01457 * //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 01458 * // Environment-first policy: If, in some state both, Yp- and Ye events are 01459 * // active, then cancel all Yp-transitions in this state, as environment has 01460 * // to be updated first. 01461 * 01462 * // loop all states 01463 * StateSet::Iterator sit = parallel1.StatesBegin(); 01464 * StateSet::Iterator sit_end = parallel1.StatesEnd(); 01465 * 01466 * for(; sit != sit_end; sit++) 01467 * { 01468 * // figure active Yp-events and active Ye-events 01469 * //std::cout << "End: " << *sit_end <<"...done: " << *sit << std::endl; 01470 * EventSet ActiveYe; 01471 * EventSet ActiveYp = parallel1.TransRel().ActiveEvents(*sit); 01472 * ActiveYe=ActiveYp; 01473 * ActiveYe.SetIntersection(rYe); 01474 * ActiveYp.SetIntersection(rYp); 01475 * if (!(ActiveYe.Empty())&& !(ActiveYp.Empty())) 01476 * { 01477 * TransSet TransToClear; 01478 * TransSet::Iterator tit=parallel1.TransRelBegin(*sit); 01479 * TransSet::Iterator tit_end=parallel1.TransRelEnd(*sit); 01480 * for(;tit!=tit_end;tit++) 01481 * { 01482 * //std::cout << "finding Yp-events to delete... "; 01483 * if(ActiveYp.Exists(tit->Ev)) 01484 * { 01485 * TransToClear.Insert(*tit); 01486 * } 01487 * } 01488 * tit=TransToClear.Begin(); 01489 * tit_end=TransToClear.End(); 01490 * for(;tit!=tit_end;tit++) 01491 * { 01492 * //std::cout<<" ...deleting" <<std::endl; 01493 * parallel1.ClrTransition(*tit); 01494 * } 01495 * } 01496 * } 01497 * 01498 * //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 01499 * 01500 */ 01501 01502 01503 // Insert Error Behaviour, i.e. make UP and UE free in (YP,UP)-port of result: 01504 // free UP: 01505 FreeInput(parallel1, rUp, rYp, parallel2, "errYp_Ye", "errUp"); 01506 //parallel1.Write("tmp_IOS4.gen"); 01507 // free UE: 01508 FreeInput(parallel2, rUe, rYe, parallel1, "errYp_Ye", "errUe"); 01509 //parallel2.Write("tmp_IOS5.gen"); 01510 01511 rIOShuffAB = parallel1; 01512 } 01513 01514 //********************************************************** 01515 //******************** Cycles ************************ 01516 //********************************************************** 01517 01518 01519 // ***Search for strongly connected ycless components (SCC)*** 01520 // This function partitions the stateset of a generator into equivalent classes 01521 // such that states x1 and x2 are equivalent iff there is a ycless path from x1 01522 // to x2 AND a ycless path from x2 to x1. 01523 // This function implements the algorithm based on a depth first search 01524 // presented in: 01525 // -Aho, Hopcroft, Ullman: The Design and Analysis of Computer Algorithms- 01526 // 01527 // Most of the comments in this function have been literally taken from 01528 // this book! 01529 // 01530 // Parameters (an api with generator and Yc-events as input and SCCs as output 01531 // is provided right below this method.) 01532 // -state: State, from which the current recursion is started. 01533 // -rcount: denotes the current depth of the recursion. 01534 // -Yc: set of Yc-events 01535 // -UnMarkedOnly: if set true, being unmarked is an additional condition for equivalence of states 01536 // -NewStates: Set of states that up to now were not found by the depth first search 01537 // -STACK: stack of state indeces 01538 // -StackStates: set of states whose indeces are on STACK. 01539 // -DFN: map assigning to each state its Depth-First Number 01540 // -LOWLINK: map assigning to each state its LOWLINK Number 01541 // -SCCset: result - the set of strongly connected components 01542 // -UnMarkedSCCset: result - the set of strongly connected components consisting exclusively of marked states 01543 // -Roots: result - the set of states that each are root of some SCC. 01544 // 01545 // ToDo: handle exceptions. 01546 // 01547 01548 void SearchYclessScc( 01549 const Idx state, 01550 int& rcount, // why is this a ref? 01551 const Generator& rGen, 01552 const EventSet& rYc, 01553 const bool UnMarkedOnly, 01554 StateSet& rNewStates, 01555 std::stack<Idx>& rSTACK, 01556 StateSet& rStackStates, 01557 std::map<const Idx, int>& rDFN, 01558 std::map<const Idx, int>& rLOWLINK, 01559 std::set<StateSet>& rSccSet, 01560 StateSet& rRoots) 01561 { 01562 FD_DF("SerchYclessScc: -- search from state "<< state << "--"); 01563 01564 // mark state "old"; 01565 rNewStates.Erase(state); 01566 01567 // DFNUMBER[state] <- count; 01568 rDFN[state]=rcount; 01569 01570 // count <- count+1; 01571 rcount++; 01572 01573 // LOWLINK[v] <- DFNUMBER[v]; 01574 rLOWLINK[state]=rDFN[state]; 01575 //cout<<"count: "<<rcount<<" state: "<<state<<" DFN: "<<rDFN[state]<<endl; 01576 01577 // push state on STACK; 01578 rSTACK.push(state); 01579 rStackStates.Insert(state); 01580 01581 //<<create set "L[state]" of successor states of state, without states reached via a Yc-event: 01582 StateSet SuccStates = StateSet(); 01583 TransSet::Iterator it = rGen.TransRelBegin(state); 01584 TransSet::Iterator it_end = rGen.TransRelEnd(state); 01585 for (; it != it_end; ++it) { 01586 if(!rYc.Exists(it->Ev)||(UnMarkedOnly &! rGen.ExistsMarkedState(it->X2))) 01587 { 01588 SuccStates.Insert(it->X2); 01589 } 01590 } 01591 01592 // for each vertex *sit on L[state] do 01593 StateSet::Iterator sit = SuccStates.Begin(); 01594 StateSet::Iterator sit_end = SuccStates.End(); 01595 for (; sit != sit_end; ++sit) 01596 { 01597 // if *sit is marked "new" then 01598 if(rNewStates.Exists(*sit)) 01599 {// begin 01600 01601 // SearchC(*sit); 01602 SearchYclessScc(*sit, rcount, rGen, rYc, UnMarkedOnly, rNewStates, rSTACK, rStackStates, rDFN, rLOWLINK, rSccSet, rRoots); 01603 // LOWLINK[state] <- MIN(LOWLINK[state],LOWLINK[*sit]); 01604 if(rLOWLINK[*sit]<rLOWLINK[state]) 01605 { 01606 rLOWLINK[state]=rLOWLINK[*sit]; 01607 } 01608 }//end 01609 01610 else 01611 { 01612 // if DFNUMBER[*sit]<DFNUMBER[state] and [*sit] is on STACK then 01613 if((rDFN[*sit]<rDFN[state])&&(rStackStates.Exists(*sit))) 01614 { 01615 // LOWLINK[state]<-MIN(DFNUMBER[*sit],LOWLINK[state]); 01616 if(rDFN[*sit]<rLOWLINK[state]) 01617 { 01618 rLOWLINK[state]=rDFN[*sit]; 01619 } 01620 } 01621 } 01622 }//end for 01623 // if LOWLINK[state]=DFNUMBER[state] (i.e. state is root of a SCC) then 01624 if((rLOWLINK[state]==rDFN[state])) 01625 { 01626 // per def., each state in a graph is element of a SCC, thus: 01627 // check if size of SCC is>1 or (else) SCC contains (non-{epsilon,yc}-)selfloops 01628 // to avoid print of trivial SCCs 01629 bool realscc=rSTACK.top()!=state; //size of SCC>1 ? if not, check for selfloops: 01630 if(!realscc) 01631 { 01632 TransSet::Iterator it = rGen.TransRelBegin(state); 01633 TransSet::Iterator it_end = rGen.TransRelEnd(state); 01634 for (; it != it_end; ++it) 01635 { 01636 if((it->X2==state)&&(!rYc.Exists(it->Ev))) 01637 { 01638 realscc=true; //at least one yc-less selfloop found -> SCC is nontrivial 01639 break; 01640 } 01641 } 01642 } 01643 01644 //~ if(realscc) // be aware: "else" statement is NOT correct at this point, as realscc-value is changed in the above if-clause 01645 //~ { 01646 //~ // cout<<endl<<"found ycless SCC with root "<<state<<", consisting of the following states:"<<endl<<"begin"<<endl; 01647 //~ rRoots.Insert(state); 01648 //~ } 01649 01650 //create SCC 01651 StateSet Scc; 01652 bool purelyUnMarked=true; 01653 // begin 01654 // repeat 01655 while(true) 01656 {// begin 01657 // pop x from top of STACK and print x; 01658 Idx top=rSTACK.top(); 01659 if(realscc) // things outside the "if(realscc)"-clause have to be done in any case! 01660 { 01661 // cout<<top; 01662 Scc.Insert(top); 01663 if(rGen.ExistsMarkedState(top)) purelyUnMarked=false; 01664 } 01665 rStackStates.Erase(top); 01666 rSTACK.pop(); 01667 01668 // until x=state; 01669 if(top==state) 01670 { 01671 // print "end of SCC", insert SCC into SCCset; 01672 if(realscc) 01673 { 01674 // cout<<endl<<"end"<<endl; 01675 if(!purelyUnMarked || UnMarkedOnly) 01676 { 01677 rSccSet.insert(Scc); 01678 rRoots.Insert(state); 01679 } 01680 } 01681 //system("pause"); 01682 break; 01683 } 01684 // cout<<", "<<endl; 01685 } //end while 01686 } // end if 01687 } 01688 01689 // YclessScc(Generator,Yc-events, SccSet, Roots) 01690 // -> api using SearchYclessScc() from above. 01691 bool YclessScc( 01692 const Generator& rGen, 01693 const EventSet& rYc, 01694 std::set<StateSet>& rSccSet, 01695 StateSet& rRoots) 01696 { 01697 FD_DF("YclessScc(" << rGen.Name() << ")"); 01698 01699 // inititalize results: 01700 rRoots.Clear(); 01701 rSccSet.clear(); 01702 // initialize counter for depthfirstnumbers(DFN): 01703 int count=1; 01704 01705 // initialize stack of states (state indeces): 01706 std::stack<Idx> STACK; 01707 // due to lack of STACK-iterator: initialize set of states that are on STACK: 01708 StateSet StackStates = StateSet(); 01709 01710 // initialize set of states to be examined: 01711 StateSet NewStates=rGen.AccessibleSet(); 01712 01713 // initialize map of state indeces to their DFN: 01714 std::map<const Idx, int> DFN; 01715 // initialize map of state indeces to their LOWLINK: 01716 std::map<const Idx, int> LOWLINK; 01717 01718 // figure initial state: 01719 Idx InitState = *rGen.InitStatesBegin(); 01720 // start recursive depth-first search for Scc's: 01721 while(!NewStates.Empty()) { 01722 // the following 'if' isn't necessary, but provokes search begin at initial state of rGen 01723 if(NewStates.Exists(InitState)) { 01724 SearchYclessScc(InitState, count, rGen, rYc, false, NewStates, STACK, StackStates, DFN, LOWLINK, rSccSet, rRoots); 01725 } else { 01726 SearchYclessScc(*NewStates.Begin(), count, rGen, rYc, false, NewStates, STACK, StackStates, DFN, LOWLINK, rSccSet, rRoots); 01727 } 01728 } 01729 01730 return !rSccSet.empty(); 01731 } 01732 01733 // YclessUnMarkedScc(Generator,Yc-events, SccSet, Roots) 01734 // -> api using SearchYclessScc() from above. 01735 bool YclessUnmarkedScc( 01736 const Generator& rGen, 01737 const EventSet& rYc, 01738 std::set<StateSet>& rSccSet, 01739 StateSet& rRoots) 01740 { 01741 FD_DF("YclessScc(" << rGen.Name() << ")"); 01742 01743 // inititalize results: 01744 rRoots.Clear(); 01745 rSccSet.clear(); 01746 // initialize counter for depthfirstnumbers(DFN): 01747 int count=1; 01748 01749 // initialize stack of states (state indeces): 01750 std::stack<Idx> STACK; 01751 // due to lack of STACK-iterator: initialize set of states that are on STACK: 01752 StateSet StackStates = StateSet(); 01753 01754 // initialize set of states to be examined: 01755 StateSet NewStates=rGen.AccessibleSet()-rGen.MarkedStates(); 01756 01757 // initialize map of state indeces to their DFN: 01758 std::map<const Idx, int> DFN; 01759 // initialize map of state indeces to their LOWLINK: 01760 std::map<const Idx, int> LOWLINK; 01761 01762 // figure initial state: 01763 Idx InitState = *rGen.InitStatesBegin(); 01764 // start recursive depth-first search for Scc's: 01765 while(!NewStates.Empty()) { 01766 // the following 'if' isn't necessary, but provokes search begin at initial state of rGen 01767 if(NewStates.Exists(InitState)) { 01768 SearchYclessScc(InitState, count, rGen, rYc, true, NewStates, STACK, StackStates, DFN, LOWLINK, rSccSet, rRoots); 01769 } else { 01770 SearchYclessScc(*NewStates.Begin(), count, rGen, rYc, true, NewStates, STACK, StackStates, DFN, LOWLINK, rSccSet, rRoots); 01771 } 01772 } 01773 01774 return !rSccSet.empty(); 01775 } 01776 01777 01778 // YclessScc(rGen,rYc,rSccSet) 01779 // -> api using YclessScc() from above. 01780 bool YclessScc( 01781 const Generator& rGen, 01782 const EventSet& rYc, 01783 std::set<StateSet>& rSccSet) 01784 { 01785 FD_DF("YclessScc(" << rGen.Name() << ")"); 01786 01787 // inititalize result: 01788 rSccSet.clear(); 01789 01790 StateSet Roots; 01791 return YclessScc(rGen,rYc,rSccSet,Roots); 01792 } 01793 01794 // IsYcLive(rGen,rYc) 01795 bool IsYcLive( 01796 const Generator& rGen, 01797 const EventSet& rYc) 01798 { 01799 FD_DF("IsYcLive(" << rGen.Name() << ")"); 01800 01801 std::set<StateSet> rSccSet; 01802 01803 // Generator is YcLive if no YcLessScc is found 01804 YclessScc(rGen,rYc,rSccSet); 01805 return rSccSet.size()==0; 01806 } 01807 01808 // WriteStateSets(rStateSets) 01809 // Write set of StateSet's to console. 01810 void WriteStateSets( 01811 const std::set<StateSet>& rStateSets) 01812 { 01813 FD_DF("WriteStateSets()"); 01814 std::cout<<std::endl; 01815 if(rStateSets.empty()) { 01816 std::cout<<"WriteStateSets: Set of state sets is empty."<<std::endl; 01817 FD_DF("WriteStateSets: Set of state sets is empty."); 01818 return; 01819 } 01820 std::cout<<">WriteStateSets: Set of state sets begin:"<< std::endl; 01821 std::set<StateSet>::iterator StateSetit = rStateSets.begin(); 01822 std::set<StateSet>::iterator StateSetit_end = rStateSets.end(); 01823 for (; StateSetit != StateSetit_end; ++StateSetit) { 01824 std::cout<<std::endl<<" >> State set begin:"<< std::endl; 01825 StateSet::Iterator sit = StateSetit->Begin(); 01826 StateSet::Iterator sit_end = StateSetit->End(); 01827 for (; sit != sit_end; ++sit) { 01828 std::cout<<" >> "<<*sit<<std::endl; 01829 } 01830 std::cout<<" >> State set end."<< std::endl; 01831 } 01832 std::cout<<std::endl<<">WriteStateSets: Set of state sets end."<<std::endl; 01833 } 01834 01835 // WriteStateSets(rGen,rStateSets) 01836 // Write set of StateSet's to console. 01837 // Use rGen for symbolic state names 01838 void WriteStateSets( 01839 const Generator& rGen, 01840 const std::set<StateSet>& rStateSets) 01841 { 01842 FD_DF("WriteStateSets()"); 01843 std::cout<<std::endl; 01844 if(rStateSets.empty()) { 01845 std::cout<<"WriteStateSets: Set of state sets is empty."<<std::endl; 01846 FD_DF("WriteStateSets: Set of state sets is empty."); 01847 return; 01848 } 01849 std::cout<<">WriteStateSets: Set of state sets begin:"<< std::endl; 01850 std::set<StateSet>::iterator StateSetit = rStateSets.begin(); 01851 std::set<StateSet>::iterator StateSetit_end = rStateSets.end(); 01852 for (; StateSetit != StateSetit_end; ++StateSetit) { 01853 std::cout<<std::endl<<" >> State set begin:"<< std::endl; 01854 std::cout<<" "<<rGen.StateSetToString(*StateSetit)<<std::endl; 01855 std::cout<<" >> State set end."<< std::endl; 01856 } 01857 std::cout<<std::endl<<">WriteStateSets: Set of state sets end."<<std::endl; 01858 } 01859 01860 // SccEntries(rGen,rSccSet,rEntryStates,rEntryTransSet) 01861 void SccEntries( 01862 const Generator& rGen, 01863 const std::set<StateSet>& rSccSet, 01864 StateSet& rEntryStates, 01865 TransSetX2EvX1& rEntryTransSet) { 01866 01867 FD_DF("SccEntries(...)"); 01868 01869 // prepare results: 01870 rEntryStates.Clear(); 01871 rEntryTransSet.Clear(); 01872 01873 //extract all transitions sorted by target state X2 01874 TransSetX2EvX1 trel; 01875 rGen.TransRel(trel); 01876 FD_DF("SccEntries: Entry states of all SCCs:"); 01877 01878 //loop through all SCCs: 01879 std::set<StateSet>::iterator sccit = rSccSet.begin(); 01880 std::set<StateSet>::iterator sccit_end = rSccSet.end(); 01881 for (int i=0; sccit != sccit_end; ++sccit, i++) { 01882 FD_DF("SccEntries: SCC " << i << " begin:"); 01883 //loop through all states: 01884 StateSet::Iterator sit = sccit->Begin(); 01885 StateSet::Iterator sit_end = sccit->End(); 01886 for (; sit != sit_end; ++sit) { 01887 //check if sit is initial state: 01888 if(rGen.ExistsInitState(*sit)) { 01889 rEntryStates.Insert(*sit); 01890 } 01891 //loop through all transitions with target state X2=sit: 01892 TransSetX2EvX1::Iterator tit=trel.BeginByX2(*sit); 01893 TransSetX2EvX1::Iterator tit_end=trel.EndByX2(*sit); 01894 for(;tit!=tit_end;tit++) { 01895 //if sit is successor of a state X1 that is element of a SCC different 01896 //from the current SCC "StateSetit" and if sit has not been added to 01897 //rEntryStates up to now, then add sit to EntryStates: 01898 if(!sccit->Exists(tit->X1)) { 01899 // insert entry transition: 01900 rEntryTransSet.Insert(*tit); 01901 // if new, insert entry state: 01902 if(!rEntryStates.Exists(*sit)) { 01903 // Perk: check if Insert returns false anyway if element already 01904 // existed before. if so, then write: 01905 // if(rEntryStates.Insert(*sit)) FD_DF("SccEntries: Entry state:" <<*sit); 01906 FD_DF("SccEntries: Entry state:" <<*sit); 01907 rEntryStates.Insert(*sit); 01908 } 01909 } 01910 } 01911 } 01912 FD_DF("SccEntries: SCC " << i << " end:"); 01913 } 01914 FD_DF("SccEntries: done"); 01915 } 01916 01917 // CloneScc(rGen,rScc,rSccSet,rEntryState,rEntryStates,rEntryTransSet) 01918 void CloneScc( 01919 Generator& rGen, 01920 const StateSet& rScc, 01921 std::set<StateSet>& rSccSet, 01922 const Idx EntryState, 01923 StateSet& rEntryStates, 01924 TransSetX2EvX1& rEntryTransSet) 01925 { 01926 FD_DF("CloneScc(...)"); 01927 // initialize map from original SCC-states to their clones: 01928 std::map<const Idx, Idx> clone; 01929 // initialize clone-SCC: 01930 StateSet CloneScc; 01931 // clone SCC-states: 01932 StateSet::Iterator sit=rScc.Begin(); 01933 StateSet::Iterator sit_end=rScc.End(); 01934 for(;sit!=sit_end;sit++) { 01935 // if sit is marked, also mark its clone 01936 if(rGen.ExistsMarkedState(*sit)) { 01937 clone[*sit]=rGen.InsMarkedState(); 01938 CloneScc.Insert(clone[*sit]); 01939 // cout<<"marked state "<<clone[*sit]<<" of "<<*sit<<" inserted."; 01940 } 01941 // or else insert unmarked state 01942 else { 01943 clone[*sit]=rGen.InsState(); 01944 CloneScc.Insert(clone[*sit]); 01945 // cout<<"unmarked state "<<clone[*sit]<<" of "<<*sit<<" inserted."; 01946 } 01947 } 01948 // add clone of SCC to set of all SCCs: 01949 rSccSet.insert(CloneScc); 01950 // clone all transitions: 01951 sit=rScc.Begin(); 01952 for(;sit!=sit_end;sit++) { 01953 TransSet::Iterator tit=rGen.TransRelBegin(*sit); 01954 TransSet::Iterator tit_end=rGen.TransRelEnd(*sit); 01955 for(;tit!=tit_end;tit++) { 01956 // clone all transitions within SCC: 01957 if(rScc.Exists(tit->X2)) { 01958 rGen.SetTransition(clone[*sit],tit->Ev,clone[tit->X2]); 01959 } 01960 //...and transitions leaving the SC: 01961 else { 01962 rGen.SetTransition(clone[*sit],tit->Ev,tit->X2); 01963 //**** added 06.09.2007: 01964 // If this cloned transition leads to an entry state of 01965 // some other SCC, then it is a new entry transition: 01966 if(rEntryStates.Exists(tit->X2)) { 01967 rEntryTransSet.Insert(clone[*sit],tit->Ev,tit->X2); 01968 } 01969 //**** 01970 } 01971 } 01972 } 01973 // move the head of all entry transitions leading to EntryState to the clone of EntryState: 01974 TransSet TransToClear, EntryTransToInsert; 01975 TransSetX2EvX1::Iterator tit=rEntryTransSet.BeginByX2(EntryState); 01976 TransSetX2EvX1::Iterator tit_end=rEntryTransSet.EndByX2(EntryState); 01977 for(;tit!=tit_end;tit++) { 01978 // cout<<endl<<"Moving entryTransition "<<"("<<tit->X1<<","<<rGen.EventName(tit->Ev)<<","<<tit->X2<<")"; 01979 // cout<<" to target state "<<clone[EntryState]; 01980 rGen.SetTransition(tit->X1,tit->Ev,clone[EntryState]); 01981 //prebook new moved transition to be inserted in rEntryTransSet: 01982 EntryTransToInsert.Insert(tit->X1,tit->Ev,clone[EntryState]); 01983 //prebook transitions to former entry state to clear in rGen and rEntryTransSet: 01984 TransToClear.Insert(*tit); 01985 } 01986 //clear former transitions in rGen and rEntryTransSet: 01987 TransSet::Iterator tit2=TransToClear.Begin(); 01988 TransSet::Iterator tit2_end=TransToClear.End(); 01989 for(;tit2!=tit2_end;tit2++) { 01990 rGen.ClrTransition(*tit2); 01991 //erase transitions to former entry state from rEntryTransSet: 01992 rEntryTransSet.Erase(*tit2); 01993 } 01994 // update rEntryTransSet with new moved entry transitions: 01995 TransSet::Iterator tit3=EntryTransToInsert.Begin(); 01996 TransSet::Iterator tit3_end=EntryTransToInsert.End(); 01997 for(;tit3!=tit3_end;tit3++) { 01998 //insert new moved transitions in rEntryTransSet: 01999 rEntryTransSet.Insert(*tit3); 02000 } 02001 //update rEntryStateSet: 02002 rEntryStates.Erase(EntryState); // erase former ambiguous entry state 02003 rEntryStates.Insert(clone[EntryState]); // insert unique entry state of cloned SCC 02004 } 02005 02006 // CloneUnMarkedScc(rGen,rScc,rSccSet,rEntryState,rEntryStates,rEntryTransSet) 02007 void CloneUnMarkedScc( 02008 Generator& rGen, 02009 const StateSet& rScc, 02010 const Idx EntryState, 02011 const StateSet& rEntryStates, 02012 TransSetX2EvX1& rEntryTransSet) 02013 { 02014 FD_DF("CloneUnMarkedScc(...)"); 02015 // initialize map from original SCC-states to their clones: 02016 std::map<const Idx, Idx> clone; 02017 // initialize clone-SCC: 02018 StateSet CloneScc; 02019 // clone all SCC-states but EntryState: 02020 StateSet::Iterator sit=rScc.Begin(); 02021 StateSet::Iterator sit_end=rScc.End(); 02022 for(;sit!=sit_end;sit++) { 02023 if(*sit != EntryState) { 02024 clone[*sit]=rGen.InsState(); 02025 CloneScc.Insert(clone[*sit]); 02026 } 02027 else clone[*sit]=*sit; // entry state is not cloned 02028 02029 } 02030 02031 //*** Think about this: 02032 // // add clone of SCC to set of all SCCs: 02033 // rSccSet.insert(CloneScc); 02034 //*** 02035 02036 // clone all transitions: 02037 TransSet TransToClear; 02038 sit=rScc.Begin(); 02039 bool isEntryState=false; 02040 TransSet::Iterator tit,tit_end; 02041 for(;sit!=sit_end;sit++) { 02042 isEntryState=(*sit==EntryState); 02043 tit=rGen.TransRelBegin(*sit); 02044 tit_end=rGen.TransRelEnd(*sit); 02045 for(;tit!=tit_end;tit++) { 02046 // clone all transitions within SCC: 02047 if(rScc.Exists(tit->X2)) { 02048 rGen.SetTransition(clone[*sit],tit->Ev,clone[tit->X2]); 02049 // if transition starts at entry state, only keep the clone transition 02050 if(isEntryState) { 02051 // prebook this transition to be cleared 02052 TransToClear.Insert(*tit); 02053 } 02054 } 02055 //...and transitions leaving the SCC: 02056 else { 02057 rGen.SetTransition(clone[*sit],tit->Ev,tit->X2); 02058 //**** added 06.09.2007: 02059 // If this cloned transition leads to an entry state of 02060 // some other SCC, then it is a new entry transition: 02061 if(rEntryStates.Exists(tit->X2)) { 02062 rEntryTransSet.Insert(clone[*sit],tit->Ev,tit->X2); 02063 } 02064 //**** 02065 } 02066 } 02067 } 02068 02069 // clear prebooked transitions 02070 tit=TransToClear.Begin(); 02071 tit_end=TransToClear.End(); 02072 for(;tit!=tit_end;tit++) { 02073 rGen.ClrTransition(*tit); 02074 } 02075 02076 } 02077 //============================ 02078 02079 02080 02081 // YcAcyclic(rGen,rYc,rResGen) 02082 void YcAcyclic( 02083 const Generator& rGen, 02084 const EventSet& rYc, 02085 Generator& rResGen) 02086 { 02087 FD_DF("YcAcyclic: Statesize before: "<<rGen.Size()<<" - starting..."); 02088 // initialize set of ycless strongly connected components (SCCs): 02089 std::set<StateSet> SccSet,UnMarkedSccSet; 02090 // initialize set of all states that are member or root or entry state of some SCC: 02091 StateSet Scc,Roots,EntryStates,notRoots,UnMarkedRoots; 02092 // initialize set of transitions that enter some SCC from a different SCC, 02093 // sorted by target states X2 (which are entry states): 02094 TransSetX2EvX1 EntryTransSet; 02095 // take rGen as first candidate: 02096 rResGen=rGen; 02097 // counter for below while loop: 02098 // int i=0; 02099 02100 while(true) { 02101 //++i; 02102 // check for SCCs and return if there are none -> ResGen is the result. 02103 // cout<<endl<<"Round "<<i<<": Searching for remaining Yc-less SCCs..."; 02104 if(!YclessScc(rResGen,rYc,SccSet,Roots)) { 02105 //time_t *t2; 02106 //time(t2); 02107 //cout<<"...finished in "<<difftime(*t2, *t1)<<" seconds."; 02108 //rResGen.DotWrite("tmp_YcAcyclic_res"); 02109 FD_DF("YcAcyclic: Statesize of result: "<<rResGen.Size()); 02110 // cout<<". Statemin..."; 02111 // Generator tmp; 02112 // StateMin(rResGen,tmp); 02113 // cout<<"done. New Statesize:"<<tmp.Size(); 02114 // tmp.ClrStateNames(); 02115 // rResGen=tmp; 02116 // tmp.Clear(); 02117 //rResGen.Write("tmp_YcAcyclic.gen"); 02118 return; 02119 } 02120 //cout<<endl<<"...found "<<SCCset.size()<<" Yc-less SCCs: computing entry states..."; 02121 // cout<<"Found following Yc-less SCCs:"<<endl; 02122 // WriteStateSets(SCCset); 02123 // system("pause"); 02124 // else figure entry states and entry transitions of the SCCs 02125 SccEntries(rResGen,SccSet,EntryStates,EntryTransSet); 02126 02127 // root states are kept as entry states of the original SCCs, for all other 02128 // entry states clone SCCs: 02129 notRoots=EntryStates - Roots; 02130 //cout<<"...found "<<notRoots.Size()<<" entry states that are not roots. Start cloning SCCs..."<<endl; 02131 // cout<<endl<<"EntryStates before cloning:"<<endl; 02132 // EntryStates.DWrite(); 02133 // cout<<endl<<"Roots before cloning:"<<endl; 02134 // Roots.DWrite(); 02135 // cout<<endl<<"notRoots before cloning:"<<endl; 02136 // notRoots.DWrite(); 02137 02138 StateSet::Iterator sit=notRoots.Begin(); 02139 StateSet::Iterator sit_end=notRoots.End(); 02140 for(;sit!=sit_end;sit++) 02141 { 02142 // figure SCC with entry state sit: 02143 std::set<StateSet>::iterator sccit = SccSet.begin(); 02144 std::set<StateSet>::iterator sccit_end = SccSet.end(); 02145 for (; sccit != sccit_end; ++sccit) 02146 { 02147 if(sccit->Exists(*sit)) 02148 { 02149 Scc=*sccit; 02150 break; 02151 } 02152 } 02153 // clone this SCC (and add clone to SCCset): 02154 // cout<<"cloning SCCC:"<<endl; 02155 // SCC.DWrite(); 02156 CloneScc(rResGen,Scc,SccSet,*sit,EntryStates,EntryTransSet); 02157 // cout<<endl<<"New set of SCCs:"<<endl; 02158 // WriteStateSets(SccSet); 02159 } 02160 //cout<<endl<<"...done. Identifying unique entry states..."; 02161 // rResGen.Write("tmp_YcAcyclic_step.gen"); 02162 // rResGen.DotWrite("tmp_YcAcyclic_step"); 02163 // ++i; 02164 // cout<<endl<<"Printed intermediate result "<<i<<"."<<endl; 02165 // system("pause"); 02166 02167 // Now, all SCCs have one unique entry state. 02168 // If some SCC contains a sub-SCC that a) includes the entry 02169 // state of the whole SCC and b) consists of only unmarked 02170 // states, then this sub-SCC has to be copied to resolve the 02171 // ambiguity. 02172 if( !( ((rResGen.States()-rResGen.MarkedStates())*EntryStates).Empty() ) ) { 02173 // find possible unmarked sub-SCCs including EntryState 02174 YclessUnmarkedScc(rResGen,rYc,UnMarkedSccSet,UnMarkedRoots); 02175 std::set<StateSet>::iterator sccit = UnMarkedSccSet.begin(); 02176 std::set<StateSet>::iterator sccit_end = UnMarkedSccSet.end(); 02177 for (; sccit != sccit_end; ++sccit) { 02178 // check if this unmarked sub-SCC includes an EntryState; if so: clone it 02179 if( !( ((*sccit)*EntryStates).Empty() ) ) { 02180 Idx EntryState=*(((*sccit)*EntryStates).Begin()); 02181 CloneUnMarkedScc(rResGen,*sccit,EntryState,EntryStates,EntryTransSet); 02182 } 02183 } 02184 } 02185 02186 02187 02188 //"Back transitions" leading 02189 // from a SCC to its own entry state have to be cancelled, 02190 // if they are not Yc-transitions: 02191 02192 // 2) loop through all SCCs and find Ycless back transitions: 02193 TransSet TransToClear; 02194 std::set<StateSet>::iterator sccit = SccSet.begin(); 02195 std::set<StateSet>::iterator sccit_end = SccSet.end(); 02196 //cout<<endl<<"Determining non-yc-backtransitions..."; 02197 for (; sccit != sccit_end; ++sccit) 02198 { 02199 //loop through all states: 02200 StateSet::Iterator sit = sccit->Begin(); 02201 StateSet::Iterator sit_end = sccit->End(); 02202 for (; sit != sit_end; ++sit) 02203 { 02204 //cout<<endl<<"looping state "<<*sit<<endl; 02205 // loop through all transitions: 02206 TransSet::Iterator tit=rResGen.TransRelBegin(*sit); 02207 TransSet::Iterator tit_end=rResGen.TransRelEnd(*sit); 02208 for(;tit!=tit_end;tit++) 02209 { 02210 // Check if tit leads back to entry state of current SCC 02211 // and if it is not a Yc-transition: 02212 if(sccit->Exists(tit->X2) && EntryStates.Exists(tit->X2) 02213 &&!rYc.Exists(tit->Ev)) 02214 { 02215 //cout<<" - Trans to clear: "<<tit->Ev<<endl; 02216 TransToClear.Insert(*tit); 02217 } 02218 } 02219 } 02220 } 02221 //cout<<endl<<"...found "<<TransToClear.Size()<<" transitions. Deleting these transitions..."; 02222 // 3) Clear back transitions: 02223 TransSet::Iterator tit=TransToClear.Begin(); 02224 TransSet::Iterator tit_end=TransToClear.End(); 02225 for(;tit!=tit_end;tit++) 02226 { 02227 //cout<<"clearing transition ("<<tit->X1<<","<<rResGen.EventName(tit->Ev)<<","<<tit->X2<<")"<<endl; 02228 rResGen.ClrTransition(*tit); 02229 } 02230 02231 // ++i; 02232 // rResGen.Write("tmp_YcAcyclic_step.gen"); 02233 // rResGen.DotWrite("tmp_YcAcyclic_step"); 02234 // cout<<endl<<"Printed intermediate result "<<i<<"."<<endl; 02235 // system("pause"); 02236 // cout<<endl<<"...transitions deletetd, next round!"; 02237 // cout<<endl<<"state size of current intermediate result: "<<rResGen.Size(); 02238 //cout<<endl<<". Press enter to start statemin."<<endl; 02239 //string anykey; 02240 //getline( cin, anykey ); 02241 02242 // cout<<". Statemin..."; 02243 // Generator tmp; 02244 // StateMin(rResGen,tmp); 02245 // cout<<"done. New Statesize:"<<tmp.Size(); 02246 // rResGen=tmp; 02247 // tmp.Clear(); 02248 02249 // system("pause"); 02250 } //end while(true): resulting generator might contain SCCs within the 02251 // SCCs that have been "broken" in this step -> continue while-loop. 02252 } 02253 02254 //********************************************************** 02255 //******************** hio synthesis ************************ 02256 //********************************************************** 02257 02258 // ConstrSynth_Beta(rPlant,rYp,rUp,rOpConstr) 02259 void ConstrSynth_Beta( 02260 Generator& rPlant, 02261 const EventSet& rYp, 02262 const EventSet& rUp, 02263 const Generator& rLocConstr, 02264 Generator& rOpConstraint) { 02265 02266 FD_DF("ConstrSynth_Beta(...)"); 02267 02268 // helper 02269 Generator tmpGen; 02270 EventSet sigmap=rYp+rUp; 02271 02272 //prepare rsult: 02273 rOpConstraint.Clear(); 02274 02275 // respect optional local constraints 02276 Parallel(rPlant,rLocConstr,rOpConstraint); 02277 02278 // calculate YpAcyclic sublanguage: 02279 YcAcyclic(rOpConstraint,rYp,tmpGen); 02280 rOpConstraint.Clear(); 02281 02282 // compute normal, complete, controllable and nonblocking sublanguage 02283 // note: tmpGen has role of spec 02284 NormalCompleteSynthNB(rPlant,rUp,sigmap,tmpGen,rOpConstraint); 02285 tmpGen.Clear(); 02286 02287 // project to P-Alphabet 02288 Project(rOpConstraint,sigmap,tmpGen); 02289 rOpConstraint.Clear(); 02290 02291 // minimize state space 02292 StateMin(tmpGen,tmpGen); 02293 tmpGen.ClearStateNames(); 02294 02295 // eneable symbolic state names for error states 02296 tmpGen.StateNamesEnabled(true); 02297 rOpConstraint.StateNamesEnabled(true); 02298 // make YP free in OpConstr 02299 FreeInput(tmpGen, rYp, rUp, rOpConstraint, "errUp","errYp"); 02300 02301 rOpConstraint.Name("ConstrSynth_Beta("+rPlant.Name()+")"); 02302 02303 return; 02304 } 02305 02306 // HioSynthUnchecked(rPlant,rSpec,rConstr,rLocConstr,rYc,rUc,rYp,rUp,rYel,rUel,rController) 02307 void HioSynthUnchecked( 02308 const Generator& rPlant, 02309 const Generator& rSpec, 02310 const Generator& rExtConstr, 02311 const Generator& rLocConstr, 02312 const EventSet& rYc, 02313 const EventSet& rUc, 02314 const EventSet& rYp, 02315 const EventSet& rUp, 02316 const EventSet& rYel, 02317 const EventSet& rUel, 02318 Generator& rController) 02319 { 02320 FD_DF("HioSynth(...)"); 02321 //prepare rsult: 02322 rController.Clear(); 02323 //make copy of plant, spec for modifications 02324 Generator plant,spec; 02325 plant = rPlant; 02326 spec = rSpec; 02327 02328 //create necessary eventsets: 02329 EventSet sigmacp; 02330 sigmacp.SetUnion(rUc + rYc + rUp + rYp); 02331 EventSet sigmace; 02332 sigmace.SetUnion(rUc + rYc + rUel + rYel); 02333 02334 EventSet allsigma; 02335 allsigma.SetUnion(rPlant.Alphabet()); 02336 allsigma.SetUnion(rSpec.Alphabet()); 02337 02338 EventSet controllable, wait; 02339 controllable.SetUnion(rUp); 02340 controllable.SetUnion(rYc); 02341 02342 //make alphabets of plant and spec match: 02343 InvProject(plant,allsigma); 02344 InvProject(spec,allsigma); 02345 02346 // FD_DF("******************** actual plant: composition with external constraints"); 02347 02348 // generate plant under constraint: 02349 Parallel(plant,rExtConstr,plant); 02350 //plant.Write("tmp_cplant.gen"); 02351 02352 //FD_DF("******************** mininmal hio structure, composition with plant"); 02353 Generator minhio; 02354 minhio = IoSortCL(rYc,rUc,rYp,rUp,rYel,rUel); 02355 //minhio.Write("tmp_minhio.gen"); 02356 02357 // generate plant in hio structure: 02358 Parallel(plant,minhio,plant); 02359 plant.ClearStateNames(); 02360 //plant.Write("tmp_hiocplant.gen"); 02361 02362 //FD_DF("******************** composition plant-specification: tmp_plantspec.gen "); 02363 02364 // composition of plant, I/O sorting, constraint and specification: 02365 Generator plantspec; 02366 Parallel(plant,spec,plantspec); 02367 //plantspec.Write("tmp_plantspec.gen"); 02368 plantspec.ClearStateNames(); 02369 FD_DF("Size of plantspec: "<<plantspec.Size()<<" - Statemin..."); 02370 StateMin(plantspec,plantspec); 02371 FD_DF("done. New Statesize: "<<plantspec.Size()<<"."); 02372 plantspec.ClearStateNames(); 02373 //plantspec.Write("results/tmp_plantspec.gen"); 02374 FD_DF("******************** computing YcAcyclic(plantspec):"); 02375 02376 // calculate YcAcyclic sublanguage of plantspec: 02377 Generator yclifeplantspec; 02378 YcAcyclic(plantspec,rYc,yclifeplantspec); 02379 yclifeplantspec.ClearStateNames(); 02380 //yclifeplantspec.Write("tmp_YcAcyclic.gen"); 02381 02382 //FD_DF("******************** actual spec: composition yclifeplantspec||minhio||locconstr (tmp_actualspec.gen)"); 02383 //generate plantspec with closed-loop I/O sorting: 02384 Parallel(yclifeplantspec,minhio,plantspec); 02385 yclifeplantspec.Clear(); 02386 //add local constraints to plantspec: the result is the actual spec for synthesis 02387 Parallel(plantspec,rLocConstr,plantspec); 02388 plantspec.ClearStateNames(); 02389 plantspec.Name("actualspec"); 02390 //plantspec.Write("tmp_actualspec.gen"); 02391 02392 //FD_DF("******************** closed loop synthesis: tmp_closedloop.gen/.dot"); 02393 02394 // compute normal, complete and controllable sublangugae of actualspec w.r.t. plant under constraints (cplant): 02395 Generator loop; 02396 NormalCompleteSynthNB(plant,controllable,sigmacp,plantspec,loop); 02397 plantspec.Clear(); 02398 //loop.Write("tmp_closedloop.gen"); 02399 02400 FD_DF("size of closed loop before StateMin: "<<loop.Size()<<", starting StateMin..."); 02401 StateMin(loop,loop); 02402 FD_DF("...size of closed loop after StateMin (tmp_closedloop.gen): "<<loop.Size()); 02403 //std::cout<<"ClosedLoop.IsTrim: "<<loop.IsTrim(); 02404 loop.ClearStateNames(); 02405 // loop.Write("tmp_closedloop.gen"); 02406 FD_DF("********* IsYcLive(closed loop): "<<IsYcLive(loop,rYc)); 02407 plant.Clear(); 02408 02409 //calculate external closedloop: 02410 FD_DF("******************** external closed loop: tmp_extloop.gen"); 02411 Generator extloop; 02412 Project(loop,sigmace,extloop); 02413 FD_DF("size of external closed loop: "<<extloop.Size()); 02414 02415 // // recheck if specification is met: 02416 // if(LanguageInclusion(extloop,rSpec)) { 02417 // FD_DF("External closed loop meets specification."); 02418 // } // Perk: change below to LanguageInclusion with reverse order of parameters 02419 // // and move into above bracket. 02420 // if(LanguageEquality(extloop,rSpec)) { 02421 // FD_DF("External closed loop EQUALS specification."); 02422 // } 02423 02424 extloop.ClearStateNames(); 02425 //extloop.Write("tmp_extloop.gen"); 02426 02427 FD_DF("******************** project closed loop: tmp_controller.gen"); 02428 02429 Generator controller; 02430 Project(loop,sigmacp,controller); 02431 loop.Clear(); 02432 controller.ClearStateNames(); 02433 //controller.Write("tmp_controller.gen"); 02434 02435 // extend to io-controller: result 02436 FreeInput(controller, rYp, rUp, rController, "errUp","errYp"); 02437 controller.Clear(); 02438 FD_DF("size of marked IO controller: "<<rController.Size()<<". PrefixClosure, StateMin..."); 02439 02440 // the following procedure erases all marking information to reduce the result's state space! This step is unproblematic as long as the specification 02441 // 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 02442 // wether this step is correct or should be omitted . 02443 if(!(rSpec.AccessibleSet()<=rSpec.MarkedStates())) { 02444 FD_WARN("Careful: marking information of the specification has been erased from the resulting controller."); 02445 } 02446 PrefixClosure(rController); 02447 StateMin(rController,rController); 02448 FD_DF("...size of prefix-closed IO controller after StateMin: "<<rController.Size()); 02449 rController.ClearStateNames(); 02450 rController.Name("HioSynth("+rPlant.Name()+","+rSpec.Name()+")"); 02451 FD_DF("IO controller synthesis done. ******************** " ); 02452 } 02453 02454 // HioSynth(rPlant,rSpec,rConstr,rLocConstr,rYc,rUc,rYp,rUp,rYel,rUel,rController) 02455 void HioSynth( 02456 const Generator& rPlant, 02457 const Generator& rSpec, 02458 const Generator& rExtConstr, 02459 const Generator& rLocConstr, 02460 const EventSet& rYc, 02461 const EventSet& rUc, 02462 const EventSet& rYp, 02463 const EventSet& rUp, 02464 const EventSet& rYel, 02465 const EventSet& rUel, 02466 Generator& rController) 02467 { 02468 02469 rController.Clear(); 02470 02471 #ifdef FAUDES_CHECKED 02472 // exception on empty alphabets 02473 if (rYc.Empty()){ 02474 std::stringstream errstr; 02475 errstr << "Empty Yc alphabet\n"; 02476 throw Exception("HioSynth", errstr.str(), 0); 02477 } 02478 if (rUc.Empty()){ 02479 std::stringstream errstr; 02480 errstr << "Empty Uc alphabet\n"; 02481 throw Exception("HioSynth", errstr.str(), 0); 02482 } 02483 if (rYp.Empty()){ 02484 std::stringstream errstr; 02485 errstr << "Empty Yp alphabet\n"; 02486 throw Exception("HioSynth", errstr.str(), 0); 02487 } 02488 if (rUp.Empty()){ 02489 std::stringstream errstr; 02490 errstr << "Empty Up alphabet\n"; 02491 throw Exception("HioSynth", errstr.str(), 0); 02492 } 02493 if (rYel.Empty()){ 02494 std::stringstream errstr; 02495 errstr << "Empty Ye alphabet\n"; 02496 throw Exception("HioSynth", errstr.str(), 0); 02497 } 02498 if (rUel.Empty()){ 02499 std::stringstream errstr; 02500 errstr << "Empty Ue alphabet\n"; 02501 throw Exception("HioSynth", errstr.str(), 0); 02502 } 02503 02504 // create resulting alphabet while checking for disjoint sets 02505 EventSet alphabet,errevents; 02506 // initialize with rYc 02507 alphabet.SetUnion(rYc); 02508 // insert remaining events one by one and check if new 02509 EventSet::Iterator evit; 02510 // rUc 02511 for (evit = rUc.Begin(); evit != rUc.End(); ++evit) { 02512 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 02513 } 02514 // rYp 02515 for (evit = rYp.Begin(); evit != rYp.End(); ++evit) { 02516 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 02517 } 02518 // rUp 02519 for (evit = rUp.Begin(); evit != rUp.End(); ++evit) { 02520 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 02521 } 02522 // rYe 02523 for (evit = rYel.Begin(); evit != rYel.End(); ++evit) { 02524 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 02525 } 02526 // rUe 02527 for (evit = rUel.Begin(); evit != rUel.End(); ++evit) { 02528 if(!(alphabet.Insert(*evit))) errevents.Insert(*evit); 02529 } 02530 // throw exception on non disjoint alphabets 02531 if (!errevents.Empty()){ 02532 std::stringstream errstr; 02533 errstr << "Non-disjoint parameters; ambiguous events:\n" <<errevents.ToString(); 02534 throw Exception("HioSynth", errstr.str(), 0); 02535 } 02536 // check alphabet matches: 02537 EventSet plantEvents, specEvents; 02538 plantEvents=rPlant.Alphabet(); 02539 specEvents=rSpec.Alphabet(); 02540 // plant and spec must share environment alphabet 02541 if (!(plantEvents*specEvents==rYel+rUel)){ 02542 std::stringstream errstr; 02543 errstr << "Alphabet mismatch between plant and spec:\n"; 02544 errstr << "plant: " << plantEvents.ToString() << "\n"; 02545 errstr << "spec: " << specEvents.ToString() << "\n"; 02546 errstr << "Yel+Uel: " << (rYel+rUel).ToString() << "\n"; 02547 throw Exception("HioSynth", errstr.str(), 0); 02548 } 02549 // ExtConstr must relate to spec alphabet 02550 if (!(rExtConstr.Alphabet()<=specEvents)){ 02551 std::stringstream errstr; 02552 errstr << "Alphabet mismatch between external constraints and spec.\n"; 02553 throw Exception("HioSynth", errstr.str(), 0); 02554 } 02555 // LocConstr must relate to plant alphabet 02556 if (!(rLocConstr.Alphabet()<=plantEvents)){ 02557 std::stringstream errstr; 02558 errstr << "Alphabet mismatch between internal constraints and plant.\n"; 02559 throw Exception("HioSynth", errstr.str(), 0); 02560 } 02561 02562 // check I/O plant form of spec (note: plant may be composed group and thus need not be in I/o plant form) 02563 HioPlant spec(rSpec,rYc,rUc,rYel,rUel); 02564 std::string report; 02565 if(!IsIoPlantForm(spec,report)){ 02566 std::stringstream errstr; 02567 errstr << "Spec not in IoPlantForm:\n" << report; 02568 throw Exception("HioSynth", errstr.str(), 0); 02569 } 02570 report.clear(); 02571 #endif 02572 02573 // do hio synthesis 02574 HioSynthUnchecked(rPlant,rSpec,rExtConstr,rLocConstr,rYc,rUc,rYp,rUp,rYel,rUel,rController); 02575 } 02576 02577 // HioSynthMonolithic(rPlant,rSpec,rSc,rSp,rSe,rController) 02578 void HioSynthMonolithic( 02579 const HioPlant& rPlant, 02580 const HioPlant& rSpec, 02581 const HioConstraint& rSc, 02582 const HioConstraint& rSp, 02583 const HioConstraint& rSe, 02584 HioController& rController) { 02585 02586 rController.Clear(); 02587 02588 #ifdef FAUDES_CHECKED 02589 // check I/O plant form of rPlant (further parameter checks in HioSynth()) 02590 // tmp non-const copy of const rPlant 02591 HioPlant plant=rPlant; 02592 std::string report; 02593 if(!IsIoPlantForm(plant,report)){ 02594 std::stringstream errstr; 02595 errstr << "Plant not in IoPlantForm:\n" << report; 02596 throw Exception("HioSynthMonolithic", errstr.str(), 0); 02597 } 02598 plant.Clear(); 02599 report.clear(); 02600 #endif 02601 02602 // extract alphabets 02603 EventSet yc,uc,yp,up,ye,ue; 02604 yc=rSpec.YpEvents(); 02605 uc=rSpec.UpEvents(); 02606 yp=rPlant.YpEvents(); 02607 up=rPlant.UpEvents(); 02608 ye=rSpec.YeEvents(); 02609 ue=rSpec.UeEvents(); 02610 02611 // generator for composed external constraints 02612 Generator extConstr; 02613 Parallel(rSc,rSe,extConstr); 02614 02615 // run HioSynth procedure 02616 HioSynth(rPlant,rSpec,extConstr,rSp,yc,uc,yp,up,ye,ue,rController); 02617 02618 // set event and state attributes 02619 rController.SetYc(yc); 02620 rController.SetUc(uc); 02621 rController.SetYp(yp); 02622 rController.SetUp(up); 02623 02624 IsIoControllerForm(rController); 02625 } 02626 02627 void HioSynthHierarchical( 02628 const HioPlant& rIoShuffle, 02629 const HioEnvironment& rEnvironment, 02630 const HioPlant& rSpec, 02631 const Generator& rIntConstr, 02632 const HioConstraint& rSc, 02633 const HioConstraint& rSl, 02634 HioController& rController) { 02635 02636 rController.Clear(); 02637 02638 #ifdef FAUDES_CHECKED 02639 // check I/O plant form of rPlant (further parameter checks in HioSynth()) 02640 // tmp non-const copy of const rPlant 02641 HioPlant plant=rIoShuffle; 02642 std::string report; 02643 if(!IsIoPlantForm(plant,report)){ 02644 std::stringstream errstr; 02645 errstr << "IoShuffle not in IoPlantForm:\n" << report; 02646 throw Exception("HioSynthHierarchical", errstr.str(), 0); 02647 } 02648 plant.Clear(); 02649 report.clear(); 02650 02651 // check I/O environment form 02652 // tmp non-const copy of const rEnvironment 02653 HioEnvironment env=rEnvironment; 02654 if(!IsIoEnvironmentForm(env,report)){ 02655 std::stringstream errstr; 02656 errstr << "Environment not in IoEnvironmentForm:\n" << report; 02657 throw Exception("HioSynthHierarchical", errstr.str(), 0); 02658 } 02659 env.Clear(); 02660 report.clear(); 02661 02662 // check for matching alphabets between ioshuffle, environment and spec 02663 if (!(rIoShuffle.EEvents()==rEnvironment.EEvents())){ 02664 std::stringstream errstr; 02665 errstr << "Alphabet mismatch between I/O-shuffle and environment.\n"; 02666 throw Exception("HioSynthHierarchical", errstr.str(), 0); 02667 } 02668 // check for matching alphabets between ioshuffle, environment and spec 02669 if (!(rSpec.EEvents()==rEnvironment.LEvents())){ 02670 std::stringstream errstr; 02671 errstr << "Alphabet mismatch between specification and environment.\n"; 02672 throw Exception("HioSynthHierarchical", errstr.str(), 0); 02673 } 02674 02675 //(further parameter checks in HioSynth()) 02676 02677 #endif 02678 // compose ioshuffle and environment 02679 Generator ioShuffParEnv; 02680 Parallel(rIoShuffle,rEnvironment,ioShuffParEnv); 02681 02682 // extract alphabets 02683 EventSet yc,uc,yp,up,ye,ue; 02684 yc=rSpec.YpEvents(); 02685 uc=rSpec.UpEvents(); 02686 yp=rIoShuffle.YpEvents(); 02687 up=rIoShuffle.UpEvents(); 02688 ye=rSpec.YeEvents(); 02689 ue=rSpec.UeEvents(); 02690 02691 // generator for composed external constraints 02692 Generator extConstr; 02693 Parallel(rSc,rSl,extConstr); 02694 02695 // run HioSynth procedure 02696 HioSynth(ioShuffParEnv,rSpec,extConstr,rIntConstr,yc,uc,yp,up,ye,ue,rController); 02697 02698 // set event and state attributes 02699 rController.SetYc(yc); 02700 rController.SetUc(uc); 02701 rController.SetYp(yp); 02702 rController.SetUp(up); 02703 02704 IsIoControllerForm(rController); 02705 } 02706 02707 // end of hio_functions - below just archive 02708 02709 //###################################################### 02710 //############ Special versions for IoModule - will soon be obsolete 02711 02712 //IoShuffle_Musunoi() - Version with hio-parameters 02713 void IoShuffle_Musunoi( 02714 const HioPlant& rPlantA, 02715 const HioPlant& rPlantB, 02716 int depth, 02717 Generator& rIOShuffAB) 02718 { 02719 FD_DF("IoShuffle()_Musunoi"); 02720 02721 //Extract alphabets: 02722 EventSet A,B,SigmaP, Yp, Up, Ye, Ue; 02723 Yp = rPlantA.YpEvents()+rPlantB.YpEvents(); 02724 Ye = rPlantA.YeEvents()+rPlantB.YeEvents(); 02725 Up = rPlantA.UpEvents()+rPlantB.UpEvents(); 02726 Ue = rPlantA.UeEvents()+rPlantB.UeEvents(); 02727 A = rPlantA.Alphabet(); 02728 B = rPlantB.Alphabet(); 02729 02730 02731 // parallel composition of plantA and plantB (i.e. shuffle as there are no shared events) 02732 Generator parallel1, parallel2; 02733 Parallel(rPlantA,rPlantB,parallel1); 02734 02735 // restrict to event pairs [(SigA SigA)*+(SigB SigB)*]*, which results 02736 // in correct I/O sorting L_IO. 02737 Generator EventPairs; // generator of above sorting language 02738 EventPairs.InjectAlphabet(A + B); 02739 Idx state1,state2,state3; 02740 state1=EventPairs.InsInitState("1"); 02741 EventPairs.SetMarkedState(state1); 02742 state2=EventPairs.InsMarkedState("2"); 02743 state3=EventPairs.InsMarkedState("3"); 02744 EventSet::Iterator evit; 02745 for (evit = A.Begin(); evit != A.End(); ++evit) { 02746 EventPairs.SetTransition(state1,*evit,state2); 02747 EventPairs.SetTransition(state2,*evit,state1); 02748 } 02749 for (evit = B.Begin(); evit != B.End(); ++evit) { 02750 EventPairs.SetTransition(state1,*evit,state3); 02751 EventPairs.SetTransition(state3,*evit,state1); 02752 } 02753 Parallel(parallel1,EventPairs,parallel2); 02754 02755 //restrict to IO-sorting structure with forced alternation: 02756 02757 // Old Vers before Dez 4 2006: + of whole alphabets 02758 EventSet Ap, Bp, Ae, Be, SigmaE; 02759 02760 Ap = rPlantA.Alphabet(); 02761 Bp = rPlantB.Alphabet(); 02762 02763 Ae = rPlantA.Alphabet(); 02764 Be = rPlantB.Alphabet(); 02765 02766 02767 02768 //************************************************************************* 02769 //// New Vers: Alternation of YP Events only 02770 //// -> currently leads to normality problems during superposed controller synthesis 02771 SigmaP.SetUnion(Yp); 02772 SigmaP.SetUnion(Up); 02773 Ap.SetIntersection(SigmaP); 02774 Bp.SetIntersection(SigmaP); 02775 02776 SigmaE.SetUnion(Ye); 02777 SigmaE.SetUnion(Ue); 02778 Ae.SetIntersection(SigmaE); 02779 Be.SetIntersection(SigmaE); 02780 02781 02782 //************************************************************************* 02783 Generator AltAB; 02784 Ap.Name("A"); 02785 Bp.Name("B"); 02786 CheapAltAB(Ap,Bp,depth,AltAB); 02787 // Alt_AB.Write("tmp_Alternation_AB.gen"); 02788 Parallel(parallel2, AltAB, parallel1); 02789 //parallel2.Write("tmp_IOS3.gen"); 02790 02791 02792 02793 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 02794 //*** Environment-first policy: If, in some state both, Yp- and Ye events are 02795 //*** active, then cancel all Yp-transitions in this state, as environment has 02796 //*** to be updated first. 02797 02798 // loop all states 02799 StateSet::Iterator sit = parallel1.StatesBegin(); 02800 StateSet::Iterator sit_end = parallel1.StatesEnd(); 02801 02802 for(; sit != sit_end; sit++) 02803 { 02804 // figure active Yp-events and active Ye-events 02805 //std::cout << "End: " << *sit_end <<"...done: " << *sit << std::endl; 02806 EventSet ActiveYe; 02807 EventSet ActiveYp = parallel1.TransRel().ActiveEvents(*sit); 02808 ActiveYe=ActiveYp; 02809 ActiveYe.SetIntersection(Ye); 02810 ActiveYp.SetIntersection(Yp); 02811 02812 if (!(ActiveYe.Empty())&& !(ActiveYp.Empty())) 02813 { 02814 TransSet TransToClear; 02815 TransSet::Iterator tit=parallel1.TransRelBegin(*sit); 02816 TransSet::Iterator tit_end=parallel1.TransRelEnd(*sit); 02817 for(;tit!=tit_end;tit++) 02818 { 02819 //std::cout << "finding Yp-events to delete... "; 02820 if(ActiveYp.Exists(tit->Ev)) 02821 { 02822 TransToClear.Insert(*tit); 02823 } 02824 } 02825 tit=TransToClear.Begin(); 02826 tit_end=TransToClear.End(); 02827 for(;tit!=tit_end;tit++) 02828 { 02829 //std::cout<<" ...deleting" <<std::endl; 02830 parallel1.ClrTransition(*tit); 02831 } 02832 } 02833 } 02834 02835 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 02836 02837 02838 02839 // Insert Error Behaviour, i.e. make UP and UE free in (YP,UP)-port of result: 02840 // free UP: 02841 02842 FreeInput(parallel1, Up, Yp, parallel2, "errYp_Ye", "errUp"); 02843 //parallel1.Write("tmp_IOS4.gen"); 02844 // free UE: 02845 FreeInput(parallel2, Ue, Ye, parallel1, "errYp_Ye", "errUe"); 02846 //parallel2.Write("tmp_IOS5.gen"); 02847 02848 rIOShuffAB = parallel1; 02849 } 02850 02851 // HioSynth_Musunoi() 02852 void HioSynth_Musunoi(const Generator& rPlant, const HioPlant& rSpec, 02853 const Generator& rConstr, const Generator& rLocConstr, 02854 const EventSet& rYp, const EventSet& rUp, 02855 Generator& rController) 02856 { 02857 EventSet rYc, rUc, rYe, rUe; 02858 rYc = (rSpec.YpEvents()); 02859 rUc = (rSpec.UpEvents()); 02860 rYe = (rSpec.YeEvents()); 02861 rUe = (rSpec.UeEvents()); 02862 02863 02864 //make copy of plant, spec, constr and alphabets 02865 Generator plant,spec,constr,locconstr; 02866 plant = rPlant; 02867 spec = rSpec; 02868 constr = rConstr; 02869 locconstr = rLocConstr; 02870 02871 EventSet yc,uc,yp,up,ye,ue; 02872 yc = rYc; 02873 uc = rUc; 02874 yp = rYp; 02875 up = rUp; 02876 ye = rYe; 02877 ue = rUe; 02878 02879 //create necessary eventsets: 02880 EventSet sigmacp; 02881 sigmacp.SetUnion(rUc + rYc + rUp + rYp); 02882 EventSet sigmace; 02883 sigmace.SetUnion(rUc + rYc + rUe + rYe); 02884 02885 EventSet allsigma; 02886 allsigma.SetUnion(rPlant.Alphabet()); 02887 allsigma.SetUnion(rSpec.Alphabet()); 02888 02889 EventSet controllable; 02890 controllable.SetUnion(up); 02891 controllable.SetUnion(yc); 02892 02893 //make alphabets of plant and spec match: 02894 InvProject(plant,allsigma); 02895 InvProject(spec,allsigma); 02896 02897 FD_DF("******************** actual plant: composition with environment constraint: tmp_cplant.gen "); 02898 02899 // generate plant under constraint: 02900 Generator cplant; 02901 Parallel(plant,constr,cplant); 02902 //cplant.Write("tmp_cplant.gen"); 02903 02904 FD_DF("******************** mininmal hio structure: tmp_minhio.gen, composition with plant: tmp_hioplant.gen "); 02905 Generator minhio; 02906 minhio = IoSortCL(yc,uc,yp,up,ye,ue); 02907 //minhio.Write("tmp_minhio.gen"); 02908 02909 // generate plant in hio structure: 02910 Generator hiocplant; 02911 Parallel(cplant,minhio,hiocplant); 02912 //hiocplant.Write("tmp_hiocplant.gen"); 02913 02914 FD_DF("******************** composition plant-specification: tmp_plantspec.gen "); 02915 02916 // composition of plant, I/O sorting, constraint and specification: 02917 Generator plantspec,plantspecMin; 02918 Parallel(hiocplant,spec,plantspec); 02919 //plantspec.Write("tmp_plantspec.gen"); 02920 plantspec.ClearStateNames(); 02921 // plantspec.DotWrite("tmp_plantspec"); 02922 FD_DF("Size of plantspec: "<<plantspec.Size()<<" - Statemin..."); 02923 //string anykey; 02924 //getline(cin,anykey); 02925 StateMin(plantspec,plantspecMin); 02926 FD_DF("done. New Statesize: "<<plantspecMin.Size()<<"."); 02927 plantspec=plantspecMin; 02928 plantspecMin.Clear(); 02929 plantspec.ClearStateNames(); 02930 FD_DF("******************** computing YcAcyclic(plantspec):"); 02931 02932 // calculate YcAcyclic sublanguage of plantspec: 02933 Generator yclifeplantspec; 02934 YcAcyclic(plantspec,yc,yclifeplantspec); 02935 Generator yclifeplantspecMin; 02936 //cout <<endl<< " StateMin(yclifeplantspec)..." << endl; 02937 //StateMin(yclifeplantspec,yclifeplantspecMin); 02938 //cout<<endl<<"Statesize of yclifeplantspec after StateMin (tmp_YcAcyclic_Min.gen): "<<yclifeplantspecMin.Size(); 02939 yclifeplantspecMin=yclifeplantspec; 02940 yclifeplantspecMin.ClearStateNames(); 02941 //yclifeplantspecMin.Write("tmp_YcAcyclic_Min.gen"); 02942 02943 FD_DF("******************** actual spec: composition yclifeplantspec||minhio||locconstr (tmp_actualspec.gen)"); 02944 //generate plantspec with closed-loop I/O sorting: 02945 Parallel(yclifeplantspecMin,minhio,plantspec); 02946 02947 //add local constraints to plantspec: the result is the actual spec for synthesis 02948 Generator actualspec; 02949 Parallel(plantspec,locconstr,actualspec); 02950 //actualspec.Write("tmp_actualspec.gen"); 02951 02952 FD_DF("******************** closed loop synthesis: tmp_closedloop.gen/.dot"); 02953 02954 //std::cout<<"Starting NormalCompleteSynth...."; 02955 FD_DF("Starting NormalCompleteSynth...."); 02956 02957 // compute normal, complete and controllable sublangugae of actualspec w.r.t. plant under constraints (cplant): 02958 Generator loop; 02959 NormalCompleteSynth(hiocplant,controllable,yc+uc+yp+up,actualspec,loop); 02960 //loop.Write("tmp_closedloop.gen"); 02961 //loop.DotWrite("tmp_closedloop"); 02962 02963 FD_DF("size of closed loop before StateMin: "<<loop.Size()<<", starting StateMin..."); 02964 02965 //std::cout<<"Starting NormalCompleteSynth....done... starting StateMin"; 02966 FD_DF("Starting NormalCompleteSynth....done... starting StateMin"); 02967 02968 Generator minloop; 02969 StateMin(loop,minloop); 02970 FD_DF("...size of closed loop after StateMin (tmp_closedloop.gen): "<<minloop.Size()); 02971 //minloop=loop; 02972 minloop.ClearStateNames(); 02973 //minloop.Write("tmp_closedloop.gen"); 02974 // test: recheck for YCless SCCs: 02975 Generator minlooptest; 02976 minlooptest=minloop; 02977 std::set<StateSet> SccSet; 02978 YclessScc(minlooptest,yc,SccSet); 02979 FD_DF(""); 02980 FD_DF("*********number of Yc-less strongly connencted components in closed loop (should be zero): " 02981 <<SccSet.size()); 02982 02983 // minloop.DotWrite("tmp_minclosedloop"); 02984 02985 //calculate external closedloop: 02986 FD_DF("******************** external closed loop: tmp_extloop.gen/.dot"); 02987 Generator extloop; 02988 Project(minloop,sigmace,extloop); 02989 FD_DF("size of external closed loop: "<<extloop.Size());; 02990 02991 // recheck if specification is met: 02992 if(LanguageInclusion(extloop,rSpec)) { 02993 FD_DF("External closed loop meets specification."); 02994 } 02995 if(LanguageEquality(extloop,rSpec)) { 02996 FD_DF("External closed loop EQUALS specification."); 02997 } 02998 02999 extloop.ClearStateNames(); 03000 //extloop.Write("tmp_extloop.gen"); 03001 //extloop.DotWrite("tmp_extloop"); 03002 03003 FD_DF("******************** project closed loop: tmp_controller.gen/.dot "); 03004 03005 Generator controller; 03006 Project(minloop,sigmacp,controller); 03007 controller.ClearStateNames(); 03008 //controller.Write("tmp_controller.gen"); 03009 // controller.DotWrite("tmp_controller"); 03010 03011 FD_DF("******************** extend to IO controller: tmp_IOcontroller.gen/.dot "); 03012 03013 // extend to io-controller 03014 Generator IoController, minIOcontroller; 03015 FreeInput(controller, yp, up, IoController, "errUp","errYp"); 03016 //IoController.Write("tmp_IOcontroller.gen"); 03017 // IoController.DotWrite("tmp_IOcontroller"); 03018 FD_DF("size of IO controller: "<<IoController.Size()<<", StateMin..."); 03019 StateMin(IoController,minIOcontroller); 03020 FD_DF("...size of IO controller after StateMin: "<<minIOcontroller.Size()); 03021 minIOcontroller.ClearStateNames(); 03022 //minIOcontroller.Write("tmp_IOcontroller.gen"); 03023 03024 // RESULT: 03025 rController = minIOcontroller; 03026 03027 ////******************************************************************* 03028 // // uncomment this, if you use complete_synth, instead of 03029 // // normal_complete_synth, for controller design: 03030 03031 //cout <<endl<< "******************** checking normality... " << endl; 03032 // 03033 //if(!isnormal(minloop,hiocplant,sigmacp)) 03034 // { 03035 // cout<<endl<<"isnormal says: false! :("<<endl; 03036 // } 03037 //else 03038 // { 03039 // cout<<endl<<"isnormal says: true! :)"<<endl; 03040 // } 03041 ////******************************************************************* 03042 03043 FD_DF("IO controller synthesis done. ******************** " ); 03044 } 03045 03046 }//namespace faudes |
libFAUDES 2.14g --- 2009-12-3 --- c++ source docu by doxygen 1.5.6