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(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 Generator& rGenPlant, const Generator& 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 Generator& rGenPlant, const Generator& 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 Generator 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 Generator& rGenPlant, const Generator& 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 Generator& rGenPlant, const Generator& rGenCand) { 00360 00361 // perform composition (variant of cfl_parallel.cpp) 00362 std::map< std::pair<Idx,Idx> , Idx> revmap; 00363 Generator 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.20d --- 2011.04.26 --- c++ source docu by doxygen