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 
00025 
00026 namespace faudes {
00027 
00028 
00029 
00030 
00031 /*
00032 ***************************************************************************************
00033 ***************************************************************************************
00034  Implementation
00035 ***************************************************************************************
00036 ***************************************************************************************
00037 */
00038 
00039 
00040 //void NormalityConsistencyCheck(rL,rOAlph,rK) 
00041 void NormalityConsistencyCheck(
00042   const Generator& rL,
00043   const EventSet& rOAlph,
00044   const Generator& rK) {
00045   
00046   FD_DF("NormalityConsistencyCheck(...)");
00047   
00048   if (!(rK.IsDeterministic())) {
00049    std::stringstream errstr;
00050      errstr << "Nondeterministic parameter rK.";
00051    if(!(rL.IsDeterministic())) errstr << "Nondeterministic parameter rL.";
00052      throw Exception("NormalityConsistencyCheck", errstr.str(), 101);
00053   }
00054   if (!(rL.IsDeterministic())) {
00055    std::stringstream errstr;
00056    errstr << "Nondeterministic parameter rL.";
00057    if(!(rL.IsDeterministic())) errstr << "Nondeterministic parameter rL.";
00058    throw Exception("NormalityConsistencyCheck", errstr.str(), 101);
00059     }
00060   
00061   EventSet Kevents,Sigma;
00062   Sigma=rL.Alphabet();
00063   Kevents=rK.Alphabet();
00064   
00065   // observable events have to be subset of Sigma
00066   if(!(rOAlph<=Sigma)) {
00067     EventSet only_in_OAlph = rOAlph - Sigma;
00068     std::stringstream errstr;
00069     errstr << "Not all observable events are contained in Sigma: " 
00070        << only_in_OAlph.ToString() << ".";
00071     throw Exception("NormalityConsistencyCheck", errstr.str(), 100);
00072   } 
00073    
00074   // alphabets must match  
00075   if ( Sigma != Kevents) {
00076     EventSet only_in_L = Sigma - Kevents;
00077     EventSet only_in_K = Kevents - Sigma;
00078     only_in_L.Name("Only_In_L");
00079     only_in_L.Name("Only_In_K");
00080     std::stringstream errstr;
00081     errstr << "Alphabets of generators do not match.";
00082     if(!only_in_L.Empty())
00083       errstr <<  " " << only_in_L.ToString() << ".";
00084     if(!only_in_K.Empty())
00085       errstr <<  " " << only_in_K.ToString() << ".";
00086     throw Exception("NormalityConsistencyCheck", errstr.str(), 100);
00087   }
00088   
00089   // K must be subset of L
00090   if (!LanguageInclusion(rK,rL)) {
00091     std::stringstream errstr;
00092     errstr << "K is not subset of L.";
00093     throw Exception("NormalityConsistencyCheck", errstr.str(), 0);
00094   }
00095 }
00096 
00097 // IsNormal(rK,rL,rOAlph)
00098 bool IsNormal(
00099   const Generator& rL,
00100   const EventSet& rOAlph,
00101   const Generator& rK) 
00102 {
00103   FD_DF("IsNormal(...)");
00104   
00105   NormalityConsistencyCheck(rL,rOAlph,rK);
00106   
00107   //extract overall alphabet:
00108   EventSet Sigma;
00109   Sigma=rL.Alphabet();
00110   
00111   //extract alphabet of rK:
00112   EventSet Kevents;
00113   Kevents=rK.Alphabet();
00114   
00115   //calculate p(K)
00116   Generator Ktest1, Ktest2;
00117   Project(rK,rOAlph,Ktest1);
00118   
00119   //calculate pinv(p(K))
00120   InvProject(Ktest1, Sigma);
00121   
00122   //check normality: pinv(p(K)) intersect L = K?
00123   LanguageIntersection(Ktest1,rL,Ktest2);
00124   return LanguageInclusion(Ktest2,rK);
00125   // Remark: LanguageEquality is not necessary, as inclusion
00126   // in the reverse direction is always met.
00127 }
00128 
00129 // IsNormalAlt(rK,rL,rOAlph)
00130 bool IsNormalAlt(
00131   const Generator& rL,
00132   const EventSet& rOAlph,
00133     const Generator& rK) 
00134 {
00135   FD_DF("IsNormalAlt(...)");
00136   
00137   NormalityConsistencyCheck(rL,rOAlph,rK);
00138   
00139   //extract overall alphabet:
00140   EventSet Sigma;
00141   Sigma=rL.Alphabet();
00142   
00143   //extract alphabet of rK:
00144   EventSet Kevents;
00145   Kevents=rK.Alphabet();
00146   
00147   //calculate p(K)
00148   Generator Ktest1, Ktest2;
00149   Project(rK,rOAlph,Ktest1);
00150   
00151   //calculate pinv(p(K))
00152   InvProject(Ktest1, Sigma);
00153   
00154   //check normality: p(K) || L = K?
00155   Parallel(Ktest1,rL,Ktest2);
00156   return LanguageInclusion(Ktest2,rK);
00157   // Remark: LanguageEquality is not necessary, as inclusion
00158   // in the reverse direction is always met.
00159 }
00160 
00161 
00162 // IsNormal rti wrapper
00163 bool IsNormal(const cGenerator& rPlantGen, const vGenerator& rSupCandGen) {
00164   return IsNormal(rPlantGen, rPlantGen.ObservableEvents(),rSupCandGen);
00165 }
00166 
00167 
00168 // ConcatenateFullLanguage(rGen)
00169 void ConcatenateFullLanguage(vGenerator& rGen) {
00170   FD_DF("ConcatenateFullLanguage(" << rGen.Name() << ")");
00171   
00172   // prepare result
00173   rGen.Name("ConcatenateFullLanguage(" + rGen.Name() + ")");
00174   
00175   // treat trivial empty result in case of empty marked language
00176   if(rGen.MarkedStatesSize()==0) {
00177     rGen.Clear();
00178     return;
00179   }
00180   
00181   // helpers
00182   EventSet alph=rGen.Alphabet();
00183   StateSet StatesToClear;
00184   TransSet TransToClear,TransToSet;
00185   StateSet::Iterator sit;
00186   TransSet::Iterator tit;
00187   EventSet::Iterator evit;
00188   
00189   // clear all transitions in marked states
00190   for (sit = rGen.MarkedStatesBegin(); sit != rGen.MarkedStatesEnd(); ++sit) {
00191       for (tit = rGen.TransRelBegin(*sit); tit != rGen.TransRelEnd(*sit); ++tit) {
00192           TransToClear.Insert(*tit);
00193       }
00194   }
00195   
00196   for (tit = TransToClear.Begin(); tit != TransToClear.End(); ++tit) {
00197       rGen.ClrTransition(*tit);
00198   }
00199   TransToClear.Clear();
00200   rGen.Accessible();
00201   
00202   // all marked states become eqivalent -> switch transitions leading to marked states to one remaining marked state
00203   // and delete all the others; note: for this special purpose, this procedure is faster than running StateMin.
00204   // if an init state is marked the effort is even less (as the result is Sigma* itself, see "else" below)
00205   bool initmarked = !( (rGen.InitStates() * rGen.MarkedStates()).Empty() );
00206   if (!initmarked) {
00207     // define remaining marked state (there is one because of nonzero MarkedStatesSize)
00208     sit = rGen.MarkedStatesBegin();
00209     Idx marked = *sit;
00210     // switch transitions to all other marked states if there are any
00211     if(rGen.MarkedStatesSize()>1) {
00212       // extract transitions sorted by target state X2
00213       TransSetX2EvX1 trel;
00214       rGen.TransRel(trel);
00215       TransSetX2EvX1::Iterator tit2;
00216       
00217       // switch transitions to all other marked states to the one remaining marked state
00218       ++sit;
00219       for (; sit != rGen.MarkedStatesEnd(); ++sit) {
00220           for (tit2 = trel.BeginByX2(*sit); tit2 != trel.EndByX2(*sit); ++tit2) {
00221           // switch transition target to remaining marked state
00222           TransToSet.Insert(tit2->X1,tit2->Ev,marked);
00223           // note: original transitions are cleared later with clearing the corresp. marked states.
00224           }
00225       }
00226       
00227       // delete all but remaining marked state (note: by doing so, also corresp. transitions are cleared.)
00228       sit = rGen.MarkedStatesBegin();
00229       ++sit;
00230       for (; sit != rGen.MarkedStatesEnd(); ++sit) {
00231       StatesToClear.Insert(*sit);
00232       }
00233       for (sit=StatesToClear.Begin(); sit != StatesToClear.End(); ++sit) {
00234       rGen.DelState(*sit);
00235       }
00236       StatesToClear.Clear();
00237       
00238       // insert switched transitions
00239       for (tit = TransToSet.Begin(); tit != TransToSet.End(); ++tit) {
00240           rGen.SetTransition(*tit);
00241       }
00242       TransToSet.Clear();
00243       }
00244 
00245     // now concatenate Sigma* by selflooping marked state with all events
00246     for (evit = alph.Begin(); evit != alph.End(); ++evit) {
00247       rGen.SetTransition(marked,*evit,marked);
00248     }
00249     
00250   }
00251   // consider marked init state case
00252   else {
00253     // reduce to empty string language
00254     rGen.ClearStates();
00255     rGen.ClearTransRel();
00256     Idx state=rGen.InsInitState();
00257     rGen.SetMarkedState(state);
00258     // now concatenate Sigma* by selflooping marked state with all events
00259     for (evit = alph.Begin(); evit != alph.End(); ++evit) {
00260       rGen.SetTransition(state,*evit,state);
00261     }
00262     
00263     }
00264   
00265   return;
00266 }
00267 
00268 
00269 //  SupNorm(rL,rOAlph,rK,rResult)
00270 bool SupNorm(
00271   Generator& rL,
00272   const EventSet& rOAlph,
00273   const Generator& rK, 
00274   Generator& rResult)
00275 {
00276   FD_DF("SupNorm(" << rK.Name() << "," << rL.Name() << "," << rOAlph.Name() << ")");
00277   
00278   NormalityConsistencyCheck(rL,rOAlph,rK);
00279   
00280   // prepare result
00281   rResult.Clear();
00282   
00283   //extract overall alphabet:
00284   EventSet allevents;
00285   allevents=rL.Alphabet();
00286   
00287   //extract alphabet of rK:
00288   EventSet Kevents=rK.Alphabet();
00289   
00290   // remember name and marked states of rL
00291   std::string rLname=rL.Name();
00292   StateSet rLmarked=rL.MarkedStates();
00293   
00294   // involved operations from regular.h operate on the marked
00295   // languages -> turn generated languages into marked langs
00296   rL.InjectMarkedStates(rL.States());
00297   //###PrefixClosure(rL);
00298   Generator prK=rK;
00299   prK.InjectMarkedStates(prK.States());
00300   //###PrefixClosure(prK);
00301   rResult = prK;
00302   
00303   // calculate "L-K" (ToDo: use LanguageDifference):
00304   LanguageComplement(rResult);
00305   FD_DF("SupNorm: size of complement(K): "<<rResult.Size()<<",marked: "<<rResult.MarkedStatesSize());
00306   Generator tempgen;
00307   LanguageIntersection(rL, rResult, tempgen);
00308   rResult.Clear();
00309   FD_DF("SupNorm: sizeof L U complement(K)=L-K: "<<tempgen.Size());
00310   
00311   // calculate Pinv(P(L-K)):
00312   Project(tempgen,rOAlph,rResult);
00313   tempgen.Clear();
00314   FD_DF("SupNorm: sizeof p(L-K): "<< rResult.Size());
00315   InvProject(rResult,allevents);
00316   FD_DF("SupNorm: sizeof pinv(p(L-K)): "<<rResult.Size());
00317   
00318 //  FD_DF("SupNorm: sizeof pinv(p(L-K)): "<<rResult.Size());
00319 
00320   //calculate remaining set difference -> supnorm(K)
00321   LanguageComplement(rResult);
00322   LanguageIntersection(prK, rResult, tempgen);
00323   rResult=tempgen;
00324   tempgen.Clear();
00325   FD_DF("SupNorm: sizeof K - pinv(p(L-K)) (result): "<<rResult.Size());
00326   
00327   // language MARKED by rResult is the result -> remove blocking states, mark all remaining states.
00328   rResult.Trim();
00329   rResult.InjectMarkedStates(rResult.States());
00330   
00331   // restore original rL
00332   rL.Name(rLname);
00333   rL.InjectMarkedStates(rLmarked);
00334   
00335   return !( rResult.InitStatesEmpty() );
00336 }
00337 
00338 //  SupNormClosed(rL,rOAlph,rK,rResult)
00339 bool SupNormClosed(
00340   Generator& rL,
00341   const EventSet& rOAlph,
00342   const Generator& rK, 
00343   Generator& rResult)
00344 {
00345   FD_DF("SupNormClosed(" << rK.Name() << "," << rL.Name() << "," << rOAlph.Name() << ")");
00346   
00347   NormalityConsistencyCheck(rL,rOAlph,rK);
00348   
00349   // prepare result
00350   rResult.Clear();
00351   
00352   //extract overall alphabet:
00353   EventSet allevents;
00354   allevents=rL.Alphabet();
00355   
00356   //extract alphabet of rK:
00357   EventSet Kevents=rK.Alphabet();
00358   
00359   // remember name and marked states of rL
00360   std::string rLname=rL.Name();
00361   StateSet rLmarked=rL.MarkedStates();
00362   
00363   // involved operations from regular.h operate on the marked
00364   // languages -> turn generated languages into marked langs
00365   rL.InjectMarkedStates(rL.States());
00366   //###PrefixClosure(rL);
00367   Generator prK=rK;
00368   prK.InjectMarkedStates(prK.States());
00369   //###PrefixClosure(prK);
00370   rResult = prK;
00371   
00372   // calculate "L-K" (ToDo: use LanguageDifference):
00373   LanguageComplement(rResult);
00374   FD_DF("SupNormClosed: size of complement(K): "<<rResult.Size()<<",marked: "<<rResult.MarkedStatesSize());
00375   Generator tempgen;
00376   LanguageIntersection(rL, rResult, tempgen);
00377   rResult.Clear();
00378   FD_DF("SupNormClosed: sizeof L U complement(K)=L-K: "<<tempgen.Size());
00379   
00380   // calculate Pinv(P(L-K)):
00381   Project(tempgen,rOAlph,rResult);
00382   tempgen.Clear();
00383   FD_DF("SupNormClosed: sizeof p(L-K): "<< rResult.Size());
00384   InvProject(rResult,allevents);
00385   FD_DF("SupNormClosed: sizeof pinv(p(L-K)): "<<rResult.Size());
00386   
00387   //concatenate Pinv(P(L-K)) with Sigma*: this leads to closed result
00388   ConcatenateFullLanguage(rResult); // special function for fast concatenation of Sigma*.
00389   
00390   //  FD_DF("SupNormClosed: sizeof pinv(p(L-K))Sigma*: "<<rResult.Size());
00391 
00392   //calculate remaining set difference -> supnormClosed(K)
00393   LanguageComplement(rResult);
00394   LanguageIntersection(prK, rResult, tempgen);
00395   rResult=tempgen;
00396   tempgen.Clear();
00397   FD_DF("SupNormClosed: sizeof K - pinv(p(L-K))Sigma* (result): "<<rResult.Size());
00398   
00399   // language MARKED by rResult is the result -> remove blocking states, mark all remaining states.
00400   rResult.Trim();
00401   rResult.InjectMarkedStates(rResult.States());
00402   
00403   // restore original rL
00404   rL.Name(rLname);
00405   rL.InjectMarkedStates(rLmarked);
00406   
00407   // mark result corresponding to rL
00408   LanguageIntersection(rResult,rL,rResult);
00409   
00410   return !( rResult.InitStatesEmpty() );
00411 }
00412 
00413 
00414 
00415 // SupPrefixClosed(rK,rResult)
00416 bool SupPrefixClosed(
00417   const Generator& rK,
00418   Generator& rResult) {
00419   
00420   FD_DF("SupPrefixClosed("<<rK.Name()<<")");
00421   
00422   // prepare Result:
00423   rResult.Clear();
00424   rResult.Name("SupPrefixClosed("+rK.Name()+")");
00425   
00426   // check for marked initial state, empty result if not
00427   if( (rK.InitStates() * rK.MarkedStates()).Empty() ) return false;
00428   
00429   rResult=rK;  
00430   
00431   // erase all transitions not leading to a marked state
00432   // todo: Depth-first-search could be faster
00433   TransSet trel=rResult.TransRel();
00434   TransSet::Iterator tit=trel.Begin();
00435   TransSet::Iterator tit_end=trel.End();
00436   for(;tit!=tit_end;tit++) {
00437     if(!(rResult.ExistsMarkedState(tit->X2))) {
00438       rResult.ClrTransition(*tit);
00439       }
00440   }
00441   
00442   // make reachable (cosmetic)
00443   rResult.Trim();
00444   
00445   // as there is at least one marked init state, result is nonempty
00446   return true;
00447 }
00448 
00449 // SupNormAlt(rK,rL,rOAlph,ClosedResult,rResult)
00450 bool SupNormAlt(
00451   Generator& rL,
00452   const EventSet& rOAlph,
00453   const Generator& rK, 
00454   Generator& rResult) 
00455 {
00456   FD_DF("SupNorm(...)");
00457   
00458   NormalityConsistencyCheck(rL,rOAlph,rK);
00459   
00460   // prepare result
00461   rResult.Clear();
00462   rResult = rK;
00463   
00464   //extract overall alphabet:
00465   EventSet allevents;
00466   allevents=rL.Alphabet();
00467   
00468   //extract alphabet of rK:
00469   EventSet Kevents;
00470   Kevents=rK.Alphabet();
00471   
00472   // remember name and marked states of rL
00473   std::string rLname=rL.Name();
00474   StateSet rLmarked=rL.MarkedStates();
00475   
00476   // involved operations from regular.h treat only the marked
00477   // languages -> turn generated languages into marked langs
00478   rResult.InjectMarkedStates(rResult.States());
00479   //###PrefixClosure(rResult);
00480   rL.InjectMarkedStates(rL.States());
00481   //##PrefixClosure(rL);
00482   Generator Kquer=rK;
00483   Kquer.InjectMarkedStates(Kquer.States());
00484   //###PrefixClosure(Kquer);
00485   
00486   // calculate "L-K" (ToDo: use LanguageDifference):
00487   LanguageComplement(rResult);
00488   FD_DF("SupNorm: size of complement(K): "<<rResult.Size()<<",marked: "<<rResult.MarkedStatesSize());
00489   Generator tempgen;
00490   LanguageIntersection(rL, rResult, tempgen);
00491   rResult.Clear();
00492   FD_DF("SupNorm: sizeof L U complement(K)=L-K: "<<tempgen.Size());
00493   
00494   // calculate Pinv(P(L-K)):
00495   Project(tempgen,rOAlph,rResult);
00496   tempgen.Clear();
00497   FD_DF("SupNorm: sizeof p(L-K): "<< rResult.Size());
00498   InvProject(rResult,allevents);
00499   FD_DF("SupNorm: sizeof pinv(p(L-K)): "<<rResult.Size());
00500   
00501   // Remark: different from the above supnorm version, we do not
00502   // concatenate Sigma* here, but make the result prefix-closed
00503   // at the end.
00504 
00505   //calculate remaining set difference
00506   LanguageComplement(rResult);
00507   LanguageIntersection(Kquer, rResult, tempgen);
00508   rResult=tempgen;
00509   FD_DF("SupNorm: sizeof K - pinv(p(L-K))Sigma* (result): "<<rResult.Size());
00510   
00511   // make prefix-closed
00512   SupPrefixClosed(tempgen,rResult);
00513 
00514   // language MARKED by rResult is the result -> turn marked language into generated language
00515   rResult.Trim(); //may be unnecessesary
00516   
00517   // restore original rL
00518   rL.Name(rLname);
00519   rL.InjectMarkedStates(rLmarked);
00520   
00521   // mark result corresponding to rL
00522   LanguageIntersection(rResult,rL,rResult);
00523   
00524   return rResult.Empty();
00525 
00526 }
00527 
00528 
00529 
00530 /** rti wrapper */
00531 void SupNorm(
00532   const vGenerator& rPlantGen, 
00533   const EventSet&  rOAlph,
00534   const vGenerator& rSpecGen, 
00535   vGenerator& rResGen) {
00536 
00537   // trust deferred copy ...
00538   vGenerator pg=rPlantGen;
00539   SupNorm(pg,rOAlph,rSpecGen,rResGen);
00540 
00541 }
00542 
00543 /** rti wrapper */
00544 void SupNorm(
00545   const cGenerator& rPlantGen, 
00546   const vGenerator& rSpecGen, 
00547   vGenerator& rResGen) {
00548 
00549   // trust deferred copy ...
00550   vGenerator pg=rPlantGen;
00551   SupNorm(pg,rPlantGen.ObservableEvents(),rSpecGen,rResGen);
00552 
00553 }
00554 
00555 /** rti wrapper */
00556 void SupNormClosed(
00557   const vGenerator& rPlantGen, 
00558   const EventSet&  rOAlph,
00559   const vGenerator& rSpecGen, 
00560   vGenerator& rResGen) {
00561 
00562   // trust deferred copy ...
00563   vGenerator pg=rPlantGen;
00564   SupNormClosed(pg,rOAlph,rSpecGen,rResGen);
00565 
00566 }
00567 
00568 /** rti wrapper */
00569 void SupNormClosed(
00570   const cGenerator& rPlantGen, 
00571   const vGenerator& rSpecGen, 
00572   vGenerator& rResGen) {
00573 
00574   // trust deferred copy ...
00575   vGenerator pg=rPlantGen;
00576   SupNormClosed(pg,rPlantGen.ObservableEvents(),rSpecGen,rResGen);
00577 
00578 }
00579 
00580 } // end namespace

libFAUDES 2.18b --- 2010-12-17 --- c++ source docu by doxygen 1.6.3