About
User Reference
C++ API
luafaudes
Developer
Links
libFAUDES online
libFAUDES

Sections

Index

syn_supnorm.cpp

Go to the documentation of this file.
00001 /** @file syn_supnorm.cpp Supremal normal sublanguage */
00002 
00003 /* FAU Discrete Event Systems Library (libfaudes)
00004 
00005    Copyright (C) 2006  Bernd Opitz
00006    Exclusive copyright is granted to Klaus Schmidt
00007 
00008    This library is free software; you can redistribute it and/or
00009    modify it under the terms of the GNU Lesser General Public
00010    License as published by the Free Software Foundation; either
00011    version 2.1 of the License, or (at your option) any later version.
00012 
00013    This library is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016    Lesser General Public License for more details.
00017 
00018    You should have received a copy of the GNU Lesser General Public
00019    License along with this library; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00021    
00022 
00023 #include "syn_supnorm.h"
00024 #include "syn_supcon.h"
00025 
00026 
00027 namespace faudes {
00028 
00029 
00030 
00031 
00032 /*
00033 ***************************************************************************************
00034 ***************************************************************************************
00035  Implementation
00036 ***************************************************************************************
00037 ***************************************************************************************
00038 */
00039 
00040 
00041 //void NormalityConsistencyCheck(rL,rOAlph,rK) 
00042 void NormalityConsistencyCheck(
00043   const Generator& rL,
00044   const EventSet& rOAlph,
00045   const Generator& rK) {
00046   
00047   FD_DF("NormalityConsistencyCheck(...)");
00048   
00049   if (!(rK.IsDeterministic())) {
00050    std::stringstream errstr;
00051      errstr << "Nondeterministic parameter rK.";
00052    if(!(rL.IsDeterministic())) errstr << "Nondeterministic parameter rL.";
00053      throw Exception("NormalityConsistencyCheck", errstr.str(), 101);
00054   }
00055   if (!(rL.IsDeterministic())) {
00056    std::stringstream errstr;
00057    errstr << "Nondeterministic parameter rL.";
00058    if(!(rL.IsDeterministic())) errstr << "Nondeterministic parameter rL.";
00059    throw Exception("NormalityConsistencyCheck", errstr.str(), 101);
00060     }
00061   
00062   EventSet Kevents,Sigma;
00063   Sigma=rL.Alphabet();
00064   Kevents=rK.Alphabet();
00065   
00066   // observable events have to be subset of Sigma
00067   if(!(rOAlph<=Sigma)) {
00068     EventSet only_in_OAlph = rOAlph - Sigma;
00069     std::stringstream errstr;
00070     errstr << "Not all observable events are contained in Sigma: " 
00071        << only_in_OAlph.ToString() << ".";
00072     throw Exception("NormalityConsistencyCheck", errstr.str(), 100);
00073   } 
00074    
00075   // alphabets must match  
00076   if ( Sigma != Kevents) {
00077     EventSet only_in_L = Sigma - Kevents;
00078     EventSet only_in_K = Kevents - Sigma;
00079     only_in_L.Name("Only_In_L");
00080     only_in_L.Name("Only_In_K");
00081     std::stringstream errstr;
00082     errstr << "Alphabets of generators do not match.";
00083     if(!only_in_L.Empty())
00084       errstr <<  " " << only_in_L.ToString() << ".";
00085     if(!only_in_K.Empty())
00086       errstr <<  " " << only_in_K.ToString() << ".";
00087     throw Exception("NormalityConsistencyCheck", errstr.str(), 100);
00088   }
00089   
00090   // K must be subset of L
00091   if (!LanguageInclusion(rK,rL)) {
00092     std::stringstream errstr;
00093     errstr << "K is not subset of L.";
00094     throw Exception("NormalityConsistencyCheck", errstr.str(), 0);
00095   }
00096 }
00097 
00098 // IsNormal(rK,rL,rOAlph)
00099 bool IsNormal(
00100   const Generator& rL,
00101   const EventSet& rOAlph,
00102   const Generator& rK) 
00103 {
00104   FD_DF("IsNormal(...)");
00105 
00106   // bail out on empty K
00107   // note: this is required to survive the
00108   // determinism test when rK has no states at all
00109   if(IsEmptyLanguage(rK)) return true;
00110   
00111   // determinism required
00112   NormalityConsistencyCheck(rL,rOAlph,rK);
00113   
00114   //extract overall alphabet:
00115   EventSet Sigma;
00116   Sigma=rL.Alphabet();
00117   
00118   //extract alphabet of rK:
00119   EventSet Kevents;
00120   Kevents=rK.Alphabet();
00121   
00122   //calculate p(K)
00123   Generator Ktest1, Ktest2;
00124   Ktest1.StateNamesEnabled(false);
00125   Ktest2.StateNamesEnabled(false);
00126   Project(rK,rOAlph,Ktest1);
00127   
00128   //calculate pinv(p(K))
00129   InvProject(Ktest1, Sigma);
00130   
00131   //check normality: pinv(p(K)) intersect L = K?
00132   LanguageIntersection(Ktest1,rL,Ktest2);
00133   return LanguageInclusion(Ktest2,rK);
00134   
00135   // Remark: testing for LanguageEquality is not required, as inclusion
00136   // in the reverse direction is always met (assuming K\subseteq L)
00137 }
00138 
00139 
00140 
00141 // IsNormal rti wrapper
00142 bool IsNormal(const System& rPlantGen, const Generator& rSupCandGen) {
00143   return IsNormal(rPlantGen, rPlantGen.ObservableEvents(),rSupCandGen);
00144 }
00145 
00146 
00147 // ConcatenateFullLanguage(rGen)
00148 void ConcatenateFullLanguage(Generator& rGen) {
00149   FD_DF("ConcatenateFullLanguage(" << rGen.Name() << ")");
00150   
00151   // prepare result
00152   rGen.Name("ConcatenateFullLanguage(" + rGen.Name() + ")");
00153   
00154   // treat trivial empty result in case of empty marked language
00155   if(rGen.MarkedStatesSize()==0) {
00156     rGen.Clear();
00157     return;
00158   }
00159   
00160   // helpers
00161   EventSet alph=rGen.Alphabet();
00162   StateSet StatesToClear;
00163   TransSet TransToClear,TransToSet;
00164   StateSet::Iterator sit;
00165   TransSet::Iterator tit;
00166   EventSet::Iterator evit;
00167   
00168   // clear all transitions in marked states
00169   for (sit = rGen.MarkedStatesBegin(); sit != rGen.MarkedStatesEnd(); ++sit) {
00170       for (tit = rGen.TransRelBegin(*sit); tit != rGen.TransRelEnd(*sit); ++tit) {
00171           TransToClear.Insert(*tit);
00172       }
00173   }
00174   
00175   for (tit = TransToClear.Begin(); tit != TransToClear.End(); ++tit) {
00176       rGen.ClrTransition(*tit);
00177   }
00178   TransToClear.Clear();
00179   rGen.Accessible();
00180   
00181   // all marked states become eqivalent -> switch transitions leading to marked states to one remaining marked state
00182   // and delete all the others; note: for this special purpose, this procedure is faster than running StateMin.
00183   // if an init state is marked the effort is even less (as the result is Sigma* itself, see "else" below)
00184   bool initmarked = !( (rGen.InitStates() * rGen.MarkedStates()).Empty() );
00185   if (!initmarked) {
00186     // define remaining marked state (there is one because of nonzero MarkedStatesSize)
00187     sit = rGen.MarkedStatesBegin();
00188     Idx marked = *sit;
00189     // switch transitions to all other marked states if there are any
00190     if(rGen.MarkedStatesSize()>1) {
00191       // extract transitions sorted by target state X2
00192       TransSetX2EvX1 trel;
00193       rGen.TransRel(trel);
00194       TransSetX2EvX1::Iterator tit2;
00195       
00196       // switch transitions to all other marked states to the one remaining marked state
00197       ++sit;
00198       for (; sit != rGen.MarkedStatesEnd(); ++sit) {
00199           for (tit2 = trel.BeginByX2(*sit); tit2 != trel.EndByX2(*sit); ++tit2) {
00200           // switch transition target to remaining marked state
00201           TransToSet.Insert(tit2->X1,tit2->Ev,marked);
00202           // note: original transitions are cleared later with clearing the corresp. marked states.
00203           }
00204       }
00205       
00206       // delete all but remaining marked state (note: by doing so, also corresp. transitions are cleared.)
00207       sit = rGen.MarkedStatesBegin();
00208       ++sit;
00209       for (; sit != rGen.MarkedStatesEnd(); ++sit) {
00210       StatesToClear.Insert(*sit);
00211       }
00212       for (sit=StatesToClear.Begin(); sit != StatesToClear.End(); ++sit) {
00213       rGen.DelState(*sit);
00214       }
00215       StatesToClear.Clear();
00216       
00217       // insert switched transitions
00218       for (tit = TransToSet.Begin(); tit != TransToSet.End(); ++tit) {
00219           rGen.SetTransition(*tit);
00220       }
00221       TransToSet.Clear();
00222       }
00223 
00224     // now concatenate Sigma* by selflooping marked state with all events
00225     for (evit = alph.Begin(); evit != alph.End(); ++evit) {
00226       rGen.SetTransition(marked,*evit,marked);
00227     }
00228     
00229   }
00230   // consider marked init state case
00231   else {
00232     // reduce to empty string language
00233     rGen.ClearStates();
00234     rGen.ClearTransRel();
00235     Idx state=rGen.InsInitState();
00236     rGen.SetMarkedState(state);
00237     // now concatenate Sigma* by selflooping marked state with all events
00238     for (evit = alph.Begin(); evit != alph.End(); ++evit) {
00239       rGen.SetTransition(state,*evit,state);
00240     }
00241     
00242     }
00243   
00244   return;
00245 }
00246 
00247 
00248 //  SupNorm(rL,rOAlph,rK,rResult)
00249 bool SupNorm(
00250   const Generator& rL,
00251   const EventSet& rOAlph,
00252   const Generator& rK, 
00253   Generator& rResult)
00254 {
00255   FD_DF("SupNorm(" << rL.Name() << "," << rK.Name() << "," << rOAlph.Name() << ")");
00256   
00257   // exceprions
00258   NormalityConsistencyCheck(rL,rOAlph,rK);
00259   
00260   //extract overall alphabet:
00261   EventSet allevents;
00262   allevents=rL.Alphabet();
00263   
00264   //extract alphabet of rK:
00265   EventSet Kevents=rK.Alphabet();
00266     
00267   // involved operations from cfl_regular.h operate on the marked
00268   // languages -> turn generated languages into marked langusges
00269   Generator prL=rL;
00270   prL.InjectMarkedStates(rL.States());
00271   Generator prK=rK;
00272   prK.InjectMarkedStates(prK.States());
00273   
00274   // calculate "L-K" 
00275   LanguageDifference(prL,prK,rResult);
00276   
00277   // calculate Pinv(P(L-K)):
00278   Project(rResult,rOAlph,rResult);
00279   FD_DF("SupNorm: sizeof p(L-K): "<< rResult.Size());
00280   InvProject(rResult,allevents);
00281   FD_DF("SupNorm: sizeof pinv(p(L-K)): "<< rResult.Size());
00282 
00283   //calculate remaining set difference -> supnorm(K)
00284   LanguageDifference(prK,rResult,rResult);
00285   
00286   // cosmetics: remove blocking states
00287   rResult.Trim();
00288    
00289   // done
00290   rResult.Name("SupNorm("+rL.Name()+", "+rK.Name()+")");  
00291   return !( rResult.InitStatesEmpty() );
00292 }
00293 
00294 //  SupNormClosed(rL,rOAlph,rK,rResult)
00295 bool SupNormClosed(
00296   const Generator& rL,
00297   const EventSet& rOAlph,
00298   const Generator& rK, 
00299   Generator& rResult)
00300 {
00301   FD_DF("SupNormClosed(" << rL.Name() << "," << rK.Name() << "," << rOAlph.Name() << ")");
00302   
00303   NormalityConsistencyCheck(rL,rOAlph,rK);
00304   
00305   //extract overall alphabet:
00306   EventSet allevents;
00307   allevents=rL.Alphabet();
00308   
00309   //extract alphabet of rK:
00310   EventSet Kevents=rK.Alphabet();
00311   
00312   // involved operations from regular.h operate on the marked
00313   // languages -> turn generated languages into marked langs
00314   Generator prL=rL;
00315   prL.InjectMarkedStates(prL.States());
00316   Generator prK=rK;
00317   prK.InjectMarkedStates(prK.States());
00318   
00319   // calculate "L-K" 
00320   LanguageDifference(prL,prK,rResult);
00321 
00322   // calculate Pinv(P(L-K)):
00323   Project(rResult,rOAlph,rResult);
00324   FD_DF("SupNormClosed: sizeof p(L-K): "<< rResult.Size());
00325   InvProject(rResult,allevents);
00326   FD_DF("SupNormClosed: sizeof pinv(p(L-K)): "<< rResult.Size());
00327   
00328   //concatenate Pinv(P(L-K)) with Sigma*: this leads to closed result
00329   ConcatenateFullLanguage(rResult); // special function for efficient concatenation of Sigma*.
00330   
00331   FD_DF("SupNormClosed: sizeof pinv(p(L-K))Sigma*: "<< rResult.Size());
00332 
00333   //calculate remaining set difference -> supnormClosed(K)
00334   LanguageDifference(prK,rResult,rResult);
00335 
00336   // cosmetics: remove blocking states
00337   rResult.Trim();
00338 
00339   // done
00340   rResult.Name("SupNormClosed("+rL.Name()+", "+rK.Name()+")"); 
00341   return !( rResult.InitStatesEmpty() );
00342 }
00343 
00344 
00345 //  SupConNorm(rL,rCAlph,rOAlph,rK,rResult)
00346 void SupConNorm(
00347   const Generator& rL,
00348   const EventSet& rCAlph,
00349   const EventSet& rOAlph,
00350   const Generator& rK, 
00351   Generator& rResult)
00352 {
00353   FD_DF("SupConNorm(" << rL.Name() << "," << rK.Name() << ")");
00354   // 0.: intersect K with L to match requirements of SupNormClosed
00355   Generator K;
00356   K.StateNamesEnabled(false);
00357   Product(rL,rK,K);
00358   // 1. normal and closed sublanguage (operates on / returns generated language)
00359   Generator N;
00360   N.StateNamesEnabled(false);
00361   SupNormClosed(rL,rOAlph,K,N);
00362   // 2. project to sigma_o (generated languages)
00363   Generator N0,L0;
00364   N0.StateNamesEnabled(false);
00365   L0.StateNamesEnabled(false);
00366   Project(N,rOAlph,N0);
00367   Project(rL,rOAlph,L0);
00368   // 3. supremal controllable sublanguage (generated languages)
00369   EventSet sig_co = rCAlph * rOAlph;
00370   Generator K0;
00371   K0.StateNamesEnabled(false);
00372   SupCon(L0,sig_co,N0,K0);
00373   // 4. inverese project to sigma  (on generated language)
00374   InvProject(K0,rL.Alphabet());
00375   // 5. intersect with L (generated languages)
00376   LanguageIntersection(K0,rL,rResult);
00377   // convenience: mark the generated language
00378   rResult.InjectMarkedStates(rResult.States());
00379 }  
00380 
00381 
00382 //  SupConNorm(rL,rCAlph,rOAlph,rK,rResult)
00383 void SupConNormNB(
00384   const Generator& rL,
00385   const EventSet& rCAlph,
00386   const EventSet& rOAlph,
00387   const Generator& rK, 
00388   Generator& rResult)
00389 {
00390   FD_DF("SupConNormNB(" << rL.Name() << "," << rK.Name() << ")");
00391   // initialize: K0
00392   Generator K0;
00393   K0.StateNamesEnabled(false);
00394   Product(rL,rK,K0);
00395   K0.Coaccessible();
00396   // initialize: closure(rL)
00397   Generator L=rL;
00398   L.StateNamesEnabled(false);
00399   L.Trim();
00400   L.InjectMarkedStates(L.States());
00401   // loop
00402   Generator Ki=K0;
00403   Ki.StateNamesEnabled(false);
00404   while(1) {
00405     FD_DF("SupConNormNB(" << rL.Name() << "," << rK.Name() << "): #" << Ki.Size() << " m#" << Ki.MarkedStatesSize());
00406     // keep copy of recent
00407     rResult=Ki;
00408     // cheep closure (for coreachable generator)
00409     Ki.InjectMarkedStates(Ki.States());
00410     // synthesise closed
00411     SupConNorm(L,rCAlph,rOAlph,Ki,Ki);
00412     // restrict
00413     Product(K0,Ki,Ki);
00414     Ki.Coaccessible();
00415     // test (sequence is decreasing anyway)
00416     if(LanguageInclusion(rResult,Ki)) break;
00417   }  
00418   FD_DF("SupConNormNB(" << rL.Name() << "," << rK.Name() << "): done");
00419 }  
00420 
00421 
00422 // SupPrefixClosed(rK,rResult)
00423 bool SupPrefixClosed(
00424   const Generator& rK,
00425   Generator& rResult) {
00426   
00427   FD_DF("SupPrefixClosed("<<rK.Name()<<")");
00428   
00429   // prepare Result:
00430   rResult.Name("SupPrefixClosed("+rK.Name()+")");
00431   
00432   // check for marked initial state, empty result if not
00433   if( (rK.InitStates() * rK.MarkedStates()).Empty() ) {
00434     rResult.Clear();
00435     return false;
00436   }
00437 
00438   rResult.Assign(rK);  
00439   
00440   // erase all transitions not leading to a marked state
00441   // todo: Depth-first-search could be faster
00442   TransSet trel=rResult.TransRel();
00443   TransSet::Iterator tit=trel.Begin();
00444   TransSet::Iterator tit_end=trel.End();
00445   for(;tit!=tit_end;tit++) {
00446     if(!(rResult.ExistsMarkedState(tit->X2))) {
00447       rResult.ClrTransition(*tit);
00448       }
00449   }
00450   
00451   // make reachable (cosmetic)
00452   rResult.Trim();
00453   
00454   // as there is at least one marked init state, result is nonempty
00455   return true;
00456 }
00457 
00458 
00459 
00460 /** rti wrapper */
00461 void SupNorm(
00462   const System& rPlantGen, 
00463   const Generator& rSpecGen, 
00464   Generator& rResGen) 
00465 {
00466   // prepare result
00467   Generator* pResGen = &rResGen;
00468   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00469     pResGen= rResGen.New();
00470   }
00471   // execute
00472   SupNorm(rPlantGen,rPlantGen.ObservableEvents(),rSpecGen,*pResGen);
00473   // copy all attributes of input alphabet
00474   pResGen->EventAttributes(rPlantGen.Alphabet());
00475   // copy result
00476   if(pResGen != &rResGen) {
00477     pResGen->Move(rResGen);
00478     delete pResGen;
00479   }
00480 }
00481 
00482 /** rti wrapper */
00483 void SupNormClosed(
00484   const System& rPlantGen, 
00485   const Generator& rSpecGen, 
00486   Generator& rResGen) 
00487 {
00488   // prepare result
00489   Generator* pResGen = &rResGen;
00490   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00491     pResGen= rResGen.New();
00492   }
00493   // execute
00494   SupNormClosed(rPlantGen,rPlantGen.ObservableEvents(),rSpecGen,*pResGen);
00495   // copy all attributes of input alphabet
00496   pResGen->EventAttributes(rPlantGen.Alphabet());
00497   // copy result
00498   if(pResGen != &rResGen) {
00499     pResGen->Move(rResGen);
00500     delete pResGen;
00501   }
00502 }
00503 
00504 
00505 /** rti wrapper */
00506 void SupConNorm(
00507   const System& rPlantGen, 
00508   const Generator& rSpecGen, 
00509   Generator& rResGen) 
00510 {
00511   // prepare result
00512   Generator* pResGen = &rResGen;
00513   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00514     pResGen= rResGen.New();
00515   }
00516   // execute
00517   SupConNorm(rPlantGen,rPlantGen.ControllableEvents(),rPlantGen.ObservableEvents(),rSpecGen,*pResGen);
00518   // copy all attributes of input alphabet
00519   pResGen->EventAttributes(rPlantGen.Alphabet());
00520   // copy result
00521   if(pResGen != &rResGen) {
00522     pResGen->Move(rResGen);
00523     delete pResGen;
00524   }
00525 }
00526 
00527 /** rti wrapper */
00528 void SupConNormNB(
00529   const System& rPlantGen, 
00530   const Generator& rSpecGen, 
00531   Generator& rResGen) 
00532 {
00533   FD_WARN("SupConNormNB(" << rPlantGen.Name() << "," << rSpecGen.Name() << "): rti wrapper");
00534   // prepare result
00535   Generator* pResGen = &rResGen;
00536   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00537     pResGen= rResGen.New();
00538   }
00539   // execute
00540   SupConNormNB(rPlantGen,rPlantGen.ControllableEvents(),rPlantGen.ObservableEvents(),rSpecGen,*pResGen);
00541   // copy all attributes of input alphabet
00542   pResGen->EventAttributes(rPlantGen.Alphabet());
00543   // copy result
00544   if(pResGen != &rResGen) {
00545     pResGen->Move(rResGen);
00546     delete pResGen;
00547   }
00548 }
00549 
00550 } // end namespace

libFAUDES 2.20s --- 2011.10.12 --- c++ source docu by doxygen