syn_supreduce.cpp

Go to the documentation of this file.
00001 /** @file syn_supreduce.cpp Supervisor Reduction */
00002 
00003 /* FAU Discrete Event Systems Library (libfaudes)
00004 
00005    Copyright (C) 2006  Bernd Opitz
00006    Exclusive copyright is granted to Klaus Schmidt
00007 
00008    This library is free software; you can redistribute it and/or
00009    modify it under the terms of the GNU Lesser General Public
00010    License as published by the Free Software Foundation; either
00011    version 2.1 of the License, or (at your option) any later version.
00012 
00013    This library is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016    Lesser General Public License for more details.
00017 
00018    You should have received a copy of the GNU Lesser General Public
00019    License along with this library; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00021    
00022 
00023 #include "syn_supreduce.h"
00024 
00025 
00026 namespace faudes {
00027 
00028 
00029 
00030 
00031 /*
00032 ***************************************************************************************
00033 ***************************************************************************************
00034  Implementation
00035 ***************************************************************************************
00036 ***************************************************************************************
00037 */
00038 
00039 
00040 // SupReduce(rPlantGen, rSupGen, rReducedSup)
00041 bool SupReduce(const System& rPlantGen, const System& rSupGen, System& rReducedSup) {
00042   FD_DF("SupReduce...");
00043 
00044   // CONSISTENCY CHECK:
00045 
00046   // alphabets must match
00047   if (rPlantGen.Alphabet() != rSupGen.Alphabet()) {
00048     EventSet only_in_plant = rPlantGen.Alphabet() - rSupGen.Alphabet();
00049     EventSet only_in_spec = rSupGen.Alphabet() - rPlantGen.Alphabet();
00050     std::stringstream errstr;
00051     errstr << "Alphabets of generators do not match. Only in plant: " 
00052       << only_in_plant.ToString() << ". Only in spec: "
00053       << only_in_spec.ToString() << ".";
00054     throw Exception("SupReduce", errstr.str(), 100);
00055   }
00056 
00057   // plant and spec must be deterministic
00058   bool plant_det = rPlantGen.IsDeterministic();
00059   bool sup_det = rSupGen.IsDeterministic();
00060 
00061   if ((plant_det == false) && (sup_det == true)) {
00062     std::stringstream errstr;
00063     errstr << "Plant generator must be deterministic, " << "but is nondeterministic";
00064     throw Exception("SupReduce", errstr.str(), 201);
00065   }
00066   else if ((plant_det == true) && (sup_det == false)) {
00067     std::stringstream errstr;
00068     errstr << "Supervisor generator must be deterministic, " << "but is nondeterministic";
00069     throw Exception("SupReduce", errstr.str(), 203);
00070   }
00071   else if ((plant_det == false) && (sup_det == false)) {
00072     std::stringstream errstr;
00073     errstr << "Plant and supervisor generator must be deterministic, "
00074                     << "but both are nondeterministic";
00075     throw Exception("SupReduce", errstr.str(), 204);
00076   }
00077   // Clear the result generator rReducedsup
00078   rReducedSup.Clear();
00079 
00080   // HELPERS:
00081   System previousSupReduced = rSupGen;
00082   std::vector<StateSet> class2States; // control equivalent states in supervisor
00083   std::map<Idx, Idx> state2Class; // map from state Idx to its control equivalent class
00084   std::vector<std::set<Idx> > waitList; // list of states for  classes to be merged
00085   EventSet alwaysEnabledEvents = rSupGen.Alphabet(); // set of events that are never disabled
00086   // Initialize the helpers that store information about the equivalence classes
00087   StateSet::Iterator sIt, sEndIt;
00088   sIt = rSupGen.States().Begin();
00089   sEndIt = rSupGen.States().End();
00090   for(; sIt != sEndIt; sIt++){ // Note: States are ordered by index
00091       class2States.push_back(StateSet() );
00092       class2States.back().Insert(*sIt); 
00093       state2Class[*sIt] = class2States.size() - 1;
00094   }
00095   // Evaluate the composition of plant and supervisor in order to classify corresponding states
00096   System tmp;
00097   std::map<std::pair<Idx,Idx>, Idx> reverseCompositionMap;
00098   std::map<std::pair<Idx,Idx>, Idx>::const_iterator rcIt, rcEndIt;
00099   Parallel(rPlantGen, rSupGen, reverseCompositionMap, tmp);
00100   rcIt = reverseCompositionMap.begin();
00101   rcEndIt = reverseCompositionMap.end();
00102   std::map<Idx,ReductionStateInfo> supStateInfo;
00103   std::map<Idx,ReductionStateInfo>::iterator rsIt;
00104   // Find the plant states that belong to each supervisor state
00105   for(; rcIt != rcEndIt; rcIt++){
00106       rsIt = supStateInfo.find(rcIt->first.second);
00107       if(rsIt == supStateInfo.end() )
00108   supStateInfo[rcIt->first.second] = ReductionStateInfo();
00109 
00110       supStateInfo[rcIt->first.second].mPlantStates.Insert(rcIt->first.first);
00111   }
00112   /*std::cout << "States per supervisor state " << std::endl;
00113   for(rsIt = supStateInfo.begin(); rsIt != supStateInfo.end(); rsIt++)
00114      std::cout << "sup state: " << rsIt->first << " plant states " << rsIt->second.mPlantStates.ToString() << std::endl;*/ // REMOVE
00115   // Determine the state properties for all supervisor stateset
00116   for(rsIt = supStateInfo.begin(); rsIt != supStateInfo.end(); rsIt++){
00117       rsIt->second.mEnabledEvents = rSupGen.ActiveEventSet(rsIt->first); // all events enabled at current state2Class
00118       sIt = rsIt->second.mPlantStates.Begin();
00119       sEndIt = rsIt->second.mPlantStates.End();
00120       rsIt->second.mPlantMarked = false;
00121       for(; sIt != sEndIt; sIt++){
00122    rsIt->second.mDisabledEvents = rsIt->second.mDisabledEvents + rPlantGen.ActiveEventSet(*sIt); // compute active events in plant_det for state *sIt
00123    rsIt->second.mPlantMarked = rsIt->second.mPlantMarked || rPlantGen.ExistsMarkedState(*sIt); // compute colors of corresponding plant states 
00124       }
00125   
00126       rsIt->second.mDisabledEvents = rsIt->second.mDisabledEvents - rsIt->second.mEnabledEvents; // compute disable events (events that are not enabled
00127       rsIt->second.mMarkedState = rSupGen.ExistsMarkedState(rsIt->first);
00128       alwaysEnabledEvents = alwaysEnabledEvents -  rsIt->second.mDisabledEvents; // subtract disabled events from always enabled events
00129   }
00130   //std::cout << "Always enabled events: " << alwaysEnabledEvents.ToString() << std::endl;
00131   // if no events are disabled, then the reduced supervisor has only one state without events
00132   if(rSupGen.Alphabet() == alwaysEnabledEvents){
00133       Idx state = rReducedSup.InsState();
00134       rReducedSup.SetMarkedState(state);
00135       rReducedSup.SetInitState(state);
00136       return true;
00137   }
00138   /*for(rsIt = supStateInfo.begin(); rsIt != supStateInfo.end(); rsIt++)
00139       std::cout << "state: " << rsIt->first << " enabled: " << rsIt->second.mEnabledEvents.ToString() << " disabled: " << rsIt->second.mDisabledEvents.ToString() << std::endl;*/ // REMOVE
00140   
00141   std::map<Idx,bool> usedEventsMap;
00142   EventSet::Iterator eIt = alwaysEnabledEvents.Begin();
00143   for( ; eIt != alwaysEnabledEvents.End(); eIt++)// map that indicates if always enabled event is relevant for supervisor (true) or not (false)
00144     usedEventsMap[*eIt] = false;
00145   // ==========================
00146   // Algorithm
00147   //===========================
00148   // go through all supervisor states
00149   std::map<Idx,Idx>::const_iterator mIt;
00150   std::map<Idx,Idx>::const_iterator mEndIt = state2Class.end();
00151   mEndIt--;
00152   std::map<Idx,Idx>::const_iterator mbIt, mbEndIt;
00153   mbEndIt = state2Class.end();
00154   
00155  /* std::cout << "Classes to states" << std::endl;
00156   for(unsigned int i = 0; i < class2States.size(); i ++)
00157      std::cout << "class: " << i << " state " << class2States[i].ToString() << std::endl;
00158   
00159   std::cout << "State to class" << std::endl;
00160   for(mIt = state2Class.begin(); mIt != state2Class.end(); mIt++)
00161     std::cout << "state: " << mIt->first << " class: " << mIt->second << std::endl; */ // REMOVE
00162   
00163   for(mIt = state2Class.begin(); mIt != mEndIt; mIt++){
00164     // Evaluate min{k \in I | x_k \in  [x_i]}; since StateSets are ordered by index, this simply means finding the first state in the class of x_i
00165     if( mIt->first > *class2States[mIt->second].Begin() ){// state is already in other equivalence class 
00166       continue;
00167     }
00168     mbIt = ++mIt;
00169     mIt--;
00170    //std::cout << "state i: " << mIt->first << std::endl;
00171     for(; mbIt != mbEndIt; mbIt++) {// approach from back
00172   //if(j > min{k \in I  | x_k \in [x_j]}
00173   if(mbIt->first > *class2States[mbIt->second].Begin() ){
00174     continue;
00175   }
00176   //std::cout << "state j: " << mbIt->first << std::endl;
00177   
00178   // Start actual algorithm after filtering
00179   waitList.clear();
00180   //if((mIt->first == 1 && mbIt->first == 4) ){
00181   //waitList.push_back(std::set<Idx>() );
00182   //waitList.back().insert(mIt->first);
00183   //waitList.back().insert(mbIt->first); REMOVE
00184   //}
00185   bool flag = CheckMergibility(mIt->first,mbIt->first,waitList,mIt->first, rSupGen, supStateInfo, state2Class, class2States);
00186   if(flag == true){// merge classes indicated by waitList
00187       std::vector<std::set<Idx> >::const_iterator wlIt, wlEndIt;
00188       //std::cout << "size of weitlist " << waitList.size() << std::endl;
00189       wlIt = waitList.begin();
00190       wlEndIt = waitList.end();
00191       for(; wlIt != wlEndIt; wlIt++){// go through waiting list
00192     //std::cout << " states " << *wlIt->begin() << " " << *(++wlIt->begin() ) << std::endl;
00193     if(state2Class[*wlIt->begin() ] == state2Class[*(++(wlIt->begin() ) ) ])// no action is required if the states are already in the same class
00194       continue;
00195     class2States[state2Class[*wlIt->begin() ] ] = class2States[state2Class[*wlIt->begin()] ] + class2States[state2Class[*(++(wlIt->begin() ) ) ] ]; // union of state sets of both classes
00196     Idx removeClass = state2Class[*(++(wlIt->begin() ) ) ];
00197     sIt = class2States[removeClass ].Begin();
00198     sEndIt = class2States[removeClass ].End();
00199     for(; sIt != sEndIt; sIt++)
00200       state2Class[*sIt] = state2Class[*wlIt->begin() ]; // change class of all states that were merged
00201       
00202     class2States[removeClass ].Clear(); // clear merged class 
00203 
00204       /*std::cout << "Classes to states" << std::endl;
00205       for(unsigned int i = 0; i < class2States.size(); i ++)
00206         std::cout << "class: " << i << " state " << class2States[i].ToString() << std::endl;
00207       
00208       std::cout << "State to class" << std::endl;
00209        std::map<Idx,Idx>::const_iterator cIt;
00210       for(cIt = state2Class.begin(); cIt != state2Class.end(); cIt++)
00211         std::cout << "state: " << cIt->first << " class: " << cIt->second << std::endl; */ // REMOVE
00212       }
00213   }
00214     }
00215   }
00216 
00217   // ===============================
00218   // Construct the reduced superisor
00219   // ===============================
00220   // Every state corresponds to a class that we found and we try to avoid adding trnasitions with always enabled events
00221   std::map<Idx,Idx> class2ReducedStates;
00222   Idx newStateIdx;
00223   rReducedSup.InjectAlphabet(rSupGen.Alphabet() );
00224   // First generate one state for each class in the reduced generator
00225   for(unsigned int i = 0; i < class2States.size(); i++){
00226     if(class2States[i].Empty() == true)// if the state set is empty, then the class is not used
00227   continue;
00228     else{// create new state in the reduced supervisor for the class
00229       newStateIdx = rReducedSup.InsState();
00230       class2ReducedStates[i ] = newStateIdx; // save state for the class
00231     }
00232   }// all states of the reduced generator are now generated and stored
00233 
00234   // Now add the transitions to the reduced generator
00235   TransSet::Iterator tIt, tEndIt;
00236   Idx newGoalState; // goal state for transition to be added
00237   for(unsigned int i = 0; i < class2States.size(); i++){
00238     if(class2States[i].Empty() == true)// if the state set is empty, then the class is not used
00239   continue;
00240     sIt = class2States[i].Begin();
00241     sEndIt = class2States[i].End();
00242     newStateIdx = class2ReducedStates[i]; 
00243     for(; sIt != sEndIt; sIt++){// go through all states of the current class
00244   if(rSupGen.ExistsInitState(*sIt) )// determine the initial state of the reduced supervisor
00245     rReducedSup.InsInitState(newStateIdx);
00246   
00247   if(rSupGen.ExistsMarkedState(*sIt) )
00248     rReducedSup.SetMarkedState(newStateIdx); // insert the supervisor colors per state
00249   
00250   tIt = rSupGen.TransRelBegin(*sIt); // transitions of state *sIt in supervisor
00251   tEndIt = rSupGen.TransRelEnd(*sIt); 
00252   for( ; tIt != tEndIt; tIt++){
00253     newGoalState = class2ReducedStates[state2Class[tIt->X2] ]; // goal state of transition in the reduced supervisor
00254     if(alwaysEnabledEvents.Exists(tIt->Ev) == true && newGoalState != newStateIdx )// always enabled event changes class and is thus relevant for supervisor
00255       usedEventsMap[tIt->Ev] = true;
00256     
00257     rReducedSup.SetTransition(newStateIdx, tIt->Ev, newGoalState); 
00258   }
00259     }
00260   }
00261   if(previousSupReduced.Size() == rReducedSup.Size() ){
00262     std::map<Idx,bool>::const_iterator uIt = usedEventsMap.begin();
00263     for(; uIt != usedEventsMap.end(); uIt++){// delete the unused events from the reduced supervisor
00264       if(uIt->second == false){
00265   rReducedSup.DelEvent(uIt->first);
00266       }
00267     }
00268   }
00269   else{
00270       previousSupReduced.Clear();
00271       Deterministic(rReducedSup,previousSupReduced);
00272       SupReduce(rPlantGen,previousSupReduced,rReducedSup);
00273   }
00274   return true;
00275 }
00276 
00277 // CheckMergibility(statep, stateq, rWaitingList, cNode)
00278 bool CheckMergibility(Idx stateI, Idx stateJ, std::vector<std::set<Idx> >& rWaitList, Idx cNode, const System& rSupGen,
00279        const std::map<Idx,ReductionStateInfo>& rSupStateInfo, const std::map<Idx,Idx>& rState2Class, const std::vector<StateSet>& rClass2States){
00280   // Loop through all state combinations in the current classes 
00281   //std::cout << "stateI " << stateI << " stateJ " << stateJ << " show Waitlist" << std::endl;
00282   /* for(unsigned int i = 0; i < rWaitList.size(); i++)
00283     std::cout << *rWaitList[i].begin() << " " << *(++rWaitList[i].begin() ) << std::endl;*/
00284   StateSet::Iterator siIt, siEndIt, sjIt, sjEndIt;
00285   StateSet statesI, statesJ;
00286   statesI = rClass2States[rState2Class.find(stateI)->second]; // all states of the class of stateI
00287   statesJ = rClass2States[rState2Class.find(stateJ)->second ]; // all states of the class of stateJ
00288   // add the states on the waitlist to statesI and statesJ
00289   for(unsigned int i = 0; i < rWaitList.size(); i++){
00290       // StateI
00291       if(*rWaitList[i].begin() == stateI )
00292   statesI = statesI + rClass2States[rState2Class.find(*(++rWaitList[i].begin() ) )->second]; // add classes for corresponding state on waitList
00293       if(*(++rWaitList[i].begin() ) == stateI )
00294   statesI = statesI + rClass2States[rState2Class.find(*rWaitList[i].begin() )->second];  // add classes for corresponding state on waitList
00295       // StateJ
00296       if(*rWaitList[i].begin() == stateJ )
00297   statesJ = statesJ + rClass2States[rState2Class.find(*(++rWaitList[i].begin() ) )->second]; // add classes for corresponding state on waitList
00298       if(*(++rWaitList[i].begin() ) == stateJ )
00299   statesJ = statesJ + rClass2States[rState2Class.find(*rWaitList[i].begin() )->second];  // add classes for corresponding state on waitList
00300   }
00301   //std::cout << "statesI " << statesI.ToString() << " stateJ " << statesJ.ToString() << std::endl;// REMOVE
00302   siIt = statesI.Begin(); // Iterators for states of class for stateI
00303   siEndIt = statesI.End();
00304   sjIt = statesJ.Begin(); // Iterators for states of class for stateJ
00305   sjEndIt = statesJ.End();  
00306   std::set<Idx> statePair;
00307   for( ; siIt != siEndIt; siIt++){// loop over states for stateI
00308     sjIt = statesJ.Begin();
00309     for(; sjIt != sjEndIt; sjIt++){ // loop over states for stateJ
00310       // only look at state pairs that are not already in the same class2ReducedStates
00311       if(rClass2States[rState2Class.find(*siIt)->second].Exists(*sjIt) )
00312   continue;
00313       
00314       statePair.clear();
00315       statePair.insert(*siIt);
00316       statePair.insert(*sjIt);
00317       //std::cout << "mergibility states: " << *siIt << " and " << *sjIt << std::endl;
00318 
00319       if(*siIt == *sjIt)
00320   continue;
00321       bool continueLoop = false;
00322       for(unsigned int i = 0; i < rWaitList.size(); i++)
00323   if(rWaitList[i] == statePair){
00324     continueLoop = true;
00325     break;
00326   }
00327       if(continueLoop == true)// the current state pair is already on the waiting list
00328     continue;
00329       
00330       // tmoor: fix nonstandard std::map::at()
00331       const ReductionStateInfo& siinf=rSupStateInfo.find(*siIt)->second;
00332       const ReductionStateInfo& sjinf=rSupStateInfo.find(*sjIt)->second;
00333 
00334       // Check if the state pair belongs to the control relation \mathcal{R}: 
00335       // E(*siIt) \cap D(*sjIt) = E(*sjIt) \cap D(*siIt) = \emptyset and C(*siIt) = C(*sjIt) \Rightarrow M(*siIt) = M(*sjIt)
00336       if( !(siinf.mEnabledEvents * sjinf.mDisabledEvents).Empty() ) return false;
00337       if( !(sjinf.mEnabledEvents * siinf.mDisabledEvents).Empty() ) return false;
00338       
00339       // Check if the marking of the states is consistent
00340       if( (siinf.mPlantMarked == sjinf.mPlantMarked) && (siinf.mPlantMarked != sjinf.mPlantMarked) )
00341   return false;
00342 
00343 
00344 
00345       /*
00346       // original (for reference)
00347   
00348       // Check if the state pair belongs to the control relation \mathcal{R}: 
00349       // E(*siIt) \cap D(*sjIt) = E(*sjIt) \cap D(*siIt) = \emptyset and C(*siIt) = C(*sjIt) \Rightarrow M(*siIt) = M(*sjIt)
00350       if( !(rSupStateInfo.at(*siIt).mEnabledEvents * rSupStateInfo.at(*sjIt).mDisabledEvents).Empty() || 
00351   !(rSupStateInfo.at(*sjIt).mEnabledEvents * rSupStateInfo.at(*siIt).mDisabledEvents).Empty() ) 
00352   return false;
00353       
00354       // Check if the marking of the states is consistent
00355       if( (rSupStateInfo.at(*siIt).mPlantMarked == rSupStateInfo.at(*sjIt).mPlantMarked) && (rSupStateInfo.at(*siIt).mPlantMarked != rSupStateInfo.at(*sjIt).mPlantMarked) )
00356   return false;
00357 
00358       */     
00359       rWaitList.push_back(std::set<Idx>() );
00360       rWaitList.back().insert(*siIt);
00361       rWaitList.back().insert(*sjIt);
00362 
00363       EventSet sharedEvents = rSupGen.ActiveEventSet(*siIt) * rSupGen.ActiveEventSet(*sjIt);
00364       EventSet::Iterator eIt, eEndIt;
00365       eIt = sharedEvents.Begin();
00366       eEndIt = sharedEvents.End();
00367       Idx goalStateI, goalStateJ;
00368       for( ; eIt != eEndIt; eIt++){// go over all shared active events of the current states
00369   goalStateI = (rSupGen.TransRelBegin(*siIt,*eIt) )->X2;
00370   goalStateJ = (rSupGen.TransRelBegin(*sjIt,*eIt) )->X2;
00371   if(*rState2Class.find( goalStateI ) == *rState2Class.find( goalStateJ ) )// event leads to same class
00372     continue;
00373   statePair.clear();
00374   statePair.insert(goalStateI);
00375   statePair.insert(goalStateJ);
00376   continueLoop = false;
00377   for(unsigned int i = 0; i < rWaitList.size(); i++){
00378     if(rWaitList[i] == statePair)// the current goal state pair is already on the waiting list
00379     continueLoop = true;
00380     break;
00381   }
00382   if(continueLoop == true)// the current state pair is already on the waiting list
00383     continue;
00384     
00385   // find classes of goalStateI and goalStateJ and check if they are already merged
00386   if( *(rClass2States.at( rState2Class.find(goalStateI)->second ).Begin() ) < cNode)
00387     return false;
00388   if( *(rClass2States.at(rState2Class.find(goalStateJ)->second ).Begin() ) < cNode)
00389     return false;      
00390   bool flag = CheckMergibility(goalStateI, goalStateJ, rWaitList, cNode, rSupGen, rSupStateInfo, rState2Class, rClass2States);
00391   if(flag == false){
00392     return false;
00393   }
00394       }
00395     }
00396   }
00397   return true;
00398 }
00399 
00400 } // name space 

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