syn_wsupcon.cpp

Go to the documentation of this file.
00001 /** @file syn_wsupcon.cpp Supremal controllable sublanguage for infinite time behaviours */
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_wsupcon.h"
00025 #include "syn_supcon.h"
00026 #include "syn_supnorm.h"
00027 #include "syn_functions.h"
00028 
00029 
00030 namespace faudes {
00031 
00032 
00033 /*
00034 ***************************************************************************************
00035 ***************************************************************************************
00036  Implementation IsOmegaControllabe
00037 ***************************************************************************************
00038 ***************************************************************************************
00039 */
00040 
00041 // IsOmegaControllable()
00042 bool IsOmegaControllable(
00043   const Generator& rGenPlant, 
00044   const EventSet&  rCAlph, 
00045   const Generator& rGenCand) 
00046 {
00047   FD_DF("IsOmegaControllable(\"" <<  rGenPlant.Name() << "\", \"" << rGenCand.Name() << "\")");
00048 
00049   // alphabets must match
00050   if ( rGenPlant.Alphabet() != rGenCand.Alphabet()) {
00051     std::stringstream errstr;
00052     errstr << "Alphabets of generators do not match.";
00053     throw Exception("IsOmegaControllable(..)", errstr.str(), 100);
00054   }
00055 
00056 #ifdef FAUDES_CHECKED
00057   // generators are meant to be nonblocking
00058   if( !IsOmegaTrim(rGenCand) ) {
00059     std::stringstream errstr;
00060     errstr << "Argument \"" << rGenCand.Name() << "\" is not omega-trim.";
00061     throw Exception("IsOmegaControllable(..)", errstr.str(), 201);
00062   }
00063   if( !IsOmegaTrim(rGenPlant) ) {
00064     std::stringstream errstr;
00065     errstr << "Argument \"" << rGenPlant.Name() << "\" is not omega-trim.";
00066     throw Exception("IsOmegaControllable(..)", errstr.str(), 201);
00067   }
00068 #endif
00069 
00070   // the trivial case: empty cand is fine
00071   // (we must treat this case because empty generators are not regarded deterministic)
00072   if(rGenCand.Empty()) {
00073     FD_DF("IsOmegaControllable(..): empty candidate, pass");
00074     return true;
00075   }
00076 
00077   // the trivial case: empty plant is fails
00078   // (we must treat this case because empty generators are not regarded deterministic)
00079   if(rGenPlant.Empty()) {
00080     FD_DF("IsOmegaControllable(..): empty plant, fail");
00081     return false;
00082   }
00083 
00084 #ifdef FAUDES_CHECKED
00085   // generators are meant to be deterministic
00086   if ( !IsDeterministic(rGenCand) ||  !IsDeterministic(rGenPlant)) {
00087     std::stringstream errstr;
00088     errstr << "Arguments are expected to be deterministic.";
00089     throw Exception("IsOmegaControllable", errstr.str(), 202);
00090   }
00091 #endif
00092 
00093   // test controllability
00094   StateSet dummy;
00095   if(!IsControllableUnchecked(rGenPlant,rCAlph,rGenCand,dummy)) return false;
00096 
00097   // test relative closedness
00098   if(!IsRelativelyOmegaClosedUnchecked(rGenPlant,rGenCand)) return false;
00099 
00100   // pass
00101   FD_DF("IsOmegaControllable(...): passed");
00102   return true;
00103 }
00104 
00105 
00106 // IsOmegaControllable() wrapper
00107 bool IsOmegaControllable(
00108   const System& rPlantGen, 
00109   const Generator& rCandGen) 
00110 {
00111   return IsOmegaControllable(rPlantGen,rPlantGen.ControllableEvents(),rCandGen);
00112 }
00113 
00114 /*
00115 ***************************************************************************************
00116 ***************************************************************************************
00117  Implementation SupConCmplClosed
00118 ***************************************************************************************
00119 ***************************************************************************************
00120 */
00121 
00122 
00123 // supcon complete
00124 void SupConCmplClosed(
00125   const Generator& rPlantGen, 
00126   const EventSet&  rCAlph,
00127   const Generator& rSpecGen, 
00128   Generator& rResGen)
00129 { 
00130   FD_DF("SupConCmplClosed(" << rPlantGen.Name() << "," << rSpecGen.Name()<< ")");
00131   
00132   // exceptions on invalid parameters, same as std synthesis
00133   ControlProblemConsistencyCheck(rPlantGen,rCAlph,rSpecGen);  
00134 
00135   // prepare result
00136   Generator* pResGen = &rResGen;
00137   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00138     pResGen= rResGen.New();
00139   }
00140   pResGen->Clear();
00141   pResGen->Name("SupConCmplClosed("+rPlantGen.Name()+", "+rSpecGen.Name()+")");
00142   pResGen->InjectAlphabet(rPlantGen.Alphabet());
00143   
00144   //check for trivial result
00145   if(rSpecGen.InitStatesEmpty()){
00146     FD_DF("SupConCmplClosed: empty language specification - empty result.");
00147   }  
00148     
00149 
00150   // have a reverse composition map
00151   std::map< std::pair<Idx,Idx>, Idx> revmap;
00152 
00153   // parallel composition (result is reachable)
00154   SupConProduct(rPlantGen, rCAlph, rSpecGen, revmap, *pResGen);
00155 
00156   // make resulting generator complete and controllabel
00157   while(true) {
00158     Idx state_num = pResGen->Size();
00159     if(pResGen->InitStates().Empty()) break;
00160     pResGen->Complete();
00161     if(pResGen->InitStates().Empty()) break;
00162     SupConClosedUnchecked(rPlantGen, rCAlph, *pResGen);
00163     if(pResGen->Size() == state_num) break;
00164   }
00165 
00166   // convenience state names
00167   if(rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && rResGen.StateNamesEnabled()) 
00168     SetComposedStateNames(rPlantGen, rSpecGen, revmap, *pResGen);
00169   else
00170     pResGen->StateNamesEnabled(false);
00171 
00172   // copy result
00173   if(pResGen != &rResGen) {
00174     pResGen->Move(rResGen);
00175     delete pResGen;
00176   }
00177 
00178 }
00179 
00180 
00181 // user wrapper
00182 void SupConCmplClosed(
00183   const System& rPlantGen, 
00184   const Generator& rSpecGen, 
00185   Generator& rResGen) 
00186 {
00187 
00188   // execute 
00189   SupConCmplClosed(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,rResGen);
00190 
00191   // copy all attributes of input alphabet
00192   rResGen.EventAttributes(rPlantGen.Alphabet());
00193 
00194 }
00195 
00196 
00197 
00198 
00199 /*
00200 ***************************************************************************************
00201 ***************************************************************************************
00202  Implementation SupConCmplNB
00203 ***************************************************************************************
00204 ***************************************************************************************
00205 */
00206 
00207 
00208 // supcon complete
00209 void SupConCmplNB(
00210   const Generator& rPlantGen, 
00211   const EventSet&  rCAlph,
00212   const Generator& rSpecGen, 
00213   Generator& rResGen)
00214 { 
00215   FD_DF("SupConCmplNB(" << rPlantGen.Name() << "," << rSpecGen.Name()<< ")");
00216   
00217   // exceptions on invalid parameters, same as std synthesis
00218   ControlProblemConsistencyCheck(rPlantGen,rCAlph,rSpecGen);  
00219 
00220   // prepare result
00221   Generator* pResGen = &rResGen;
00222   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00223     pResGen= rResGen.New();
00224   }
00225   pResGen->Clear();
00226   pResGen->Name("SupConCmplNB("+rPlantGen.Name()+", "+rSpecGen.Name()+")");
00227   pResGen->InjectAlphabet(rPlantGen.Alphabet());
00228   
00229   //check for trivial result
00230   if(rSpecGen.InitStatesEmpty()){
00231     FD_DF("SupConCmplNB: empty language specification - empty result.");
00232   }  
00233     
00234 
00235   // have a reverse composition map
00236   std::map< std::pair<Idx,Idx>, Idx> revmap;
00237 
00238   // parallel composition (result is reachable)
00239   SupConProduct(rPlantGen, rCAlph, rSpecGen, revmap, *pResGen);
00240 
00241   // make resulting generator complete and controllabel and coaccessible
00242   while(true) {
00243     Idx state_num = pResGen->Size();
00244     if(pResGen->InitStates().Empty()) break;
00245     pResGen->Coaccessible();
00246     if(pResGen->InitStates().Empty()) break;
00247     pResGen->Complete();
00248     if(pResGen->InitStates().Empty()) break;
00249     SupConClosedUnchecked(rPlantGen, rCAlph, *pResGen);
00250     if(pResGen->Size() == state_num) break;
00251   }
00252 
00253   // convenience state names
00254   if(rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && rResGen.StateNamesEnabled()) 
00255     SetComposedStateNames(rPlantGen, rSpecGen, revmap, *pResGen);
00256   else
00257     pResGen->StateNamesEnabled(false);
00258 
00259   // copy result
00260   if(pResGen != &rResGen) {
00261     pResGen->Move(rResGen);
00262     delete pResGen;
00263   }
00264 
00265 }
00266 
00267 
00268 // user wrapper
00269 void SupConCmplNB(
00270   const System& rPlantGen, 
00271   const Generator& rSpecGen, 
00272   Generator& rResGen) 
00273 {
00274 
00275   // execute 
00276   SupConCmplNB(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,rResGen);
00277 
00278   // copy all attributes of input alphabet
00279   rResGen.EventAttributes(rPlantGen.Alphabet());
00280 
00281 }
00282 
00283 
00284 
00285 /*
00286 ***************************************************************************************
00287 ***************************************************************************************
00288  Implementation SupConNormCmplNB
00289 ***************************************************************************************
00290 ***************************************************************************************
00291 */
00292 
00293 
00294 //  SupConNormCmplNB(rL,rCAlph,rOAlph,rK,rResult)
00295 void SupConNormCmplNB(
00296   const Generator& rL,
00297   const EventSet& rCAlph,
00298   const EventSet& rOAlph,
00299   const Generator& rK, 
00300   Generator& rResult)
00301 {
00302   FD_DF("SupConNormCmplNB(" << rL.Name() << "," << rK.Name() << ")");
00303   // initialize: K0
00304   Generator K0;
00305   K0.StateNamesEnabled(false);
00306   Product(rL,rK,K0);
00307   K0.Coaccessible();
00308   // initialize: closure(rL)
00309   Generator L=rL;
00310   L.StateNamesEnabled(false);
00311   L.Trim();
00312   MarkAllStates(L);
00313   // loop
00314   Generator Ki=K0;
00315   Ki.StateNamesEnabled(false);
00316   while(1) {
00317     FD_DF("SupConNormCmplNB(" << rL.Name() << "," << rK.Name() << "): #" << Ki.Size() << " m#" << Ki.MarkedStatesSize());
00318     // keep copy of recent
00319     rResult=Ki;
00320     // cheep closure (for coreachable generator)
00321     Ki.InjectMarkedStates(Ki.States());
00322     // synthesise closed
00323     SupConNormClosed(L,rCAlph,rOAlph,Ki,Ki);
00324     Complete(Ki);
00325     // restrict
00326     Product(K0,Ki,Ki);
00327     Ki.Coaccessible();
00328     // test (sequence is decreasing anyway)
00329     if(LanguageInclusion(rResult,Ki)) break;
00330   }  
00331   FD_DF("SupConNormCmplNB(" << rL.Name() << "," << rK.Name() << "): done");
00332 }  
00333 
00334 
00335 /** rti wrapper */
00336 void SupConNormCmplNB(
00337   const System& rPlantGen, 
00338   const Generator& rSpecGen, 
00339   Generator& rResGen) 
00340 {
00341   FD_DF("SupConNormCmplNB(" << rPlantGen.Name() << "," << rSpecGen.Name() << "): rti wrapper");
00342   // prepare result
00343   Generator* pResGen = &rResGen;
00344   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
00345     pResGen= rResGen.New();
00346   }
00347   // execute
00348   SupConNormCmplNB(rPlantGen,rPlantGen.ControllableEvents(),rPlantGen.ObservableEvents(),rSpecGen,*pResGen);
00349   // copy all attributes of input alphabet
00350   pResGen->EventAttributes(rPlantGen.Alphabet());
00351   // copy result
00352   if(pResGen != &rResGen) {
00353     pResGen->Move(rResGen);
00354     delete pResGen;
00355   }
00356 }
00357 
00358 
00359 /*
00360 ***************************************************************************************
00361 ***************************************************************************************
00362  Computation of the controllable prefix / enforcing omega-controlled liveness
00363 ***************************************************************************************
00364 ***************************************************************************************
00365 */
00366 
00367 
00368 
00369 /*
00370 Initial libFAUDES implementation of omega-controlled liveness, tmoor 2011, last used 
00371 for libFAUDES 2.22p. The function retsricts the candidate to states for which a
00372 prefix-closed controller exists such that in closed-loop configuration the acceptance condition
00373 is implied by the plant acceptance condition. This corresponds to the controllable prefix,
00374 originally proposed by J. Thistle et al. The actual implementation, however, is based on a sufficient 
00375 but not necessary test. It therefore identifies a subset of the controllable prefix, which may 
00376 turn out empty even when a prefix-closed controller exists. The below code is obsolete and will 
00377 be removed eventually.
00378 */
00379 
00380 /*
00381 
00382 // OmegaControlledLiveness(...)
00383 bool OmegaControlledLiveness(
00384   Generator& rSupCandGen, 
00385   const EventSet& rCAlph,
00386   StateSet& rMarkedPlantStates, 
00387   StateSet& rMarkedSpecStates)
00388 {
00389   FD_DF("OmegaControlledLiveness(...)");
00390 
00391   // set of critical states
00392   StateSet critical;
00393    
00394   // return true if parallelcomp contains no initial states
00395   if(rSupCandGen.InitStatesEmpty()) {
00396     return true;
00397   }
00398 
00399 #ifdef FAUDES_DEBUG_FUNCTION
00400   FD_DF("OmegaControlledLiveness(): marked states: ");
00401   StateSet ssd= rMarkedPlantStates + rMarkedSpecStates;
00402   ssd.Write();
00403 #endif
00404 
00405   // find un-marked sccs
00406   StateSet astates = rMarkedPlantStates + rMarkedSpecStates;
00407   SccFilter umfilter(SccFilter::FmIgnoreTrivial | SccFilter::FmStatesAvoid, astates);
00408   std::list<StateSet> umsccs;
00409   StateSet umroots;
00410   ComputeScc(rSupCandGen,umfilter,umsccs,umroots); 
00411 
00412   // report
00413   std::list<StateSet>::iterator ssit=umsccs.begin();
00414   for(;ssit!=umsccs.end(); ++ssit) {
00415     FD_DF("OmegaControlledLiveness(): unmarked scc: " << ssit->ToString());
00416   }  
00417 
00418   // good-states iteration
00419   StateSet goodstates = rMarkedSpecStates;
00420   
00421   // drive states to good states
00422   while(true) {
00423     // LoopCallback();
00424     // allow for user interrupt, incl progress report
00425     FD_WPC(1,2,"OmegaControlledLiveness(): iterating states"); 
00426     // test individual states
00427     FD_DF("OmegaControlledLiveness(): iterate over states (#" << rSupCandGen.Size() << ")");
00428     bool found=false;
00429 
00430     StateSet::Iterator sit = rSupCandGen.StatesBegin();
00431     StateSet::Iterator sit_end = rSupCandGen.StatesEnd();
00432     for(; sit!=sit_end; ++sit) {
00433       bool fail = false;  // cbaier 20121011
00434       bool positive=false; // cbaier 20121011
00435       // goodstate anyway
00436       if(goodstates.Exists(*sit)) continue;
00437       // test transitions
00438       TransSet::Iterator tit = rSupCandGen.TransRelBegin(*sit);
00439       TransSet::Iterator tit_end = rSupCandGen.TransRelEnd(*sit);
00440       // no transitions at all
00441       if(tit==tit_end) continue;
00442       // loop over successors
00443       for(; tit!=tit_end; ++tit) {
00444         if(goodstates.Exists(tit->X2)) 
00445   {positive=true; // cbaier 20121011: added 
00446   continue;}
00447         if(rCAlph.Exists(tit->Ev)) continue;
00448         
00449       // good states survive the loop // cbaier 20121011: added
00450       if(tit!=tit_end) { 
00451   fail=true;
00452         break;
00453         }                            
00454       }
00455       
00456       // good states survive
00457       if(!fail && positive) {    // cbaier 20121011: changed
00458         FD_DF("OmegaControlledLiveness(): good state " << rSupCandGen.SStr(*sit));
00459         goodstates.Insert(*sit);
00460         found=true;
00461       }
00462     }  
00463       
00464     // test individual unmarked sccs
00465     FD_DF("OmegaControlledLiveness(): iterate over unmarked sccs (#" << umsccs.size() <<")");
00466     std::list<StateSet>::iterator ssit=umsccs.begin();
00467     while(ssit!=umsccs.end()) { 
00468       bool fail=false;
00469       bool positive=false;
00470       sit=ssit->Begin();
00471       sit_end=ssit->End();
00472       for(; sit!=sit_end; ++sit) {
00473         // goodstate anyway
00474         if(goodstates.Exists(*sit)) continue;
00475         // test transitions
00476         TransSet::Iterator tit = rSupCandGen.TransRelBegin(*sit);
00477         TransSet::Iterator tit_end = rSupCandGen.TransRelEnd(*sit);
00478         // no transitions at all
00479         if(tit==tit_end) continue;        
00480         // loop over successors
00481         for(; tit!=tit_end; ++tit) {
00482           if(goodstates.Exists(tit->X2)) { positive=true; continue;}
00483           if(rCAlph.Exists(tit->Ev)) continue;  // tmoor 20110202: fixed typo
00484           if(ssit->Exists(tit->X2)) continue;
00485           break;
00486         }
00487         // good states survive the loop
00488         if(tit!=tit_end) {
00489           fail=true;
00490           break;
00491         }
00492       }
00493       
00494       // prepare next scc iterator
00495       std::list<StateSet>::iterator ssitnext=ssit;
00496       ++ssitnext;
00497       bool lend= (ssitnext==umsccs.end());
00498       // all states passed, then they are all good
00499       if(!fail && positive) {
00500         FD_DF("OmegaControlledLiveness(): good scc " << ssit->ToString());
00501         goodstates.InsertSet(*ssit);
00502         umsccs.erase(ssit);
00503         found=true;
00504       }
00505       // break on end of list
00506       if(lend) break;
00507       // progress
00508       ssit=ssitnext;
00509     }
00510     
00511     // exit
00512     if(!found) break;
00513   };
00514 
00515   // delete critical states
00516   FD_DF("OmegaControlledLiveness(): good states: " << goodstates.ToString())
00517   StateSet::Iterator sit = rSupCandGen.StatesBegin();
00518   StateSet::Iterator sit_end = rSupCandGen.StatesEnd();
00519   for(; sit!=sit_end; ++sit) {
00520     if(!goodstates.Exists(*sit))
00521       rSupCandGen.DelState(*sit);
00522   }
00523 
00524   // return true
00525   FD_DF("OmegaControlledLiveness(): done");
00526   return true;
00527 }
00528 
00529 */
00530 
00531 
00532 /*
00533 This implementation is a direct transscript of the mu-calculus formulas stated in "Control of 
00534 w-Automata, Church's Problem, and the Emptiness Problem for Tree w-Automata", by J. Thistle and 
00535 W.M. Wonham, 1992, adapted for the special case of deterministic Buchi-automata. Referring to the 
00536 referenced literature, the corresponding iteration is "essentially optimal" in terms of performance. 
00537 In the below implementation, we unwind each individual mu/nu quantifiation literally and resist 
00538 to apply strategic substitutions in order to obtain a reference implementation. This is suspected 
00539 to introduce (linear) penalty for avoidable boolean operations on sets of states. In a recent study, 
00540 Christian Wamser proposes fine-tuned alternative implementation which will be integrated in 
00541 libFAUDES in due course.
00542 */
00543 
00544 bool OmegaControlledLiveness(
00545   Generator& rSupCandGen, 
00546   const EventSet& rCAlph,
00547   const StateSet& rPlantMarking) 
00548 {
00549   
00550   FD_DF("OmegaControlledLiveness()");
00551 
00552   // declare iterate sets
00553   StateSet resolved, initialK, targetLstar;
00554   StateSet initialL, targetL;
00555   StateSet domainL, target1;
00556   StateSet target, domain, theta;
00557  
00558   // convenience
00559   const StateSet& full = rSupCandGen.States();
00560   Idx fsz=full.Size();
00561 
00562   // evaluate mu(resolved).nu(initialK)[ p(initialK * markedK + resolved )) ];
00563   // here, p(T) denotes the set of states that can be driven to enter T under liveness assumption inf-markL;
00564   // use std. mu-nu-iteration
00565   resolved.Clear();     
00566   while(true) {
00567     Idx rsz = resolved.Size();
00568     initialK = full;
00569     while(true) {
00570       Idx iKsz = initialK.Size();
00571 
00572       // prepare target for P(): targetLstar = initialK * markedK + resolved 
00573       targetLstar = (initialK * rSupCandGen.MarkedStates()) + resolved;
00574       FD_DF("OmegaControlledLiveness(): [STD] iterate resolved/targetLstar #" << xsz << "/" << targetLstar.Size());
00575 
00576       // evaluate p(targetLstar) = mu(initialL).[ thetaTilde(targetLstar+initialL) ] 
00577       // here, thetaTilde(T) denotes the set of states that can be controlled such that T is persistently
00578       // reachable and markL is not passed before T is entered;
00579       // start with initialL:=0 and iterate initialL += thetaTilde(targetLstar+initialL); 
00580       initialL.Clear();
00581       while(true) {
00582         Idx iLsz = initialL.Size();
00583 
00584         // prepare targetL=targetLstar+initialL
00585         targetL=targetLstar+initialL; 
00586         FD_DF("OmegaControlledLiveness(): [STD] ---- iterate targetL #" << targetL.Size());
00587 
00588         // evaluate thetaTilde(targetL)=nu(domainL).mu(target1)[ theta(targetL+(target1-markL), domainL-markL) ];
00589         // here, theta(T,D) is the set of states that, by one transition, can enter T and can be controlled not to exit D+T;
00590         // start with domainL:=full and iterate domainL -= mu(target1)[theta(targetL+(target1-markL), domainL-markL)];
00591         domainL=full;
00592         targetL = targetLstar + initialL;
00593         while(true) {
00594           Idx dLsz = domainL.Size();
00595           FD_DF("OmegaControlledLiveness(): [STD] --- iterate domainL #" << domainL.Size());
00596             
00597           // user interrupt/ progress
00598           FD_WPC(1,2,"OmegaControlledLiveness(): [STD] iterating reverse dynamics"); 
00599    
00600           // prepare domain = domainL - marL
00601     domain=domainL-rPlantMarking;
00602 
00603           // evaluate mu(target1)[ theta(targetL+(target1-markL), domain) ];
00604           // start with target1:=0 and iterate target+=theta(targetL+(target1-markL), domainL-markL) ]; 
00605           target1.Clear();
00606           while(true) {
00607             Idx t1sz = target1.Size();
00608        
00609             // prepare target= targetL+(target1-markL)
00610             target = targetL + (target1-rPlantMarking);
00611 
00612             // evaluate theta(target,domain) 
00613             FD_DF("OmegaControlledLiveness(): [STD] -- evaluate theta for target/domain # " 
00614                << target.Size() << "/" << domain.Size());
00615             theta.Clear();
00616             StateSet::Iterator sit = full.Begin(); 
00617             StateSet::Iterator sit_end = full.End(); 
00618             for(;sit!=sit_end;++sit) {
00619               bool pass = false;
00620               bool fail = false;      
00621               TransSet::Iterator tit = rSupCandGen.TransRelBegin(*sit);
00622               TransSet::Iterator tit_end = rSupCandGen.TransRelEnd(*sit);
00623               for(;tit!=tit_end; ++tit) {
00624                 if(target.Exists(tit->X2)) {pass = true; continue;}
00625                 if(domain.Exists(tit->X2)) {continue;}
00626               if(!rCAlph.Exists(tit->Ev)){ fail = true; break;}
00627               }
00628               if(pass && !fail) {
00629                 theta.Insert(*sit);
00630                 FD_DF("OmegaControlledLiveness(): [STD] theta found state " << rSupCandGen.SStr(*sit));
00631         }
00632             } // end: theta   
00633   
00634             // mu-loop on target1
00635             target1.InsertSet(theta);
00636             if(target1.Size()==t1sz) break;
00637             if(target1.Size()==fsz) break;
00638           } // end: mu
00639 
00640           FD_DF("OmegaControlledLiveness(): [STD] -- mu-target1 # " << target1.Size());
00641   
00642           // nu-loop on domainL
00643           domainL.RestrictSet(target1);
00644           if(domainL.Size()==dLsz) break;
00645           if(domainL.Size()==0) break;
00646         } // end: nu
00647       
00648         FD_DF("OmegaControlledLiveness(): [STD] --- nu-domainL-mu-target1 # " << domainL.Size());
00649 
00650         // mu-loop on initialL
00651         initialL.InsertSet(domainL);
00652         if(initialL.Size()==iLsz) break;
00653         if(initialL.Size()==fsz) break;
00654       } // end: mu
00655 
00656       // nu-loop on initialK
00657       initialK.RestrictSet(initialL);
00658       if(initialK.Size()==iKsz) break;
00659       if(initialK.Size()==0) break;
00660     } // end: nu
00661 
00662     // mu-loop on resolved
00663     resolved.InsertSet(initialK);
00664     if(resolved.Size()==rsz) break;
00665     if(resolved.Size()==fsz) break;
00666   } // end: mu
00667  
00668   // restrict candidate to resolved states
00669   rSupCandGen.DelStates(full - resolved);
00670 
00671   // done
00672   return true;
00673 }
00674 
00675   
00676 /*
00677 Variant of the controllable prefix to extract a particular feedback map. Again, this is 
00678 very close to the relevant literature and meant as a reference. A more efficient 
00679 implementation proposed by Christian Wamser will be integrated in due course.
00680 */
00681 
00682 bool OmegaControlledLiveness(
00683   Generator& rSupCandGen, 
00684   const EventSet& rCAlph,
00685   const StateSet& rPlantMarking, 
00686   std::map< Idx , EventSet>& rFeedbackMap)
00687 {
00688   
00689   FD_WARN("OmegaControlledLiveness()");
00690 
00691   // declare iterate sets
00692   StateSet resolved, initialK, targetLstar;
00693   StateSet initialL, targetL;
00694   StateSet domainL, target1;
00695   StateSet target, domain, theta;
00696  
00697   // record controls per state
00698   EventSet disable;   
00699   std::map< Idx , EventSet> controls1;
00700   std::map< Idx , EventSet> controls1L;
00701   std::map< Idx , EventSet> controls1X;
00702 
00703   // convenience
00704   const StateSet& full = rSupCandGen.States();
00705   Idx fsz=full.Size();
00706 
00707   // evaluate mu(resolved).nu(initialK)[ p(initialK * markedK + resolved )) ];
00708   resolved.Clear();     
00709   while(true) {
00710     Idx xsz = resolved.Size();
00711     initialK = full;
00712     while(true) {
00713       Idx rsz = initialK.Size();
00714       targetLstar = (initialK * rSupCandGen.MarkedStates()) + resolved;
00715       FD_WARN("OmegaControlledLiveness(): [FBM] iterate resolved/targetLstar #" << xsz << "/" << targetLstar.Size());
00716 
00717       // reset controls
00718       controls1L.clear();
00719 
00720       // evaluate p(targetLstar) = mu(initialL).[ thetaTilde(targetLstar+initialL) ] 
00721       initialL.Clear();
00722       while(true) {
00723         Idx t1Lsz = initialL.Size();
00724         targetL = targetLstar + initialL;
00725         FD_WARN("OmegaControlledLiveness(): [FBM] ---- iterate targetL #" << targetL.Size());
00726 
00727         // evaluate thetaTilde(targetL)=nu(domainL).mu(target1)[ theta(targetL+(target1-markL), domainL-markL) ];
00728         domainL=full;
00729         while(true) {
00730           Idx dsz = domainL.Size();
00731     domain=domainL-rPlantMarking;
00732           FD_WARN("OmegaControlledLiveness(): [FBM] --- iterate domain #" << domain.Size());
00733             
00734           // reset controls
00735           controls1.clear();
00736 
00737           // user interrupt/ progress
00738           FD_WPC(1,2,"OmegaControlledLiveness(): [FBM] iterating reverse dynamics"); 
00739    
00740           // evaluate mu(target1)[ theta(targetL+(target1-markL), domain) ];
00741           target1.Clear();
00742           while(true) {
00743             Idx t1sz = target1.Size();
00744             target = targetL + (target1-rPlantMarking);
00745 
00746             // evaluate theta(target,domain) 
00747             FD_WARN("OmegaControlledLiveness(): [FBM] -- evaluate theta for target/domain # " 
00748                << target.Size() << "/" << domain.Size());
00749             theta.Clear();
00750             StateSet::Iterator sit = full.Begin(); 
00751             StateSet::Iterator sit_end = full.End(); 
00752             for(;sit!=sit_end;++sit) {
00753               bool pass = false;
00754               bool fail = false;      
00755               disable.Clear();
00756               TransSet::Iterator tit = rSupCandGen.TransRelBegin(*sit);
00757               TransSet::Iterator tit_end = rSupCandGen.TransRelEnd(*sit);
00758               for(;tit!=tit_end; ++tit) {
00759                 if(target.Exists(tit->X2)) { pass = true; continue; }
00760                 if(domain.Exists(tit->X2)) { continue; }
00761               if(!rCAlph.Exists(tit->Ev)){ fail = true; break; }
00762                 disable.Insert(tit->Ev); 
00763               }
00764               if(pass && !fail) {
00765                 theta.Insert(*sit);
00766                 if(controls1.find(*sit)==controls1.end()) controls1[*sit]=disable;
00767                 FD_WARN("OmegaControlledLiveness(): [FBM] theta found state " << rSupCandGen.SStr(*sit));
00768                 if(!disable.Empty())disable.Write();
00769         }
00770             } // end: theta   
00771   
00772             // mu-loop on target1
00773             target1.InsertSet(theta);
00774             if(target1.Size()==t1sz) break;
00775             if(target1.Size()==fsz) break;
00776           } // end: mu
00777 
00778           FD_WARN("OmegaControlledLiveness(): [FBM] -- mu-target1 # " << target1.Size());
00779   
00780           // nu-loop on domainL
00781           domainL.RestrictSet(target1);
00782           if(domainL.Size()==dsz) break;
00783           if(domainL.Size()==0) break;
00784         } // end: nu
00785       
00786         FD_WARN("OmegaControlledLiveness(): [FBM] --- nu-domainL-mu-target1 # " << domainL.Size());
00787 
00788         // merge controls
00789   std::map< Idx , EventSet>::iterator cit=controls1.begin();
00790   std::map< Idx , EventSet>::iterator cit_end=controls1.end();
00791         for(;cit!=cit_end;++cit) {
00792           if(controls1L.find(cit->first)!=controls1L.end()) continue;
00793           controls1L[cit->first]=cit->second;
00794         } 
00795   
00796         // mu-loop on initialL
00797         initialL.InsertSet(domainL);
00798         if(initialL.Size()==t1Lsz) break;
00799         if(initialL.Size()==fsz) break;
00800       } // end: mu
00801 
00802       // nu-loop on initialK
00803       initialK.RestrictSet(initialL);
00804       if(initialK.Size()==rsz) break;
00805       if(initialK.Size()==0) break;
00806     } // end: nu
00807 
00808     // merge controls
00809     std::map< Idx , EventSet>::iterator cit=controls1L.begin();
00810     std::map< Idx , EventSet>::iterator cit_end=controls1L.end();
00811     for(;cit!=cit_end;++cit) {
00812       if(controls1X.find(cit->first)!=controls1X.end()) continue;
00813       controls1X[cit->first]=cit->second;
00814     } 
00815 
00816     // mu-loop on resolved
00817     resolved.InsertSet(initialK);
00818     if(resolved.Size()==xsz) break;
00819     if(resolved.Size()==fsz) break;
00820   } // end: mu
00821  
00822   // restrict candidate to valid restrict
00823   rSupCandGen.DelStates(full - resolved);
00824 
00825   // re-write controls as feedback map
00826   EventSet ucalph = rSupCandGen.Alphabet() - rCAlph;
00827   StateSet::Iterator sit = resolved.Begin();
00828   StateSet::Iterator sit_end = resolved.End();
00829   for(;sit!=sit_end;++sit) {
00830     FD_WARN("OmegaControlledLiveness(): [FBM] controls " << rSupCandGen.SStr(*sit) << " " << controls1X[*sit].ToString());
00831     rFeedbackMap[*sit]= (rSupCandGen.ActiveEventSet(*sit) + ucalph) - controls1X[*sit];
00832   }
00833 
00834   // done
00835   return true;
00836 }
00837   
00838 
00839   
00840 
00841 // helper class: mergable control pattern
00842 class MCtrlPattern {
00843 public:
00844   // merge with other
00845   void merge(const MCtrlPattern& other) {
00846     disable_all.InsertSet(other.disable_all);
00847     enable_one.insert(other.enable_one.begin(),other.enable_one.end());
00848   }
00849   // test conflict
00850   bool conflict() {
00851     std::set< EventSet >::iterator eit =enable_one.begin();
00852     std::set< EventSet >::iterator eit_end =enable_one.end();
00853     for(; eit!=eit_end ; ++eit) 
00854       if( (*eit - disable_all).Empty() ) return true;
00855     return false;
00856   }
00857   // member variables
00858   EventSet disable_all;
00859   std::set< EventSet > enable_one;
00860 };
00861 
00862 
00863 
00864 /* 
00865 Variant of a controllable prefix under partial observation. This is **experimantal**.
00866 Based on the situation of full observation, this variant records control patterns
00867 used to establish controlled liveness and only accepts a new state if the corresponding
00868 pattern complies all recorded patterns that correspond to the same observation.
00869 The result is a (possibly strict) subset of the controllable prefix for the purpose.
00870 Theoretical background will be provided in due course.
00871 */
00872 
00873 bool OmegaControlledLiveness(
00874   Generator& rSupCandGen, 
00875   const EventSet& rCAlph,
00876   const StateSet& rPlantMarking, 
00877   std::map< Idx , Idx>& rControllerStatesMap,
00878   std::map< Idx , EventSet>& rFeedbackMap)
00879 {
00880   
00881   FD_WARN("OmegaControlledLiveness(): [POBS]: cand #" << rSupCandGen.Size());
00882 
00883   // debugging: interpret empty controllermap as identity
00884   StateSet::Iterator xit = rSupCandGen.StatesBegin(); 
00885   StateSet::Iterator xit_end = rSupCandGen.StatesEnd(); 
00886   for(;xit!=xit_end;++xit) {
00887     std::map< Idx , Idx >::const_iterator cxit=rControllerStatesMap.find(*xit);
00888     if(cxit==rControllerStatesMap.end()) rControllerStatesMap[*xit]=*xit;
00889   }
00890 
00891   // informative
00892   std::map< Idx , Idx>::const_iterator oit = rControllerStatesMap.begin();
00893   std::set< Idx > ostates;  
00894   for(; oit != rControllerStatesMap.end(); ++oit)
00895     ostates.insert(oit->second);
00896   FD_WARN("OmegaControlledLiveness(): [POBS]: " << "obs #" << ostates.size());
00897 
00898    // declare iterate sets
00899   StateSet resolved, initialK, targetLstar;
00900   StateSet initialL, targetL;
00901   StateSet domainL, target1;
00902   StateSet target, domain, theta;
00903  
00904   // record controls per state
00905   EventSet disable;   
00906   EventSet enable;   
00907   std::map< Idx , MCtrlPattern> controlsT;
00908   std::map< Idx , MCtrlPattern> controls1;
00909   std::map< Idx , MCtrlPattern> controls1L;
00910   std::map< Idx , MCtrlPattern> controls1X;
00911  
00912   // convenience
00913   const StateSet& full = rSupCandGen.States();
00914   Idx fsz=full.Size();
00915 
00916   // evaluate mu(resolved).nu(initialK)[ p(initialK * markedK + resolved )) ];
00917   resolved.Clear();     
00918   while(true) {
00919     Idx xsz = resolved.Size();
00920     initialK = full;
00921     while(true) {
00922       Idx rsz = initialK.Size();
00923       targetLstar = (initialK * rSupCandGen.MarkedStates()) + resolved;
00924       FD_WARN("OmegaControlledLiveness(): [POBS] iterate resolved/targetLstar #" << xsz << "/" << targetLstar.Size());
00925 
00926       // reset controls
00927       controls1L.clear();
00928 
00929       // evaluate p(targetLstar) = mu(initialL).[ thetaTilde(targetLstar+initialL) ] 
00930       initialL.Clear();
00931       while(true) {
00932         Idx t1Lsz = initialL.Size();
00933         targetL = targetLstar + initialL;
00934         FD_WARN("OmegaControlledLiveness(): [POBS] ---- iterate targetL #" << targetL.Size());
00935 
00936         // evaluate thetaTilde(targetL)=nu(domainL).mu(target1)[ theta(targetL+(target1-markL), domainL-markL) ];
00937         domainL=full;
00938         while(true) {
00939           Idx dsz = domainL.Size();
00940     domain=domainL-rPlantMarking;
00941           FD_WARN("OmegaControlledLiveness(): [POBS] --- iterate domain #" << domain.Size());
00942             
00943           // reset controls
00944           controls1.clear();
00945 
00946           // user interrupt/ progress
00947           FD_WPC(1,2,"OmegaControlledLiveness(): [POBS] iterating reverse dynamics"); 
00948    
00949           // evaluate mu(target1)[ theta(targetL+(target1-markL), domain) ];
00950           target1.Clear();
00951           while(true) {
00952             Idx t1sz = target1.Size();
00953             target = targetL + (target1-rPlantMarking);
00954 
00955             // evaluate theta(target,domain) in three passes
00956             FD_WARN("OmegaControlledLiveness(): [POBS] -- evaluate theta for target/domain # " 
00957                << target.Size() << "/" << domain.Size());
00958             theta.Clear();
00959             controlsT.clear();
00960 
00961             // pass 1: find new candidate states and acumulate required controls
00962             StateSet::Iterator sit = full.Begin(); 
00963             StateSet::Iterator sit_end = full.End(); 
00964             for(;sit!=sit_end;++sit) {
00965               Idx cx=rControllerStatesMap[*sit];
00966               bool pass = false;
00967               bool fail = false;      
00968               disable.Clear();
00969               enable.Clear();
00970               TransSet::Iterator tit = rSupCandGen.TransRelBegin(*sit);
00971               TransSet::Iterator tit_end = rSupCandGen.TransRelEnd(*sit);
00972               for(;tit!=tit_end; ++tit) {
00973                 if(disable.Exists(tit->Ev)) continue;
00974                 if(target.Exists(tit->X2)) {enable.Insert(tit->Ev); pass = true; continue;}
00975                 if(domain.Exists(tit->X2)) {continue;}
00976               if(!rCAlph.Exists(tit->Ev)){ fail = true; break;}
00977                 disable.Insert(tit->Ev); 
00978               }
00979               if(pass && !fail) {
00980                 // initialize control with existing patterns
00981           if(controlsT.find(cx)==controlsT.end()) {
00982               if(controls1.find(cx)!=controls1.end()) 
00983                     controlsT[cx].merge(controls1[cx]);
00984               if(controls1L.find(cx)!=controls1L.end()) 
00985                     controlsT[cx].merge(controls1L[cx]);
00986               if(controls1X.find(cx)!=controls1X.end()) 
00987                     controlsT[cx].merge(controls1X[cx]);
00988     }
00989                 // apply additional pattern
00990                 controlsT[cx].disable_all.InsertSet(disable);
00991                 controlsT[cx].enable_one.insert(enable);
00992         }
00993             } // end: theta pass 1
00994 
00995             // pass 2: merge new controls to controls1, reject conflicting 
00996       std::map< Idx , MCtrlPattern >::iterator cpit=controlsT.begin();
00997       std::map< Idx , MCtrlPattern >::iterator cpit_end=controlsT.end();
00998       while(cpit!=cpit_end) {
00999               if(cpit->second.conflict()) {controlsT.erase(cpit++); continue;}
01000               controls1[cpit->first].merge(cpit->second);
01001         ++cpit;
01002       }
01003 
01004             // pass 3: evaluate theta by accumulated controls control
01005             sit = rSupCandGen.StatesBegin(); 
01006             sit_end = rSupCandGen.StatesEnd(); 
01007             for(;sit!=sit_end;++sit) {
01008               bool pass = false;
01009               bool fail = false;      
01010               Idx cx=rControllerStatesMap[*sit];
01011               if(controls1.find(cx)==controls1.end()) continue;
01012               disable=controls1[cx].disable_all;
01013               TransSet::Iterator tit = rSupCandGen.TransRelBegin(*sit);
01014               TransSet::Iterator tit_end = rSupCandGen.TransRelEnd(*sit);
01015               for(;tit!=tit_end; ++tit) {
01016                 if(disable.Exists(tit->Ev)) continue;
01017                 if(target.Exists(tit->X2)) {pass = true; continue;}
01018                 if(domain.Exists(tit->X2)) {continue;}
01019               fail = true;
01020               }
01021               if(pass && !fail) {
01022                 theta.Insert(*sit);
01023                 //FD_WARN("OmegaControlledLiveness(): [POBS] theta candidate verified " << rSupCandGen.SStr(*sit));
01024         }
01025             } // end: theta  pass 3
01026 
01027             // mu-loop on target1
01028             target1.InsertSet(theta);
01029             if(target1.Size()==t1sz) break;
01030             if(target1.Size()==fsz) break;
01031           } // end: mu
01032 
01033           FD_WARN("OmegaControlledLiveness(): [POBS] -- mu-target1 # " << target1.Size());
01034   
01035           // nu-loop on domainL
01036           domainL.RestrictSet(target1);
01037           if(domainL.Size()==dsz) break;
01038           if(domainL.Size()==0) break;
01039         } // end: nu
01040       
01041         FD_WARN("OmegaControlledLiveness(): [POBS] --- nu-domainL-mu-target1 # " << domainL.Size());
01042 
01043         // merge controls
01044   std::map< Idx , MCtrlPattern>::iterator cit = controls1.begin();
01045   std::map< Idx , MCtrlPattern>::iterator cit_end = controls1.end();
01046         for(;cit!=cit_end;++cit) 
01047           controls1L[cit->first].merge(cit->second);
01048   
01049         // mu-loop on initialL
01050         initialL.InsertSet(domainL);
01051         if(initialL.Size()==t1Lsz) break;
01052         if(initialL.Size()==fsz) break;
01053       } // end: mu
01054 
01055       // nu-loop on initialK
01056       initialK.RestrictSet(initialL);
01057       if(initialK.Size()==rsz) break;
01058       if(initialK.Size()==0) break;
01059     } // end: nu
01060 
01061     // merge controls
01062     std::map< Idx , MCtrlPattern>::iterator cit = controls1L.begin();
01063     std::map< Idx , MCtrlPattern>::iterator cit_end = controls1L.end();
01064     for(;cit!=cit_end;++cit) 
01065       controls1X[cit->first].merge(cit->second);
01066 
01067     // mu-loop on resolved
01068     resolved.InsertSet(initialK);
01069     if(resolved.Size()==xsz) break;
01070     if(resolved.Size()==fsz) break;
01071   } // end: mu
01072  
01073   // restrict candidate to valid restrict
01074   rSupCandGen.DelStates(full - resolved);
01075 
01076   // debugging
01077   if(rSupCandGen.IsCoaccessible())
01078     FD_WARN("OmegaControlledLiveness(): [POBS] ---- coaccessible ok");
01079   if(rSupCandGen.IsComplete())
01080     FD_WARN("OmegaControlledLiveness(): [POBS] ---- complete ok");
01081   if(!rSupCandGen.InitStates().Empty())
01082     FD_WARN("OmegaControlledLiveness(): [POBS] ---- init state ok");
01083 
01084   // re-write controls as feedback map (w.r.t. candidate states)
01085   StateSet::Iterator sit = resolved.Begin();
01086   StateSet::Iterator sit_end = resolved.End();
01087   for(;sit!=sit_end;++sit) {
01088     Idx cx=rControllerStatesMap[*sit];
01089     //FD_WARN("OmegaControlledLiveness(): [POBS] controls at cx=" << cx << " for plant state " << rSupCandGen.SStr(*sit) << " " << controls1X[cx].disable_all.ToString());
01090     rFeedbackMap[*sit]= rSupCandGen.Alphabet() - controls1X[cx].disable_all;
01091   }
01092 
01093   // done
01094   return true;
01095 }
01096 
01097 
01098 /*
01099 ***************************************************************************************
01100 ***************************************************************************************
01101  Implementation of OmegaSupConNB and friends
01102 ***************************************************************************************
01103 ***************************************************************************************
01104 */
01105 
01106 // helper class: omega-product state
01107 class OPSState {
01108 public:
01109   // minimal interface
01110   OPSState() {};
01111   OPSState(const Idx& rq1, const Idx& rq2, const bool& rf) :
01112     q1(rq1), q2(rq2), m1required(rf) {};
01113   std::string Str(void) { return ToStringInteger(q1)+"|"+
01114       ToStringInteger(q2)+"|"+ToStringInteger(m1required); };
01115   // order
01116   bool operator < (const OPSState& other) const {
01117     if (q1 < other.q1) return(true);
01118     if (q1 > other.q1) return(false);
01119     if (q2 < other.q2) return(true);
01120     if (q2 > other.q2) return(false);
01121     if (m1required && !other.m1required) return(true);
01122     return(false);
01123   }
01124   // member variables
01125   Idx q1;
01126   Idx q2;
01127   bool m1required;
01128 };
01129 
01130 
01131 // OmegaSupConProduct(rPlantGen, rCAlph, rSpecGen, rReverseCompositionMap, rResGen)
01132 void OmegaSupConProduct(
01133   const Generator& rPlantGen, 
01134   const EventSet& rCAlph,
01135   const Generator& rSpecGen,
01136   std::map< OPSState , Idx>& rProductCompositionMap, 
01137   Generator& rResGen) 
01138 {
01139   FD_DF("OmegaSupConProduct(" << &rPlantGen << "," << &rSpecGen << ")");
01140   
01141   // prepare result
01142   rResGen.Clear();
01143   rResGen.InjectAlphabet(rPlantGen.Alphabet());
01144 
01145   // trivial case
01146   if (rPlantGen.InitStatesEmpty()) {
01147     FD_DF("OmegaSupConProduct: plant got no initial states. "
01148             << "parallel composition contains empty language.");
01149     return;
01150   }
01151   if (rSpecGen.InitStatesEmpty()) {
01152     FD_DF("OmegaSupConProduct: spec got no initial states. "
01153               << "parallel composition contains empty language.");
01154     return;
01155   }
01156 
01157   // todo stack
01158   std::stack< OPSState > todo;
01159   // current/next state as pair with flag
01160   OPSState currentp, nextp;
01161   // current/next state as target index
01162   Idx currentt, nextt;  
01163   TransSet::Iterator ptit, ptit_end, stit, stit_end;
01164   std::map< OPSState, Idx>::iterator rcit;
01165   // critical states
01166   StateSet critical;
01167   // disabled events
01168   EventSet disable;
01169 
01170 
01171   // push initial state on todo stack
01172   currentp = OPSState(*rPlantGen.InitStatesBegin(), *rSpecGen.InitStatesBegin(), true);
01173   todo.push(currentp);
01174   currentt=rResGen.InsInitState();
01175   rProductCompositionMap[currentp] = currentt;
01176 
01177   // process/feed todo stack
01178   FD_DF("OmegaSupConProduct: processing reachable states:");
01179   while(!todo.empty()) {
01180     // allow for user interrupt
01181     // LoopCallback();
01182     // allow for user interrupt, incl progress report
01183     FD_WPC(rProductCompositionMap.size(),rProductCompositionMap.size()+todo.size(),"OmegaSupConProduct(): processing"); 
01184     FD_DF("OmegaSupConProduct(): processing" << rProductCompositionMap.size() << " " << todo.size()); 
01185     // get next reachable state from todo stack
01186     currentp = todo.top();
01187     currentt = rProductCompositionMap[currentp];
01188     todo.pop();
01189     // skip critical (tmoor 201308)
01190     if(critical.Exists(currentt)) continue; 
01191     // report
01192     FD_DF("OmegaSupConProduct: processing (" << currentp.Str() << " -> " << currentt <<")");
01193 
01194     // iterate over transitions, pass1: figure whether current state becomes critical (tmoor 201308)
01195     ptit = rPlantGen.TransRelBegin(currentp.q1);
01196     ptit_end = rPlantGen.TransRelEnd(currentp.q1);
01197     stit = rSpecGen.TransRelBegin(currentp.q2);
01198     stit_end = rSpecGen.TransRelEnd(currentp.q2);
01199     disable.Clear();
01200     // process all transitions and increment iterators strategically
01201     while((ptit != ptit_end) && (stit != stit_end)) {
01202       FD_DF("OmegaSupConProduct: current plant-transition: " << rPlantGen.TStr(*ptit) );
01203       FD_DF("OmegaSupConProduct: current spec-transition: " << rSpecGen.TStr(*stit));
01204       // case A: execute common event
01205       if(ptit->Ev == stit->Ev) {
01206         nextp = OPSState(ptit->X2, stit->X2,currentp.m1required);
01207         if(currentp.m1required) {
01208       if(rPlantGen.ExistsMarkedState(currentp.q1)) nextp.m1required=false;
01209         } else {
01210       if(rSpecGen.ExistsMarkedState(currentp.q2)) nextp.m1required=true;
01211         }
01212         // figure whether successor state is known to be critical
01213     rcit = rProductCompositionMap.find(nextp);
01214         if(rcit != rProductCompositionMap.end()) { 
01215     if(critical.Exists(rcit->second)) {
01216       FD_DF("OmegaSupconOmegaParallel: common event " << rSpecGen.EStr(stit->Ev) << " to a critical states");
01217             // if event is uncontrollable, current state becomes critical
01218       if(!rCAlph.Exists(ptit->Ev)) {
01219         FD_DF("OmegaSupConProduct: critical insert" << currentt);
01220         critical.Insert(currentt); // tmoor 201308
01221         // exit all loops
01222         ptit = ptit_end;
01223         stit = stit_end;
01224               break;
01225       } 
01226             // else, event is disabled 
01227             disable.Insert(stit->Ev);     
01228     }
01229   }
01230         // increment transition
01231         ++ptit;
01232         ++stit;
01233       }
01234       // case B: process plant event that is disabled by the specification
01235       else if (ptit->Ev < stit->Ev) {
01236   FD_DF("SupConProduct:  "  << rPlantGen.EStr(ptit->Ev) << " is enabled in the plant but disabled in the specification");
01237   // if the event is uncontrollable, this makes the current state critical
01238   if (!rCAlph.Exists(ptit->Ev)) {
01239     FD_DF("OmegaSupConProduct: disabled event " << rPlantGen.EStr(ptit->Ev)  << " is uncontrollable");
01240     FD_DF("OmegaSupConProduct: critical insert" << currentt);
01241     critical.Insert(currentt);
01242     // exit all loops
01243     ptit = ptit_end;
01244     stit = stit_end;
01245     break;
01246   }
01247   FD_DF("OmegaSupConProduct: incrementing plant transrel");
01248   ++ptit;
01249       } 
01250       // increment titg and titg, case C: process h event that is not enabled for g
01251       else {
01252   FD_DF("OmegaSupConProduct: incrementing spec transrel");
01253   ++stit;
01254       }
01255     } // end while incrementing 
01256     // increment iterators case D: process leftover events of plant
01257     while (ptit != ptit_end) {
01258       FD_DF("OmegaSupConProduct: current g-transition: " << rPlantGen.TStr(*ptit));
01259       FD_DF("OmegaSupConProduct: current h-transition: end");
01260       // if uncontrollable event leaves candidate
01261       if (!rCAlph.Exists(ptit->Ev)) {
01262   FD_DF("OmegaSupConProduct: asynchron executed uncontrollable "
01263            << "event " << rPlantGen.EStr(ptit->Ev) << " leaves specification:");
01264   FD_DF("SupConProduct: critical insert" << rPlantGen.SStr(currentt));
01265   critical.Insert(currentt);
01266   // exit this loop 
01267   break;
01268       }
01269       FD_DF("OmegaSupConProduct: incrementing g transrel");
01270       ++ptit;
01271     } // end iterating pass1
01272 
01273     // skip critical (tmoor 201308)
01274     if(critical.Exists(currentt)) continue; 
01275 
01276     // iterate over transitions, pass2: execute shared events (tmoor 201308)
01277     FD_DF("OmegaSupConProduct(): processing pass2"); 
01278     ptit = rPlantGen.TransRelBegin(currentp.q1);
01279     ptit_end = rPlantGen.TransRelEnd(currentp.q1);
01280     stit = rSpecGen.TransRelBegin(currentp.q2);
01281     stit_end = rSpecGen.TransRelEnd(currentp.q2);
01282     // process all transitions and increment iterators strategically
01283     while((ptit != ptit_end) && (stit != stit_end)) {
01284       FD_DF("OmegaSupConProduct: current plant-transition: " << rPlantGen.TStr(*ptit) );
01285       FD_DF("OmegaSupConProduct: current spec-transition: " << rSpecGen.TStr(*stit));
01286       // case A: execute common event
01287       if(ptit->Ev == stit->Ev) {
01288         if(!disable.Exists(stit->Ev)) { 
01289       FD_DF("OmegaSupConProduct: executing common event "  << rPlantGen.EStr(ptit->Ev));
01290           nextp = OPSState(ptit->X2, stit->X2,currentp.m1required);
01291           if(currentp.m1required) {
01292         if(rPlantGen.ExistsMarkedState(currentp.q1)) nextp.m1required=false;
01293           } else {
01294         if(rSpecGen.ExistsMarkedState(currentp.q2)) nextp.m1required=true;
01295           }
01296           // figure target index
01297     rcit = rProductCompositionMap.find(nextp);
01298     // if state is new: add to todo list and result
01299     if(rcit == rProductCompositionMap.end()) {
01300             todo.push(nextp);
01301             nextt = rResGen.InsState();
01302             rProductCompositionMap[nextp] = nextt;
01303             if(!nextp.m1required) 
01304               if(rSpecGen.ExistsMarkedState(nextp.q2)) 
01305                 rResGen.SetMarkedState(nextt);                   
01306             FD_DF("OmegaSupConProduct:   todo push: (" << nextp.Str() << ") -> " << nextt);
01307           } else {
01308             nextt = rcit->second;
01309           }
01310     // set the transition and increment iterators
01311           FD_DF("OmegaSuperParallel:  add transition to new generator: " << rResGen.TStr(Transition(currentt, ptit->Ev, nextt)));
01312           rResGen.SetTransition(currentt, ptit->Ev, nextt);
01313   }
01314         // increment transition
01315         ++ptit;
01316         ++stit;
01317       } // end: if processing common event 
01318       // case B: process plant event that is disabled by the specification
01319       else if (ptit->Ev < stit->Ev) {
01320   ++ptit;
01321       } 
01322       // increment titg and titg, case C: process h event that is not enabled for g
01323       else {
01324   ++stit;
01325       }
01326     } // end while incrementing for pass2
01327 
01328   } // while todo
01329 
01330   FD_DF("OmegaSupConProduct: deleting critical states: " << critical.ToString());
01331   rResGen.DelStates(critical);
01332 
01333   // restrict composition map
01334   std::map< OPSState , Idx>::iterator cit = rProductCompositionMap.begin();
01335   while(cit != rProductCompositionMap.end())
01336     if(!rResGen.ExistsState(cit->second)) rProductCompositionMap.erase(cit++);
01337     else cit++;
01338 
01339 }
01340 
01341 
01342 
01343 
01344 // OmegaSupConNBUnchecked(rPlantGen, rCAlph, rSpecGen,rResGen)
01345 void OmegaSupConNBUnchecked(
01346   const Generator& rPlantGen,
01347   const EventSet& rCAlph,  
01348   const Generator& rSpecGen,
01349   StateSet& rPlantMarking,
01350   Generator& rResGen) 
01351 {
01352   FD_DF("OmegaSupConNBUnchecked(\"" <<  rPlantGen.Name() << "\", \"" << rSpecGen.Name() << "\")");
01353 
01354   // PREPARE RESULT:  
01355   Generator* pResGen = &rResGen;
01356   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
01357     pResGen= rResGen.New();
01358   }
01359   pResGen->Clear();
01360   pResGen->InjectAlphabet(rPlantGen.Alphabet());
01361 
01362   // controllable events
01363   FD_DF("OmegaSupConNB: controllable events: "   << rCAlph.ToString());
01364 
01365   // perform product
01366   std::map< OPSState , Idx> cmap; 
01367   OmegaSupConProduct(rPlantGen, rCAlph, rSpecGen, cmap, *pResGen);
01368 
01369   // figure plant marking
01370   rPlantMarking.Clear();
01371   std::map< OPSState, Idx>::iterator pcit;
01372   for(pcit=cmap.begin(); pcit!=cmap.end(); ++pcit) 
01373     if(rPlantGen.ExistsMarkedState(pcit->first.q1))
01374        rPlantMarking.Insert(pcit->second);
01375 
01376   // fix statenames (debugging)
01377 #ifdef FAUDES_DEBUG_FUNCTION
01378   std::map< OPSState, Idx>::iterator dcit;
01379   for(dcit=cmap.begin(); dcit!=cmap.end(); ++dcit) {
01380     Idx x1=dcit->first.q1;
01381     Idx x2=dcit->first.q2;
01382     bool m1requ=dcit->first.m1required;
01383     Idx x12=dcit->second;
01384     if(!pResGen->ExistsState(x12)) continue;
01385     std::string name1= rPlantGen.StateName(x1);
01386     if(name1=="") name1=ToStringInteger(x1);
01387     std::string name2= rSpecGen.StateName(x2);
01388     if(name2=="") name1=ToStringInteger(x2);
01389     std::string name12;
01390     if(m1requ) name12= name1 + "|" + name2 + "|r1m";
01391     else name12= name1 + "|" + name2 + "|r2m";
01392     name12=pResGen->UniqueStateName(name12);
01393     pResGen->StateName(x12,name12);
01394   }
01395 #endif
01396 
01397 #ifdef FAUDES_DEBUG_FUNCTION
01398   pResGen->DWrite();
01399   pResGen->Write("tmp_syn_xxx_"+pResGen->Name()+".gen");
01400   pResGen->WriteStateSet(rPlantMarking);
01401 #endif
01402 
01403   // iterate for required properties
01404   while(true) {
01405     // catch trivial
01406     if(pResGen->Empty()) break;
01407     // fast inner loop: prefix controllability and omega-trim
01408     while(true) {
01409       Idx count1 = pResGen->Size();
01410       FD_WARN("OmegaSupConNB: iterate: do prefix con on #"   << pResGen->Size());
01411       SupConClosedUnchecked(rPlantGen, rCAlph, *pResGen);
01412       FD_WARN("OmegaSupConNB: iterate: do coaccessible on #"   << pResGen->Size());
01413       pResGen->Coaccessible();
01414       FD_WARN("OmegaSupConNB: iterate: do accessible on #"   << pResGen->Size());
01415       pResGen->Accessible();
01416       FD_WARN("OmegaSupConNB: iterate: do complete on #"   << pResGen->Size());
01417       pResGen->Complete();
01418       if(pResGen->Size() == count1) break;
01419       if(pResGen->Size() == 0) break;
01420     }
01421     // slow outer loop: controlled liveness aka restrict to controllable prefix
01422     Idx count2 = pResGen->Size();
01423     FD_WARN("OmegaSupConNB: iterate: do controlled liveness  on #"   << pResGen->Size());
01424     OmegaControlledLiveness(*pResGen,rCAlph,rPlantMarking);
01425     if(pResGen->Size() == count2) break;    
01426   }
01427 
01428   // fix statenames ...
01429   std::map< OPSState, Idx>::iterator rcit;
01430   if(rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && pResGen->StateNamesEnabled()) 
01431   for(rcit=cmap.begin(); rcit!=cmap.end(); rcit++) {
01432     Idx x1=rcit->first.q1;
01433     Idx x2=rcit->first.q2;
01434     bool m1requ=rcit->first.m1required;
01435     Idx x12=rcit->second;
01436     if(!pResGen->ExistsState(x12)) continue;
01437     std::string name1= rPlantGen.StateName(x1);
01438     if(name1=="") name1=ToStringInteger(x1);
01439     std::string name2= rSpecGen.StateName(x2);
01440     if(name2=="") name1=ToStringInteger(x2);
01441     std::string name12;
01442     if(m1requ) name12= name1 + "|" + name2 + "|r1m";
01443     else name12= name1 + "|" + name2 + "|r2m";
01444     name12=pResGen->UniqueStateName(name12);
01445     pResGen->StateName(x12,name12);
01446   }
01447 
01448   // .. or clear them (?)
01449   if(!(rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && pResGen->StateNamesEnabled())) 
01450     pResGen->StateNamesEnabled(false);
01451 
01452   // copy result
01453   if(pResGen != &rResGen) {
01454     pResGen->Move(rResGen);
01455     delete pResGen;
01456   }
01457 
01458   FD_WARN("OmegaSupConNB: return #"   << rResGen.Size());
01459 }
01460 
01461 
01462 // OmegaSupConNormNBUnchecked(rPlantGen, rCAlph, rOAlph, rSpecGen, rFeedbackMap, rResGen)
01463 void OmegaSupConNormNBUnchecked(
01464   const Generator& rPlantGen,
01465   const EventSet& rCAlph,  
01466   const EventSet& rOAlph,  
01467   const Generator& rSpecGen,
01468   StateSet& rPlantMarking,
01469   std::map< Idx , Idx >& rObserverStateMap,
01470   std::map< Idx , EventSet>& rFeedbackMap, 
01471   Generator& rResGen) 
01472 {
01473   FD_WARN("OmegaSupConNormNB(\"" <<  rPlantGen.Name() << "\", \"" << rSpecGen.Name() << "\")");
01474 
01475   // prepare result
01476   Generator* pResGen = &rResGen;
01477   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
01478     pResGen= rResGen.New();
01479   }
01480   pResGen->Clear();
01481   pResGen->InjectAlphabet(rPlantGen.Alphabet());
01482 
01483   // report events
01484   FD_WARN("OmegaSupConNormNB: controllable events: "   << rCAlph.ToString());
01485   FD_WARN("OmegaSupConNormNB: un-observabel events: "   << (rPlantGen.Alphabet()-rOAlph).ToString());
01486 
01487   // perform product
01488   std::map< OPSState , Idx> cmap; 
01489   OmegaSupConProduct(rPlantGen, rCAlph, rSpecGen, cmap, *pResGen);
01490   pResGen->OmegaTrim();
01491 
01492   // no statenames impülemented
01493   pResGen->StateNamesEnabled(false);
01494 
01495   // figure plant marking
01496   rPlantMarking.Clear();
01497   std::map< OPSState, Idx>::iterator pcit;
01498   for(pcit=cmap.begin(); pcit!=cmap.end(); ++pcit) 
01499     if(rPlantGen.ExistsMarkedState(pcit->first.q1))
01500        rPlantMarking.Insert(pcit->second);
01501 
01502   // extend by observer states
01503   Generator obsG= *pResGen;
01504   MarkAllStates(obsG);
01505   Project(obsG,rOAlph,obsG);
01506   InvProject(obsG,pResGen->Alphabet());
01507   std::map< std::pair<Idx,Idx>, Idx> rObserverCompositionMap;
01508   Product(*pResGen, obsG, rObserverCompositionMap, *pResGen);
01509   // track plantmarking
01510   StateSet fixmarking;
01511   std::map< std::pair<Idx,Idx>, Idx>::iterator cit;
01512   for(cit=rObserverCompositionMap.begin(); cit!=rObserverCompositionMap.end();++cit) 
01513      if(rPlantMarking.Exists(cit->first.first)) fixmarking.Insert(cit->second);
01514   rPlantMarking=fixmarking;
01515   // construct reverse map "pResGen.State --> obsG.State"
01516   std::map< std::pair<Idx,Idx>, Idx>::iterator sit;
01517   for(sit=rObserverCompositionMap.begin(); sit!=rObserverCompositionMap.end();++sit) 
01518     rObserverStateMap[sit->second]=sit->first.second;
01519   
01520 #ifdef FAUDES_DEBUG_FUNCTION
01521   pResGen->DWrite();
01522   pResGen->Write("tmp_syn_xxx_"+pResGen->Name()+".gen");
01523   pResGen->WriteStateSet(rPlantMarking);
01524 #endif
01525 
01526   FD_WARN("OmegaSupConNormNB(): cand #" << pResGen->Size() << " obs #" << obsG.Size());
01527   // make resulting generator trim until it's fully controllable
01528   while(true) {
01529     // catch trivial
01530     if(pResGen->Empty()) break;
01531     // fast inner loop: prefix controllability and omega-trim
01532     while(true) {
01533       Idx count1 = pResGen->Size();
01534       FD_WARN("OmegaSupConNormNB: iterate: do prefix-contr  on #"   << pResGen->Size());
01535       SupConClosedUnchecked(rPlantGen, rCAlph, *pResGen);
01536       FD_WARN("OmegaSupConNormNB: iterate: do accessible on #"   << pResGen->Size());
01537       pResGen->Accessible();
01538       FD_WARN("OmegaSupConNormNB: iterate: do coaccessible on #"   << pResGen->Size());
01539       pResGen->Coaccessible();
01540       FD_WARN("OmegaSupConNormNB: iterate: do prefix-norm  on #"   << pResGen->Size());
01541       SupConNormClosedUnchecked(rPlantGen, rOAlph, rOAlph, obsG, *pResGen);
01542       FD_WARN("OmegaSupConNormNB: iterate: do coaccessible on #"   << pResGen->Size());
01543       pResGen->Coaccessible();
01544       FD_WARN("OmegaSupConNormNB: iterate: do accessible on #"   << pResGen->Size());
01545       pResGen->Accessible();
01546       FD_WARN("OmegaSupConNormNB: iterate: do complete on #"   << pResGen->Size());
01547       pResGen->Complete();
01548       if(pResGen->Size() == count1) break;
01549       if(pResGen->Size() == 0) break;
01550     }
01551     // slow outer loop: controlled liveness
01552     Idx count2 = pResGen->Size();
01553     FD_WARN("OmegaSupConNormNB: iterate: do controlled liveness  on #"   << pResGen->Size());
01554 
01555     // cosmetic: restrict observer map and count effective states
01556     std::map< Idx , Idx>::iterator oit = rObserverStateMap.begin();
01557     while(oit != rObserverStateMap.end())
01558       if(!pResGen->ExistsState(oit->first)) rObserverStateMap.erase(oit++);
01559       else oit++;
01560     std::set< Idx > ostates;  
01561     for(oit = rObserverStateMap.begin(); oit != rObserverStateMap.end(); ++oit)
01562       ostates.insert(oit->second);
01563 
01564     //omega controlled liveness aka controllabe prefix
01565     FD_WARN("OmegaSupConNormNB(): cand #" << pResGen->Size() << " obs #" << ostates.size());
01566     std::map< Idx , EventSet> feedback;
01567     OmegaControlledLiveness(*pResGen,rCAlph,rPlantMarking,rObserverStateMap,feedback);
01568     //OmegaControlledLiveness(*pResGen,rCAlph,rPlantMarking);
01569     if(pResGen->Size() == count2) break;    
01570   }
01571 
01572   // copy result
01573   if(pResGen != &rResGen) {
01574     pResGen->Move(rResGen);
01575     delete pResGen;
01576   }
01577 }
01578 
01579 
01580 /*
01581 ****************************************
01582 * SUPCON: WRAPPER / USER FUNCTIONS     *
01583 ****************************************
01584 */
01585 
01586 
01587 // OmegaSupConNB(rPlantGen, rCAlph, rSpecGen, rResGen)
01588 void OmegaSupConNB(
01589   const Generator& rPlantGen, 
01590   const EventSet& rCAlph, 
01591   const Generator& rSpecGen, 
01592   Generator& rResGen) 
01593 {
01594   // consitenct check
01595   ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen);  
01596   // execute
01597   StateSet plantmarking;
01598   OmegaSupConNBUnchecked(rPlantGen, rCAlph, rSpecGen, plantmarking, rResGen);
01599   // record name
01600   rResGen.Name(CollapsString("OmegaSupConNB(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"));
01601 }
01602 
01603 
01604 // OmegaSupConNB for Systems:
01605 // uses and maintains controllablity from plant 
01606 void OmegaSupConNB(
01607   const System& rPlantGen, 
01608   const Generator& rSpecGen, 
01609   Generator& rResGen) {
01610   // prepare result
01611   Generator* pResGen = &rResGen;
01612   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
01613     pResGen= rResGen.New();
01614   }
01615   // execute 
01616   OmegaSupConNB(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,*pResGen);
01617   // copy all attributes of input alphabet
01618   pResGen->EventAttributes(rPlantGen.Alphabet());
01619   // copy result
01620   if(pResGen != &rResGen) {
01621     pResGen->Move(rResGen);
01622     delete pResGen;
01623   }
01624 }
01625 
01626 // OmegaConNB(rPlantGen, rCAlph, rSpecGen, rResGen)
01627 void OmegaConNB(
01628   const Generator& rPlantGen, 
01629   const EventSet& rCAlph, 
01630   const Generator& rSpecGen, 
01631   Generator& rResGen) 
01632 {
01633 
01634   // consitency check
01635   ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen);  
01636   // compute supremal closed-loop behaviour
01637   StateSet plantmarking;
01638   OmegaSupConNBUnchecked(rPlantGen, rCAlph, rSpecGen, plantmarking, rResGen);
01639   // compute restrictive feedback
01640   std::map< Idx , EventSet> feedback;
01641   OmegaControlledLiveness(rResGen, rCAlph, plantmarking, feedback);
01642   // apply restrictive feedback
01643   StateSet::Iterator sit = rResGen.StatesBegin();
01644   StateSet::Iterator sit_end = rResGen.StatesEnd();
01645   for(;sit!=sit_end;++sit) {
01646     const EventSet& pattern = feedback[*sit];
01647     TransSet::Iterator tit = rResGen.TransRelBegin(*sit);
01648     TransSet::Iterator tit_end = rResGen.TransRelEnd(*sit);
01649     while(tit!=tit_end) {
01650       if(pattern.Exists(tit->Ev)) { tit++; continue;};
01651       rResGen.ClrTransition(tit++);
01652     }
01653   }
01654   // cosmetic trim
01655   rResGen.Trim();
01656 
01657 #ifdef FAUDES_CODE
01658   // during development: test controllability and livenes  
01659   if(!IsControllable(rPlantGen,rCAlph,rResGen)) {
01660     throw Exception("OmegaConNB(..)", "ERROR: controllability test failed", 500);
01661   }
01662   if(!IsRelativelyOmegaClosed(rPlantGen,rResGen)) {
01663     throw Exception("OmegaConNB(..)", "ERROR: rel. top. closedness test failed", 500);
01664   }
01665 #endif
01666 
01667   // record name
01668   rResGen.Name(CollapsString("OmegaConNB(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"));
01669 }
01670 
01671 // OmegaConNB for Systems:
01672 // uses and maintains controllablity from plant 
01673 void OmegaConNB(
01674   const System& rPlantGen, 
01675   const Generator& rSpecGen, 
01676   Generator& rResGen) {
01677   // prepare result
01678   Generator* pResGen = &rResGen;
01679   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
01680     pResGen= rResGen.New();
01681   }
01682   // execute 
01683   OmegaConNB(rPlantGen, rPlantGen.ControllableEvents(),rSpecGen,*pResGen);
01684   // copy all attributes of input alphabet
01685   pResGen->EventAttributes(rPlantGen.Alphabet());
01686   // copy result
01687   if(pResGen != &rResGen) {
01688     pResGen->Move(rResGen);
01689     delete pResGen;
01690   }
01691 }
01692 
01693 
01694 // OmegaSupConNormNB(rPlantGen, rCAlph, rOAlph, rSpecGen, rResGen)
01695 void OmegaSupConNormNB(
01696   const Generator& rPlantGen, 
01697   const EventSet& rCAlph, 
01698   const EventSet& rOAlph, 
01699   const Generator& rSpecGen, 
01700   Generator& rResGen) 
01701 {
01702   // consitenct check
01703   ControlProblemConsistencyCheck(rPlantGen, rCAlph, rOAlph, rSpecGen);  
01704   // execute
01705   std::map< Idx , Idx> constates;
01706   std::map< Idx , EventSet> feedback;
01707   StateSet plantmarking;
01708   OmegaSupConNormNBUnchecked(rPlantGen, rCAlph, rOAlph, rSpecGen, plantmarking, constates, feedback, rResGen);
01709   // record name
01710   rResGen.Name(CollapsString("OmegaSupConNormNB(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"));
01711 }
01712 
01713 
01714 // OmegaSupConNormNB for Systems:
01715 // uses and maintains controllablity from plant 
01716 void OmegaSupConNormNB(
01717   const System& rPlantGen, 
01718   const Generator& rSpecGen, 
01719   Generator& rResGen) {
01720   // prepare result
01721   Generator* pResGen = &rResGen;
01722   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
01723     pResGen= rResGen.New();
01724   }
01725   // execute 
01726   OmegaSupConNormNB(rPlantGen, rPlantGen.ControllableEvents(),rPlantGen.ObservableEvents(),rSpecGen,*pResGen);
01727   // copy all attributes of input alphabet
01728   pResGen->EventAttributes(rPlantGen.Alphabet());
01729   // copy result
01730   if(pResGen != &rResGen) {
01731     pResGen->Move(rResGen);
01732     delete pResGen;
01733   }
01734 }
01735 
01736 // OmegaConNrmNB(rPlantGen, rCAlph, rOAlph, rSpecGen, rResGen)
01737 void OmegaConNormNB(
01738   const Generator& rPlantGen, 
01739   const EventSet& rCAlph, 
01740   const EventSet& rOAlph, 
01741   const Generator& rSpecGen, 
01742   Generator& rResGen) 
01743 {
01744 
01745   // consitency check
01746   ControlProblemConsistencyCheck(rPlantGen, rCAlph, rOAlph, rSpecGen);  
01747   // compute supremal closed-loop behaviour
01748   StateSet plantmarking;
01749   std::map< Idx , Idx> cxmap;
01750   std::map< Idx , EventSet> feedback;
01751   OmegaSupConNormNBUnchecked(rPlantGen, rCAlph, rOAlph, rSpecGen, plantmarking, cxmap, feedback, rResGen);
01752   // compute restrictive feedback
01753   OmegaControlledLiveness(rResGen, rCAlph, plantmarking, cxmap, feedback);
01754   // apply restrictive feedback
01755   StateSet::Iterator sit = rResGen.StatesBegin();
01756   StateSet::Iterator sit_end = rResGen.StatesEnd();
01757   for(;sit!=sit_end;++sit) {
01758     // Idx cx = cxmap[*sit]; etc ...
01759     const EventSet& pattern = feedback[*sit];
01760     TransSet::Iterator tit = rResGen.TransRelBegin(*sit);
01761     TransSet::Iterator tit_end = rResGen.TransRelEnd(*sit);
01762     while(tit!=tit_end) {
01763       if(pattern.Exists(tit->Ev)) { tit++; continue;};
01764       rResGen.ClrTransition(tit++);
01765     }
01766   }
01767   // trim (?)
01768   rResGen.OmegaTrim();
01769 //#ifdef FAUDES_CODE
01770   // during development: test controllability, normality and livenes  
01771   if(!IsControllable(rPlantGen,rCAlph,rResGen)) {
01772     throw Exception("OmegaConNormNB(..)", "ERROR: controllability test failed", 500);
01773   }
01774   if(!IsRelativelyOmegaClosed(rPlantGen,rResGen)) {
01775     throw Exception("OmegaConNormNB(..)", "ERROR: rel. top. closedness test failed", 500);
01776   }
01777   Generator prK=rResGen;
01778   MarkAllStates(prK);
01779   Generator prL=rPlantGen;
01780   prL.Trim();
01781   MarkAllStates(prL);
01782   if(!IsNormal(prL,rOAlph,prK)){
01783     throw Exception("OmegaConNormNB(..)", "ERROR: prefix normality test failed", 500);
01784   }
01785 //#endif
01786 
01787   // record name
01788   rResGen.Name(CollapsString("OmegaConNormNB(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"));
01789 }
01790 
01791 // OmegaConNormNB for Systems
01792 // uses and maintains controllablity from plant 
01793 void OmegaConNormNB(
01794   const System& rPlantGen, 
01795   const Generator& rSpecGen, 
01796   Generator& rResGen) {
01797   // prepare result
01798   Generator* pResGen = &rResGen;
01799   if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
01800     pResGen= rResGen.New();
01801   }
01802   // execute 
01803   OmegaConNormNB(rPlantGen, rPlantGen.ControllableEvents(),rPlantGen.ObservableEvents(), rSpecGen,*pResGen);
01804   // copy all attributes of input alphabet
01805   pResGen->EventAttributes(rPlantGen.Alphabet());
01806   // copy result
01807   if(pResGen != &rResGen) {
01808     pResGen->Move(rResGen);
01809     delete pResGen;
01810   }
01811 }
01812 
01813 
01814 
01815 } // name space 

libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen