About
User Reference
C++ API
luafaudes
Developer
Links
libFAUDES online
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 Generator& rGenPlant, const Generator& 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   Generator product;
00073   product.StateNamesEnabled(false);
00074   Product(rGenPlant,rGenCand,revmap,product);
00075 
00076   // test all reachable states
00077   std::map< std::pair<Idx,Idx> , Idx>::iterator rit;
00078   for(rit=revmap.begin(); rit!=revmap.end(); ++rit) {
00079     // ok: not GPlant-marked state is not considered
00080     if(!rGenPlant.ExistsMarkedState(rit->first.first)) 
00081       continue;
00082     // ok: GPlant-marked state also has GCand-mark
00083     if(rGenCand.ExistsMarkedState(rit->first.second))
00084       continue;
00085     // failure: GPlant-marked state has no GCand-mark
00086     break;
00087   }
00088 
00089   // ok if loop passed
00090   return rit==revmap.end();
00091 
00092 }
00093 
00094 
00095 
00096 //IsRelativelyPrefixClosed(rGenPlant,rGenCand)
00097 bool IsRelativelyPrefixClosed(const Generator& rGenPlant, const Generator& rGenCand) {
00098 
00099   FD_DF("IsRelativelyPrefixClosed(\"" <<  rGenPlant.Name() << "\", \"" << rGenCand.Name() << "\")");
00100 
00101   // alphabets must match
00102   if ( rGenPlant.Alphabet() != rGenCand.Alphabet()) {
00103     std::stringstream errstr;
00104     errstr << "Alphabets of generators do not match.";
00105     throw Exception("IsRelativelyPrefixClosed", errstr.str(), 100);
00106   }
00107 
00108 #ifdef FAUDES_CHECKED
00109   // generators are meant to be nonblocking
00110   if ( !IsNonblocking(rGenCand) ||  !IsNonblocking(rGenPlant)) {
00111     std::stringstream errstr;
00112     errstr << "Arguments are expected to be nonblocking.";
00113     throw Exception("IsRelativelyPrefixClosed", errstr.str(), 201);
00114   }
00115 #endif
00116 
00117 #ifdef FAUDES_CHECKED
00118   // generators are meant to be deterministic
00119   if ( !IsDeterministic(rGenCand) ||  !IsDeterministic(rGenPlant)) {
00120     std::stringstream errstr;
00121     errstr << "Arguments are expected to be deterministic.";
00122     throw Exception("IsRelativelyPrefixClosed", errstr.str(), 202);
00123   }
00124 #endif
00125 
00126   // perform composition (variation from cfl_parallel.cpp)
00127   FD_DF("IsRelativelyPrefixClosed(..): perform product");
00128 
00129   // todo stack
00130   std::stack< std::pair<Idx,Idx> > todo;
00131   // current pair, new pair
00132   std::pair<Idx,Idx> currentstates, newstates;
00133   // accessible states
00134   std::set< std::pair<Idx,Idx> > productstates;
00135   // iterators
00136   StateSet::Iterator lit1, lit2;
00137   TransSet::Iterator tit1, tit1_end, tit2, tit2_end;
00138   std::set< std::pair<Idx,Idx> >::iterator rcit;
00139   // sense violation of L(GCand) <= L(GPlant)
00140   bool inclusion12=true;
00141 
00142   // push all combinations of initial states on todo stack
00143   FD_DF("IsRelativelyPrefixClosed(..): perform product: adding all combinations of initial states to todo");
00144   for (lit1 = rGenCand.InitStatesBegin(); 
00145       lit1 != rGenCand.InitStatesEnd(); ++lit1) {
00146     for (lit2 = rGenPlant.InitStatesBegin(); 
00147         lit2 != rGenPlant.InitStatesEnd(); ++lit2) {
00148       currentstates = std::make_pair(*lit1, *lit2);
00149       todo.push(currentstates);
00150       productstates.insert(currentstates);
00151       FD_DF("IsRelativelyPrefixClosed(..): perform product: (" << 
00152       *lit1 << "|" << *lit2 << ")");
00153     }
00154   }
00155 
00156   // start algorithm
00157   FD_DF("IsRelativelyPrefixClosed(..): perform product: Product: processing reachable states:");
00158   while (! todo.empty() && inclusion12) {
00159     // allow for user interrupt
00160     LoopCallback();
00161     // get next reachable state from todo stack
00162     currentstates = todo.top();
00163     todo.pop();
00164     FD_DF("Processing (" << currentstates.first << "|" 
00165     << currentstates.second << ")");
00166     // iterate over all rGenCand transitions
00167     tit1 = rGenCand.TransRelBegin(currentstates.first);
00168     tit1_end = rGenCand.TransRelEnd(currentstates.first);
00169     tit2 = rGenPlant.TransRelBegin(currentstates.second);
00170     tit2_end = rGenPlant.TransRelEnd(currentstates.second);
00171     Idx curev1=0;
00172     bool resolved12=true;
00173     while((tit1 != tit1_end) && (tit2 != tit2_end)) {
00174       // sense new event
00175       if(tit1->Ev != curev1) {
00176         if(!resolved12) inclusion12=false;
00177   curev1=tit1->Ev;
00178         resolved12=false;
00179       }
00180       // shared event
00181       if(tit1->Ev == tit2->Ev) {
00182         resolved12=true;
00183         newstates = std::make_pair(tit1->X2, tit2->X2);
00184         // add to todo list if composition state is new
00185         rcit = productstates.find(newstates);
00186         if(rcit == productstates.end()) {
00187           todo.push(newstates);
00188           productstates.insert(newstates);
00189           FD_DF("Product: todo push: (" << newstates.first << "|" 
00190     << newstates.second << ")");
00191         }
00192         ++tit1;
00193         ++tit2;
00194       }
00195       // try resync tit1
00196       else if (tit1->Ev < tit2->Ev) {
00197         ++tit1;
00198       }
00199       // try resync tit2
00200       else if (tit1->Ev > tit2->Ev) {
00201         ++tit2;
00202       }
00203     }
00204     // last event was not resolved in the product
00205     if(!resolved12) inclusion12=false;
00206   }
00207   // report
00208 #ifdef FAUDES_DEBUG_FUNCTION
00209   FD_DF("IsRelativelyClosed(): Product: done"); 
00210   if(!inclusion12) {
00211     FD_DF("IsRelativelyClosed(): Product: inclusion L(G1) <= L(G2) not satisfied"); 
00212   }
00213 #endif
00214 
00215   // bail out when inclusion condition is violated
00216   if(!inclusion12) return false;
00217 
00218   // test all reachable states
00219   std::set< std::pair<Idx,Idx> >::iterator rit;
00220   for(rit=productstates.begin(); rit!=productstates.end(); ++rit) {
00221     // ok: state is GPlant-marked and GCand-marked
00222     if(rGenPlant.ExistsMarkedState(rit->second)) 
00223     if(rGenCand.ExistsMarkedState(rit->first))
00224       continue;
00225     // ok: state is neither GPlant-marked nor GCand-marked
00226     if(!rGenPlant.ExistsMarkedState(rit->second)) 
00227     if(!rGenCand.ExistsMarkedState(rit->first))
00228       continue;
00229     // failure: markin mismatch
00230     break;
00231   }
00232 
00233   // ok if loop passed
00234   return rit==productstates.end();
00235 
00236 }
00237 
00238 
00239 
00240 
00241 // IsOmegaRelativelyMarked(rGenPlant,rGenCand)
00242 bool IsRelativelyOmegaMarked(const Generator& rGenPlant, const Generator& rGenCand) {
00243 
00244 
00245   FD_DF("IsRelativelyOmegaMarked(\"" <<  rGenPlant.Name() << "\", \"" << rGenCand.Name() << "\")");
00246 
00247   // alphabets must match
00248   if ( rGenPlant.Alphabet() != rGenCand.Alphabet()) {
00249     std::stringstream errstr;
00250     errstr << "Alphabets of generators do not match.";
00251     throw Exception("RelativelyOmegaMarked", errstr.str(), 100);
00252   }
00253 
00254 #ifdef FAUDES_CHECKED
00255   // generators are meant to be nonblocking
00256   if ( !IsOmegaTrim(rGenCand) ||  !IsOmegaTrim(rGenPlant)) {
00257     std::stringstream errstr;
00258     errstr << "Arguments are expected to be nonblocking.";
00259     throw Exception("IsRelativelyOmegaMarked", errstr.str(), 201);
00260   }
00261 #endif
00262 
00263 #ifdef FAUDES_CHECKED
00264   // generators are meant to be deterministic
00265   if ( !IsDeterministic(rGenCand) ||  !IsDeterministic(rGenPlant)) {
00266     std::stringstream errstr;
00267     errstr << "Arguments are expected to be deterministic.";
00268     throw Exception("IsRelativelyOmegaMarked", errstr.str(), 202);
00269   }
00270 #endif
00271 
00272   
00273   // perform composition
00274   std::map< std::pair<Idx,Idx> , Idx> revmap;
00275   Generator product;
00276   product.StateNamesEnabled(false);
00277   StateSet markCand;
00278   StateSet markPlant;
00279   Product(rGenPlant,rGenCand,revmap,markPlant,markCand,product);
00280 
00281   // find all relevant SCCs
00282   SccFilter umfilter(SccFilter::IgnoreTrivial | SccFilter::StatesAvoid| SccFilter::StatesRequire, 
00283     markCand,markPlant);
00284   std::list<StateSet> umsccs;
00285   StateSet umroots;
00286   ComputeScc(product,umfilter,umsccs,umroots); 
00287 
00288   // report
00289   std::list<StateSet>::iterator ssit=umsccs.begin();
00290   for(;ssit!=umsccs.end(); ++ssit) {
00291     FD_DF("IsRelativelyOmegaMarked(): GPlant-marked scc without GCand-mark: " << ssit->ToString());
00292   }  
00293 
00294   // result is true if no problematic SCCs exist
00295   return umsccs.size()==0;
00296 
00297 
00298 }
00299 
00300 
00301 
00302 
00303 
00304 // IsOmegaRelativelyClosed(rGenPlant,rGenCand)
00305 bool IsRelativelyOmegaClosed(const Generator& rGenPlant, const Generator& rGenCand) {
00306 
00307 
00308   FD_DF("IsRelativelyOmegaClosed(\"" <<  rGenPlant.Name() << "\", \"" << rGenCand.Name() << "\")");
00309 
00310   // alphabets must match
00311   if ( rGenPlant.Alphabet() != rGenCand.Alphabet()) {
00312     std::stringstream errstr;
00313     errstr << "Alphabets of generators do not match.";
00314     throw Exception("RelativelyOmegaClosed", errstr.str(), 100);
00315   }
00316 
00317 #ifdef FAUDES_CHECKED
00318   // generators are meant to be nonblocking
00319   if( !IsOmegaTrim(rGenCand) ) {
00320     std::stringstream errstr;
00321     errstr << "Argument \"" << rGenCand.Name() << "\" is not omegatrim.";
00322     throw Exception("IsRelativelyOmegaClosed", errstr.str(), 201);
00323   }
00324   if( !IsOmegaTrim(rGenPlant) ) {
00325     std::stringstream errstr;
00326     errstr << "Argument \"" << rGenPlant.Name() << "\" is not omega-trim.";
00327     throw Exception("IsRelativelyOmegaClosed", errstr.str(), 201);
00328   }
00329 #endif
00330 
00331 
00332   // the trivial case: if B1 is empty it is relatively closed
00333   // (we must treat this case because empty generators are not regarded deterministic)
00334   if(rGenCand.Empty()) {
00335     FD_DF("IsRelativelyOmegaClosed(..): empty candidate: pass");
00336     return true;
00337   }
00338 
00339   // the trivial case: if B2 is empty but B1 is not empty, the test failed
00340   // (we must treat this case because empty generators are not regarded deterministic)
00341   if(rGenPlant.Empty()) {
00342     FD_DF("IsRelativelyOmegaClosed(..): non-empty candidate. empty plant: fail");
00343     return false;
00344   }
00345 
00346 #ifdef FAUDES_CHECKED
00347   // generators are meant to be deterministic
00348   if ( !IsDeterministic(rGenCand) ||  !IsDeterministic(rGenPlant)) {
00349     std::stringstream errstr;
00350     errstr << "Arguments are expected to be deterministic.";
00351     throw Exception("IsRelativelyOmegaClosed", errstr.str(), 202);
00352   }
00353 #endif
00354 
00355   // doit
00356   return IsRelativelyOmegaClosedUnchecked(rGenPlant,rGenCand);
00357 }
00358 
00359   
00360 // IsOmegaRelativelyClosed(rGenPlant,rGenCand)
00361 bool IsRelativelyOmegaClosedUnchecked(const Generator& rGenPlant, const Generator& rGenCand) {
00362 
00363   // perform composition (variant of cfl_parallel.cpp)
00364   std::map< std::pair<Idx,Idx> , Idx> revmap;
00365   Generator product;
00366   product.StateNamesEnabled(false);
00367   StateSet mark1;
00368   StateSet mark2;
00369 
00370   // shared alphabet
00371   product.InjectAlphabet(rGenCand.Alphabet());
00372 
00373   // todo stack
00374   std::stack< std::pair<Idx,Idx> > todo;
00375   // current pair, new pair
00376   std::pair<Idx,Idx> currentstates, newstates;
00377   // state
00378   Idx tmpstate;
00379   // iterators  
00380   StateSet::Iterator lit1, lit2;
00381   TransSet::Iterator tit1, tit1_end, tit2, tit2_end;
00382   std::map< std::pair<Idx,Idx>, Idx>::iterator rcit;
00383   // sense violation of L(G1) <= L(G2)
00384   bool inclusion12=true;
00385 
00386   // push all combinations of initial states on todo stack
00387   FD_DF("IsRelativelyOmegaClosed(): Product composition A");
00388   for (lit1 = rGenCand.InitStatesBegin(); 
00389       lit1 != rGenCand.InitStatesEnd(); ++lit1) {
00390     for (lit2 = rGenPlant.InitStatesBegin(); 
00391         lit2 != rGenPlant.InitStatesEnd(); ++lit2) {
00392       currentstates = std::make_pair(*lit1, *lit2);
00393       todo.push(currentstates);
00394       tmpstate = product.InsInitState();
00395       revmap[currentstates] = tmpstate;
00396       FD_DF("IsRelativelyOmegaClosed(): Product composition A:   (" << *lit1 << "|" << *lit2 << ") -> " 
00397           << revmap[currentstates]);
00398     }
00399   }
00400 
00401   // start algorithm
00402   while (! todo.empty() && inclusion12) {
00403     // allow for user interrupt
00404     LoopCallback();
00405     // get next reachable state from todo stack
00406     currentstates = todo.top();
00407     todo.pop();
00408     FD_DF("IsRelativelyOmegaClosed(): Product composition B: (" << currentstates.first << "|" 
00409         << currentstates.second << ") -> " << revmap[currentstates]);
00410     // iterate over all rGenCand transitions
00411     tit1 = rGenCand.TransRelBegin(currentstates.first);
00412     tit1_end = rGenCand.TransRelEnd(currentstates.first);
00413     tit2 = rGenPlant.TransRelBegin(currentstates.second);
00414     tit2_end = rGenPlant.TransRelEnd(currentstates.second);
00415     Idx curev1=0;
00416     bool resolved12=true;
00417     while((tit1 != tit1_end) && (tit2 != tit2_end)) {
00418       // sense new event
00419       if(tit1->Ev != curev1) {
00420         if(!resolved12) inclusion12=false;
00421   curev1=tit1->Ev;
00422         resolved12=false;
00423       }
00424       // shared event
00425       if (tit1->Ev == tit2->Ev) {
00426         resolved12=true;
00427         newstates = std::make_pair(tit1->X2, tit2->X2);
00428         // add to todo list if composition state is new
00429         rcit = revmap.find(newstates);
00430         if (rcit == revmap.end()) {
00431           todo.push(newstates);
00432           tmpstate = product.InsState();
00433           revmap[newstates] = tmpstate;
00434           FD_DF("IsRelativelyOmegaClosed(): Product composition C: (" << newstates.first << "|" 
00435              << newstates.second << ") -> " << revmap[newstates]);
00436         }
00437         else {
00438           tmpstate = rcit->second;
00439         }
00440         product.SetTransition(revmap[currentstates], tit1->Ev, tmpstate);
00441         ++tit1;
00442         ++tit2;
00443       }
00444       // try resync tit1
00445       else if (tit1->Ev < tit2->Ev) {
00446         ++tit1;
00447       }
00448       // try resync tit2
00449       else if (tit1->Ev > tit2->Ev) {
00450         ++tit2;
00451       }
00452     }
00453     // last event was not resolved in the product
00454     if(!resolved12) inclusion12=false;
00455   }
00456   // report
00457 #ifdef FAUDES_DEBUG_FUNCTION
00458   FD_DF("IsRelativelyOmegaClosed(): Product: done"); 
00459   if(!inclusion12) {
00460     FD_DF("IsRelativelyOmegaClosed(): Product: inclusion L(G1) <= L(G2) not satisfied"); 
00461   }
00462 #endif
00463 
00464   // bail out
00465   if(!inclusion12) return false;
00466 
00467   // retrieve marking from reverse composition map
00468   std::map< std::pair<Idx,Idx>, Idx>::iterator rit;
00469   for(rit=revmap.begin(); rit!=revmap.end(); ++rit){
00470     if(rGenCand.ExistsMarkedState(rit->first.first)) mark1.Insert(rit->second);
00471     if(rGenPlant.ExistsMarkedState(rit->first.second)) mark2.Insert(rit->second);
00472   }
00473 
00474   // find all relevant SCCs 1
00475   SccFilter umfilter12(SccFilter::IgnoreTrivial | SccFilter::StatesAvoid| SccFilter::StatesRequire, 
00476     mark1,mark2);
00477   std::list<StateSet> umsccs12;
00478   StateSet umroots12;
00479   ComputeScc(product,umfilter12,umsccs12,umroots12); 
00480 
00481   // report
00482   std::list<StateSet>::iterator ssit=umsccs12.begin();
00483   for(;ssit!=umsccs12.end(); ++ssit) {
00484     FD_DF("IsRelativelyOmegaClosed(): G2-marked scc without G1-mark: " << ssit->ToString());
00485   }  
00486 
00487   // result is false if we found problematic SCCs to exist
00488   if(umsccs12.size()!=0) return false;
00489 
00490   // find all relevant SCCs 2
00491   SccFilter umfilter21(SccFilter::IgnoreTrivial | SccFilter::StatesAvoid| SccFilter::StatesRequire, 
00492     mark2,mark1);
00493   std::list<StateSet> umsccs21;
00494   StateSet umroots21;
00495   ComputeScc(product,umfilter21,umsccs21,umroots21); 
00496 
00497   // report
00498   ssit=umsccs21.begin();
00499   for(;ssit!=umsccs21.end(); ++ssit) {
00500     FD_DF("IsRelativelyOmegaClosed(): G1-marked scc without G2-mark: " << ssit->ToString());
00501   }  
00502 
00503   // result is false if we found problematic SCCs to exist
00504   if(umsccs21.size()!=0) return false;
00505 
00506   // done, all tests passed
00507   FD_DF("IsRelativelyOmegaClosed(): pass");
00508   return true;
00509 }
00510 
00511 
00512 
00513 } // name space 

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