ios_algorithms.cppGo to the documentation of this file.00001 #include "ios_algorithms.h" 00002 #include "syn_wsupcon.h" 00003 00004 namespace faudes { 00005 00006 // IsIoSystem() implementation 00007 bool IsIoSystem(const IoSystem& rIoSystem, 00008 StateSet& rQU, 00009 StateSet& rQY, 00010 StateSet& rQErr) 00011 { 00012 FD_DIO("IsIoSystem("<< rIoSystem.Name() << ",...)"); 00013 // prepare result 00014 rQU.Clear(); 00015 rQY.Clear(); 00016 rQErr.Clear(); 00017 rQErr.Name("ErrorStates"); 00018 // completeness (iterate over accessible states only) 00019 FD_DIO("IsIoSystem("<< rIoSystem.Name() << ",...): testing completeness"); 00020 StateSet acc = rIoSystem.AccessibleSet(); 00021 StateSet coacc = rIoSystem.CoaccessibleSet(); 00022 StateSet::Iterator sit=acc.Begin(); 00023 StateSet::Iterator sit_end=acc.End(); 00024 for(;sit!=sit_end;sit++){ 00025 // cannot extend 00026 TransSet::Iterator tit=rIoSystem.TransRelBegin(*sit); 00027 TransSet::Iterator tit_end=rIoSystem.TransRelEnd(*sit); 00028 if(tit==tit_end) rQErr.Insert(*sit); 00029 // not coreachable 00030 if(!coacc.Exists(*sit)) rQErr.Insert(*sit); 00031 } 00032 if(!rQErr.Empty()) { 00033 FD_DIO("IsIoSystem("<< rIoSystem.Name() << ",...): not complete"); 00034 return false; 00035 } 00036 // insist in a u-y partition 00037 EventSet errev; 00038 bool hasu=false; 00039 bool hasy=false; 00040 EventSet::Iterator eit = rIoSystem.AlphabetBegin(); 00041 EventSet::Iterator eit_end= rIoSystem.AlphabetEnd(); 00042 for(; eit != eit_end; ++eit) { 00043 if(rIoSystem.InputEvent(*eit)) 00044 hasu=true; 00045 if(rIoSystem.InputEvent(*eit)) 00046 hasy=true; 00047 if(rIoSystem.InputEvent(*eit)) 00048 if(rIoSystem.OutputEvent(*eit)) 00049 errev.Insert(*eit); 00050 if(!rIoSystem.InputEvent(*eit)) 00051 if(!rIoSystem.OutputEvent(*eit)) 00052 errev.Insert(*eit); 00053 } 00054 if(!errev.Empty()) { 00055 FD_DIO("IsIoSystem("<< rIoSystem.Name() << ",...): not a u-y partition of events"); 00056 TransSet::Iterator tit=rIoSystem.TransRelBegin(); 00057 TransSet::Iterator tit_end=rIoSystem.TransRelEnd(); 00058 for(; tit!=tit_end; tit++) 00059 if(errev.Exists(tit->Ev)) rQErr.Insert(tit->X1); 00060 return false; 00061 } 00062 if(!hasu || !hasy) { 00063 FD_DIO("IsIoSystem("<< rIoSystem.Name() << ",...): trivial partition"); 00064 return false; 00065 } 00066 // io-alternation: fill todo stack with initial states 00067 FD_DIO("IsIoSystem("<< rIoSystem.Name() << ",...): i/o alternation"); 00068 std::stack<Idx> todo; 00069 sit = rIoSystem.InitStatesBegin(); 00070 sit_end= rIoSystem.InitStatesEnd(); 00071 for(; sit != sit_end; ++sit) { 00072 // figure type of initial state 00073 TransSet::Iterator tit=rIoSystem.TransRelBegin(*sit); 00074 TransSet::Iterator tit_end=rIoSystem.TransRelEnd(*sit); 00075 for(; tit!=tit_end; tit++) { 00076 if(rIoSystem.InputEvent(tit->Ev)) rQU.Insert(*sit); 00077 if(rIoSystem.OutputEvent(tit->Ev)) rQY.Insert(*sit); 00078 } 00079 // push 00080 todo.push(*sit); 00081 } 00082 // io-alternation: multiple initialstates are fine, but must be of same type. 00083 if(!rQU.Empty() && !rQY.Empty()) { 00084 sit = rIoSystem.InitStatesBegin(); 00085 sit_end= rIoSystem.InitStatesEnd(); 00086 for(; sit != sit_end; ++sit) { 00087 rQErr.Insert(*sit); 00088 return false; 00089 } 00090 } 00091 // io-alternation: process stack 00092 while(not todo.empty()) { 00093 const Idx current = todo.top(); 00094 todo.pop(); 00095 bool uok = rQU.Exists(current); 00096 bool yok = rQY.Exists(current); 00097 // iterate all transitions 00098 TransSet::Iterator tit=rIoSystem.TransRelBegin(current); 00099 TransSet::Iterator tit_end=rIoSystem.TransRelEnd(current); 00100 for(; tit!=tit_end; tit++) { 00101 if(!rQY.Exists(tit->X2) && !rQU.Exists(tit->X2)) 00102 todo.push(tit->X2); 00103 if(rIoSystem.InputEvent(tit->Ev)) { 00104 rQY.Insert(tit->X2); 00105 if(!uok) rQErr.Insert(current); 00106 } 00107 if(rIoSystem.OutputEvent(tit->Ev)) { 00108 rQU.Insert(tit->X2); 00109 if(!yok) rQErr.Insert(current); 00110 } 00111 } 00112 } 00113 if(!rQErr.Empty()) { 00114 return false; 00115 } 00116 // done 00117 return true; 00118 } 00119 00120 00121 // IsIoSystem wrapper function 00122 bool IsIoSystem(IoSystem& rIoSystem) { 00123 StateSet QU,QY, QErr; 00124 bool res= IsIoSystem(rIoSystem, QU, QY, QErr); 00125 rIoSystem.InputStates(QU); 00126 rIoSystem.OutputStates(QY); 00127 rIoSystem.ErrorStates(QErr); 00128 return res; 00129 } 00130 00131 00132 // rti function interface 00133 void IoStatePartition(IoSystem& rIoSystem) { 00134 IsIoSystem(rIoSystem); 00135 } 00136 00137 00138 // IsInputLocallyFree wrapper function 00139 bool IsInputLocallyFree(IoSystem& rIoSystem) { 00140 FD_DIO("IsInputLocallyFree("<< rIoSystem.Name() << ",...)"); 00141 StateSet QErr; 00142 bool res=IsInputLocallyFree(rIoSystem, QErr); 00143 rIoSystem.ErrorStates(QErr); 00144 return res; 00145 } 00146 00147 // IsInputLocallyFree implementation 00148 bool IsInputLocallyFree(const IoSystem& rIoSystem, StateSet& rQErr) { 00149 FD_DIO("IsInputLocallyFree("<< rIoSystem.Name() << ",...)"); 00150 // prepare result 00151 rQErr.Clear(); 00152 rQErr.Name("ErrorStates"); 00153 // have set of all input events 00154 EventSet sigu=rIoSystem.InputEvents(); 00155 // test all states 00156 StateSet::Iterator sit = rIoSystem.StatesBegin(); 00157 StateSet::Iterator sit_end= rIoSystem.StatesEnd(); 00158 for(; sit != sit_end; ++sit) { 00159 // get all enabled inputs 00160 EventSet lsigu; 00161 TransSet::Iterator tit=rIoSystem.TransRelBegin(*sit); 00162 TransSet::Iterator tit_end=rIoSystem.TransRelEnd(*sit); 00163 for(; tit!=tit_end; tit++) 00164 if(rIoSystem.InputEvent(tit->Ev)) lsigu.Insert(tit->Ev); 00165 //FD_DIO("DUMP " << rIoSystem.StateName(*sit) << " "<< lsigu.ToString()); 00166 // no inputs? fine 00167 if(lsigu.Empty()) continue; 00168 // all inputs? fine 00169 if(lsigu == sigu) continue; 00170 // error 00171 rQErr.Insert(*sit); 00172 //FD_DIO("DUMP " << *sit << " " << rQErr.ToString()); 00173 } 00174 return rQErr.Empty(); 00175 } 00176 00177 00178 // IsInputOmegaFree wrapper function 00179 bool IsInputOmegaFree(IoSystem& rIoSystem) { 00180 FD_DIO("IsInputOmegaFree("<< rIoSystem.Name() << ",...)"); 00181 StateSet QErr; 00182 bool res=IsInputOmegaFree(rIoSystem, QErr); 00183 rIoSystem.ErrorStates(QErr); 00184 return res; 00185 } 00186 00187 // Is InputOmegaFree implementation 00188 bool IsInputOmegaFree(const IoSystem& rIoSystem, StateSet& rQErr) { 00189 FD_DIO("IsInputOmegaFree("<< rIoSystem.Name() << ",...)"); 00190 00191 // test for locally free input first 00192 rQErr.Clear(); 00193 if(!IsInputLocallyFree(rIoSystem,rQErr)) { 00194 FD_DIO("IsInputOmegaFree("<< rIoSystem.Name() << ",...): failed for locally free"); 00195 return false; 00196 } 00197 00198 // prepare good state iteration 00199 StateSet goodstates=rIoSystem.MarkedStates(); 00200 EventSet yalph=rIoSystem.OutputEvents(); 00201 rQErr=rIoSystem.AccessibleSet()-goodstates; 00202 rQErr.Name("ErrorStates"); 00203 00204 // control to good states 00205 while(true) { 00206 // test individual states 00207 FD_DIO("IsInputOmegaFree(...): iterate over good states"); 00208 bool found=false; 00209 StateSet::Iterator sit = rQErr.Begin(); 00210 while(sit!=rQErr.End()) { 00211 // pre-increment 00212 StateSet::Iterator cit=sit++; 00213 // goodstate anyway 00214 if(goodstates.Exists(*cit)) continue; 00215 // test transitions 00216 TransSet::Iterator tit = rIoSystem.TransRelBegin(*cit); 00217 TransSet::Iterator tit_end = rIoSystem.TransRelEnd(*cit); 00218 // no transitions at all 00219 if(tit==tit_end) continue; 00220 // loop over successors 00221 bool block=true; 00222 for(; tit!=tit_end; ++tit) { 00223 if(goodstates.Exists(tit->X2)) { block=false; continue; } 00224 if(yalph.Exists(tit->Ev)) continue; 00225 break; 00226 } 00227 // good states survive the loop and dont block 00228 if(tit==tit_end && !block) { 00229 FD_DIO("IsInputOmegaFree(): ins good state " << rIoSystem.SStr(*cit)); 00230 goodstates.Insert(*cit); 00231 rQErr.Erase(cit); 00232 found=true; 00233 } 00234 } 00235 // exit 00236 if(!found) break; 00237 }; 00238 00239 // errorstates 00240 if(rQErr.Empty()) { 00241 FD_DIO("IsInputOmegaFree(): accessible <= good: passed"); 00242 return true; 00243 } 00244 00245 // fail 00246 FD_DIO("IsInputOmegaFree(): accessible <= good: failed"); 00247 return false; 00248 } 00249 00250 00251 // IoFreeInput() wrapper 00252 void IoFreeInput(IoSystem& rIoSystem) { 00253 IoFreeInput(rIoSystem,rIoSystem.InputEvents()); 00254 } 00255 00256 // IoFreeInput() 00257 void IoFreeInput(Generator& rGen, const EventSet& rUAlph) { 00258 FD_DIO("IoFreeInput("<< rGen.Name() << ",...)"); 00259 // test alphabet 00260 if(!(rUAlph <= rGen.Alphabet())){ 00261 std::stringstream errstr; 00262 errstr << "Input alphabet must be contained in generator alphabet"; 00263 throw Exception("IoFreeInput(..)", errstr.str(), 100); 00264 } 00265 // prepare error states 00266 Idx qyerr=0; 00267 Idx querr=0; 00268 // declare some local vars 00269 EventSet::Iterator eit; 00270 EventSet::Iterator eit_end; 00271 // test all states 00272 StateSet::Iterator sit = rGen.StatesBegin(); 00273 StateSet::Iterator sit_end= rGen.StatesEnd(); 00274 for(; sit != sit_end; ++sit) { 00275 // get all enabled inputs 00276 EventSet lsigu; 00277 TransSet::Iterator tit=rGen.TransRelBegin(*sit); 00278 TransSet::Iterator tit_end=rGen.TransRelEnd(*sit); 00279 for(; tit!=tit_end; tit++) 00280 if(rUAlph.Exists(tit->Ev)) lsigu.Insert(tit->Ev); 00281 // no inputs? fine 00282 if(lsigu.Empty()) continue; 00283 // all inputs? fine 00284 if(lsigu == rUAlph) continue; 00285 // no error states yet? insert them 00286 if(qyerr==0) { 00287 // todo: be smart in state names when enabled 00288 qyerr = rGen.InsMarkedState(); 00289 querr = rGen.InsMarkedState(); 00290 // enable all transition 00291 eit=rGen.Alphabet().Begin(); 00292 eit_end=rGen.Alphabet().End(); 00293 for(; eit!=eit_end; eit++) { 00294 if(rUAlph.Exists(*eit)) 00295 rGen.SetTransition(querr,*eit,qyerr); 00296 else 00297 rGen.SetTransition(qyerr,*eit,querr); 00298 } 00299 } 00300 // fix the state at hand 00301 eit=rUAlph.Begin(); 00302 eit_end=rUAlph.End(); 00303 for(; eit!=eit_end; eit++) 00304 if(!lsigu.Exists(*eit)) 00305 rGen.SetTransition(*sit,*eit,qyerr); 00306 // continue with next state 00307 } 00308 } 00309 00310 // IoRemoveDummyStates 00311 void RemoveIoDummyStates(IoSystem& rIoSystem) { 00312 FD_DIO("RemoveIoDummyStates("<< rIoSystem.Name() << ",...)"); 00313 // have set of all input/output events 00314 EventSet sigu=rIoSystem.InputEvents(); 00315 EventSet sigy=rIoSystem.OutputEvents(); 00316 // have results 00317 StateSet qerr1; // a) find all outputs to unique successor 00318 StateSet qerr2; // b) collect successors from a) 00319 StateSet qerr2a; // c) from qerr2 only keep all with unique successor 00320 StateSet qerr; // d) restrict candidates to cyclic behaviour 00321 // find states with all outputs leading to the same successor 00322 // record as type 1 candidate 00323 StateSet::Iterator sit = rIoSystem.StatesBegin(); 00324 StateSet::Iterator sit_end= rIoSystem.StatesEnd(); 00325 for(; sit != sit_end; ++sit) { 00326 // get all enabled events, track for unique successor 00327 EventSet lsig; 00328 Idx qsuc=0; 00329 bool qunique=true; 00330 TransSet::Iterator tit=rIoSystem.TransRelBegin(*sit); 00331 TransSet::Iterator tit_end=rIoSystem.TransRelEnd(*sit); 00332 for(; tit!=tit_end; tit++) { 00333 if(qsuc==0) qsuc=tit->X2; 00334 if(qsuc!=tit->X2) { qunique=false; break;} 00335 lsig.Insert(tit->Ev); 00336 } 00337 // non unique successor? discard 00338 if(!qunique || qsuc==0) continue; 00339 // outputs not enabled? discard 00340 if(!(lsig == sigy)) continue; 00341 // record candidate 00342 qerr1.Insert(*sit); 00343 qerr2.Insert(qsuc); 00344 } 00345 FD_DIO("RemoveIoDummyStates(): Candidates type 1 " << qerr1.ToString()); 00346 FD_DIO("RemoveIoDummyStates(): Candidates type 2 " << qerr2.ToString()); 00347 // only keep type 2 candidates with all inputs enabled and 00348 // leading to a type 1 candidate 00349 sit = qerr2.Begin(); 00350 sit_end= qerr2.End(); 00351 for(; sit != sit_end; ++sit) { 00352 // get all enabled events, track for unique successor 00353 EventSet lsig; 00354 Idx qsuc=0; 00355 bool qunique=true; 00356 TransSet::Iterator tit=rIoSystem.TransRelBegin(*sit); 00357 TransSet::Iterator tit_end=rIoSystem.TransRelEnd(*sit); 00358 for(; tit!=tit_end; tit++) { 00359 if(qsuc==0) qsuc=tit->X2; 00360 if(qsuc!=tit->X2) { qunique=false; break;} 00361 lsig.Insert(tit->Ev); 00362 } 00363 // non unique successor? discard 00364 if(!qunique) continue; 00365 // successor not in candidates? discard 00366 if(!qerr1.Exists(qsuc)) continue; 00367 // inputs not enabled? discard 00368 if(!(lsig == sigu)) continue; 00369 // record candidate 00370 qerr2a.Insert(*sit); 00371 } 00372 FD_DIO("RemoveIoDummyStates(): Candidates type 2 (approved) " << qerr2a.ToString()); 00373 // only keep loops 00374 while(1) { 00375 StateSet qrm1; 00376 sit = qerr1.Begin(); 00377 sit_end= qerr1.End(); 00378 for(; sit != sit_end; ++sit) { 00379 TransSet::Iterator tit=rIoSystem.TransRelBegin(*sit); 00380 TransSet::Iterator tit_end=rIoSystem.TransRelEnd(*sit); 00381 if(tit==tit_end) { qrm1.Insert(*sit); break;} 00382 if(!qerr2a.Exists(tit->X2)) { qrm1.Insert(*sit); break;} 00383 } 00384 qerr1.EraseSet(qrm1); 00385 StateSet qrm2; 00386 sit = qerr2a.Begin(); 00387 sit_end= qerr2a.End(); 00388 for(; sit != sit_end; ++sit) { 00389 TransSet::Iterator tit=rIoSystem.TransRelBegin(*sit); 00390 TransSet::Iterator tit_end=rIoSystem.TransRelEnd(*sit); 00391 if(tit==tit_end) { qrm2.Insert(*sit); break;} 00392 if(!qerr1.Exists(tit->X2)) { qrm2.Insert(*sit); break;} 00393 } 00394 qerr2a.EraseSet(qrm2); 00395 if(qrm1.Empty() && qrm2.Empty()) break; 00396 } 00397 qerr=qerr1 + qerr2; 00398 FD_DIO("RemoveIoDummyStates(): Dummy states" << qerr.ToString()); 00399 sit = qerr.Begin(); 00400 sit_end= qerr.End(); 00401 for(; sit != sit_end; ++sit) 00402 rIoSystem.DelState(*sit); 00403 FD_DIO("RemoveIoDummyStates(): done"); 00404 } 00405 00406 // IoSynthesis(rPlant,rSpec,rSup,rErrorStates) 00407 void IoSynthesisNB(const IoSystem& rPlant, const Generator& rSpec, IoSystem& rSup) { 00408 FD_DIO("IosSynthesisNB"); 00409 00410 // synthesis 00411 EventSet ualph = rPlant.InputEvents(); 00412 EventSet yalph = rPlant.OutputEvents(); 00413 OmegaSupConNB(rPlant,ualph,rSpec,rSup) ; 00414 00415 // fix event attributes 00416 rSup.InputEvents(yalph); 00417 rSup.OutputEvents(ualph); 00418 } 00419 00420 // IoSynthesis(rPlant,rSpec,rSup,rErrorStates) 00421 void IoSynthesis(const IoSystem& rPlant, const Generator& rSpec, IoSystem& rSup) { 00422 FD_DIO("IosSynthesis"); 00423 00424 // synthesis 00425 EventSet ualph = rPlant.InputEvents(); 00426 EventSet yalph = rPlant.OutputEvents(); 00427 SupConCmplClosed(rPlant,ualph,rSpec,rSup) ; 00428 00429 // fix event attributes 00430 rSup.InputEvents(yalph); 00431 rSup.OutputEvents(ualph); 00432 } 00433 00434 00435 }// end: namespace faudes libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen |