mtc_statemin.cppGo to the documentation of this file.00001 /** @file mtc_statemin.cpp 00002 00003 State space minimization 00004 00005 */ 00006 00007 /* FAU Discrete Event Systems Library (libfaudes) 00008 00009 Copyright (C) 2008 Matthias Singer 00010 Copyright (C) 2006 Bernd Opitz 00011 Exclusive copyright is granted to Klaus Schmidt 00012 00013 This library is free software; you can redistribute it and/or 00014 modify it under the terms of the GNU Lesser General Public 00015 License as published by the Free Software Foundation; either 00016 version 2.1 of the License, or (at your option) any later version. 00017 00018 This library is distributed in the hope that it will be useful, 00019 but WITHOUT ANY WARRANTY; without even the implied warranty of 00020 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00021 Lesser General Public License for more details. 00022 00023 You should have received a copy of the GNU Lesser General Public 00024 License along with this library; if not, write to the Free Software 00025 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 00026 00027 #include "mtc_statemin.h" 00028 00029 namespace faudes { 00030 00031 // mtcStateMin(rGen, rResGen) 00032 void mtcStateMin(MtcSystem& rGen, MtcSystem& rResGen) { 00033 std::vector<StateSet> subsets; 00034 std::vector<Idx> newindices; 00035 mtcStateMin(rGen, rResGen, subsets, newindices); 00036 } 00037 00038 // mtcStateMin(rGen, rResGen, rSubSets, rNewIndices) 00039 void mtcStateMin(MtcSystem& rGen, MtcSystem& rResGen, 00040 std::vector<StateSet>& rSubsets, std::vector<Idx>& rNewIndices) { 00041 FD_DF("statemin: *** computing state space minimization of multi-tasking generator " 00042 << &rGen << " ***"); 00043 FD_DF("statemin: making generator accessible"); 00044 #ifdef FAUDES_DEBUG_FUNCTION 00045 FD_WARN("mtcStateMin: debug out") 00046 rGen.Write("tmp_smin_m.gen"); 00047 #endif 00048 // make accessible 00049 rGen.Accessible(); 00050 #ifdef FAUDES_DEBUG_FUNCTION 00051 FD_WARN("mtcStateMin: debug out") 00052 rGen.Write("tmp_smin_a.gen"); 00053 #endif 00054 00055 00056 if (rGen.Size() < 2) { 00057 FD_DF("statemin: generator size < 2. returning given generator"); 00058 //rGen.Copy(rResGen); changed !! test 00059 rResGen = rGen; 00060 rSubsets.push_back(rGen.States() ); 00061 rNewIndices.push_back(*( rResGen.States().Begin() ) ); 00062 return; 00063 } 00064 00065 // ensure generator is deterministic 00066 if (! rGen.IsDeterministic()) { 00067 throw Exception("mtcStateMin", "input automaton nondeterministic", 505); 00068 } 00069 00070 // prepare result 00071 rResGen.Clear(); 00072 rResGen.Name(rGen.Name()+" [mtc minstate]"); 00073 00074 rResGen.ClearStateAttributes(); 00075 rResGen.InjectAlphabet(rGen.Alphabet()); 00076 00077 rResGen.SetControllable(rGen.ControllableEvents()); 00078 rResGen.SetForcible(rGen.ForcibleEvents()); 00079 rResGen.ClrObservable(rGen.UnobservableEvents()); 00080 00081 00082 // blocks B[i] 00083 std::vector<StateSet>& b = rSubsets; // convenience notation "b" 00084 Idx i, j; 00085 // set of active b (iterators) 00086 std::set<Idx> active; 00087 std::set<Idx>::iterator ait; 00088 // reverse transrel 00089 TransSetEvX2X1 rtransrel; 00090 rGen.TransRel(rtransrel); 00091 TransSetEvX2X1::Iterator rtit, rtit_end; 00092 // other stuff 00093 StateSet::Iterator lit; 00094 TransSet::Iterator tit; 00095 00096 // set up b "B[i]" 00097 i = 0; 00098 00099 #ifdef FAUDES_DEBUG_FUNCTION 00100 FD_WARN("mtcStateMin: debug out: states"); 00101 rGen.States().Write(); 00102 FD_WARN("mtcStateMin: debug out: colored states"); 00103 rGen.ColoredStates().Write(); 00104 FD_WARN("mtcStateMin: debug out: unolored states"); 00105 rGen.UncoloredStates().Write(); 00106 #endif 00107 00108 if (rGen.UncoloredStates().Size() > 0) { 00109 b.push_back(rGen.UncoloredStates()); 00110 active.insert(i++); 00111 FD_DF("statemin: new block B[" << i-1 << "] = {" << 00112 (rGen.UncoloredStates()).ToString() << "}"); 00113 } 00114 // find states that have the same associated colors 00115 std::map<Idx,ColorSet> stateColorMap = rGen.StateColorMap(); 00116 std::map<Idx,ColorSet>::const_iterator sit_end = stateColorMap.end(); 00117 std::map<ColorSet,StateSet> SameColors; 00118 std::map<ColorSet,StateSet>::iterator csit; 00119 std::map<Idx,ColorSet>::const_iterator sit; 00120 00121 for(sit = stateColorMap.begin(); sit != sit_end; ++sit){ 00122 csit = SameColors.find(sit->second); 00123 FD_DF("stateColorMap, state: " << ToStringInteger(sit->first) << ", colors: " << (sit->second).ToString()); 00124 if(csit != SameColors.end() ) 00125 csit->second.Insert(sit->first); 00126 else{ 00127 StateSet NewStateSet; 00128 NewStateSet.Insert(sit->first); 00129 SameColors[sit->second] = NewStateSet; 00130 } 00131 } 00132 00133 // create the initial set of equivalence classes 00134 std::map<ColorSet,StateSet>::const_iterator csit_end = SameColors.end(); 00135 for(csit = SameColors.begin(); csit != csit_end; ++csit){ 00136 b.push_back(csit->second); // Colored StateSets 00137 active.insert(i++); 00138 FD_DF("statemin: new block B[" << i-1 << "] = {" << 00139 csit->second.ToString() << "}"); 00140 } 00141 00142 // while there is an active block B 00143 while (! active.empty()) { 00144 FD_WP("mtcStateMin: blocks/active: " << b.size() << " / " << active.size()); 00145 #ifdef FD_DF 00146 FD_DF("statemin: if there is an active block B..."); 00147 std::set<Idx>::iterator _it1; 00148 std::stringstream str; 00149 for (_it1 = active.begin(); _it1 != active.end(); ++_it1) { 00150 str << *_it1 << " "; 00151 } 00152 FD_DF("active: "+str.str()); 00153 std::vector<StateSet>::iterator _it2; 00154 str.clear(); 00155 for (_it2 = b.begin(); _it2 != b.end(); ++_it2) { 00156 str << "{" << _it2->ToString() << "} "; 00157 } 00158 str << std::endl; 00159 FD_DF("B: "+str.str()); 00160 #endif 00161 // current block B[i] 00162 i = *(active.begin()); 00163 // inactivate B[i] 00164 active.erase(active.begin()); 00165 FD_DF("statemin: getting active block B[" << i << "] = {" << 00166 b.at(i).ToString() << "}"); 00167 // b_current <- B[i] 00168 StateSet b_current = b.at(i); 00169 00170 // compute C = f^-1(B[i]) for every event in B[i] (as b_current) 00171 StateSet c; 00172 EventSet::Iterator eit; 00173 // iteration over alphabet 00174 for (eit = rGen.AlphabetBegin(); eit != rGen.AlphabetEnd(); ++eit) { 00175 c.Clear(); 00176 // iteration over states in current block 00177 for (lit = b_current.Begin(); lit != b_current.End(); ++lit) { 00178 // find predecessor states by current ev + x2 00179 rtit = rtransrel.BeginByEvX2(*eit, *lit); 00180 rtit_end = rtransrel.EndByEvX2(*eit, *lit); 00181 for (; rtit != rtit_end; ++rtit) { 00182 c.Insert(rtit->X1); 00183 } 00184 } 00185 // if predecessor states where found 00186 if (! c.Empty()) { 00187 // search for new block on next event or coming end of rtransrel with 00188 // x1 as *lit 00189 FD_DF("statemin: computed predecessor states C = {" << c.ToString() 00190 << "} for event " << rGen.EventName(*eit)); 00191 00192 // foreach block D 00193 for (j=0; j < b.size(); ++j) { 00194 FD_DF("statemin: examining block B[" << j << "] = {" << 00195 b.at(j).ToString() << "}"); 00196 // compute D' = D intersection C 00197 StateSet d_ = b.at(j) * c; 00198 // compute D'' = D - D'; remove D, add D'' 00199 StateSet d__ = b.at(j) - d_; 00200 // check D split by B 00201 if (d_.Empty() || d__.Empty()) { 00202 FD_DF("statemin: -> no split"); 00203 continue; 00204 } 00205 FD_DF("statemin: -> split:"); 00206 b[j] = d_; 00207 FD_DF("statemin: new block B[" << j << "] = {" 00208 << d_.ToString() << "}"); 00209 b.push_back(d__); 00210 FD_DF("statemin: new block B[" << b.size()-1 << "] = {" 00211 << d__.ToString() << "}"); 00212 // if D was active 00213 if (active.count(j) > 0) { 00214 // then mark both D', D'' active 00215 active.insert((Idx)b.size()- 1); 00216 FD_DF("statemin: mark active: " << b.size()-1); 00217 } 00218 // else mark smaller of D', D'' active 00219 else { 00220 if (d_.Size() < d__.Size()) { 00221 active.insert(j); 00222 FD_DF("statemin: mark active: " << j); 00223 } 00224 else { 00225 active.insert((Idx)b.size()-1); 00226 FD_DF("statemin: mark active: " << b.size()-1); 00227 } 00228 } 00229 } // foreach block D 00230 c.Clear(); 00231 } 00232 } 00233 } 00234 00235 FD_DF("statemin: *** building minimized generator ***"); 00236 // build minimized generator 00237 std::map<Idx,Idx> minstatemap; 00238 Idx newstate; 00239 // loop over all blocks B 00240 for (i = 0; i < b.size(); i++) { 00241 // create state in new generator for every block 00242 newstate = rResGen.InsState(); 00243 rNewIndices.push_back(newstate); 00244 FD_DF("statemin: block {" << b.at(i).ToString() 00245 << "} -> new state " << newstate); 00246 std::ostringstream ostr; 00247 Idx count = 0; 00248 for (lit = b.at(i).Begin(); lit != b.at(i).End(); lit++) { 00249 count++; 00250 // set minstatemap entry for every state in gen 00251 minstatemap[*lit] = newstate; 00252 if (rResGen.StateNamesEnabled()) { 00253 FD_DF("StateNamesEnabled: index: \""<< ToStringInteger(*lit) << "\", name: \"" << rGen.StateName(*lit) << "\""); 00254 if (rGen.StateName(*lit) == "") { 00255 ostr << ToStringInteger(*lit) << ","; 00256 FD_DF("StateName \"\", ostr = " << ostr.str()); 00257 } 00258 else { 00259 ostr << rGen.StateName(*lit) << ","; 00260 FD_DF("StateName exists, ostr = " << ostr.str()); 00261 } 00262 } 00263 // set istates 00264 if (rGen.ExistsInitState(*lit)) { 00265 rResGen.SetInitState(newstate); 00266 FD_DF("statemin: -> initial state"); 00267 } 00268 if(count == 1){ //all states in b.at(i) have the same colors 00269 std::map<Idx,ColorSet>::const_iterator col_it; 00270 col_it = stateColorMap.find(*lit); 00271 // are there any colors to set for the current state? 00272 if (col_it != stateColorMap.end()) { 00273 // insert corresponding colors if they are not already set for the current state 00274 FD_DF("mtcStateMin: insert colors " << col_it->second.ToString() << " to state " << newstate); 00275 rResGen.InsColors(newstate, col_it->second); 00276 } 00277 } 00278 } 00279 if (rResGen.StateNamesEnabled()) { 00280 std::string statename = ostr.str(); 00281 statename.erase(statename.length()-1); 00282 statename = "{" + statename + "}"; 00283 FD_DF("Set state name: name: \"" << statename << "\", index: \"" << newstate << "\""); 00284 rResGen.StateName(newstate, statename); 00285 } 00286 } 00287 // create transition relation 00288 for (tit = rGen.TransRelBegin(); tit != rGen.TransRelEnd(); ++tit) { 00289 rResGen.SetTransition(minstatemap[tit->X1], tit->Ev, minstatemap[tit->X2]); 00290 FD_DF("statemin: adding transition: " 00291 << minstatemap[tit->X1] << "-" << tit->Ev << "-" 00292 << minstatemap[tit->X2]); 00293 } 00294 #ifdef FAUDES_DEBUG_FUNCTION 00295 FD_WARN("mtcStateMin: debug out: result") 00296 rResGen.Write("tmp_smin_r.gen"); 00297 #endif 00298 } 00299 00300 // RTI wrapper 00301 void mtcStateMin(const MtcSystem& rGen, MtcSystem& rResGen) { 00302 MtcSystem gen(rGen); 00303 mtcStateMin(gen,rResGen); 00304 00305 FD_WARN("mtcStateMin: debug out") 00306 rGen.GraphWrite("tmp_smin_w.png"); 00307 rGen.DotWrite("tmp_smin_w.dot"); 00308 00309 } 00310 00311 } // namespace faudes libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen |