libFAUDES

Sections

Index

syn_functions.cpp

Go to the documentation of this file.
00001 /** @file syn_functions.cpp Misc functions related to synthesis */
00002 
00003 /* FAU Discrete Event Systems Library (libfaudes)
00004 
00005    Copyright (C) 2010 Thomas Moor
00006 
00007    This library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public
00009    License as published by the Free Software Foundation; either
00010    version 2.1 of the License, or (at your option) any later version.
00011 
00012    This library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License along with this library; if not, write to the Free Software
00019    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00020 
00021 
00022 //#define FAUDES_DEBUG_FUNCTION
00023    
00024 #include "syn_functions.h"
00025 
00026 
00027 namespace faudes {
00028 
00029 
00030 
00031 
00032 /*
00033 ***************************************************************************************
00034 ***************************************************************************************
00035  Implementation
00036 ***************************************************************************************
00037 ***************************************************************************************
00038 */
00039 
00040 
00041 
00042 //IsRelativelyMarked(rGenPlant,rGenCand)
00043 bool IsRelativelyMarked(const vGenerator& rGenPlant, const vGenerator& rGenCand) {
00044 
00045   // alphabets must match
00046   if ( rGenPlant.Alphabet() != rGenCand.Alphabet()) {
00047     std::stringstream errstr;
00048     errstr << "Alphabets of generators do not match.";
00049     throw Exception("IsRelativelyMarked", errstr.str(), 100);
00050   }
00051 
00052 #ifdef FAUDES_CHECKED
00053   // generators are meant to be nonblocking
00054   if ( !IsNonblocking(rGenCand) ||  !IsNonblocking(rGenPlant)) {
00055     std::stringstream errstr;
00056     errstr << "Arguments are expected to be nonblocking.";
00057     throw Exception("IsRelativelyMarked", errstr.str(), 201);
00058   }
00059 #endif
00060 
00061 #ifdef FAUDES_CHECKED
00062   // generators are meant to be deterministic
00063   if ( !IsDeterministic(rGenCand) ||  !IsDeterministic(rGenPlant)) {
00064     std::stringstream errstr;
00065     errstr << "Arguments are expected to be deterministic.";
00066     throw Exception("IsRelativelyMarked", errstr.str(), 202);
00067   }
00068 #endif
00069 
00070   // perform composition
00071   std::map< std::pair<Idx,Idx> , Idx> revmap;
00072   vGenerator product;
00073   Product(rGenPlant,rGenCand,revmap,product);
00074 
00075   // test all reachable states
00076   std::map< std::pair<Idx,Idx> , Idx>::iterator rit;
00077   for(rit=revmap.begin(); rit!=revmap.end(); ++rit) {
00078     // ok: not GPlant-marked state is not considered
00079     if(!rGenPlant.ExistsMarkedState(rit->first.first)) 
00080       continue;
00081     // ok: GPlant-marked state also has GCand-mark
00082     if(rGenCand.ExistsMarkedState(rit->first.second))
00083       continue;
00084     // failure: GPlant-marked state has no GCand-mark
00085     break;
00086   }
00087 
00088   // ok if loop passed
00089   return rit==revmap.end();
00090 
00091 }
00092 
00093 
00094 
00095 //IsRelativelyPrefixClosed(rGenPlant,rGenCand)
00096 bool IsRelativelyPrefixClosed(const vGenerator& rGenPlant, const vGenerator& rGenCand) {
00097 
00098   FD_DF("IsRelativelyPrefixClosed(\"" <<  rGenPlant.Name() << "\", \"" << rGenCand.Name() << "\")");
00099 
00100   // alphabets must match
00101   if ( rGenPlant.Alphabet() != rGenCand.Alphabet()) {
00102     std::stringstream errstr;
00103     errstr << "Alphabets of generators do not match.";
00104     throw Exception("IsRelativelyPrefixClosed", errstr.str(), 100);
00105   }
00106 
00107 #ifdef FAUDES_CHECKED
00108   // generators are meant to be nonblocking
00109   if ( !IsNonblocking(rGenCand) ||  !IsNonblocking(rGenPlant)) {
00110     std::stringstream errstr;
00111     errstr << "Arguments are expected to be nonblocking.";
00112     throw Exception("IsRelativelyPrefixClosed", errstr.str(), 201);
00113   }
00114 #endif
00115 
00116 #ifdef FAUDES_CHECKED
00117   // generators are meant to be deterministic
00118   if ( !IsDeterministic(rGenCand) ||  !IsDeterministic(rGenPlant)) {
00119     std::stringstream errstr;
00120     errstr << "Arguments are expected to be deterministic.";
00121     throw Exception("IsRelativelyPrefixClosed", errstr.str(), 202);
00122   }
00123 #endif
00124 
00125   // perform composition (variation from cfl_parallel.cpp)
00126   FD_DF("IsRelativelyPrefixClosed(..): perform product");
00127 
00128   // todo stack
00129   std::stack< std::pair<Idx,Idx> > todo;
00130   // current pair, new pair
00131   std::pair<Idx,Idx> currentstates, newstates;
00132   // accessible states
00133   std::set< std::pair<Idx,Idx> > productstates;
00134   // iterators
00135   StateSet::Iterator lit1, lit2;
00136   TransSet::Iterator tit1, tit1_end, tit2, tit2_end;
00137   std::set< std::pair<Idx,Idx> >::iterator rcit;
00138   // sense violation of L(GCand) <= L(GPlant)
00139   bool inclusion12=true;
00140 
00141   // push all combinations of initial states on todo stack
00142   FD_DF("IsRelativelyPrefixClosed(..): perform product: adding all combinations of initial states to todo");
00143   for (lit1 = rGenCand.InitStatesBegin(); 
00144       lit1 != rGenCand.InitStatesEnd(); ++lit1) {
00145     for (lit2 = rGenPlant.InitStatesBegin(); 
00146         lit2 != rGenPlant.InitStatesEnd(); ++lit2) {
00147       currentstates = std::make_pair(*lit1, *lit2);
00148       todo.push(currentstates);
00149       productstates.insert(currentstates);
00150       FD_DF("IsRelativelyPrefixClosed(..): perform product: (" << 
00151       *lit1 << "|" << *lit2 << ")");
00152     }
00153   }
00154 
00155   // start algorithm
00156   FD_DF("IsRelativelyPrefixClosed(..): perform product: Product: processing reachable states:");
00157   while (! todo.empty() && inclusion12) {
00158     // allow for user interrupt
00159     LoopCallback();
00160     // get next reachable state from todo stack
00161     currentstates = todo.top();
00162     todo.pop();
00163     FD_DF("Processing (" << currentstates.first << "|" 
00164     << currentstates.second << ")");
00165     // iterate over all rGenCand transitions
00166     tit1 = rGenCand.TransRelBegin(currentstates.first);
00167     tit1_end = rGenCand.TransRelEnd(currentstates.first);
00168     tit2 = rGenPlant.TransRelBegin(currentstates.second);
00169     tit2_end = rGenPlant.TransRelEnd(currentstates.second);
00170     Idx curev1=0;
00171     bool resolved12=true;
00172     while((tit1 != tit1_end) && (tit2 != tit2_end)) {
00173       // sense new event
00174       if(tit1->Ev != curev1) {
00175         if(!resolved12) inclusion12=false;
00176   curev1=tit1->Ev;
00177         resolved12=false;
00178       }
00179       // shared event
00180       if(tit1->Ev == tit2->Ev) {
00181         resolved12=true;
00182         newstates = std::make_pair(tit1->X2, tit2->X2);
00183         // add to todo list if composition state is new
00184         rcit = productstates.find(newstates);
00185         if(rcit == productstates.end()) {
00186           todo.push(newstates);
00187           productstates.insert(newstates);
00188           FD_DF("Product: todo push: (" << newstates.first << "|" 
00189     << newstates.second << ")");
00190         }
00191         ++tit1;
00192         ++tit2;
00193       }
00194       // try resync tit1
00195       else if (tit1->Ev < tit2->Ev) {
00196         ++tit1;
00197       }
00198       // try resync tit2
00199       else if (tit1->Ev > tit2->Ev) {
00200         ++tit2;
00201       }
00202     }
00203     // last event was not resolved in the product
00204     if(!resolved12) inclusion12=false;
00205   }
00206   // report
00207 #ifdef FAUDES_DEBUG_FUNCTION
00208   FD_DF("IsRelativelyClosed(): Product: done"); 
00209   if(!inclusion12) {
00210     FD_DF("IsRelativelyClosed(): Product: inclusion L(G1) <= L(G2) not satisfied"); 
00211   }
00212 #endif
00213 
00214   // bail out when inclusion condition is violated
00215   if(!inclusion12) return false;
00216 
00217   // test all reachable states
00218   std::set< std::pair<Idx,Idx> >::iterator rit;
00219   for(rit=productstates.begin(); rit!=productstates.end(); ++rit) {
00220     // ok: state is GPlant-marked and GCand-marked
00221     if(rGenPlant.ExistsMarkedState(rit->second)) 
00222     if(rGenCand.ExistsMarkedState(rit->first))
00223       continue;
00224     // ok: state is neither GPlant-marked nor GCand-marked
00225     if(!rGenPlant.ExistsMarkedState(rit->second)) 
00226     if(!rGenCand.ExistsMarkedState(rit->first))
00227       continue;
00228     // failure: markin mismatch
00229     break;
00230   }
00231 
00232   // ok if loop passed
00233   return rit==productstates.end();
00234 
00235 }
00236 
00237 
00238 
00239 
00240 // IsOmegaRelativelyMarked(rGenPlant,rGenCand)
00241 bool IsRelativelyOmegaMarked(const vGenerator& rGenPlant, const vGenerator& rGenCand) {
00242 
00243 
00244   FD_DF("IsRelativelyOmegaMarked(\"" <<  rGenPlant.Name() << "\", \"" << rGenCand.Name() << "\")");
00245 
00246   // alphabets must match
00247   if ( rGenPlant.Alphabet() != rGenCand.Alphabet()) {
00248     std::stringstream errstr;
00249     errstr << "Alphabets of generators do not match.";
00250     throw Exception("RelativelyOmegaMarked", errstr.str(), 100);
00251   }
00252 
00253 #ifdef FAUDES_CHECKED
00254   // generators are meant to be nonblocking
00255   if ( !IsOmegaTrim(rGenCand) ||  !IsOmegaTrim(rGenPlant)) {
00256     std::stringstream errstr;
00257     errstr << "Arguments are expected to be nonblocking.";
00258     throw Exception("IsRelativelyOmegaMarked", errstr.str(), 201);
00259   }
00260 #endif
00261 
00262 #ifdef FAUDES_CHECKED
00263   // generators are meant to be deterministic
00264   if ( !IsDeterministic(rGenCand) ||  !IsDeterministic(rGenPlant)) {
00265     std::stringstream errstr;
00266     errstr << "Arguments are expected to be deterministic.";
00267     throw Exception("IsRelativelyOmegaMarked", errstr.str(), 202);
00268   }
00269 #endif
00270 
00271   
00272   // perform composition
00273   std::map< std::pair<Idx,Idx> , Idx> revmap;
00274   vGenerator product;
00275   StateSet markCand;
00276   StateSet markPlant;
00277   Product(rGenPlant,rGenCand,revmap,markPlant,markCand,product);
00278 
00279   // find all relevant SCCs
00280   SccFilter umfilter(SccFilter::IgnoreTrivial | SccFilter::StatesAvoid| SccFilter::StatesRequire, 
00281     markCand,markPlant);
00282   std::list<StateSet> umsccs;
00283   StateSet umroots;
00284   ComputeScc(product,umfilter,umsccs,umroots); 
00285 
00286   // report
00287   std::list<StateSet>::iterator ssit=umsccs.begin();
00288   for(;ssit!=umsccs.end(); ++ssit) {
00289     FD_DF("IsRelativelyOmegaMarked(): GPlant-marked scc without GCand-mark: " << ssit->ToString());
00290   }  
00291 
00292   // result is true if no problematic SCCs exist
00293   return umsccs.size()==0;
00294 
00295 
00296 }
00297 
00298 
00299 
00300 
00301 
00302 // IsOmegaRelativelyClosed(rGenPlant,rGenCand)
00303 bool IsRelativelyOmegaClosed(const vGenerator& rGenPlant, const vGenerator& rGenCand) {
00304 
00305 
00306   FD_DF("IsRelativelyOmegaClosed(\"" <<  rGenPlant.Name() << "\", \"" << rGenCand.Name() << "\")");
00307 
00308   // alphabets must match
00309   if ( rGenPlant.Alphabet() != rGenCand.Alphabet()) {
00310     std::stringstream errstr;
00311     errstr << "Alphabets of generators do not match.";
00312     throw Exception("RelativelyOmegaClosed", errstr.str(), 100);
00313   }
00314 
00315 #ifdef FAUDES_CHECKED
00316   // generators are meant to be nonblocking
00317   if( !IsOmegaTrim(rGenCand) ) {
00318     std::stringstream errstr;
00319     errstr << "Argument \"" << rGenCand.Name() << "\" is not omegatrim.";
00320     throw Exception("IsRelativelyOmegaClosed", errstr.str(), 201);
00321   }
00322   if( !IsOmegaTrim(rGenPlant) ) {
00323     std::stringstream errstr;
00324     errstr << "Argument \"" << rGenPlant.Name() << "\" is not omega-trim.";
00325     throw Exception("IsRelativelyOmegaClosed", errstr.str(), 201);
00326   }
00327 #endif
00328 
00329 
00330   // the trivial case: if B1 is empty it is relatively closed
00331   // (we must treat this case because empty generators are not regarded deterministic)
00332   if(rGenCand.Empty()) {
00333     FD_DF("IsRelativelyOmegaClosed(..): empty candidate: pass");
00334     return true;
00335   }
00336 
00337   // the trivial case: if B2 is empty but B1 is not empty, the test failed
00338   // (we must treat this case because empty generators are not regarded deterministic)
00339   if(rGenPlant.Empty()) {
00340     FD_DF("IsRelativelyOmegaClosed(..): non-empty candidate. empty plant: fail");
00341     return false;
00342   }
00343 
00344 #ifdef FAUDES_CHECKED
00345   // generators are meant to be deterministic
00346   if ( !IsDeterministic(rGenCand) ||  !IsDeterministic(rGenPlant)) {
00347     std::stringstream errstr;
00348     errstr << "Arguments are expected to be deterministic.";
00349     throw Exception("IsRelativelyOmegaClosed", errstr.str(), 202);
00350   }
00351 #endif
00352 
00353   // doit
00354   return IsRelativelyOmegaClosedUnchecked(rGenPlant,rGenCand);
00355 }
00356 
00357   
00358 // IsOmegaRelativelyClosed(rGenPlant,rGenCand)
00359 bool IsRelativelyOmegaClosedUnchecked(const vGenerator& rGenPlant, const vGenerator& rGenCand) {
00360 
00361   // perform composition (variant of cfl_parallel.cpp)
00362   std::map< std::pair<Idx,Idx> , Idx> revmap;
00363   vGenerator product;
00364   StateSet mark1;
00365   StateSet mark2;
00366 
00367   // shared alphabet
00368   product.InjectAlphabet(rGenCand.Alphabet());
00369 
00370   // todo stack
00371   std::stack< std::pair<Idx,Idx> > todo;
00372   // current pair, new pair
00373   std::pair<Idx,Idx> currentstates, newstates;
00374   // state
00375   Idx tmpstate;
00376   // iterators  
00377   StateSet::Iterator lit1, lit2;
00378   TransSet::Iterator tit1, tit1_end, tit2, tit2_end;
00379   std::map< std::pair<Idx,Idx>, Idx>::iterator rcit;
00380   // sense violation of L(G1) <= L(G2)
00381   bool inclusion12=true;
00382 
00383   // push all combinations of initial states on todo stack
00384   FD_DF("IsRelativelyOmegaClosed(): Product composition A");
00385   for (lit1 = rGenCand.InitStatesBegin(); 
00386       lit1 != rGenCand.InitStatesEnd(); ++lit1) {
00387     for (lit2 = rGenPlant.InitStatesBegin(); 
00388         lit2 != rGenPlant.InitStatesEnd(); ++lit2) {
00389       currentstates = std::make_pair(*lit1, *lit2);
00390       todo.push(currentstates);
00391       tmpstate = product.InsInitState();
00392       revmap[currentstates] = tmpstate;
00393       FD_DF("IsRelativelyOmegaClosed(): Product composition A:   (" << *lit1 << "|" << *lit2 << ") -> " 
00394           << revmap[currentstates]);
00395     }
00396   }
00397 
00398   // start algorithm
00399   while (! todo.empty() && inclusion12) {
00400     // allow for user interrupt
00401     LoopCallback();
00402     // get next reachable state from todo stack
00403     currentstates = todo.top();
00404     todo.pop();
00405     FD_DF("IsRelativelyOmegaClosed(): Product composition B: (" << currentstates.first << "|" 
00406         << currentstates.second << ") -> " << revmap[currentstates]);
00407     // iterate over all rGenCand transitions
00408     tit1 = rGenCand.TransRelBegin(currentstates.first);
00409     tit1_end = rGenCand.TransRelEnd(currentstates.first);
00410     tit2 = rGenPlant.TransRelBegin(currentstates.second);
00411     tit2_end = rGenPlant.TransRelEnd(currentstates.second);
00412     Idx curev1=0;
00413     bool resolved12=true;
00414     while((tit1 != tit1_end) && (tit2 != tit2_end)) {
00415       // sense new event
00416       if(tit1->Ev != curev1) {
00417         if(!resolved12) inclusion12=false;
00418   curev1=tit1->Ev;
00419         resolved12=false;
00420       }
00421       // shared event
00422       if (tit1->Ev == tit2->Ev) {
00423         resolved12=true;
00424         newstates = std::make_pair(tit1->X2, tit2->X2);
00425         // add to todo list if composition state is new
00426         rcit = revmap.find(newstates);
00427         if (rcit == revmap.end()) {
00428           todo.push(newstates);
00429           tmpstate = product.InsState();
00430           revmap[newstates] = tmpstate;
00431           FD_DF("IsRelativelyOmegaClosed(): Product composition C: (" << newstates.first << "|" 
00432              << newstates.second << ") -> " << revmap[newstates]);
00433         }
00434         else {
00435           tmpstate = rcit->second;
00436         }
00437         product.SetTransition(revmap[currentstates], tit1->Ev, tmpstate);
00438         ++tit1;
00439         ++tit2;
00440       }
00441       // try resync tit1
00442       else if (tit1->Ev < tit2->Ev) {
00443         ++tit1;
00444       }
00445       // try resync tit2
00446       else if (tit1->Ev > tit2->Ev) {
00447         ++tit2;
00448       }
00449     }
00450     // last event was not resolved in the product
00451     if(!resolved12) inclusion12=false;
00452   }
00453   // report
00454 #ifdef FAUDES_DEBUG_FUNCTION
00455   FD_DF("IsRelativelyOmegaClosed(): Product: done"); 
00456   if(!inclusion12) {
00457     FD_DF("IsRelativelyOmegaClosed(): Product: inclusion L(G1) <= L(G2) not satisfied"); 
00458   }
00459 #endif
00460 
00461   // bail out
00462   if(!inclusion12) return false;
00463 
00464   // retrieve marking from reverse composition map
00465   std::map< std::pair<Idx,Idx>, Idx>::iterator rit;
00466   for(rit=revmap.begin(); rit!=revmap.end(); ++rit){
00467     if(rGenCand.ExistsMarkedState(rit->first.first)) mark1.Insert(rit->second);
00468     if(rGenPlant.ExistsMarkedState(rit->first.second)) mark2.Insert(rit->second);
00469   }
00470 
00471   // find all relevant SCCs 1
00472   SccFilter umfilter12(SccFilter::IgnoreTrivial | SccFilter::StatesAvoid| SccFilter::StatesRequire, 
00473     mark1,mark2);
00474   std::list<StateSet> umsccs12;
00475   StateSet umroots12;
00476   ComputeScc(product,umfilter12,umsccs12,umroots12); 
00477 
00478   // report
00479   std::list<StateSet>::iterator ssit=umsccs12.begin();
00480   for(;ssit!=umsccs12.end(); ++ssit) {
00481     FD_DF("IsRelativelyOmegaClosed(): G2-marked scc without G1-mark: " << ssit->ToString());
00482   }  
00483 
00484   // result is false if we found problematic SCCs to exist
00485   if(umsccs12.size()!=0) return false;
00486 
00487   // find all relevant SCCs 2
00488   SccFilter umfilter21(SccFilter::IgnoreTrivial | SccFilter::StatesAvoid| SccFilter::StatesRequire, 
00489     mark2,mark1);
00490   std::list<StateSet> umsccs21;
00491   StateSet umroots21;
00492   ComputeScc(product,umfilter21,umsccs21,umroots21); 
00493 
00494   // report
00495   ssit=umsccs21.begin();
00496   for(;ssit!=umsccs21.end(); ++ssit) {
00497     FD_DF("IsRelativelyOmegaClosed(): G1-marked scc without G2-mark: " << ssit->ToString());
00498   }  
00499 
00500   // result is false if we found problematic SCCs to exist
00501   if(umsccs21.size()!=0) return false;
00502 
00503   // done, all tests passed
00504   FD_DF("IsRelativelyOmegaClosed(): pass");
00505   return true;
00506 }
00507 
00508 
00509 
00510 } // name space 

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