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