ios_algorithms.cpp

Go 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