libFAUDES
Sections
Index
|
syn_functions.cppGo 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