syn_supreduce.cppGo 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 |