libFAUDES

Sections

Index

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

libFAUDES 2.14g --- 2009-12-3 --- c++ source docu by doxygen 1.5.6