hio_functions.cpp

Go to the documentation of this file.
00001 /** @file hio_functions.cpp Algorithms for hierarchical discrete event systems with inputs and outputs */
00002 
00003 /* Hierarchical IO Systems Plug-In for FAU Discrete Event Systems Library (libfaudes)
00004 
00005    Copyright (C) 2006  Sebastian Perk 
00006    Copyright (C) 2006  Thomas Moor 
00007    Copyright (C) 2006  Klaus Schmidt
00008 
00009 */
00010 
00011 // note: deterministic generators only 
00012 
00013 // todo: exceptions on invalid input data if FAUDES_CHECKED
00014 // todo: files eg: normal. cycles. hiotest. hiosynth.
00015 // todo: implement routines that check hio properties
00016 // todo: only use statenames if statenamesenabled (eg HioFreeInput)
00017 
00018 // todo: other todos below
00019 
00020 #include "hio_functions.h"
00021 #include "syn_include.h"
00022 
00023 
00024 namespace faudes {
00025 
00026 
00027 // This is Sebastian'y version of SupNorm with a special
00028 // marking of the result. It also uses a different order
00029 // of arguments
00030 
00031 //  SupNormSP(rL,rOAlph,rK,rResult)
00032 bool SupNormSP(
00033   Generator& rL,
00034   const EventSet& rOAlph,
00035   const Generator& rK, 
00036   Generator& rResult)
00037 {
00038   FD_DF("SupNorm(" << rK.Name() << "," << rL.Name() << "," << rOAlph.Name() << ")");
00039   
00040   NormalityConsistencyCheck(rL,rOAlph,rK);
00041   
00042   // prepare result
00043   rResult.Clear();
00044   
00045   //extract overall alphabet:
00046   EventSet allevents;
00047   allevents=rL.Alphabet();
00048   
00049   //extract alphabet of rK:
00050   EventSet Kevents=rK.Alphabet();
00051   
00052   // record name and marked states of rL
00053   std::string rLname=rL.Name();
00054   StateSet rLmarked=rL.MarkedStates();
00055   
00056   // involved operations from cfl_regular.h operate on the marked
00057   // languages -> turn generated languages into marked langs
00058   rL.InjectMarkedStates(rL.States());
00059   Generator prK=rK;
00060   prK.InjectMarkedStates(prK.States());
00061   rResult = prK;
00062   
00063   // calculate "L-K" (ToDo: use LanguageDifference):
00064   LanguageComplement(rResult);
00065   FD_DF("SupNorm: size of complement(K): "<<rResult.Size()<<",marked: "<<rResult.MarkedStatesSize());
00066   Generator tempgen;
00067   LanguageIntersection(rL, rResult, tempgen);
00068   rResult.Clear();
00069   FD_DF("SupNorm: sizeof L U complement(K)=L-K: "<<tempgen.Size());
00070   
00071   // calculate Pinv(P(L-K)):
00072   Project(tempgen,rOAlph,rResult);
00073   tempgen.Clear();
00074   FD_DF("SupNorm: sizeof p(L-K): "<< rResult.Size());
00075   InvProject(rResult,allevents);
00076   FD_DF("SupNorm: sizeof pinv(p(L-K)): "<<rResult.Size());
00077   
00078   //  FD_DF("SupNorm: sizeof pinv(p(L-K)): "<<rResult.Size());
00079 
00080   //calculate remaining set difference -> supnorm(K)
00081   LanguageComplement(rResult);
00082   LanguageIntersection(prK, rResult, tempgen);
00083   rResult=tempgen;
00084   tempgen.Clear();
00085   FD_DF("SupNorm: sizeof K - pinv(p(L-K)) (result): "<<rResult.Size());
00086   
00087   // language MARKED by rResult is the result -> remove blocking states, mark all remaining states.
00088   rResult.Trim();
00089   rResult.InjectMarkedStates(rResult.States());
00090   
00091   // restore original rL
00092   rL.Name(rLname);
00093   rL.InjectMarkedStates(rLmarked);
00094   
00095   return !( rResult.InitStatesEmpty() );
00096 }
00097 
00098 
00099 
00100 
00101 
00102 
00103 // CompleteSynth(rPlant,rCAlph,rSpec,rClosedLoop)
00104 bool CompleteSynth(
00105   const Generator& rPlant,
00106   const EventSet rCAlph, 
00107   const Generator& rSpec, 
00108   Generator& rClosedLoop) { 
00109   FD_DF("CompleteSynth(" << rPlant.Name() << "," << rSpec.Name()<< ")");
00110 
00111   // prepare result
00112   rClosedLoop.Clear();
00113   
00114   //check for trivial result
00115   if(rSpec.InitStatesEmpty()){
00116       FD_DF("CompleteSynth::empty language specification: empty closed loop.");
00117     rClosedLoop.Name("CompeleteSynth("+rPlant.Name()+", "+rSpec.Name()+")");
00118       return false; 
00119   }  
00120   
00121   // spec as candidate for closed loop
00122   Generator ClosedLoopCand=rSpec;
00123 
00124   // iterate supcon and dead end elimination
00125   while(true) {
00126     // try std synthesis
00127     FD_DF("CompleteSynth:: spec size " << ClosedLoopCand.Size());
00128     
00129     // try SupCon
00130     SupConClosed(rPlant, rCAlph, ClosedLoopCand, rClosedLoop);
00131     //std::cout<<std::endl<<"CompleteSynth:: current result after SupCon: tmp_ContLoop.gen";
00132     FD_DF("CompleteSynth: size of current result after SupCon: "<<rClosedLoop.Size());
00133     //std::cout<<" (Size: "<<rClosedLoop.Size()<<").";
00134     
00135     //check for empty result
00136     if(rClosedLoop.InitStatesEmpty()) {
00137       FD_DF("CompleteSynth:: failed: empty language result.");
00138       rClosedLoop.StateNamesEnabled(false);
00139       rClosedLoop.Name("CompeleteSynth("+rPlant.Name()+", "+rSpec.Name()+")");
00140       return false;
00141     }
00142       
00143     FD_DF("CompleteSynth:: candidate size " << rClosedLoop.Size());
00144     
00145     // find dead ends  and return success if no dead end found
00146     StateSet dead_ends=rClosedLoop.TerminalStates(rClosedLoop.AccessibleSet());
00147     if(dead_ends.Empty()) {
00148       rClosedLoop.StateNamesEnabled(false);
00149       FD_DF("CompleteSynth:: done");
00150       rClosedLoop.Name("CompeleteSynth("+rPlant.Name()+", "+rSpec.Name()+")");
00151       return true;
00152     }
00153     
00154     // report to console
00155     FD_DF("CompleteSynth:: eliminating following " << dead_ends.Size() << " dead ends");
00156     FD_DF(rClosedLoop.StateSetToString(dead_ends));
00157     
00158     // eliminate dead ends.
00159     rClosedLoop.DelStates(dead_ends);
00160     // becomes new candidate for SupCon
00161     ClosedLoopCand=rClosedLoop;
00162     
00163     //std::cout<<std::endl<<"CompleteSynth:: current result after Complete: tmp_CompleteLoop.gen";
00164     FD_DF("CompleteSynth:: size of result after removing dead ends: "<<rClosedLoop.Size());
00165     //std::cout<<" (Size: "<<rClosedLoop.Size()<<").";
00166 
00167     //check for empty result
00168     if(rClosedLoop.InitStatesEmpty()) {
00169       FD_DF("CompleteSynth:: failed: empty language result.");
00170       rClosedLoop.Name("CompeleteSynth("+rPlant.Name()+", "+rSpec.Name()+")");
00171       return false;
00172     }
00173     rClosedLoop.Clear();
00174   }
00175 }
00176 
00177 // NormalCompleteSynth(rPlant,rCAlph,rOAlph,rSpec,rClosedLoop)
00178 bool NormalCompleteSynth(
00179   Generator& rPlant, 
00180   const EventSet& rCAlph, 
00181   const EventSet& rOAlph,
00182   const Generator& rSpec,
00183   Generator& rClosedLoop) 
00184 { 
00185   FD_DF("NormalCompleteSynth(" << rPlant.Name() << "," << rSpec.Name()<< ")");
00186   
00187   // prepare result
00188   rClosedLoop.Clear();
00189   
00190   // spec as candidate for closed loop
00191   Generator Spec=rSpec;
00192   
00193   while(true) {
00194     
00195     // try CompleteSynth and check for empty result:
00196     if(!CompleteSynth(rPlant,rCAlph,Spec,rClosedLoop)) {
00197     FD_DF("NormalCompleteSynth:: failed: empty result after CompleteSynth().");
00198       std::cout<<std::endl<<"NormalCompleteSynth:: failed: empty result after CompleteSynth().";
00199     rClosedLoop.Name("NormalCompleteSynth(" + rPlant.Name() + "," + rSpec.Name()+ ")");
00200       return false;
00201     }
00202    
00203     // check for normality and return on success
00204     if(IsNormal(rPlant,rOAlph,rClosedLoop)) {
00205       FD_DF("NormalCompleteSynth:: candidate supervisor is normal. success.");
00206     rClosedLoop.Name("NormalCompleteSynth(" + rPlant.Name() + "," + rSpec.Name()+ ")");
00207       return true;
00208     }
00209     
00210     //  supremal normal sublanguage of rClosedLoop as new spec
00211     // return false on empty result
00212     FD_DF("NormalCompleteSynth:: candidate supervisor not normal. running SupNorm");
00213     if(!SupNormSP(rPlant, rOAlph, rClosedLoop, Spec)) {
00214       FD_DF("NormalCompleteSynth:: failed: empty result after SupNorm().");
00215       std::cout<<std::endl<<"NormalCompleteSynth:: failed: empty result after SupNorm().";
00216     rClosedLoop.Clear();
00217     rClosedLoop.Name("NormalCompleteSynth(" + rPlant.Name() + "," + rSpec.Name()+ ")");
00218       return false;
00219     }  
00220     
00221     Spec.StateNamesEnabled(false);
00222     //std::cout<<std::endl<<"NormalCompleteSynth:: current result after SupNorm():";
00223     //std::cout<<" Size: "<<Spec.Size()<<".";
00224     FD_DF("NormalCompleteSynth:: size of result after SupNorm(): "<<Spec.Size());
00225   }
00226 }
00227 
00228 
00229 // NormalCompleteSynthNB(rPlant,rCAlph,rOAlph,rSpec,rClosedLoop)
00230 bool NormalCompleteSynthNB(
00231   Generator& rPlant, 
00232   const EventSet& rCAlph, 
00233   const EventSet& rOAlph,
00234   const Generator& rSpec,
00235   Generator& rClosedLoop) 
00236 { 
00237   FD_DF("NormalCompleteSynth(" << rPlant.Name() << "," << rSpec.Name()<< ")");
00238   
00239   // prepare result
00240   rClosedLoop.Clear();
00241 
00242   // spec as candidate for closed loop
00243   Generator Spec=rSpec;
00244   while(true) {
00245     
00246     // try NormalCompleteSynth and check for empty result:
00247     if(!NormalCompleteSynth(rPlant,rCAlph,rOAlph,Spec,rClosedLoop)) {
00248       FD_DF("NormalCompleteSynthNB:: failed: empty result after NormalCompleteSynth().");
00249       std::cout<<std::endl<<"NormalCompleteSynthNB:: failed: empty result after NormalCompleteSynth().";
00250     rClosedLoop.Name("NormalCompleteSynthNB(" + rPlant.Name() + "," + rSpec.Name()+ ")");
00251       return false;
00252     }
00253     
00254     // check for coaccessibility and return on success
00255     if(rClosedLoop.IsTrim()) {
00256       FD_DF("NormalCompleteSynthNB:: candidate supervisor is trim. success.");
00257     rClosedLoop.Name("NormalCompleteSynthNB(" + rPlant.Name() + "," + rSpec.Name()+ ")");
00258       return true;
00259     }
00260     
00261     // supremal nonblocking sublanguage of rClosedLoop as new Spec
00262     // return false on empty result
00263     FD_DF("NormalCompleteSynthNB:: candidate supervisor not Trim. running Trim()");
00264     Spec=rClosedLoop; 
00265     if(!Spec.Trim()) {
00266       FD_DF("NormalCompleteSynthNB:: failed: empty result after Trim().");
00267       std::cout<<std::endl<<"NormalCompleteSynthNB:: failed: empty result after Trim().";
00268       rClosedLoop.Clear(); 
00269       rClosedLoop.Name("NormalCompleteSynthNB(" + rPlant.Name() + "," + rSpec.Name()+ ")");
00270       return false;
00271       }
00272     //std::cout<<std::endl<<"NormalCompleteSynthNB:: current result after Trim():";
00273     //std::cout<<" Size: "<<Spec.Size()<<".";
00274     FD_DF("NormalCompleteSynthNB:: size of result after Trim():"<<Spec.Size());
00275     }
00276 }
00277 
00278 
00279 // HioSortCL(const EventSet& rYc,rUc,rYp,rUP,rYe,rUe)
00280 Generator HioSortCL(
00281   const EventSet& rYc, 
00282   const EventSet& rUc,
00283   const EventSet& rYp, 
00284   const EventSet& rUp,
00285   const EventSet& rYe,
00286   const EventSet& rUe)
00287 {
00288     FD_DF("HioSortCL(...)");
00289 
00290   #ifdef FAUDES_CHECKED
00291   // check for nonempty sets
00292   if (rYc.Empty()||rUc.Empty()||rYp.Empty()||rUp.Empty()||rYe.Empty()||rUe.Empty()){
00293       std::stringstream errstr;
00294       errstr << "At least one empty parameter.";
00295       throw Exception("HioSortCL", errstr.str(), 0);
00296   }
00297   #endif
00298   
00299   // create resulting alphabet while checking for disjoint sets
00300   EventSet alphabet,errevents;
00301   // initialize with rYc
00302   alphabet.SetUnion(rYc);
00303   // insert remaining events one by one and check if new
00304     EventSet::Iterator evit;
00305   // rUc
00306     for (evit = rUc.Begin(); evit != rUc.End(); ++evit) {
00307     if(!(alphabet.Insert(*evit))) errevents.Insert(*evit);
00308     }
00309   // rYp
00310     for (evit = rYp.Begin(); evit != rYp.End(); ++evit) {
00311     if(!(alphabet.Insert(*evit))) errevents.Insert(*evit);
00312     }
00313   // rUp
00314     for (evit = rUp.Begin(); evit != rUp.End(); ++evit) {
00315     if(!(alphabet.Insert(*evit))) errevents.Insert(*evit);
00316     }
00317   // rYe
00318     for (evit = rYe.Begin(); evit != rYe.End(); ++evit) {
00319     if(!(alphabet.Insert(*evit))) errevents.Insert(*evit);
00320     }
00321   // rUe
00322     for (evit = rUe.Begin(); evit != rUe.End(); ++evit) {
00323     if(!(alphabet.Insert(*evit))) errevents.Insert(*evit);
00324     }
00325   
00326   #ifdef FAUDES_CHECKED
00327   // throw exception on non disjoint alphabets
00328   if (!errevents.Empty()){
00329     std::stringstream errstr;
00330     errstr << "Non-disjoint parameters; ambiguous events:\n" <<errevents.ToString();
00331     throw Exception("HioSortCL", errstr.str(), 0);
00332   }
00333   #endif
00334   
00335   // create result
00336     Generator ResGen;
00337   
00338     ResGen.Name("HioSortCL("+rYc.Name()+","+rUc.Name()+","+rYp.Name()+","+rUp.Name()+","+rYe.Name()+","+rUe.Name()+")");
00339   
00340     ResGen.InjectAlphabet(alphabet);
00341   alphabet.Clear();
00342   
00343     // 5 marked states with initial state 1:
00344     ResGen.InsInitState("Yp_or_Ye");
00345     ResGen.SetMarkedState("Yp_or_Ye");
00346     ResGen.InsMarkedState("Yc_or_Up");
00347     ResGen.InsMarkedState("Uc");
00348     ResGen.InsMarkedState("Up");
00349     ResGen.InsMarkedState("Ue");
00350     
00351     // set transitions according to desired ioSorting structure:
00352     // all Yp-events lead from state 1 to state 2:
00353     for (evit = rYp.Begin(); evit != rYp.End(); ++evit) {
00354       ResGen.SetTransition("Yp_or_Ye",rYp.SymbolicName(*evit),"Yc_or_Up");
00355     }
00356     // all Yc-events lead from state 2 to state 3:
00357     for (evit = rYc.Begin(); evit != rYc.End(); ++evit) {
00358       ResGen.SetTransition("Yc_or_Up",rYc.SymbolicName(*evit),"Uc");
00359     }
00360     // all Uc-events lead from state 3 to state 4:
00361     for (evit = rUc.Begin(); evit != rUc.End(); ++evit) {
00362       ResGen.SetTransition("Uc",rUc.SymbolicName(*evit),"Up");
00363     }
00364     // all Up-events lead from state 2 and 4 to state 1:
00365     for (evit = rUp.Begin(); evit != rUp.End(); ++evit) {
00366       ResGen.SetTransition("Yc_or_Up",rUp.SymbolicName(*evit),"Yp_or_Ye");
00367       ResGen.SetTransition("Up",rUp.SymbolicName(*evit),"Yp_or_Ye");
00368     }
00369     // all Ye-events lead from state 1 to state 5:
00370     for (evit = rYe.Begin(); evit != rYe.End(); ++evit) {
00371       ResGen.SetTransition("Yp_or_Ye",rYe.SymbolicName(*evit),"Ue");
00372     }
00373     // all Ue-events lead from state 5 to state 1:
00374     for (evit = rUe.Begin(); evit != rUe.End(); ++evit) {
00375       ResGen.SetTransition("Ue",rUe.SymbolicName(*evit),"Yp_or_Ye");
00376     }
00377     return ResGen;
00378 } 
00379 
00380 // HioFreeInput(rGen,rInput,rOutput,rResGen,rErrState1,rErrState2,rErrState1Idx,rErrState2Idx) 
00381 void HioFreeInput(
00382   const Generator& rGen, 
00383   const EventSet& rInput, 
00384   const EventSet& rOutput,
00385   Generator& rResGen,
00386   const std::string& rErrState1, 
00387   const std::string& rErrState2,
00388   Idx& rErrState1Idx,
00389   Idx& rErrState2Idx) {
00390   FD_DF("HioFreeInput( [generator] " << rGen.Name() << ")");
00391 
00392   Generator* pResGen = &rResGen;
00393   if(&rResGen== &rGen) {
00394     pResGen= rResGen.New();
00395   }  
00396  
00397   #ifdef FAUDES_CHECKED
00398   // exception on empty Input-alphabet or non-disjoint Input and Output
00399   if(rInput.Empty() || !((rInput*rOutput).Empty())) {
00400       std::stringstream errstr;
00401       errstr << "Empty Input-alphabet or non-disjoint Input and Output.\n";
00402       errstr << "Input: "<< rInput.ToString()<<"\n";
00403       errstr << "Output: "<< rOutput.ToString()<<"\n";
00404       errstr << "Input*Output: "<< (rInput*rOutput).ToString()<<"\n";
00405       throw Exception("HioFreeInput", errstr.str(), 0); 
00406     }
00407   #endif
00408   
00409   // check for enabled state names:
00410   bool StateNamesEnabled = pResGen->StateNamesEnabled();
00411   // Warning on inconsistency with error-state names
00412   if(!StateNamesEnabled && (!rErrState1.empty()||!rErrState2.empty())) {
00413     FD_WARN("HioFreeInput: state names disabled in rResGen: error state names ignored.");
00414   }
00415   
00416   // prepare result, preserve StateNamesEnabled of rGen
00417   *pResGen=rGen;
00418   pResGen->StateNamesEnabled(StateNamesEnabled);
00419   pResGen->Name("HioFreeInput("+rGen.Name()+")");
00420   
00421   //create first error state, where inserted Input-events shall lead to:
00422   std::string errstate1;
00423   if(StateNamesEnabled) {
00424     errstate1=pResGen->UniqueStateName(rErrState1); 
00425     rErrState1Idx=pResGen->InsMarkedState(errstate1);
00426   }
00427   else {
00428     rErrState1Idx=pResGen->InsMarkedState();
00429   }
00430 
00431   //find Input-states
00432   StateSet::Iterator sit=pResGen->StatesBegin();
00433   EventSet::Iterator evit;
00434   bool InputInserted = false;
00435   for(;sit!=pResGen->StatesEnd();sit++){
00436     EventSet disabledInput;
00437     disabledInput = rInput - pResGen->ActiveEventSet(*sit);
00438     //if at least one Input-event is enabled AND at least one Input-event is disabled:
00439     //insert missing Input-transitions to error state
00440     if( (disabledInput!=rInput) && !disabledInput.Empty()) {
00441       FD_DF("HioFreeInput: " << *sit << " disabledInput: " << disabledInput.ToString()); 
00442       InputInserted = true;
00443       for (evit = disabledInput.Begin(); evit != disabledInput.End(); ++evit) {
00444         pResGen->SetTransition(*sit,*evit,rErrState1Idx);
00445       }       
00446     }
00447   }//for-loop through states
00448 
00449   //insert err_Input-state and connect both err-states with Input-Output-loop in case missing Input-events were inserted:
00450   if(InputInserted) {
00451     if(StateNamesEnabled) {
00452      FD_DF("HioFreeInput(...): inserted error state 1: " << errstate1 << " with Idx: " << rErrState1Idx);
00453     }
00454     else {
00455      FD_DF("HioFreeInput(...): inserted error state 1 with Idx: " << rErrState1Idx);
00456     }
00457     if(!rOutput.Empty()) { // this 'if' and the 'if' before are seperated because of the 'else' below !
00458        //create second error state
00459        std::string errstate2;
00460        if(StateNamesEnabled) {
00461          errstate2=pResGen->UniqueStateName(rErrState2);
00462          rErrState2Idx=pResGen->InsMarkedState(errstate2);
00463          FD_DF("HioFreeInput(...): inserted error state 2: " << errstate2);
00464       }
00465         else {
00466           rErrState2Idx=pResGen->InsMarkedState();
00467           FD_DF("HioFreeInput(...): inserted error state 2 with Idx: " << rErrState2Idx);
00468       }
00469          
00470          //insert Input-events:
00471          for (evit = rInput.Begin(); evit != rInput.End(); ++evit) {
00472             pResGen->SetTransition(rErrState2Idx,*evit,rErrState1Idx);
00473          }
00474          //insert output-events:
00475          for (evit = rOutput.Begin(); evit != rOutput.End(); ++evit) {
00476            pResGen->SetTransition(rErrState1Idx,*evit,rErrState2Idx);
00477          }
00478     }
00479   }
00480    //else delete err_Output-state
00481    else {
00482      pResGen->DelState(rErrState1Idx);
00483     }
00484    // if necessary, move pResGen to rResGen
00485   if(pResGen != &rResGen) {
00486     pResGen->Move(rResGen);
00487     delete pResGen;
00488   }
00489 }
00490 
00491 // HioFreeInput(rGen,rInput,rOutput,rResGen,rErrState1,rErrState2) 
00492 void HioFreeInput(
00493   const Generator& rGen, 
00494   const EventSet& rInput, 
00495   const EventSet& rOutput,
00496   Generator& rResGen,
00497   const std::string& rErrState1, 
00498   const std::string& rErrState2) {
00499   Idx errstate1,errstate2;
00500   HioFreeInput(rGen,rInput,rOutput,rResGen,rErrState1,rErrState2,errstate1,errstate2);
00501 }
00502 
00503 // HioFreeInput(rGen,rInput,rOutput,rResGen) 
00504 void HioFreeInput(
00505   const Generator& rGen, 
00506   const EventSet& rInput, 
00507   const EventSet& rOutput,
00508   Generator& rResGen)
00509 {
00510   //Call HioFreeInput with empty names for error states
00511   std::string ErrState1,ErrState2;
00512   HioFreeInput(rGen,rInput,rOutput,rResGen,ErrState1,ErrState2);
00513 }
00514 
00515 // HioFreeInput(HioPlant,HioPlant) 
00516 void HioFreeInput(
00517   const HioPlant& rPlant,
00518   HioPlant& rResPlant) 
00519 {
00520 
00521   FD_DF("HioFreeInput( [plant] " << rPlant.Name() << ")");
00522 
00523   // Call HioFreeInput with certain names for error state,
00524   // set Err-flag
00525   Idx errstateUp,errstateUe,errstate2;
00526   std::string ErrState1,ErrState2;
00527   
00528   EventSet NoOutput,uP,uE,yP,yE;  
00529   uP=rPlant.UpEvents();
00530   uE=rPlant.UeEvents();
00531   yP=rPlant.YpEvents();
00532   yE=rPlant.YeEvents();
00533   
00534   ErrState1="UpError";
00535   HioFreeInput(rPlant,uP,NoOutput,rResPlant,ErrState1,ErrState2,errstateUp,errstate2);
00536   
00537   ErrState1="UeError";
00538   HioFreeInput(rResPlant,uE,NoOutput,rResPlant,ErrState1,ErrState2,errstateUe,errstate2);
00539   
00540   // set HioStateFlag Err
00541   if(rResPlant.ExistsState(errstateUp)) rResPlant.SetErr(errstateUp);
00542   if(rResPlant.ExistsState(errstateUe)) rResPlant.SetErr(errstateUe);
00543   
00544   // restore event attributes
00545   rResPlant.SetYp(yP);
00546   rResPlant.SetUp(uP);
00547   rResPlant.SetYe(yE);
00548   rResPlant.SetUe(uE);
00549   
00550 }
00551 
00552 // HioFreeInput(HioController,HioController)   
00553 void HioFreeInput(
00554   const HioController& rController,
00555   HioController& rResController)  
00556 {
00557   FD_DF("HioFreeInput( [controller] " << rController.Name() << ")");
00558 
00559   HioController* pResController = &rResController;
00560   if(&rResController== &rController) {
00561     pResController=rResController.New();
00562   }  
00563   
00564   // check for enabled state names:
00565   bool StateNamesEnabled = pResController->StateNamesEnabled();
00566   
00567   // prepare error state names
00568   std::string errStr1, errStr2;
00569   
00570   // prepare error state indeces
00571   Idx errIdx1, errIdx2;
00572   
00573   // prepare result, preserve StateNamesEnabled of rGen
00574   pResController->Assign(rController);
00575   //*pResController=rController; // didn't work (should work ... check!!)
00576   //pResController=&rController; // didn't work (cannot work anyway)
00577   pResController->StateNamesEnabled(StateNamesEnabled);
00578   pResController->Name("HioFreeInput("+rController.Name()+")");
00579   
00580   // figure input alphabets
00581   EventSet UcEvents = rController.UcEvents();
00582   EventSet YpEvents = rController.YpEvents();
00583   EventSet YcEvents = rController.YcEvents();
00584   EventSet UpEvents = rController.UpEvents();
00585   
00586   //create first error state, where inserted Uc- or Yp-events shall lead to:
00587   if(StateNamesEnabled) {
00588   errStr1=pResController->UniqueStateName("UcYpError"); 
00589   errIdx1=pResController->InsMarkedState(errStr1);
00590   }
00591   else {
00592   errIdx1=pResController->InsMarkedState();
00593   }
00594   // set HioStateFlag Err
00595   pResController->SetErr(errIdx1);
00596   
00597   // set state attribute QUp
00598   pResController->SetQUp(errIdx1);
00599   
00600   //find Input-states
00601   StateSet::Iterator sit=pResController->StatesBegin();
00602   EventSet::Iterator evit;
00603   bool InputInserted = false;
00604   for(;sit!=pResController->StatesEnd();sit++){
00605     EventSet disabledInput, active;
00606   active = pResController->ActiveEventSet(*sit);
00607   // first treat Uc-events
00608     disabledInput = UcEvents - active;
00609     //if at least one Input-event is enabled AND at least one Input-event is disabled:
00610     //insert missing Input-transitions to error state
00611     if( (disabledInput!=UcEvents) && !disabledInput.Empty()) {
00612       // FD_DF("HioFreeInput: " << *sit << " disabledInput: " << disabledInput.ToString());
00613       InputInserted = true;
00614       for (evit = disabledInput.Begin(); evit != disabledInput.End(); ++evit) {
00615         pResController->SetTransition(*sit,*evit,errIdx1);
00616       }       
00617     }
00618   // then treat Yp-events
00619   disabledInput = YpEvents - active;
00620     //if at least one Input-event is enabled AND at least one Input-event is disabled:
00621     //insert missing Input-transitions to error state
00622     if( (disabledInput!=YpEvents) && !disabledInput.Empty()) {
00623       // FD_DF("HioFreeInput: " << *sit << " disabledInput: " << disabledInput.ToString());
00624       InputInserted = true;
00625       for (evit = disabledInput.Begin(); evit != disabledInput.End(); ++evit) {
00626         pResController->SetTransition(*sit,*evit,errIdx1);
00627       }       
00628     }
00629   }//for-loop through states
00630 
00631   //insert err_Input-state and connect both err-states with Input-Output-loop in case missing Input-events were inserted:
00632   if(InputInserted) {
00633      //create second error state
00634    std::string errstate2;
00635    if(StateNamesEnabled) {
00636      FD_DF("HioFreeInput(...): inserted error state 1: " << errStr1);
00637      errStr2=pResController->UniqueStateName("ErrorQYp"); 
00638      errIdx2=pResController->InsMarkedState(errStr2);
00639      FD_DF("HioFreeInput(...): inserted error state 2: " << errStr2);
00640     }
00641    else {
00642      FD_DF("HioFreeInput(...): inserted error state 1 with Idx: " << errIdx1);
00643      errIdx2=pResController->InsMarkedState();
00644      FD_DF("HioFreeInput(...): inserted error state 2 with Idx: " << errIdx2);
00645     }
00646    
00647    // set HioStateFlag Err
00648    pResController->SetErr(errIdx2);
00649    // set HioStateFlag QYp
00650    pResController->SetQYp(errIdx2);
00651    
00652      //insert Up-events:
00653      for (evit = UpEvents.Begin(); evit != UpEvents.End(); ++evit) {
00654      pResController->SetTransition(errIdx1,*evit,errIdx2);
00655     }
00656    //insert Yp-events:
00657      for (evit = YpEvents.Begin(); evit != YpEvents.End(); ++evit) {
00658      pResController->SetTransition(errIdx2,*evit,errIdx1);
00659     }
00660   }
00661   
00662    //else delete error-state 1
00663    else {
00664      pResController->DelState(errIdx1);
00665     }
00666 
00667    // if necessary, move pResGen to rResGen
00668   if(pResController != &rResController) {
00669     pResController->Move(rResController);
00670     delete pResController;
00671   } 
00672    // restore event attributes
00673    rResController.SetYc(YcEvents);
00674    rResController.SetUc(UcEvents);
00675    rResController.SetYp(YpEvents);
00676    rResController.SetUp(UpEvents);
00677 }
00678   
00679 // HioFreeInput(HioEnvironment,HioEnvironment)  
00680 void HioFreeInput(
00681   const HioEnvironment& rEnvironment,
00682   HioEnvironment& rResEnvironment) 
00683 {
00684   FD_DF("HioFreeInput( [environment] " << rEnvironment.Name() << ")");
00685 
00686   HioEnvironment* pResEnvironment = &rResEnvironment;
00687   if(&rResEnvironment== &rEnvironment) {
00688     pResEnvironment=rResEnvironment.New();
00689   }  
00690   
00691   // check for enabled state names:
00692   bool StateNamesEnabled = pResEnvironment->StateNamesEnabled();
00693   
00694   // prepare error state names
00695   std::string errStr1, errStr2;
00696   
00697   // prepare error state indeces
00698   Idx errIdx1, errIdx2;
00699   
00700   // prepare result, preserve StateNamesEnabled of rGen
00701   pResEnvironment->Assign(rEnvironment);
00702   //*pResEnvironment=rEnvironment; // didn't work
00703   //pResEnvironment=&rEnvironment; // didn't work
00704   pResEnvironment->StateNamesEnabled(StateNamesEnabled);
00705   pResEnvironment->Name("HioFreeInput("+rEnvironment.Name()+")");
00706   
00707   // figure alphabets
00708   EventSet UlEvents = rEnvironment.UlEvents();
00709   EventSet YeEvents = rEnvironment.YeEvents();
00710   EventSet YlEvents = rEnvironment.YlEvents();
00711   EventSet UeEvents = rEnvironment.UeEvents();
00712   
00713   //create first error state, where inserted Uc- or Yp-events shall lead to:
00714   if(StateNamesEnabled) {
00715   errStr1=pResEnvironment->UniqueStateName("UlYeError");  
00716   errIdx1=pResEnvironment->InsMarkedState(errStr1);
00717   }
00718   else {
00719   errIdx1=pResEnvironment->InsMarkedState();
00720   }
00721   
00722   // set HioStateFlag Err
00723   pResEnvironment->SetErr(errIdx1);
00724   // set HioStateFlag QUe
00725   pResEnvironment->SetQUe(errIdx1);
00726   
00727   //find Input-states
00728   StateSet::Iterator sit=pResEnvironment->StatesBegin();
00729   EventSet::Iterator evit;
00730   bool InputInserted = false;
00731   for(;sit!=pResEnvironment->StatesEnd();sit++){
00732     EventSet disabledInput, active;
00733   active = pResEnvironment->ActiveEventSet(*sit);
00734   // first treat Uc-events
00735     disabledInput = UlEvents - active;
00736     //if at least one Input-event is enabled AND at least one Input-event is disabled:
00737     //insert missing Input-transitions to error state
00738     if( (disabledInput!=UlEvents) && !disabledInput.Empty()) {
00739       // FD_DF("HioFreeInput: " << *sit << " disabledInput: " << disabledInput.ToString());
00740       InputInserted = true;
00741       for (evit = disabledInput.Begin(); evit != disabledInput.End(); ++evit) {
00742         pResEnvironment->SetTransition(*sit,*evit,errIdx1);
00743       }       
00744     }
00745   // then treat Yp-events
00746   disabledInput = YeEvents - active;
00747     //if at least one Input-event is enabled AND at least one Input-event is disabled:
00748     //insert missing Input-transitions to error state
00749     if( (disabledInput!=YeEvents) && !disabledInput.Empty()) {
00750       // FD_DF("HioFreeInput: " << *sit << " disabledInput: " << disabledInput.ToString());
00751       InputInserted = true;
00752       for (evit = disabledInput.Begin(); evit != disabledInput.End(); ++evit) {
00753         pResEnvironment->SetTransition(*sit,*evit,errIdx1);
00754       }       
00755     }
00756   }//for-loop through states
00757 
00758   //insert err_Input-state and connect both err-states with Input-Output-loop in case missing Input-events were inserted:
00759   if(InputInserted) {
00760      //create second error state
00761    std::string errstate2;
00762    if(StateNamesEnabled) {
00763      FD_DF("HioFreeInput(...): inserted error state 1: " << errStr1);
00764      errStr2=pResEnvironment->UniqueStateName("ErrorQYe");  
00765      errIdx2=pResEnvironment->InsMarkedState(errStr2);
00766      FD_DF("HioFreeInput(...): inserted error state 2: " << errStr2);
00767     }
00768    else {
00769      FD_DF("HioFreeInput(...): inserted error state 1 with Idx: " << errIdx1);
00770      errIdx2=pResEnvironment->InsMarkedState();
00771      FD_DF("HioFreeInput(...): inserted error state 2 with Idx: " << errIdx2);
00772     }
00773 
00774    // set HioStateFlag Err
00775    pResEnvironment->SetErr(errIdx2);
00776    // set state attribute QYe
00777    pResEnvironment->SetQYe(errIdx2);
00778    
00779      //insert Ue-events:
00780      for (evit = UeEvents.Begin(); evit != UeEvents.End(); ++evit) {
00781      pResEnvironment->SetTransition(errIdx1,*evit,errIdx2);
00782     }
00783    //insert Ye-events:
00784      for (evit = YeEvents.Begin(); evit != YeEvents.End(); ++evit) {
00785      pResEnvironment->SetTransition(errIdx2,*evit,errIdx1);
00786     }
00787   }
00788   
00789    //else delete error-state 1
00790    else {
00791      pResEnvironment->DelState(errIdx1);
00792     }
00793    // if necessary, move pResGen to rResGen
00794   if(pResEnvironment != &rResEnvironment) {
00795     pResEnvironment->Move(rResEnvironment);
00796     delete pResEnvironment;
00797   }
00798      // restore event attributes
00799    rResEnvironment.SetYl(YlEvents);
00800    rResEnvironment.SetUl(UlEvents);
00801    rResEnvironment.SetYe(YeEvents);
00802    rResEnvironment.SetUe(UeEvents);
00803 }
00804 
00805 // HioFreeInput(HioConstraint,HioConstraint)   
00806 void HioFreeInput(
00807   const HioConstraint& rConstraint,
00808   HioConstraint& rResConstraint) 
00809 {
00810   // Call HioFreeInput with certain names for error states,
00811   // set Err-flags
00812   Idx errstate1,errstate2;
00813   std::string ErrState1="Y-Error";
00814   std::string ErrState2="ErrorQY";
00815   EventSet y,u;
00816   y=rConstraint.YEvents();
00817   u=rConstraint.UEvents();
00818   HioFreeInput(rConstraint,y,u,rResConstraint,ErrState1,ErrState2,errstate1,errstate2);
00819   // set HioStateFlag Err
00820   rResConstraint.SetErr(errstate1);
00821   rResConstraint.SetErr(errstate2);
00822   // restore event attributes
00823   rResConstraint.SetY(y);
00824   rResConstraint.SetU(u);
00825 }
00826 
00827 // HioFreeInput(HioPlant) 
00828 void HioFreeInput(HioPlant& rPlant) {
00829   FD_DF("HioFreeInput( [single arg plant] " << rPlant.Name() << ")");
00830   HioFreeInput(rPlant,rPlant);
00831 }
00832 
00833 // HioFreeInput(HioController) 
00834 void HioFreeInput(HioController& rController) {
00835   HioFreeInput(rController,rController);
00836 }
00837 
00838 // HioFreeInput(HioEnvironment) 
00839 void HioFreeInput(HioEnvironment& rEnvironment) {
00840   HioFreeInput(rEnvironment,rEnvironment);
00841 }
00842 
00843 // HioFreeInput(HioConstraint) 
00844 void HioFreeInput(HioConstraint& rConstraint) {
00845   HioFreeInput(rConstraint,rConstraint);
00846 }
00847 
00848 
00849 
00850 //**********************************************************
00851 //******************** Completeness ************************
00852 //**********************************************************
00853 
00854 
00855 
00856 //**********************************************************
00857 //******************** I/O-shuffle ************************
00858 //**********************************************************
00859 
00860 //******************** current version: marked parameters + marking of alternation ************************
00861 
00862 // MarkHioShuffle(rGen1,rGen2,rMapOrigToResult,rShuffle)
00863 void MarkHioShuffle(const Generator& rGen1,const Generator& rGen2,
00864   const std::map< std::pair<Idx,Idx>, Idx >& rMapOrigToResult,
00865   Generator& rShuffle) {
00866   
00867   // invert mapOrigToResult (possible, as map is expected to be from parallel composition and thus must be bijective)
00868   std::map< Idx, std::pair<Idx,Idx> > mapResultToOrig;
00869   std::map< std::pair<Idx,Idx>, Idx >::const_iterator iter; 
00870     for( iter = rMapOrigToResult.begin(); iter != rMapOrigToResult.end(); ++iter ) {
00871       mapResultToOrig.insert(std::make_pair( iter->second, iter->first ));
00872     }
00873   
00874   // (I) duplicate all non-marked states, whose corresponding state in rGen1 or rGen2 is marked.
00875   StateSet nonmarked=rShuffle.States()-rShuffle.MarkedStates();
00876   StateSet::Iterator sit;
00877   std::map< Idx, Idx > rGen1Clones,rGen2Clones;
00878   for(sit = nonmarked.Begin(); sit != nonmarked.End(); sit ++) {
00879     // marked in rGen1?
00880     if(rGen1.ExistsMarkedState(mapResultToOrig[*sit].first)) {
00881       rGen1Clones[*sit]=rShuffle.InsMarkedState();
00882     }
00883     // marked in rGen2?
00884     if(rGen2.ExistsMarkedState(mapResultToOrig[*sit].first)) {
00885       rGen2Clones[*sit]=rShuffle.InsMarkedState();
00886     }
00887   }
00888   
00889   // (II) MOVE HEAD OF rGen1-transitions whose X2 has a rGen1-clone, and head of rGen2-transitions whose
00890   //        X2 has a rGen2-clone
00891   TransSet TransToClear, TransToSet;
00892     TransSet::Iterator tit=rShuffle.TransRelBegin();
00893   TransSet::Iterator tit_end=rShuffle.TransRelEnd();
00894   std::map<Idx,Idx>::iterator cloneit;
00895   bool x1hasGen1Clone,x1hasGen2Clone, x2hasClone;
00896   for(;tit!=tit_end;tit++) {
00897     
00898     x1hasGen1Clone=false;
00899     x1hasGen2Clone=false;
00900     x2hasClone=false;
00901   
00902     //##################################################
00903     // CASE (I) - X2 has clone: move head of transition, also duplicate transition if X1 has clone
00904     //##################################################
00905     
00906     // preliminarily check if X1 has clone
00907     cloneit=rGen1Clones.find(tit->X1);
00908     if(cloneit!=rGen1Clones.end()) x1hasGen1Clone=true;
00909     cloneit=rGen2Clones.find(tit->X1);
00910     if(cloneit!=rGen2Clones.end()) x1hasGen2Clone=true;
00911     
00912     
00913     // distinguish rGen1-events and rGen2-events
00914     if(rGen1.Alphabet().Exists(tit->Ev)) {
00915       // exists rGen1-clone?
00916       cloneit=rGen1Clones.find(tit->X2);
00917       if(cloneit!=rGen1Clones.end()) {
00918         x2hasClone=true;
00919         // move head to clone: delete original trans, insert moved trans
00920         TransToClear.Insert(*tit);
00921         TransToSet.Insert(tit->X1,tit->Ev,rGen1Clones[tit->X2]);
00922         // if X1 has a clone make copy starting from clone of X1
00923         if(x1hasGen1Clone) {
00924             TransToSet.Insert(rGen1Clones[tit->X1],tit->Ev,rGen1Clones[tit->X2]);
00925           }
00926         if(x1hasGen2Clone) {
00927             TransToSet.Insert(rGen2Clones[tit->X1],tit->Ev,rGen1Clones[tit->X2]);
00928           }
00929       }
00930     }
00931     
00932     //  else, tit is rGen2-transition
00933     else {
00934       // exists rGen2-clone?
00935       cloneit=rGen2Clones.find(tit->X2);
00936       if(cloneit!=rGen2Clones.end()) {
00937         x2hasClone=true;
00938         // move head to clone: delete original trans, insert moved trans
00939         TransToClear.Insert(*tit);
00940         TransToSet.Insert(tit->X1,tit->Ev,cloneit->second);
00941         // if X1 has a clone make copy starting from clone of X1
00942         if(x1hasGen1Clone) {
00943             TransToSet.Insert(rGen1Clones[tit->X1],tit->Ev,rGen2Clones[tit->X2]);
00944           }
00945         if(x1hasGen2Clone) {
00946             TransToSet.Insert(rGen2Clones[tit->X1],tit->Ev,rGen2Clones[tit->X2]);
00947           }
00948       }
00949     }
00950     
00951     //###################################################
00952     // CASE (II) - (only) X1 has clone: duplicate transition (see Case I for case also X2 has clone)
00953     //###################################################
00954     
00955     if( (x1hasGen1Clone||x1hasGen2Clone) && !x2hasClone ) {
00956       if(x1hasGen1Clone) TransToSet.Insert(rGen1Clones[tit->X1],tit->Ev,tit->X2);
00957       if(x1hasGen2Clone) TransToSet.Insert(rGen2Clones[tit->X1],tit->Ev,tit->X2);
00958     }
00959   }
00960   
00961   // clear invalid transitions
00962   tit=TransToClear.Begin();
00963   tit_end=TransToClear.End();
00964   for(;tit!=tit_end;tit++) rShuffle.ClrTransition(*tit);
00965   
00966   // set updated transitions
00967   tit=TransToSet.Begin();
00968   tit_end=TransToSet.End();
00969   for(;tit!=tit_end;tit++) rShuffle.SetTransition(*tit);
00970   
00971   // cosmetics
00972   rShuffle.Accessible();
00973   return;
00974 }
00975 
00976 // MarkAlternationAB(Aset,Bset,AltAB)
00977 void MarkAlternationAB(
00978   const EventSet rAset, 
00979   const EventSet rBset,
00980   Generator& rAltAB)
00981 {
00982   FD_DF("MarkAlternationAB()");
00983   
00984   #ifdef FAUDES_CHECKED
00985   // validate parameters
00986   if (rAset.Empty()){
00987     std::stringstream errstr;
00988     errstr << "Empty parameter rAset.";
00989     throw Exception("CheapAltAnB", errstr.str(), 0);
00990   } 
00991   if (rBset.Empty()){
00992       std::stringstream errstr;
00993       errstr << "Empty parameter rBset.";
00994       throw Exception("CheapAltAnB", errstr.str(), 0);
00995   }
00996   #endif
00997   
00998     rAltAB.Clear();
00999     rAltAB.InjectAlphabet(rAset+rBset);
01000     
01001     Idx s1,s2,s3,s4,s5;
01002     
01003     s1=rAltAB.InsInitState();
01004     rAltAB.SetMarkedState(s1);
01005     s2=rAltAB.InsMarkedState();
01006     s3=rAltAB.InsMarkedState();
01007     s4=rAltAB.InsState();
01008     s5=rAltAB.InsState();
01009     EventSet::Iterator evit=rAset.Begin();
01010     EventSet::Iterator evit_end=rAset.End();
01011     for(;evit!=evit_end;++evit) {
01012         rAltAB.SetTransition(s1,*evit,s2);
01013         rAltAB.SetTransition(s2,*evit,s4);
01014         rAltAB.SetTransition(s3,*evit,s2);
01015         rAltAB.SetTransition(s4,*evit,s4);
01016         rAltAB.SetTransition(s5,*evit,s2);
01017     }
01018     evit=rBset.Begin();
01019     evit_end=rBset.End();
01020     for(;evit!=evit_end;++evit) {
01021         rAltAB.SetTransition(s1,*evit,s3);
01022         rAltAB.SetTransition(s2,*evit,s3);
01023         rAltAB.SetTransition(s3,*evit,s5);
01024         rAltAB.SetTransition(s4,*evit,s3);
01025         rAltAB.SetTransition(s5,*evit,s5);
01026     }
01027 }
01028 
01029 // HioShuffleUnchecked(rPlantA,rPlantB,rYp,rUp,rYe,rUe,rIOShuffAB) 
01030 void HioShuffleUnchecked(
01031   const Generator& rPlantA, 
01032   const Generator& rPlantB, 
01033   const EventSet& rYp,
01034   const EventSet& rUp, 
01035   const EventSet& rYe, 
01036   const EventSet& rUe,
01037   Generator& rIOShuffAB) 
01038 { 
01039   FD_DF("HioShuffle()");
01040 
01041   //Extract alphabets:             
01042   EventSet A,B,SigmaP;
01043   A = rPlantA.Alphabet();
01044   B = rPlantB.Alphabet();
01045 
01046   // parallel composition of plantA and plantB (i.e. shuffle as there are no shared events)
01047   Generator parallel1, parallel2;
01048   std::map< std::pair<Idx,Idx>, Idx > MapOrigToResult;
01049   Parallel(rPlantA,rPlantB,MapOrigToResult,parallel1);
01050   MarkHioShuffle(rPlantA,rPlantB,MapOrigToResult,parallel1);
01051 
01052   // restrict to event pairs [(SigA SigA)*+(SigB SigB)*]*, which results
01053   // in correct I/O sorting L_IO.
01054   Generator EventPairs; // generator of above sorting language
01055   EventPairs.InjectAlphabet(A + B);
01056   Idx state1,state2,state3;
01057   state1=EventPairs.InsInitState("1");
01058   EventPairs.SetMarkedState(state1);
01059   state2=EventPairs.InsMarkedState("2");
01060   state3=EventPairs.InsMarkedState("3");
01061   EventSet::Iterator evit;
01062   for (evit = A.Begin(); evit != A.End(); ++evit) {
01063     EventPairs.SetTransition(state1,*evit,state2);
01064     EventPairs.SetTransition(state2,*evit,state1);
01065   }
01066   for (evit = B.Begin(); evit != B.End(); ++evit) {
01067     EventPairs.SetTransition(state1,*evit,state3);
01068     EventPairs.SetTransition(state3,*evit,state1);
01069   }
01070   Parallel(parallel1,EventPairs,parallel2);
01071   parallel1 = parallel2;
01072 
01073 // //#####################################################################################
01074 // //#####################################################################################
01075 // //#####################################################################################
01076 //  //restrict to IO-sorting structure with forced alternation:
01077 //
01078 //  // Old Vers before Dez 4 2006: Alternation of whole alphabets
01079 //  A = rPlantA.Alphabet();
01080 //  B = rPlantB.Alphabet();
01081 //
01082 //
01083 ////  // New Vers: Alternation of YP Events only
01084 ////  // -> currently leads to normality problems during superposed controller synthesis
01085 ////  SigmaP.SetUnion(rYp);
01086 ////  SigmaP.SetUnion(rUp);
01087 ////  A.SetIntersection(SigmaP);
01088 ////  B.SetIntersection(SigmaP);
01089 //
01090 //
01091 //
01092 //  Generator AltAB;
01093 //  A.Name("A");
01094 //  B.Name("B");
01095 //  CheapAltAB(A,B,Depth,AltAB);
01096 //  // Alt_AB.Write("tmp_Alternation_AB.gen");
01097 //  Parallel(parallel2, AltAB, parallel1);
01098 //  //parallel2.Write("tmp_IOS3.gen");
01099 //
01100 //
01101 //
01102 
01103   
01104   // bugfix to resolve normality problem: whenever plant A
01105   // can send a yp-event and at the same time plant B can
01106   // send a ye-event, then let the ye-event be sent first:
01107   //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01108   //*** Environment-first policy: If, in some state both, Yp- and Ye events are
01109   //*** active, then cancel all Yp-transitions in this state, as environment has
01110   //*** to be updated first.
01111   
01112   FD_DF("------ HioShuffle with Environment-First-Policy! -----");
01113   
01114   // loop all states
01115   StateSet::Iterator sit = parallel1.StatesBegin();
01116   StateSet::Iterator sit_end = parallel1.StatesEnd();
01117   
01118   for(; sit != sit_end; sit++)
01119   {
01120         // figure active Yp-events and active Ye-events
01121         //std::cout << "End: " << *sit_end <<"...done: " << *sit << std::endl;
01122         EventSet ActiveYe;
01123         EventSet ActiveYp = parallel1.TransRel().ActiveEvents(*sit);
01124         ActiveYe=ActiveYp;
01125         ActiveYe.SetIntersection(rYe);
01126         ActiveYp.SetIntersection(rYp);
01127         if (!(ActiveYe.Empty())&& !(ActiveYp.Empty()))
01128         {   
01129             TransSet TransToClear;
01130             TransSet::Iterator tit=parallel1.TransRelBegin(*sit);
01131             TransSet::Iterator tit_end=parallel1.TransRelEnd(*sit);
01132             for(;tit!=tit_end;tit++)
01133                 {
01134                 //std::cout << "finding Yp-events to delete... "; 
01135                 if(ActiveYp.Exists(tit->Ev))
01136                     {
01137                     TransToClear.Insert(*tit);
01138                     }
01139                 }
01140             tit=TransToClear.Begin();
01141             tit_end=TransToClear.End();
01142             for(;tit!=tit_end;tit++)
01143             {
01144             //std::cout<<" ...deleting" <<std::endl;
01145             parallel1.ClrTransition(*tit);
01146             }
01147         } 
01148   }  
01149   
01150   //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01151 
01152 
01153 
01154 //~ ////
01155 //~ // //#####################################################################################
01156 //~ // //#####################################################################################
01157 //~ // //#####################################################################################
01158 
01159 
01160   // Insert Error Behaviour, i.e. make UP and UE free in (YP,UP)-port of result:
01161   // free UP:
01162   HioFreeInput(parallel1, rUp, rYp, parallel2, "errYp_Ye", "errUp");
01163   //parallel1.Write("tmp_IOS4.gen");
01164   // free UE:
01165   HioFreeInput(parallel2, rUe, rYe, parallel1, "errYp_Ye", "errUe");
01166   //parallel2.Write("tmp_IOS5.gen");
01167   
01168   // Mark Alternation of YP-events
01169   A.SetIntersection(rYp);
01170   B.SetIntersection(rYp);
01171   MarkAlternationAB(A,B,parallel2);
01172   Parallel(parallel2,parallel1,parallel1);
01173 
01174   rIOShuffAB = parallel1;
01175   rIOShuffAB.Name("HioShuffle("+rPlantA.Name()+rPlantB.Name()+")");
01176   return;
01177 }
01178 
01179 
01180 // HioShuffle(rPlantA,rPlantB,rYp,rUp,rYe,rUe,rIOShuffAB) 
01181 void HioShuffle(
01182   const Generator& rPlantA, 
01183   const Generator& rPlantB, 
01184   const EventSet& rYp,
01185   const EventSet& rUp, 
01186   const EventSet& rYe, 
01187   const EventSet& rUe,
01188   Generator& rIOShuffAB) 
01189 { 
01190   rIOShuffAB.Clear();
01191   #ifdef FAUDES_CHECKED
01192   // exception on empty alphabets
01193   if (rYp.Empty()){
01194    std::stringstream errstr;
01195    errstr << "Empty Yp alphabet\n";
01196    throw Exception("HioShuffle", errstr.str(), 0);
01197   }
01198   if (rUp.Empty()){
01199    std::stringstream errstr;
01200    errstr << "Empty Up alphabet\n";
01201    throw Exception("HioShuffle", errstr.str(), 0);
01202   }
01203   if (rYe.Empty()){
01204    std::stringstream errstr;
01205    errstr << "Empty Ye alphabet\n";
01206    throw Exception("HioShuffle", errstr.str(), 0);
01207   }
01208   if (rUe.Empty()){
01209    std::stringstream errstr;
01210    errstr << "Empty Ue alphabet\n";
01211    throw Exception("HioShuffle", errstr.str(), 0);
01212   }
01213   
01214   // create resulting alphabet while checking for disjoint sets
01215   EventSet alphabet,alphabetA,alphabetB,errevents;
01216   alphabetA=rPlantA.Alphabet();
01217   alphabetB=rPlantB.Alphabet();
01218   // initialize with rYp
01219   alphabet.SetUnion(rYp);
01220   // insert remaining events one by one and check if new
01221   EventSet::Iterator evit;
01222   // rUp
01223   for (evit = rUp.Begin(); evit != rUp.End(); ++evit) {
01224     if(!(alphabet.Insert(*evit))) errevents.Insert(*evit);
01225   }
01226   // rYe
01227   for (evit = rYe.Begin(); evit != rYe.End(); ++evit) {
01228     if(!(alphabet.Insert(*evit))) errevents.Insert(*evit);
01229   }
01230   // rUe
01231   for (evit = rUe.Begin(); evit != rUe.End(); ++evit) {
01232     if(!(alphabet.Insert(*evit))) errevents.Insert(*evit);
01233   }
01234   // throw exception on non disjoint alphabets
01235   if (!errevents.Empty()){
01236     std::stringstream errstr;
01237     errstr << "Non-disjoint parameters; ambiguous events:\n" <<errevents.ToString();
01238   throw Exception("HioShuffle", errstr.str(), 0);
01239   }
01240   
01241   // check alphabet match with plant A and B-alphabets:
01242   // The union of plant A and B alphabets need not equal but must be included in the union of EventSet parameters.
01243   
01244   errevents=alphabetA+alphabetB-alphabet;
01245   if (!errevents.Empty()){
01246     std::stringstream errstr;
01247     errstr << "Plant A- or plant B-events missing in Yp,Up,Ye or Ue:\n" <<errevents.ToString();
01248   throw Exception("HioShuffle", errstr.str(), 0);
01249   }
01250   
01251   // plant A and plant B must be in HioPlantForm
01252   HioPlant hioPlantA=HioPlant(rPlantA,rYp*alphabetA,rUp*alphabetA,rYe*alphabetA,rUe*alphabetA);
01253   std::string report;
01254   if(!IsHioPlantForm(hioPlantA,report)){
01255     std::stringstream errstr;
01256     errstr << "plant A not in HioPlantForm:\n" << report;
01257   throw Exception("HioShuffle", errstr.str(), 0);
01258   }
01259   
01260   HioPlant hioPlantB=HioPlant(rPlantB,rYp*alphabetB,rUp*alphabetB,rYe*alphabetB,rUe*alphabetB);
01261   report.clear();
01262   if(!IsHioPlantForm(hioPlantB,report)){
01263     std::stringstream errstr;
01264     errstr << "plant B not in HioPlantForm:\n" << report;
01265   throw Exception("HioShuffle", errstr.str(), 0);
01266   }
01267   #endif
01268   
01269   // compute I/O-shuffle 
01270   HioShuffleUnchecked(rPlantA, rPlantB, rYp, rUp, rYe, rUe, rIOShuffAB);
01271   
01272 }
01273 
01274 void HioShuffle(
01275   const HioPlant& rPlantA, 
01276   const HioPlant& rPlantB,
01277   HioPlant& rIOShuffAB) {
01278   
01279   //prepare result
01280   rIOShuffAB.Clear();
01281   
01282   EventSet yp = rPlantA.YpEvents()+rPlantB.YpEvents();
01283   EventSet up = rPlantA.UpEvents()+rPlantB.UpEvents();
01284   EventSet ye = rPlantA.YeEvents()+rPlantB.YeEvents();
01285   EventSet ue = rPlantA.UeEvents()+rPlantB.UeEvents();
01286   
01287   // compute I/O-shuffle
01288   HioShuffle(rPlantA, rPlantB, yp, up, ye, ue, rIOShuffAB);
01289   
01290   // set event and state attributes
01291   rIOShuffAB.SetYp(yp);
01292   rIOShuffAB.SetUp(up);
01293   rIOShuffAB.SetYe(ye);
01294   rIOShuffAB.SetUe(ue);
01295   
01296   IsHioPlantForm(rIOShuffAB);
01297 }
01298 //******************** old version: no marking, forced alternation ************************
01299 
01300 // CheapAltAnB(rAset,rBset,Depth,rAltAnB)
01301 void CheapAltAnB(
01302   const EventSet rAset, 
01303   const EventSet rBset,
01304   const int Depth,
01305   Generator& rAltAnB) 
01306 { 
01307   FD_DF("CheapAltAnB()");
01308   
01309   // validate parameters
01310   if (Depth<1){
01311       std::stringstream errstr;
01312       errstr << "Parameter Depth must be 1 or greater.";
01313       throw Exception("CheapAltAnB", errstr.str(), 0);
01314   }
01315   #ifdef FAUDES_CHECKED
01316   if (rAset.Empty()){
01317       std::stringstream errstr;
01318       errstr << "Empty parameter rAset.";
01319       throw Exception("CheapAltAnB", errstr.str(), 0);
01320   } 
01321   if (rBset.Empty()){
01322       std::stringstream errstr;
01323       errstr << "Empty parameter rBset.";
01324       throw Exception("CheapAltAnB", errstr.str(), 0);
01325   }
01326   #endif
01327   
01328   // prepare result
01329   rAltAnB.Clear();
01330   rAltAnB.Name("CheapAltAnB(" + rAset.Name() + "," + rBset.Name() + "," + ToStringInteger(Depth) + ")");
01331 
01332   // create initial state
01333   Idx init = rAltAnB.InsInitState("alt_"+rAset.Name()+"_init");
01334   rAltAnB.SetMarkedState(init);
01335   
01336   Idx last = init;
01337   rAltAnB.InjectAlphabet(rAset + rBset);
01338 
01339   // selfloop initial state with Bset:
01340   EventSet::Iterator evit;
01341   for (evit = rBset.Begin(); evit != rBset.End(); ++evit) {
01342       rAltAnB.SetTransition(last,*evit,last);
01343   }
01344 
01345   //create n concatenated pathes A->|a|A->|b| and transitions B from |b| to initial state.
01346   for (int i=0; i!=Depth; ++i) {
01347     Idx a = rAltAnB.InsMarkedState("alt_"+rAset.Name()+"_U"+ToStringInteger(i+1));
01348     Idx b = rAltAnB.InsMarkedState("alt_"+rAset.Name()+"_Y"+ToStringInteger(i+2));
01349     //connect last,a and b with A-transitions.
01350     for (evit = rAset.Begin(); evit != rAset.End(); ++evit) {
01351       rAltAnB.SetTransition(last,*evit,a);
01352       rAltAnB.SetTransition(a,*evit,b);
01353     }
01354     //insert B-transitions from b to init
01355     for (evit = rBset.Begin(); evit != rBset.End(); ++evit) {
01356       rAltAnB.SetTransition(b,*evit,init);
01357     }
01358     last = b;
01359   }
01360 }
01361 
01362 // CheapAltAB(rAset,rBset,Depth,rAltAnB)
01363 void CheapAltAB(
01364   const EventSet rAset, 
01365   const EventSet rBset,  
01366   const int Depth,
01367   Generator& rAltAB) 
01368 { 
01369   FD_DF("CheapAltAB()");
01370   // prepare result
01371   rAltAB.Clear();
01372   
01373   Generator AnB, BnA;
01374   CheapAltAnB(rAset,rBset,Depth,AnB);
01375   CheapAltAnB(rBset,rAset,Depth,BnA);
01376   Parallel(AnB,BnA,rAltAB);
01377   rAltAB.Name("CheapAltAB("+rAset.Name()+","+rBset.Name()+","+ToStringInteger(Depth)+")");
01378 }
01379 
01380 // HioShuffleTU(rPlantA,rPlantB,rYp,rUp,rYe,rUe,Depth,rIOShuffAB) 
01381 void HioShuffleTU(
01382   const Generator& rPlantA, 
01383   const Generator& rPlantB, 
01384   const EventSet& rUp, 
01385   const EventSet& rYp,
01386   const EventSet& rYe, 
01387   const EventSet& rUe,
01388   const int Depth,
01389   Generator& rIOShuffAB) 
01390 { 
01391   FD_DF("HioShuffle()");
01392 
01393   //Extract alphabets:             
01394   EventSet A,B,SigmaP;
01395   A = rPlantA.Alphabet();
01396   B = rPlantB.Alphabet();
01397 
01398   // parallel composition of plantA and plantB (i.e. shuffle as there are no shared events)
01399   Generator parallel1, parallel2;
01400   Parallel(rPlantA,rPlantB,parallel1);
01401 
01402   // restrict to event pairs [(SigA SigA)*+(SigB SigB)*]*, which results
01403   // in correct I/O sorting L_IO.
01404   Generator EventPairs; // generator of above sorting language
01405   EventPairs.InjectAlphabet(A + B);
01406   Idx state1,state2,state3;
01407   state1=EventPairs.InsInitState("1");
01408   EventPairs.SetMarkedState(state1);
01409   state2=EventPairs.InsMarkedState("2");
01410   state3=EventPairs.InsMarkedState("3");
01411   EventSet::Iterator evit;
01412   for (evit = A.Begin(); evit != A.End(); ++evit) {
01413     EventPairs.SetTransition(state1,*evit,state2);
01414     EventPairs.SetTransition(state2,*evit,state1);
01415   }
01416   for (evit = B.Begin(); evit != B.End(); ++evit) {
01417     EventPairs.SetTransition(state1,*evit,state3);
01418     EventPairs.SetTransition(state3,*evit,state1);
01419   }
01420   Parallel(parallel1,EventPairs,parallel2);
01421 
01422   //restrict to IO-sorting structure with forced alternation:
01423 
01424 ////////  // Old Vers before Dez 4 2006: Alternation of whole alphabets
01425 ////////  A = rPlantA.Alphabet();
01426 ////////  B = rPlantB.Alphabet();
01427 //////
01428 //////  // New Vers: Alternation of YP Events only
01429 //////  // -> currently leads to normality problems during superposed controller synthesis
01430 //////  SigmaP.SetUnion(rYp);
01431 //////  SigmaP.SetUnion(rUp);
01432 //////  A.SetIntersection(SigmaP);
01433 //////  B.SetIntersection(SigmaP);
01434 //////
01435 //////
01436 //////  Generator AltAB;
01437 //////  A.Name("A");
01438 //////  B.Name("B");
01439 //////  CheapAltAB(A,B,Depth,AltAB);
01440 //////  // Alt_AB.Write("tmp_Alternation_AB.gen");
01441 //////  Parallel(parallel2, AltAB, parallel1);
01442 //////  //parallel2.Write("tmp_IOS3.gen");
01443 
01444   // Old Vers before Dez 4 2006: Alternation of whole alphabets
01445   EventSet Ap, Bp, Ae, Be, SigmaE;
01446   
01447   Ap = rPlantA.Alphabet();
01448   Bp = rPlantB.Alphabet();
01449   
01450   Ae = rPlantA.Alphabet();
01451   Be = rPlantB.Alphabet();
01452   
01453   
01454 
01455   //*************************************************************************
01456   //// New Vers: Alternation of YP Events only
01457   //// -> currently leads to normality problems during superposed controller synthesis
01458   SigmaP.SetUnion(rYp);
01459   SigmaP.SetUnion(rUp);
01460   Ap.SetIntersection(SigmaP);
01461   Bp.SetIntersection(SigmaP);
01462   
01463   SigmaE.SetUnion(rYe);
01464   SigmaE.SetUnion(rUe);
01465   Ae.SetIntersection(SigmaE);
01466   Be.SetIntersection(SigmaE);
01467   
01468   
01469   //*************************************************************************
01470   Generator AltAB;
01471   Ap.Name("A");
01472   Bp.Name("B");
01473   CheapAltAB(Ap,Bp,Depth,AltAB);
01474   // Alt_AB.Write("tmp_Alternation_AB.gen");
01475   Parallel(parallel2, AltAB, parallel1);
01476   
01477 /*   // bugfix to resolve normality problem: whenever plant A
01478  *  // can send a yp-event and at the same time plant B can
01479  *  // send a ye-event, then let the ye-event be sent first:
01480  *   //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01481  *   // Environment-first policy: If, in some state both, Yp- and Ye events are
01482  *   // active, then cancel all Yp-transitions in this state, as environment has
01483  *   // to be updated first.
01484  *   
01485  *   // loop all states
01486  *   StateSet::Iterator sit = parallel1.StatesBegin();
01487  *   StateSet::Iterator sit_end = parallel1.StatesEnd();
01488  *   
01489  *   for(; sit != sit_end; sit++)
01490  *   {
01491  *         // figure active Yp-events and active Ye-events
01492  *         //std::cout << "End: " << *sit_end <<"...done: " << *sit << std::endl;
01493  *         EventSet ActiveYe;
01494  *         EventSet ActiveYp = parallel1.TransRel().ActiveEvents(*sit);
01495  *         ActiveYe=ActiveYp;
01496  *         ActiveYe.SetIntersection(rYe);
01497  *         ActiveYp.SetIntersection(rYp);
01498  *         if (!(ActiveYe.Empty())&& !(ActiveYp.Empty()))
01499  *         {   
01500  *             TransSet TransToClear;
01501  *             TransSet::Iterator tit=parallel1.TransRelBegin(*sit);
01502  *             TransSet::Iterator tit_end=parallel1.TransRelEnd(*sit);
01503  *             for(;tit!=tit_end;tit++)
01504  *                 {
01505  *                 //std::cout << "finding Yp-events to delete... "; 
01506  *                 if(ActiveYp.Exists(tit->Ev))
01507  *                     {
01508  *                     TransToClear.Insert(*tit);
01509  *                     }
01510  *                 }
01511  *             tit=TransToClear.Begin();
01512  *             tit_end=TransToClear.End();
01513  *             for(;tit!=tit_end;tit++)
01514  *             {
01515  *             //std::cout<<" ...deleting" <<std::endl;
01516  *             parallel1.ClrTransition(*tit);
01517  *             }
01518  *         } 
01519  *   }  
01520  *   
01521  *   //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01522  * 
01523  */
01524 
01525 
01526   // Insert Error Behaviour, i.e. make UP and UE free in (YP,UP)-port of result:
01527   // free UP:
01528   HioFreeInput(parallel1, rUp, rYp, parallel2, "errYp_Ye", "errUp");
01529   //parallel1.Write("tmp_IOS4.gen");
01530   // free UE:
01531   HioFreeInput(parallel2, rUe, rYe, parallel1, "errYp_Ye", "errUe");
01532   //parallel2.Write("tmp_IOS5.gen");
01533 
01534   rIOShuffAB = parallel1;
01535 }
01536 
01537 //**********************************************************
01538 //******************** Cycles ************************
01539 //**********************************************************
01540 
01541 
01542 // ***Search for strongly connected ycless components (SCC)***
01543 // This function partitions the stateset of a generator into equivalent classes
01544 // such that states x1 and x2 are equivalent iff there is a ycless path from x1
01545 // to x2 AND a ycless path from x2 to x1.
01546 // This function implements the algorithm based on a depth first search
01547 // presented in:
01548 // -Aho, Hopcroft, Ullman: The Design and Analysis of Computer Algorithms-
01549 //
01550 // Most of the comments in this function have been literally taken from
01551 // this book!
01552 //
01553 // Parameters (an api with generator and Yc-events as input and SCCs as output
01554 // is provided right below this method.)
01555 // -state: State, from which the current recursion is started.
01556 // -rcount: denotes the current depth of the recursion.
01557 // -Yc: set of Yc-events
01558 // -UnMarkedOnly: if set true, being unmarked is an additional condition for equivalence of states
01559 // -NewStates: Set of states that up to now were not found by the depth first search
01560 // -STACK: stack of state indeces
01561 // -StackStates: set of states whose indeces are on STACK.
01562 // -DFN: map assigning to each state its Depth-First Number
01563 // -LOWLINK: map assigning to each state its LOWLINK Number
01564 // -SCCset: result - the set of strongly connected components
01565 // -UnMarkedSCCset: result - the set of strongly connected components consisting exclusively of marked states
01566 // -Roots: result - the set of states that each are root of some SCC.
01567 //
01568 // ToDo: handle exceptions.
01569 //
01570 
01571 void SearchYclessScc(
01572   const Idx state, 
01573   int& rcount,      // why is this a ref?
01574   const Generator& rGen,
01575   const EventSet& rYc,
01576   const bool UnMarkedOnly,
01577   StateSet&  rNewStates,
01578   std::stack<Idx>& rSTACK, 
01579   StateSet& rStackStates,
01580   std::map<const Idx, int>& rDFN,
01581   std::map<const Idx, int>& rLOWLINK,
01582   std::set<StateSet>& rSccSet,
01583   StateSet& rRoots)
01584 {
01585   FD_DF("SerchYclessScc: -- search from state "<< state << "--");
01586 
01587   // mark state "old";
01588   rNewStates.Erase(state);
01589 
01590   // DFNUMBER[state] <- count;
01591   rDFN[state]=rcount;
01592 
01593   // count <- count+1;
01594   rcount++;
01595 
01596   // LOWLINK[v] <- DFNUMBER[v];
01597   rLOWLINK[state]=rDFN[state];
01598   //cout<<"count: "<<rcount<<" state: "<<state<<" DFN: "<<rDFN[state]<<endl;
01599 
01600   // push state on STACK;
01601   rSTACK.push(state);
01602   rStackStates.Insert(state);
01603 
01604   //<<create set "L[state]" of successor states of state, without states reached via a Yc-event:
01605   StateSet SuccStates = StateSet();
01606   TransSet::Iterator it = rGen.TransRelBegin(state);
01607   TransSet::Iterator it_end = rGen.TransRelEnd(state);
01608   for (; it != it_end; ++it) {
01609     if(!rYc.Exists(it->Ev)||(UnMarkedOnly &! rGen.ExistsMarkedState(it->X2)))
01610       {
01611         SuccStates.Insert(it->X2);
01612       }
01613   }
01614 
01615   // for each vertex *sit on L[state] do
01616   StateSet::Iterator sit = SuccStates.Begin();
01617   StateSet::Iterator sit_end = SuccStates.End();
01618   for (; sit != sit_end; ++sit)
01619     {
01620       // if *sit is marked "new" then
01621       if(rNewStates.Exists(*sit))
01622         {// begin
01623         
01624     // SearchC(*sit);
01625     SearchYclessScc(*sit, rcount, rGen, rYc, UnMarkedOnly, rNewStates, rSTACK, rStackStates, rDFN, rLOWLINK, rSccSet, rRoots);
01626     // LOWLINK[state] <- MIN(LOWLINK[state],LOWLINK[*sit]);
01627     if(rLOWLINK[*sit]<rLOWLINK[state])
01628       {
01629         rLOWLINK[state]=rLOWLINK[*sit];
01630       }
01631         }//end
01632         
01633       else
01634         {
01635     // if DFNUMBER[*sit]<DFNUMBER[state] and [*sit] is on STACK then
01636     if((rDFN[*sit]<rDFN[state])&&(rStackStates.Exists(*sit)))
01637       {
01638         // LOWLINK[state]<-MIN(DFNUMBER[*sit],LOWLINK[state]);
01639         if(rDFN[*sit]<rLOWLINK[state])
01640     {
01641       rLOWLINK[state]=rDFN[*sit];
01642     }
01643       }                
01644         }
01645     }//end for
01646   // if LOWLINK[state]=DFNUMBER[state] (i.e. state is root of a SCC) then
01647   if((rLOWLINK[state]==rDFN[state]))
01648     {
01649       // per def., each state in a graph is element of a SCC, thus:
01650       // check if size of SCC is>1 or (else) SCC contains (non-{epsilon,yc}-)selfloops
01651       // to avoid print of trivial SCCs
01652       bool realscc=rSTACK.top()!=state; //size of SCC>1 ? if not, check for selfloops:
01653       if(!realscc)
01654         {
01655     TransSet::Iterator it = rGen.TransRelBegin(state);
01656     TransSet::Iterator it_end = rGen.TransRelEnd(state);
01657     for (; it != it_end; ++it)
01658             {
01659         if((it->X2==state)&&(!rYc.Exists(it->Ev)))
01660                 {
01661       realscc=true; //at least one yc-less selfloop found -> SCC is nontrivial
01662       break;
01663                 }
01664             }
01665         }
01666         
01667       //~ if(realscc) // be aware: "else" statement is NOT correct at this point, as realscc-value is changed in the above if-clause
01668         //~ {
01669     //~ // cout<<endl<<"found ycless SCC with root "<<state<<", consisting of the following states:"<<endl<<"begin"<<endl;
01670     //~ rRoots.Insert(state);
01671         //~ }
01672         
01673       //create SCC
01674       StateSet Scc;
01675       bool purelyUnMarked=true;
01676       // begin
01677       // repeat
01678       while(true)
01679         {// begin
01680     // pop x from top of STACK and print x;
01681     Idx top=rSTACK.top();
01682     if(realscc) // things outside the "if(realscc)"-clause have to be done in any case!
01683             {
01684         // cout<<top;
01685         Scc.Insert(top);
01686           if(rGen.ExistsMarkedState(top)) purelyUnMarked=false;
01687             }
01688     rStackStates.Erase(top);
01689     rSTACK.pop();
01690         
01691     // until x=state;
01692     if(top==state)
01693       {
01694         // print "end of SCC", insert SCC into SCCset;
01695         if(realscc)
01696     {
01697       // cout<<endl<<"end"<<endl;
01698           if(!purelyUnMarked || UnMarkedOnly)
01699             {
01700               rSccSet.insert(Scc);
01701               rRoots.Insert(state);
01702             }
01703     }
01704         //system("pause");
01705         break;
01706       }
01707     // cout<<", "<<endl;
01708         } //end while
01709     } // end if
01710 }
01711 
01712 // YclessScc(Generator,Yc-events, SccSet, Roots)
01713 // -> api using SearchYclessScc() from above.
01714 bool YclessScc(
01715   const Generator& rGen,
01716   const EventSet& rYc,
01717   std::set<StateSet>& rSccSet,
01718   StateSet& rRoots)
01719 {
01720   FD_DF("YclessScc(" << rGen.Name() << ")");
01721 
01722   // inititalize results:
01723   rRoots.Clear();
01724   rSccSet.clear();
01725   // initialize counter for depthfirstnumbers(DFN):
01726   int count=1;
01727 
01728   // initialize stack of states (state indeces):
01729   std::stack<Idx> STACK;
01730   // due to lack of STACK-iterator: initialize set of states that are on STACK:
01731   StateSet StackStates = StateSet();
01732 
01733   // initialize set of states to be examined:
01734   StateSet  NewStates=rGen.AccessibleSet();
01735 
01736   // initialize map of state indeces to their DFN:
01737   std::map<const Idx, int> DFN;
01738   // initialize map of state indeces to their LOWLINK:
01739   std::map<const Idx, int> LOWLINK;
01740 
01741   // figure initial state:
01742   Idx InitState = *rGen.InitStatesBegin();
01743   // start recursive depth-first search for Scc's:
01744   while(!NewStates.Empty()) {
01745     // the following 'if' isn't necessary, but provokes search begin at initial state of rGen
01746     if(NewStates.Exists(InitState)) {
01747       SearchYclessScc(InitState, count, rGen, rYc, false, NewStates, STACK, StackStates, DFN, LOWLINK, rSccSet, rRoots);
01748     } else {
01749       SearchYclessScc(*NewStates.Begin(), count, rGen, rYc, false, NewStates, STACK, StackStates, DFN, LOWLINK, rSccSet, rRoots);
01750     }
01751   }
01752   
01753   return !rSccSet.empty();
01754 }
01755 
01756 // YclessUnMarkedScc(Generator,Yc-events, SccSet, Roots)
01757 // -> api using SearchYclessScc() from above.
01758 bool YclessUnmarkedScc(
01759   const Generator& rGen,
01760   const EventSet& rYc,
01761   std::set<StateSet>& rSccSet,
01762   StateSet& rRoots)
01763 {
01764   FD_DF("YclessScc(" << rGen.Name() << ")");
01765 
01766   // inititalize results:
01767   rRoots.Clear();
01768   rSccSet.clear();
01769   // initialize counter for depthfirstnumbers(DFN):
01770   int count=1;
01771 
01772   // initialize stack of states (state indeces):
01773   std::stack<Idx> STACK;
01774   // due to lack of STACK-iterator: initialize set of states that are on STACK:
01775   StateSet StackStates = StateSet();
01776 
01777   // initialize set of states to be examined:
01778   StateSet  NewStates=rGen.AccessibleSet()-rGen.MarkedStates();
01779 
01780   // initialize map of state indeces to their DFN:
01781   std::map<const Idx, int> DFN;
01782   // initialize map of state indeces to their LOWLINK:
01783   std::map<const Idx, int> LOWLINK;
01784 
01785   // figure initial state:
01786   Idx InitState = *rGen.InitStatesBegin();
01787   // start recursive depth-first search for Scc's:
01788   while(!NewStates.Empty()) {
01789     // the following 'if' isn't necessary, but provokes search begin at initial state of rGen
01790     if(NewStates.Exists(InitState)) {
01791       SearchYclessScc(InitState, count, rGen, rYc, true, NewStates, STACK, StackStates, DFN, LOWLINK, rSccSet, rRoots);
01792     } else {
01793       SearchYclessScc(*NewStates.Begin(), count, rGen, rYc, true, NewStates, STACK, StackStates, DFN, LOWLINK, rSccSet, rRoots);
01794     }
01795   }
01796   
01797   return !rSccSet.empty();
01798 }
01799 
01800 
01801 // YclessScc(rGen,rYc,rSccSet)
01802 // -> api using YclessScc() from above.
01803 bool YclessScc(
01804   const Generator& rGen,
01805   const EventSet& rYc,
01806   std::set<StateSet>& rSccSet)
01807 {
01808   FD_DF("YclessScc(" << rGen.Name() << ")");
01809 
01810   // inititalize result:
01811   rSccSet.clear();
01812   
01813   StateSet Roots;
01814   return YclessScc(rGen,rYc,rSccSet,Roots);
01815 }
01816 
01817 // IsYcLive(rGen,rYc)
01818 bool IsYcLive(
01819   const Generator& rGen,
01820   const EventSet& rYc)
01821 {
01822   FD_DF("IsYcLive(" << rGen.Name() << ")");
01823 
01824   std::set<StateSet> rSccSet;
01825   
01826   // Generator is YcLive if no YcLessScc is found
01827   YclessScc(rGen,rYc,rSccSet);
01828   return rSccSet.size()==0;
01829 }
01830 
01831 // WriteStateSets(rStateSets)
01832 // Write set of StateSet's to console.
01833 void WriteStateSets(
01834   const std::set<StateSet>& rStateSets)
01835 {
01836   FD_DF("WriteStateSets()");
01837   std::cout<<std::endl;
01838   if(rStateSets.empty()) {
01839     std::cout<<"WriteStateSets: Set of state sets is empty."<<std::endl;
01840     FD_DF("WriteStateSets: Set of state sets is empty.");
01841     return;
01842   }
01843   std::cout<<">WriteStateSets: Set of state sets begin:"<< std::endl;
01844   std::set<StateSet>::iterator StateSetit = rStateSets.begin();
01845   std::set<StateSet>::iterator StateSetit_end = rStateSets.end();
01846   for (; StateSetit != StateSetit_end; ++StateSetit) {
01847     std::cout<<std::endl<<"  >> State set begin:"<< std::endl;
01848     StateSet::Iterator sit = StateSetit->Begin();
01849     StateSet::Iterator sit_end = StateSetit->End();
01850     for (; sit != sit_end; ++sit) {
01851       std::cout<<"  >> "<<*sit<<std::endl;
01852     }
01853     std::cout<<"  >> State set end."<< std::endl;
01854   }  
01855   std::cout<<std::endl<<">WriteStateSets: Set of state sets end."<<std::endl;
01856 }
01857 
01858 // WriteStateSets(rGen,rStateSets)
01859 // Write set of StateSet's to console.
01860 // Use rGen for symbolic state names
01861 void WriteStateSets(
01862   const Generator& rGen,
01863   const std::set<StateSet>& rStateSets)
01864 {
01865   FD_DF("WriteStateSets()");
01866   std::cout<<std::endl;
01867   if(rStateSets.empty()) {
01868     std::cout<<"WriteStateSets: Set of state sets is empty."<<std::endl;
01869     FD_DF("WriteStateSets: Set of state sets is empty.");
01870     return;
01871   }
01872   std::cout<<">WriteStateSets: Set of state sets begin:"<< std::endl;
01873   std::set<StateSet>::iterator StateSetit = rStateSets.begin();
01874   std::set<StateSet>::iterator StateSetit_end = rStateSets.end();
01875   for (; StateSetit != StateSetit_end; ++StateSetit) {
01876     std::cout<<std::endl<<"  >> State set begin:"<< std::endl;
01877     std::cout<<"  "<<rGen.StateSetToString(*StateSetit)<<std::endl;
01878     std::cout<<"  >> State set end."<< std::endl;
01879   }  
01880   std::cout<<std::endl<<">WriteStateSets: Set of state sets end."<<std::endl;
01881 }
01882 
01883 // SccEntries(rGen,rSccSet,rEntryStates,rEntryTransSet)
01884 void SccEntries(
01885   const Generator& rGen,
01886   const std::set<StateSet>& rSccSet,
01887   StateSet& rEntryStates,
01888   TransSetX2EvX1& rEntryTransSet) {
01889             
01890   FD_DF("SccEntries(...)");
01891 
01892   // prepare results:
01893   rEntryStates.Clear();
01894   rEntryTransSet.Clear();
01895   
01896   //extract all transitions sorted by target state X2
01897   TransSetX2EvX1 trel;
01898   rGen.TransRel(trel);
01899   FD_DF("SccEntries: Entry states of all SCCs:");
01900 
01901   //loop through all SCCs:
01902   std::set<StateSet>::iterator sccit = rSccSet.begin();
01903   std::set<StateSet>::iterator sccit_end = rSccSet.end();
01904   for (int i=0; sccit != sccit_end; ++sccit, i++) {
01905     FD_DF("SccEntries: SCC " << i << " begin:");
01906     //loop through all states:
01907     StateSet::Iterator sit = sccit->Begin();
01908     StateSet::Iterator sit_end = sccit->End();
01909     for (; sit != sit_end; ++sit) {
01910       //check if sit is initial state:
01911       if(rGen.ExistsInitState(*sit)) {
01912         rEntryStates.Insert(*sit);
01913       }        
01914       //loop through all transitions with target state X2=sit:
01915       TransSetX2EvX1::Iterator tit=trel.BeginByX2(*sit);
01916       TransSetX2EvX1::Iterator tit_end=trel.EndByX2(*sit);
01917       for(;tit!=tit_end;tit++) {
01918         //if sit is successor of a state X1 that is element of a SCC different
01919         //from the current SCC "StateSetit" and if sit has not been added to
01920         //rEntryStates up to now, then add sit to EntryStates:
01921         if(!sccit->Exists(tit->X1)) {
01922           // insert entry transition:
01923           rEntryTransSet.Insert(*tit);
01924           // if new, insert entry state:
01925           if(!rEntryStates.Exists(*sit)) {
01926             // Perk: check if Insert returns false anyway if element already
01927             // existed before. if so, then write:
01928             // if(rEntryStates.Insert(*sit)) FD_DF("SccEntries: Entry state:" <<*sit);
01929             FD_DF("SccEntries: Entry state:" <<*sit);
01930             rEntryStates.Insert(*sit);
01931           }
01932         }
01933       }
01934     }
01935     FD_DF("SccEntries: SCC " << i << " end:");
01936   }
01937   FD_DF("SccEntries: done");
01938 }
01939 
01940 // CloneScc(rGen,rScc,rSccSet,rEntryState,rEntryStates,rEntryTransSet)
01941 void CloneScc(
01942   Generator& rGen, 
01943   const StateSet& rScc, 
01944   std::set<StateSet>& rSccSet,
01945   const Idx EntryState, 
01946   StateSet& rEntryStates, 
01947   TransSetX2EvX1& rEntryTransSet)
01948 {
01949   FD_DF("CloneScc(...)");
01950   // initialize map from original SCC-states to their clones:
01951   std::map<const Idx, Idx> clone;
01952   // initialize clone-SCC:
01953   StateSet CloneScc;
01954   // clone SCC-states:
01955   StateSet::Iterator sit=rScc.Begin();
01956   StateSet::Iterator sit_end=rScc.End();
01957   for(;sit!=sit_end;sit++) {
01958     // if sit is marked, also mark its clone
01959     if(rGen.ExistsMarkedState(*sit)) { 
01960       clone[*sit]=rGen.InsMarkedState();
01961       CloneScc.Insert(clone[*sit]);
01962       // cout<<"marked state "<<clone[*sit]<<" of "<<*sit<<" inserted.";
01963     } 
01964     // or else insert unmarked state
01965     else {
01966       clone[*sit]=rGen.InsState();
01967       CloneScc.Insert(clone[*sit]);
01968       // cout<<"unmarked state "<<clone[*sit]<<" of "<<*sit<<" inserted.";
01969     }
01970   }
01971   // add clone of SCC to set of all SCCs:
01972   rSccSet.insert(CloneScc);
01973   // clone all transitions:
01974   sit=rScc.Begin();
01975   for(;sit!=sit_end;sit++) {
01976     TransSet::Iterator tit=rGen.TransRelBegin(*sit);
01977     TransSet::Iterator tit_end=rGen.TransRelEnd(*sit);
01978     for(;tit!=tit_end;tit++) {
01979       // clone all transitions within SCC:
01980       if(rScc.Exists(tit->X2)) {
01981         rGen.SetTransition(clone[*sit],tit->Ev,clone[tit->X2]);
01982       }
01983       //...and transitions leaving the SC: 
01984       else {
01985         rGen.SetTransition(clone[*sit],tit->Ev,tit->X2);
01986         //**** added 06.09.2007:
01987         // If this cloned transition leads to an entry state of
01988         // some other SCC, then  it is a new entry transition:
01989         if(rEntryStates.Exists(tit->X2)) {
01990           rEntryTransSet.Insert(clone[*sit],tit->Ev,tit->X2);
01991         }
01992         //****
01993       }
01994     }
01995   }
01996   // move the head of all entry transitions leading to EntryState to the clone of EntryState:
01997   TransSet TransToClear, EntryTransToInsert;
01998   TransSetX2EvX1::Iterator tit=rEntryTransSet.BeginByX2(EntryState);
01999   TransSetX2EvX1::Iterator tit_end=rEntryTransSet.EndByX2(EntryState);
02000   for(;tit!=tit_end;tit++) {
02001   //    cout<<endl<<"Moving entryTransition "<<"("<<tit->X1<<","<<rGen.EventName(tit->Ev)<<","<<tit->X2<<")";
02002   //    cout<<" to target state "<<clone[EntryState];
02003     rGen.SetTransition(tit->X1,tit->Ev,clone[EntryState]);
02004     //prebook new moved transition to be inserted in rEntryTransSet:
02005     EntryTransToInsert.Insert(tit->X1,tit->Ev,clone[EntryState]);
02006     //prebook transitions to former entry state to clear in rGen and rEntryTransSet:
02007     TransToClear.Insert(*tit);
02008   }
02009   //clear former transitions in rGen and rEntryTransSet:
02010   TransSet::Iterator tit2=TransToClear.Begin();
02011   TransSet::Iterator tit2_end=TransToClear.End();
02012   for(;tit2!=tit2_end;tit2++) {
02013     rGen.ClrTransition(*tit2);
02014     //erase transitions to former entry state from rEntryTransSet:
02015     rEntryTransSet.Erase(*tit2);
02016   }
02017   // update rEntryTransSet with new moved entry transitions:
02018   TransSet::Iterator tit3=EntryTransToInsert.Begin();
02019   TransSet::Iterator tit3_end=EntryTransToInsert.End();
02020   for(;tit3!=tit3_end;tit3++) {
02021     //insert new moved transitions in rEntryTransSet:
02022     rEntryTransSet.Insert(*tit3);
02023   }
02024   //update rEntryStateSet:
02025   rEntryStates.Erase(EntryState); // erase former ambiguous entry state
02026   rEntryStates.Insert(clone[EntryState]); // insert unique entry state of cloned SCC
02027 }
02028 
02029 // CloneUnMarkedScc(rGen,rScc,rSccSet,rEntryState,rEntryStates,rEntryTransSet)
02030 void CloneUnMarkedScc(
02031   Generator& rGen, 
02032   const StateSet& rScc,
02033   const Idx EntryState, 
02034   const StateSet& rEntryStates, 
02035   TransSetX2EvX1& rEntryTransSet)
02036 {
02037   FD_DF("CloneUnMarkedScc(...)");
02038   // initialize map from original SCC-states to their clones:
02039   std::map<const Idx, Idx> clone;
02040   // initialize clone-SCC:
02041   StateSet CloneScc;
02042   // clone all SCC-states but EntryState:
02043   StateSet::Iterator sit=rScc.Begin();
02044   StateSet::Iterator sit_end=rScc.End();
02045   for(;sit!=sit_end;sit++) {
02046       if(*sit != EntryState) {
02047          clone[*sit]=rGen.InsState();
02048          CloneScc.Insert(clone[*sit]);
02049         }
02050       else clone[*sit]=*sit; // entry state is not cloned
02051       
02052     }
02053   
02054   //*** Think about this:
02055   // // add clone of SCC to set of all SCCs:
02056   // rSccSet.insert(CloneScc);
02057   //***
02058     
02059   // clone all transitions:
02060   TransSet TransToClear;
02061   sit=rScc.Begin();
02062   bool isEntryState=false;
02063   TransSet::Iterator tit,tit_end;
02064   for(;sit!=sit_end;sit++) {
02065     isEntryState=(*sit==EntryState);
02066     tit=rGen.TransRelBegin(*sit);
02067     tit_end=rGen.TransRelEnd(*sit);
02068     for(;tit!=tit_end;tit++) {
02069       // clone all transitions within SCC:
02070       if(rScc.Exists(tit->X2)) {
02071         rGen.SetTransition(clone[*sit],tit->Ev,clone[tit->X2]);
02072         // if transition starts at entry state, only keep the clone transition
02073         if(isEntryState) {
02074           // prebook this transition to be cleared
02075           TransToClear.Insert(*tit);
02076         }
02077       }
02078       //...and transitions leaving the SCC:
02079       else {
02080         rGen.SetTransition(clone[*sit],tit->Ev,tit->X2);
02081         //**** added 06.09.2007:
02082         // If this cloned transition leads to an entry state of
02083         // some other SCC, then  it is a new entry transition:
02084         if(rEntryStates.Exists(tit->X2)) {
02085           rEntryTransSet.Insert(clone[*sit],tit->Ev,tit->X2);
02086         }
02087         //****
02088       }
02089     }
02090   }
02091   
02092   // clear prebooked transitions
02093   tit=TransToClear.Begin();
02094   tit_end=TransToClear.End();
02095   for(;tit!=tit_end;tit++) {
02096     rGen.ClrTransition(*tit);
02097   }
02098 
02099 }
02100 //============================
02101 
02102 
02103 
02104 // YcAcyclic(rGen,rYc,rResGen)
02105 void YcAcyclic(
02106   const Generator& rGen,
02107   const EventSet& rYc,
02108   Generator& rResGen)
02109 {
02110   FD_DF("YcAcyclic: Statesize before: "<<rGen.Size()<<" - starting...");
02111   // initialize set of ycless strongly connected components (SCCs):
02112   std::set<StateSet> SccSet,UnMarkedSccSet;
02113   // initialize set of all states that are member or root or entry state of some SCC:
02114   StateSet Scc,Roots,EntryStates,notRoots,UnMarkedRoots;
02115   // initialize set of transitions that enter some SCC from a different SCC,
02116   // sorted by target states X2 (which are entry states):
02117   TransSetX2EvX1 EntryTransSet;
02118   // take rGen as first candidate:
02119   rResGen=rGen;
02120   // counter for below while loop:
02121   // int i=0;
02122 
02123   while(true) {
02124     //++i;
02125     // check for SCCs and return if there are none -> ResGen is the result.
02126     // cout<<endl<<"Round "<<i<<": Searching for remaining Yc-less SCCs...";
02127     if(!YclessScc(rResGen,rYc,SccSet,Roots)) {
02128        //time_t *t2;
02129        //time(t2);
02130        //cout<<"...finished in "<<difftime(*t2, *t1)<<" seconds.";
02131         //rResGen.DotWrite("tmp_YcAcyclic_res");
02132       FD_DF("YcAcyclic: Statesize of result: "<<rResGen.Size());
02133 //        cout<<". Statemin...";
02134 //        Generator tmp;
02135 //        StateMin(rResGen,tmp);
02136 //        cout<<"done. New Statesize:"<<tmp.Size();
02137 //        tmp.ClrStateNames();
02138 //        rResGen=tmp;
02139 //        tmp.Clear();
02140         //rResGen.Write("tmp_YcAcyclic.gen");
02141           return;
02142         }
02143     //cout<<endl<<"...found "<<SCCset.size()<<" Yc-less SCCs: computing entry states...";
02144 //    cout<<"Found following Yc-less SCCs:"<<endl;
02145 //    WriteStateSets(SCCset);
02146 //    system("pause");
02147     // else figure entry states and entry transitions of the SCCs
02148     SccEntries(rResGen,SccSet,EntryStates,EntryTransSet);
02149     
02150     // root states are kept as entry states of the original SCCs, for all other
02151     // entry states clone SCCs:
02152     notRoots=EntryStates - Roots;
02153     //cout<<"...found "<<notRoots.Size()<<" entry states that are not roots. Start cloning SCCs..."<<endl;
02154 //    cout<<endl<<"EntryStates before cloning:"<<endl;
02155 //    EntryStates.DWrite();
02156 //    cout<<endl<<"Roots before cloning:"<<endl;
02157 //    Roots.DWrite();
02158 //    cout<<endl<<"notRoots before cloning:"<<endl;
02159 //    notRoots.DWrite();
02160 
02161     StateSet::Iterator sit=notRoots.Begin();
02162     StateSet::Iterator sit_end=notRoots.End();
02163     for(;sit!=sit_end;sit++)
02164         {
02165         // figure SCC with entry state sit:
02166     std::set<StateSet>::iterator sccit = SccSet.begin();
02167     std::set<StateSet>::iterator sccit_end = SccSet.end();
02168         for (; sccit != sccit_end; ++sccit)
02169             {
02170             if(sccit->Exists(*sit))
02171                 {
02172                 Scc=*sccit;
02173                 break;
02174                 }
02175             }
02176         // clone this SCC (and add clone to SCCset):
02177 //        cout<<"cloning SCCC:"<<endl;
02178 //        SCC.DWrite();
02179         CloneScc(rResGen,Scc,SccSet,*sit,EntryStates,EntryTransSet);
02180 //        cout<<endl<<"New set of SCCs:"<<endl;
02181 //        WriteStateSets(SccSet);
02182         }
02183     //cout<<endl<<"...done. Identifying unique entry states...";
02184 //    rResGen.Write("tmp_YcAcyclic_step.gen");
02185 //    rResGen.DotWrite("tmp_YcAcyclic_step");
02186 //    ++i;
02187 //    cout<<endl<<"Printed intermediate result "<<i<<"."<<endl;
02188 //    system("pause");
02189 
02190     // Now, all SCCs have one unique entry state.
02191     // If some SCC contains a sub-SCC that a) includes the entry
02192     // state of the whole SCC and b) consists of only unmarked
02193     // states, then this sub-SCC has to be copied to resolve the
02194     // ambiguity.
02195     if( !(  ((rResGen.States()-rResGen.MarkedStates())*EntryStates).Empty()  ) ) {
02196         // find possible unmarked sub-SCCs including EntryState
02197         YclessUnmarkedScc(rResGen,rYc,UnMarkedSccSet,UnMarkedRoots);
02198         std::set<StateSet>::iterator sccit = UnMarkedSccSet.begin();
02199         std::set<StateSet>::iterator sccit_end = UnMarkedSccSet.end();
02200         for (; sccit != sccit_end; ++sccit) {
02201             // check if this unmarked sub-SCC includes an EntryState; if so: clone it
02202             if(  !( ((*sccit)*EntryStates).Empty() )  ) {
02203                  Idx EntryState=*(((*sccit)*EntryStates).Begin());
02204                  CloneUnMarkedScc(rResGen,*sccit,EntryState,EntryStates,EntryTransSet);
02205                 }
02206         }
02207     }
02208         
02209     
02210     
02211     //"Back transitions" leading
02212     // from a SCC to its own entry state have to be cancelled,
02213     // if they are not Yc-transitions:
02214 
02215     // 2) loop through all SCCs and find Ycless back transitions:
02216     TransSet TransToClear;
02217     std::set<StateSet>::iterator sccit = SccSet.begin();
02218     std::set<StateSet>::iterator sccit_end = SccSet.end();
02219     //cout<<endl<<"Determining non-yc-backtransitions...";
02220     for (; sccit != sccit_end; ++sccit)
02221         {
02222         //loop through all states:
02223         StateSet::Iterator sit = sccit->Begin();
02224         StateSet::Iterator sit_end = sccit->End();
02225         for (; sit != sit_end; ++sit)
02226             {
02227             //cout<<endl<<"looping state "<<*sit<<endl;
02228             // loop through all transitions:
02229             TransSet::Iterator tit=rResGen.TransRelBegin(*sit);
02230             TransSet::Iterator tit_end=rResGen.TransRelEnd(*sit);
02231             for(;tit!=tit_end;tit++)
02232                 {
02233                 // Check if tit leads back to entry state of current SCC
02234                 // and if it is not a Yc-transition:
02235                 if(sccit->Exists(tit->X2) && EntryStates.Exists(tit->X2)
02236                    &&!rYc.Exists(tit->Ev))
02237                     {
02238                     //cout<<" - Trans to clear: "<<tit->Ev<<endl;
02239                     TransToClear.Insert(*tit);
02240                     }
02241                 }
02242             }
02243         }
02244     //cout<<endl<<"...found "<<TransToClear.Size()<<" transitions. Deleting these transitions...";
02245     // 3) Clear back transitions:
02246     TransSet::Iterator tit=TransToClear.Begin();
02247     TransSet::Iterator tit_end=TransToClear.End();
02248     for(;tit!=tit_end;tit++)
02249         {
02250         //cout<<"clearing transition ("<<tit->X1<<","<<rResGen.EventName(tit->Ev)<<","<<tit->X2<<")"<<endl;
02251         rResGen.ClrTransition(*tit);
02252         }
02253         
02254 //    ++i;
02255 //    rResGen.Write("tmp_YcAcyclic_step.gen");
02256 //    rResGen.DotWrite("tmp_YcAcyclic_step");
02257 //    cout<<endl<<"Printed intermediate result "<<i<<"."<<endl;
02258 //    system("pause");
02259 //    cout<<endl<<"...transitions deletetd, next round!";
02260 //     cout<<endl<<"state size of current intermediate result: "<<rResGen.Size();
02261      //cout<<endl<<". Press enter to start statemin."<<endl;
02262      //string anykey;
02263      //getline( cin, anykey );
02264 
02265 //     cout<<". Statemin...";
02266 //     Generator tmp;
02267 //     StateMin(rResGen,tmp);
02268 //     cout<<"done. New Statesize:"<<tmp.Size();
02269 //     rResGen=tmp;
02270 //     tmp.Clear();
02271 
02272 //    system("pause");
02273     } //end while(true): resulting generator might contain SCCs within the
02274       // SCCs that have been "broken" in this step -> continue while-loop.
02275 }
02276 
02277 //**********************************************************
02278 //******************** hio synthesis ************************
02279 //**********************************************************
02280 
02281 // ConstrSynth_Beta(rPlant,rYp,rUp,rOpConstr)
02282 void ConstrSynth_Beta(
02283         Generator& rPlant,
02284   const EventSet& rYp,
02285   const EventSet& rUp,
02286   const Generator& rLocConstr,
02287   Generator& rOpConstraint) {
02288   
02289     FD_DF("ConstrSynth_Beta(...)");
02290   
02291   // helper
02292   Generator tmpGen;
02293   EventSet sigmap=rYp+rUp;
02294   
02295   //prepare rsult:
02296   rOpConstraint.Clear();
02297   
02298   // respect optional local constraints
02299   Parallel(rPlant,rLocConstr,rOpConstraint);
02300   
02301   // calculate YpAcyclic sublanguage:
02302   YcAcyclic(rOpConstraint,rYp,tmpGen);
02303   rOpConstraint.Clear();
02304   
02305   // compute normal, complete, controllable and nonblocking sublanguage
02306   // note: tmpGen has role of spec
02307   NormalCompleteSynthNB(rPlant,rUp,sigmap,tmpGen,rOpConstraint);
02308   tmpGen.Clear();
02309   
02310   // project to P-Alphabet
02311   Project(rOpConstraint,sigmap,tmpGen);
02312   rOpConstraint.Clear();
02313   
02314   // minimize state space
02315   StateMin(tmpGen,tmpGen);
02316   tmpGen.StateNamesEnabled(false);
02317   
02318   // eneable symbolic state names for error states
02319   tmpGen.StateNamesEnabled(true);
02320   rOpConstraint.StateNamesEnabled(true);
02321   // make YP free in OpConstr
02322   HioFreeInput(tmpGen, rYp, rUp, rOpConstraint, "errUp","errYp");
02323 
02324   rOpConstraint.Name("ConstrSynth_Beta("+rPlant.Name()+")");
02325   
02326   return;
02327   }
02328 
02329 // HioSynthUnchecked(rPlant,rSpec,rConstr,rLocConstr,rYc,rUc,rYp,rUp,rYel,rUel,rController)
02330 void HioSynthUnchecked(
02331   const Generator& rPlant,
02332   const Generator& rSpec,
02333   const Generator& rExtConstr,
02334   const Generator& rLocConstr,
02335   const EventSet& rYc,
02336   const EventSet& rUc, 
02337   const EventSet& rYp,
02338   const EventSet& rUp, 
02339   const EventSet& rYel,
02340   const EventSet& rUel,
02341   Generator& rController)
02342 { 
02343   FD_DF("HioSynth(...)");
02344   //prepare rsult:
02345   rController.Clear();
02346   //make copy of plant, spec for modifications
02347   Generator plant,spec;
02348   plant = rPlant;
02349   spec = rSpec;
02350   
02351   //create necessary eventsets:
02352   EventSet sigmacp;
02353   sigmacp.SetUnion(rUc + rYc + rUp + rYp);
02354   EventSet sigmace;
02355   sigmace.SetUnion(rUc + rYc + rUel + rYel);
02356   
02357   EventSet allsigma;
02358   allsigma.SetUnion(rPlant.Alphabet());
02359   allsigma.SetUnion(rSpec.Alphabet());
02360   
02361   EventSet controllable, wait;
02362   controllable.SetUnion(rUp);
02363   controllable.SetUnion(rYc);
02364 
02365   //make alphabets of plant and spec match:
02366   InvProject(plant,allsigma);
02367   InvProject(spec,allsigma);
02368   
02369   // FD_DF("******************** actual plant: composition with external constraints");
02370   
02371   // generate plant under constraint:
02372   Parallel(plant,rExtConstr,plant);
02373   //plant.Write("tmp_cplant.gen");
02374   
02375   //FD_DF("******************** mininmal hio structure, composition with plant");
02376   Generator minhio;
02377   minhio = HioSortCL(rYc,rUc,rYp,rUp,rYel,rUel);
02378   //minhio.Write("tmp_minhio.gen");
02379   
02380   // generate plant in hio structure:
02381   Parallel(plant,minhio,plant);
02382   plant.StateNamesEnabled(false);
02383   //plant.Write("tmp_hiocplant.gen");
02384   
02385   //FD_DF("******************** composition plant-specification: tmp_plantspec.gen ");
02386   
02387   // composition of plant, I/O sorting, constraint and specification:
02388   Generator plantspec;
02389   Parallel(plant,spec,plantspec);
02390   //plantspec.Write("tmp_plantspec.gen");
02391   plantspec.StateNamesEnabled(false);
02392   FD_DF("Size of plantspec: "<<plantspec.Size()<<" - Statemin...");
02393   StateMin(plantspec,plantspec);
02394   FD_DF("done. New Statesize: "<<plantspec.Size()<<".");
02395   plantspec.StateNamesEnabled(false);
02396     //plantspec.Write("results/tmp_plantspec.gen");
02397   FD_DF("******************** computing YcAcyclic(plantspec):");
02398   
02399   // calculate YcAcyclic sublanguage of plantspec:
02400   Generator yclifeplantspec;
02401   YcAcyclic(plantspec,rYc,yclifeplantspec);
02402   yclifeplantspec.StateNamesEnabled(false);
02403   //yclifeplantspec.Write("tmp_YcAcyclic.gen");
02404   
02405   //FD_DF("******************** actual spec: composition yclifeplantspec||minhio||locconstr (tmp_actualspec.gen)");
02406   //generate plantspec with closed-loop I/O sorting:
02407   Parallel(yclifeplantspec,minhio,plantspec);
02408   yclifeplantspec.Clear();
02409   //add local constraints to plantspec: the result is the actual spec for synthesis
02410   Parallel(plantspec,rLocConstr,plantspec);
02411   plantspec.StateNamesEnabled(false);
02412   plantspec.Name("actualspec");
02413   //plantspec.Write("tmp_actualspec.gen");
02414   
02415   //FD_DF("******************** closed loop synthesis: tmp_closedloop.gen/.dot");
02416   
02417   // compute normal, complete and controllable sublangugae of actualspec w.r.t. plant under constraints (cplant):
02418   Generator loop;
02419   NormalCompleteSynthNB(plant,controllable,sigmacp,plantspec,loop);
02420   plantspec.Clear();
02421   //loop.Write("tmp_closedloop.gen");
02422   
02423   FD_DF("size of closed loop before StateMin: "<<loop.Size()<<", starting StateMin...");
02424   StateMin(loop,loop);
02425   FD_DF("...size of closed loop after StateMin (tmp_closedloop.gen): "<<loop.Size());
02426     //std::cout<<"ClosedLoop.IsTrim: "<<loop.IsTrim();
02427   loop.StateNamesEnabled(false);
02428   // loop.Write("tmp_closedloop.gen");
02429   FD_DF("********* IsYcLive(closed loop): "<<IsYcLive(loop,rYc));
02430   plant.Clear();
02431   
02432   //calculate external closedloop:
02433   FD_DF("******************** external closed loop: tmp_extloop.gen");
02434   Generator extloop;
02435   Project(loop,sigmace,extloop);
02436   FD_DF("size of external closed loop: "<<extloop.Size());
02437   
02438   // // recheck if specification is met:
02439   // if(LanguageInclusion(extloop,rSpec)) {
02440     // FD_DF("External closed loop meets specification.");
02441       // } // Perk: change below to LanguageInclusion with reverse order of parameters
02442       // // and move into above bracket.
02443   // if(LanguageEquality(extloop,rSpec)) {
02444     // FD_DF("External closed loop EQUALS specification.");
02445       // }
02446   
02447   extloop.StateNamesEnabled(false);
02448   //extloop.Write("tmp_extloop.gen");
02449   
02450   FD_DF("******************** project closed loop: tmp_controller.gen");
02451   
02452   Generator controller;
02453   Project(loop,sigmacp,controller);
02454   loop.Clear();
02455   controller.StateNamesEnabled(false);
02456   //controller.Write("tmp_controller.gen");
02457   
02458   // extend to io-controller: result
02459   HioFreeInput(controller, rYp, rUp, rController, "errUp","errYp");
02460   controller.Clear();
02461   FD_DF("size of marked IO controller: "<<rController.Size()<<". PrefixClosure, StateMin...");
02462   
02463   // the following procedure erases all marking information to reduce the result's state space! This step is unproblematic as long as the specification
02464   // is a prefix-closed system, because then, all marking information comes from the plant and is restored in the closed loop. Otherwise, care has to be taken
02465   // wether this step is correct or should be omitted .
02466   if(!(rSpec.AccessibleSet()<=rSpec.MarkedStates())) {
02467   FD_WARN("Careful: marking information of the specification has been erased from the resulting controller.");
02468   }
02469   PrefixClosure(rController);
02470   StateMin(rController,rController);
02471   FD_DF("...size of prefix-closed IO controller after StateMin: "<<rController.Size());
02472   rController.StateNamesEnabled(false);
02473   rController.Name("HioSynth("+rPlant.Name()+","+rSpec.Name()+")");
02474   FD_DF("IO controller synthesis done. ******************** " );
02475 }
02476 
02477 // HioSynth(rPlant,rSpec,rConstr,rLocConstr,rYc,rUc,rYp,rUp,rYel,rUel,rController)
02478 void HioSynth(
02479   const Generator& rPlant,
02480   const Generator& rSpec,
02481   const Generator& rExtConstr,
02482   const Generator& rLocConstr,
02483   const EventSet& rYc,
02484   const EventSet& rUc, 
02485   const EventSet& rYp,
02486   const EventSet& rUp, 
02487   const EventSet& rYel,
02488   const EventSet& rUel,
02489   Generator& rController)
02490 { 
02491   
02492   rController.Clear();
02493   
02494   #ifdef FAUDES_CHECKED
02495   // exception on empty alphabets
02496   if (rYc.Empty()){
02497    std::stringstream errstr;
02498    errstr << "Empty Yc alphabet\n";
02499    throw Exception("HioSynth", errstr.str(), 0);
02500   }
02501   if (rUc.Empty()){
02502    std::stringstream errstr;
02503    errstr << "Empty Uc alphabet\n";
02504    throw Exception("HioSynth", errstr.str(), 0);
02505   }
02506   if (rYp.Empty()){
02507    std::stringstream errstr;
02508    errstr << "Empty Yp alphabet\n";
02509    throw Exception("HioSynth", errstr.str(), 0);
02510   }
02511   if (rUp.Empty()){
02512    std::stringstream errstr;
02513    errstr << "Empty Up alphabet\n";
02514    throw Exception("HioSynth", errstr.str(), 0);
02515   }
02516   if (rYel.Empty()){
02517    std::stringstream errstr;
02518    errstr << "Empty Ye alphabet\n";
02519    throw Exception("HioSynth", errstr.str(), 0);
02520   }
02521   if (rUel.Empty()){
02522    std::stringstream errstr;
02523    errstr << "Empty Ue alphabet\n";
02524    throw Exception("HioSynth", errstr.str(), 0);
02525   }
02526   
02527   // create resulting alphabet while checking for disjoint sets
02528   EventSet alphabet,errevents;
02529   // initialize with rYc
02530   alphabet.SetUnion(rYc);
02531   // insert remaining events one by one and check if new
02532   EventSet::Iterator evit;
02533   // rUc
02534   for (evit = rUc.Begin(); evit != rUc.End(); ++evit) {
02535     if(!(alphabet.Insert(*evit))) errevents.Insert(*evit);
02536   }
02537   // rYp
02538   for (evit = rYp.Begin(); evit != rYp.End(); ++evit) {
02539     if(!(alphabet.Insert(*evit))) errevents.Insert(*evit);
02540   }
02541   // rUp
02542   for (evit = rUp.Begin(); evit != rUp.End(); ++evit) {
02543     if(!(alphabet.Insert(*evit))) errevents.Insert(*evit);
02544   }
02545   // rYe
02546   for (evit = rYel.Begin(); evit != rYel.End(); ++evit) {
02547     if(!(alphabet.Insert(*evit))) errevents.Insert(*evit);
02548   }
02549   // rUe
02550   for (evit = rUel.Begin(); evit != rUel.End(); ++evit) {
02551     if(!(alphabet.Insert(*evit))) errevents.Insert(*evit);
02552   }
02553   // throw exception on non disjoint alphabets
02554   if (!errevents.Empty()){
02555      std::stringstream errstr;
02556      errstr << "Non-disjoint parameters; ambiguous events:\n" <<errevents.ToString();
02557    throw Exception("HioSynth", errstr.str(), 0);
02558   }
02559   // check alphabet matches:
02560   EventSet plantEvents, specEvents;
02561   plantEvents=rPlant.Alphabet();
02562   specEvents=rSpec.Alphabet();
02563   // plant and spec must share environment alphabet
02564   if (!(plantEvents*specEvents==rYel+rUel)){
02565      std::stringstream errstr;
02566      errstr << "Alphabet mismatch between plant and spec:\n";
02567      errstr << "plant: " << plantEvents.ToString() << "\n";
02568      errstr << "spec: " << specEvents.ToString() << "\n";
02569      errstr << "Yel+Uel:   " << (rYel+rUel).ToString() << "\n";
02570    throw Exception("HioSynth", errstr.str(), 0);  
02571   }
02572   // ExtConstr must relate to spec alphabet
02573   if (!(rExtConstr.Alphabet()<=specEvents)){
02574     std::stringstream errstr;
02575     errstr << "Alphabet mismatch between external constraints and spec.\n";
02576   throw Exception("HioSynth", errstr.str(), 0);
02577   }
02578   // LocConstr must relate to plant alphabet
02579   if (!(rLocConstr.Alphabet()<=plantEvents)){
02580     std::stringstream errstr;
02581     errstr << "Alphabet mismatch between internal constraints and plant.\n";
02582   throw Exception("HioSynth", errstr.str(), 0);
02583   }
02584   
02585   // check I/O plant form of spec (note: plant may be composed group and thus need not be in I/o plant form)
02586   HioPlant spec(rSpec,rYc,rUc,rYel,rUel);
02587   std::string report;
02588   if(!IsHioPlantForm(spec,report)){
02589     std::stringstream errstr;
02590     errstr << "Spec not in HioPlantForm:\n" << report;
02591   throw Exception("HioSynth", errstr.str(), 0);
02592   }
02593   report.clear();
02594   #endif
02595   
02596   // do hio synthesis
02597   HioSynthUnchecked(rPlant,rSpec,rExtConstr,rLocConstr,rYc,rUc,rYp,rUp,rYel,rUel,rController);
02598 }
02599 
02600 // HioSynthMonolithic(rPlant,rSpec,rSc,rSp,rSe,rController)
02601 void HioSynthMonolithic(
02602   const HioPlant& rPlant,
02603   const HioPlant& rSpec,
02604   const HioConstraint& rSc,
02605   const HioConstraint& rSp,
02606   const HioConstraint& rSe,
02607   HioController& rController) {
02608   
02609   rController.Clear();
02610   
02611   #ifdef FAUDES_CHECKED
02612   // check I/O plant form of rPlant (further parameter checks in HioSynth())
02613   // tmp non-const copy of const rPlant
02614   HioPlant plant=rPlant;
02615   std::string report;
02616   if(!IsHioPlantForm(plant,report)){
02617     std::stringstream errstr;
02618     errstr << "Plant not in HioPlantForm:\n" << report;
02619   throw Exception("HioSynthMonolithic", errstr.str(), 0);
02620   }
02621   plant.Clear();
02622   report.clear();
02623   #endif
02624   
02625   // extract alphabets
02626   EventSet yc,uc,yp,up,ye,ue;
02627   yc=rSpec.YpEvents();
02628   uc=rSpec.UpEvents();
02629   yp=rPlant.YpEvents();
02630   up=rPlant.UpEvents();
02631   ye=rSpec.YeEvents();
02632   ue=rSpec.UeEvents();
02633   
02634   // generator for composed external constraints
02635   Generator extConstr;
02636   Parallel(rSc,rSe,extConstr);
02637   
02638   // run HioSynth procedure
02639   HioSynth(rPlant,rSpec,extConstr,rSp,yc,uc,yp,up,ye,ue,rController);
02640   
02641   // set event and state attributes
02642   rController.SetYc(yc);
02643   rController.SetUc(uc);
02644   rController.SetYp(yp);
02645   rController.SetUp(up);
02646   
02647   IsHioControllerForm(rController);
02648 }
02649 
02650 void HioSynthHierarchical(
02651   const HioPlant& rHioShuffle,
02652   const HioEnvironment& rEnvironment,
02653   const HioPlant& rSpec,
02654   const Generator& rIntConstr,
02655   const HioConstraint& rSc,
02656   const HioConstraint& rSl,
02657   HioController& rController) {
02658   
02659   rController.Clear();
02660   
02661   #ifdef FAUDES_CHECKED
02662   // check I/O plant form of rPlant (further parameter checks in HioSynth())
02663   // tmp non-const copy of const rPlant
02664   HioPlant plant=rHioShuffle;
02665   std::string report;
02666   if(!IsHioPlantForm(plant,report)){
02667     std::stringstream errstr;
02668     errstr << "HioShuffle not in HioPlantForm:\n" << report;
02669   throw Exception("HioSynthHierarchical", errstr.str(), 0);
02670   }
02671   plant.Clear();
02672   report.clear();
02673   
02674   // check I/O environment form
02675   // tmp non-const copy of const rEnvironment
02676   HioEnvironment env=rEnvironment;
02677   if(!IsHioEnvironmentForm(env,report)){
02678     std::stringstream errstr;
02679     errstr << "Environment not in HioEnvironmentForm:\n" << report;
02680   throw Exception("HioSynthHierarchical", errstr.str(), 0);
02681   }
02682   env.Clear();
02683   report.clear();
02684   
02685   // check for matching alphabets between ioshuffle, environment and spec
02686   if (!(rHioShuffle.EEvents()==rEnvironment.EEvents())){
02687     std::stringstream errstr;
02688     errstr << "Alphabet mismatch between I/O-shuffle and environment.\n";
02689   throw Exception("HioSynthHierarchical", errstr.str(), 0);
02690   }  
02691   // check for matching alphabets between ioshuffle, environment and spec
02692   if (!(rSpec.EEvents()==rEnvironment.LEvents())){
02693     std::stringstream errstr;
02694     errstr << "Alphabet mismatch between specification and environment.\n";
02695   throw Exception("HioSynthHierarchical", errstr.str(), 0);
02696   }
02697   
02698    //(further parameter checks in HioSynth())
02699    
02700   #endif
02701   // compose ioshuffle and environment
02702   Generator ioShuffParEnv;
02703   Parallel(rHioShuffle,rEnvironment,ioShuffParEnv);
02704   
02705   // extract alphabets
02706   EventSet yc,uc,yp,up,ye,ue;
02707   yc=rSpec.YpEvents();
02708   uc=rSpec.UpEvents();
02709   yp=rHioShuffle.YpEvents();
02710   up=rHioShuffle.UpEvents();
02711   ye=rSpec.YeEvents();
02712   ue=rSpec.UeEvents();
02713   
02714   // generator for composed external constraints
02715   Generator extConstr;
02716   Parallel(rSc,rSl,extConstr);
02717   
02718   // run HioSynth procedure
02719   HioSynth(ioShuffParEnv,rSpec,extConstr,rIntConstr,yc,uc,yp,up,ye,ue,rController); 
02720   
02721   // set event and state attributes
02722   rController.SetYc(yc);
02723   rController.SetUc(uc);
02724   rController.SetYp(yp);
02725   rController.SetUp(up);
02726   
02727   IsHioControllerForm(rController);
02728 }
02729 
02730 // end of hio_functions - below just archive 
02731 
02732 //######################################################
02733 //############ Special versions for HioModule - will soon be obsolete
02734 
02735 //HioShuffle_Musunoi() - Version with hio-parameters
02736 void HioShuffle_Musunoi(
02737   const HioPlant& rPlantA, 
02738   const HioPlant& rPlantB, 
02739   int depth, 
02740   Generator& rIOShuffAB) 
02741 { 
02742   FD_DF("HioShuffle()_Musunoi");
02743 
02744   //Extract alphabets:             
02745   EventSet A,B,SigmaP, Yp, Up, Ye, Ue;
02746   Yp = rPlantA.YpEvents()+rPlantB.YpEvents();
02747   Ye = rPlantA.YeEvents()+rPlantB.YeEvents();
02748   Up = rPlantA.UpEvents()+rPlantB.UpEvents();
02749   Ue = rPlantA.UeEvents()+rPlantB.UeEvents();
02750   A = rPlantA.Alphabet();
02751   B = rPlantB.Alphabet();
02752   
02753 
02754   // parallel composition of plantA and plantB (i.e. shuffle as there are no shared events)
02755   Generator parallel1, parallel2;
02756   Parallel(rPlantA,rPlantB,parallel1);
02757 
02758   // restrict to event pairs [(SigA SigA)*+(SigB SigB)*]*, which results
02759   // in correct I/O sorting L_IO.
02760   Generator EventPairs; // generator of above sorting language
02761   EventPairs.InjectAlphabet(A + B);
02762   Idx state1,state2,state3;
02763   state1=EventPairs.InsInitState("1");
02764   EventPairs.SetMarkedState(state1);
02765   state2=EventPairs.InsMarkedState("2");
02766   state3=EventPairs.InsMarkedState("3");
02767   EventSet::Iterator evit;
02768   for (evit = A.Begin(); evit != A.End(); ++evit) {
02769     EventPairs.SetTransition(state1,*evit,state2);
02770     EventPairs.SetTransition(state2,*evit,state1);
02771   }
02772   for (evit = B.Begin(); evit != B.End(); ++evit) {
02773     EventPairs.SetTransition(state1,*evit,state3);
02774     EventPairs.SetTransition(state3,*evit,state1);
02775   }
02776   Parallel(parallel1,EventPairs,parallel2);
02777 
02778   //restrict to IO-sorting structure with forced alternation:
02779 
02780   // Old Vers before Dez 4 2006: + of whole alphabets
02781   EventSet Ap, Bp, Ae, Be, SigmaE;
02782   
02783   Ap = rPlantA.Alphabet();
02784   Bp = rPlantB.Alphabet();
02785   
02786   Ae = rPlantA.Alphabet();
02787   Be = rPlantB.Alphabet();
02788   
02789   
02790 
02791   //*************************************************************************
02792   //// New Vers: Alternation of YP Events only
02793   //// -> currently leads to normality problems during superposed controller synthesis
02794   SigmaP.SetUnion(Yp);
02795   SigmaP.SetUnion(Up);
02796   Ap.SetIntersection(SigmaP);
02797   Bp.SetIntersection(SigmaP);
02798   
02799   SigmaE.SetUnion(Ye);
02800   SigmaE.SetUnion(Ue);
02801   Ae.SetIntersection(SigmaE);
02802   Be.SetIntersection(SigmaE);
02803   
02804   
02805   //*************************************************************************
02806   Generator AltAB;
02807   Ap.Name("A");
02808   Bp.Name("B");
02809   CheapAltAB(Ap,Bp,depth,AltAB);
02810   // Alt_AB.Write("tmp_Alternation_AB.gen");
02811   Parallel(parallel2, AltAB, parallel1);
02812   //parallel2.Write("tmp_IOS3.gen");
02813   
02814   
02815   
02816   //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02817   //*** Environment-first policy: If, in some state both, Yp- and Ye events are
02818   //*** active, then cancel all Yp-transitions in this state, as environment has
02819   //*** to be updated first.
02820 
02821   // loop all states
02822   StateSet::Iterator sit = parallel1.StatesBegin();
02823   StateSet::Iterator sit_end = parallel1.StatesEnd();
02824   
02825   for(; sit != sit_end; sit++)
02826   {
02827         // figure active Yp-events and active Ye-events
02828         //std::cout << "End: " << *sit_end <<"...done: " << *sit << std::endl;
02829         EventSet ActiveYe;
02830         EventSet ActiveYp = parallel1.TransRel().ActiveEvents(*sit);
02831         ActiveYe=ActiveYp;
02832         ActiveYe.SetIntersection(Ye);
02833         ActiveYp.SetIntersection(Yp);
02834             
02835         if (!(ActiveYe.Empty())&& !(ActiveYp.Empty()))
02836         {   
02837             TransSet TransToClear;
02838             TransSet::Iterator tit=parallel1.TransRelBegin(*sit);
02839             TransSet::Iterator tit_end=parallel1.TransRelEnd(*sit);
02840             for(;tit!=tit_end;tit++)
02841                 {
02842                 //std::cout << "finding Yp-events to delete... "; 
02843                 if(ActiveYp.Exists(tit->Ev))
02844                     {
02845                     TransToClear.Insert(*tit);
02846                     }
02847                 }
02848             tit=TransToClear.Begin();
02849             tit_end=TransToClear.End();
02850             for(;tit!=tit_end;tit++)
02851             {
02852             //std::cout<<" ...deleting" <<std::endl;
02853             parallel1.ClrTransition(*tit);
02854             }
02855         } 
02856   }  
02857   
02858   //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02859   
02860   
02861   
02862   // Insert Error Behaviour, i.e. make UP and UE free in (YP,UP)-port of result:
02863   // free UP:
02864           
02865   HioFreeInput(parallel1, Up, Yp, parallel2, "errYp_Ye", "errUp");
02866   //parallel1.Write("tmp_IOS4.gen");
02867   // free UE:
02868   HioFreeInput(parallel2, Ue, Ye, parallel1, "errYp_Ye", "errUe");
02869   //parallel2.Write("tmp_IOS5.gen");
02870 
02871   rIOShuffAB = parallel1;
02872 }
02873 
02874 // HioSynth_Musunoi()
02875 void HioSynth_Musunoi(const Generator& rPlant, const HioPlant& rSpec,
02876     const Generator& rConstr, const Generator& rLocConstr,
02877     const EventSet& rYp,  const EventSet& rUp, 
02878     Generator& rController)
02879     {
02880 EventSet rYc, rUc, rYe, rUe;
02881 rYc = (rSpec.YpEvents());
02882 rUc = (rSpec.UpEvents());
02883 rYe = (rSpec.YeEvents());
02884 rUe = (rSpec.UeEvents());
02885 
02886 
02887 //make copy of plant, spec, constr and alphabets
02888 Generator plant,spec,constr,locconstr;
02889 plant = rPlant;
02890 spec = rSpec;
02891 constr = rConstr;
02892 locconstr = rLocConstr;
02893 
02894 EventSet yc,uc,yp,up,ye,ue;
02895 yc = rYc;
02896 uc = rUc;
02897 yp = rYp;
02898 up = rUp;
02899 ye = rYe;
02900 ue = rUe;
02901 
02902 //create necessary eventsets:
02903 EventSet sigmacp;
02904 sigmacp.SetUnion(rUc + rYc + rUp + rYp);
02905 EventSet sigmace;
02906 sigmace.SetUnion(rUc + rYc + rUe + rYe);
02907 
02908 EventSet allsigma;
02909 allsigma.SetUnion(rPlant.Alphabet());
02910 allsigma.SetUnion(rSpec.Alphabet());
02911 
02912 EventSet controllable;
02913 controllable.SetUnion(up);
02914 controllable.SetUnion(yc);
02915 
02916 //make alphabets of plant and spec match:
02917 InvProject(plant,allsigma);
02918 InvProject(spec,allsigma);
02919 
02920  FD_DF("******************** actual plant: composition with environment constraint: tmp_cplant.gen ");
02921 
02922 // generate plant under constraint:
02923 Generator cplant;
02924 Parallel(plant,constr,cplant);
02925 //cplant.Write("tmp_cplant.gen");
02926 
02927  FD_DF("******************** mininmal hio structure: tmp_minhio.gen, composition with plant: tmp_hioplant.gen ");
02928 Generator minhio;
02929 minhio = HioSortCL(yc,uc,yp,up,ye,ue);
02930 //minhio.Write("tmp_minhio.gen");
02931 
02932 // generate plant in hio structure:
02933 Generator hiocplant;
02934 Parallel(cplant,minhio,hiocplant);
02935 //hiocplant.Write("tmp_hiocplant.gen");
02936 
02937  FD_DF("******************** composition plant-specification: tmp_plantspec.gen ");
02938 
02939 // composition of plant, I/O sorting, constraint and specification:
02940 Generator plantspec,plantspecMin;
02941 Parallel(hiocplant,spec,plantspec);
02942 //plantspec.Write("tmp_plantspec.gen");
02943 plantspec.StateNamesEnabled(false);
02944 // plantspec.DotWrite("tmp_plantspec");
02945  FD_DF("Size of plantspec: "<<plantspec.Size()<<" - Statemin...");
02946 //string anykey;
02947 //getline(cin,anykey);
02948 StateMin(plantspec,plantspecMin);
02949  FD_DF("done. New Statesize: "<<plantspecMin.Size()<<".");
02950 plantspec=plantspecMin;
02951 plantspecMin.Clear();
02952 plantspec.StateNamesEnabled(false);
02953  FD_DF("******************** computing YcAcyclic(plantspec):");
02954 
02955 // calculate YcAcyclic sublanguage of plantspec:
02956 Generator yclifeplantspec;
02957 YcAcyclic(plantspec,yc,yclifeplantspec);
02958 Generator yclifeplantspecMin;
02959 //cout <<endl<< "                     StateMin(yclifeplantspec)..."  << endl;
02960 //StateMin(yclifeplantspec,yclifeplantspecMin);
02961 //cout<<endl<<"Statesize of yclifeplantspec after StateMin (tmp_YcAcyclic_Min.gen): "<<yclifeplantspecMin.Size();
02962 yclifeplantspecMin=yclifeplantspec;
02963 yclifeplantspecMin.StateNamesEnabled(false);
02964 //yclifeplantspecMin.Write("tmp_YcAcyclic_Min.gen");
02965 
02966  FD_DF("******************** actual spec: composition yclifeplantspec||minhio||locconstr (tmp_actualspec.gen)");
02967 //generate plantspec with closed-loop I/O sorting:
02968 Parallel(yclifeplantspecMin,minhio,plantspec);
02969 
02970 //add local constraints to plantspec: the result is the actual spec for synthesis
02971 Generator actualspec;
02972 Parallel(plantspec,locconstr,actualspec);
02973 //actualspec.Write("tmp_actualspec.gen");
02974 
02975  FD_DF("******************** closed loop synthesis: tmp_closedloop.gen/.dot");
02976 
02977 //std::cout<<"Starting NormalCompleteSynth....";
02978 FD_DF("Starting NormalCompleteSynth....");
02979 
02980 // compute normal, complete and controllable sublangugae of actualspec w.r.t. plant under constraints (cplant):
02981 Generator loop;
02982  NormalCompleteSynth(hiocplant,controllable,yc+uc+yp+up,actualspec,loop);
02983 //loop.Write("tmp_closedloop.gen");
02984 //loop.DotWrite("tmp_closedloop");
02985 
02986  FD_DF("size of closed loop before StateMin: "<<loop.Size()<<", starting StateMin...");
02987  
02988 //std::cout<<"Starting NormalCompleteSynth....done... starting StateMin";
02989 FD_DF("Starting NormalCompleteSynth....done... starting StateMin");
02990  
02991 Generator minloop;
02992 StateMin(loop,minloop);
02993  FD_DF("...size of closed loop after StateMin (tmp_closedloop.gen): "<<minloop.Size());
02994 //minloop=loop;
02995 minloop.StateNamesEnabled(false);
02996 //minloop.Write("tmp_closedloop.gen");
02997 // test: recheck for YCless SCCs:
02998 Generator minlooptest;
02999 minlooptest=minloop;
03000  std::set<StateSet> SccSet;
03001 YclessScc(minlooptest,yc,SccSet);
03002  FD_DF("");
03003  FD_DF("*********number of Yc-less strongly connencted components in closed loop (should be zero): "
03004        <<SccSet.size());
03005 
03006 // minloop.DotWrite("tmp_minclosedloop");
03007 
03008 //calculate external closedloop:
03009  FD_DF("******************** external closed loop: tmp_extloop.gen/.dot");
03010 Generator extloop;
03011 Project(minloop,sigmace,extloop);
03012  FD_DF("size of external closed loop: "<<extloop.Size());;
03013 
03014 // recheck if specification is met:
03015 if(LanguageInclusion(extloop,rSpec)) {
03016   FD_DF("External closed loop meets specification.");
03017     }
03018 if(LanguageEquality(extloop,rSpec)) {
03019   FD_DF("External closed loop EQUALS specification.");
03020     }
03021 
03022 extloop.StateNamesEnabled(false);
03023 //extloop.Write("tmp_extloop.gen");
03024 //extloop.DotWrite("tmp_extloop");
03025 
03026  FD_DF("******************** project closed loop: tmp_controller.gen/.dot ");
03027 
03028 Generator controller;
03029 Project(minloop,sigmacp,controller);
03030 controller.StateNamesEnabled(false);
03031 //controller.Write("tmp_controller.gen");
03032 // controller.DotWrite("tmp_controller");
03033 
03034  FD_DF("******************** extend to IO controller: tmp_IOcontroller.gen/.dot ");
03035 
03036 // extend to io-controller
03037 Generator HioController, minIOcontroller;
03038  HioFreeInput(controller, yp, up, HioController, "errUp","errYp");
03039 //HioController.Write("tmp_IOcontroller.gen");
03040 // HioController.DotWrite("tmp_IOcontroller");
03041  FD_DF("size of IO controller: "<<HioController.Size()<<", StateMin...");
03042 StateMin(HioController,minIOcontroller);
03043  FD_DF("...size of IO controller after StateMin: "<<minIOcontroller.Size());
03044 minIOcontroller.StateNamesEnabled(false);
03045 //minIOcontroller.Write("tmp_IOcontroller.gen");
03046 
03047 // RESULT:
03048 rController = minIOcontroller;
03049 
03050 ////*******************************************************************
03051 // // uncomment this, if you use complete_synth, instead of
03052 // // normal_complete_synth, for controller design:
03053 
03054 //cout <<endl<< "******************** checking normality... "  << endl;
03055 //
03056 //if(!isnormal(minloop,hiocplant,sigmacp))
03057 //    {
03058 //    cout<<endl<<"isnormal says: false! :("<<endl;
03059 //    }
03060 //else
03061 //    {
03062 //    cout<<endl<<"isnormal says: true! :)"<<endl;
03063 //    }
03064 ////*******************************************************************
03065 
03066  FD_DF("IO controller synthesis done. ******************** " );
03067 }
03068 
03069 }//namespace faudes

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