| |
libFAUDES
Sections
Index
|
statemin.cppGo to the documentation of this file.00001 /** @file statemin.cpp state space minimization */ 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 "statemin.h" 00024 #include "exception.h" 00025 #include "project.h" 00026 00027 namespace faudes { 00028 00029 // StateMin(rGen, rResGen) 00030 void StateMin(const vGenerator& rGen, vGenerator& rResGen) { 00031 // how to avoid the copy?? 00032 vGenerator* accgen=rGen.New(); 00033 *accgen=rGen; 00034 StateMin(*accgen, rResGen); 00035 } 00036 00037 // StateMin(rGen, rResGen) 00038 void aStateMin(const vGenerator& rGen, vGenerator& rResGen) { 00039 vGenerator* accgen=rGen.New(); 00040 *accgen=rGen; 00041 StateMin(*accgen, rResGen); 00042 // restore attributes 00043 rResGen.EventAttributes(accgen->Alphabet()); 00044 } 00045 00046 // StateMin(rGen, rResGen) 00047 void StateMin(vGenerator& rGen, vGenerator& rResGen) { 00048 std::vector<StateSet> subsets; 00049 std::vector<Idx> newindices; 00050 StateMin(rGen, rResGen, subsets, newindices); 00051 } 00052 00053 // StateMin(rGen, rResGen, rSubSets, rNewIndices) 00054 void StateMin(vGenerator& rGen, vGenerator& rResGen, 00055 std::vector<StateSet>& rSubsets, std::vector<Idx>& rNewIndices) { 00056 FD_DF("StateMin: *** computing state space minimization of generator " 00057 << &rGen << " ***"); 00058 FD_DF("StateMin: making generator accessible"); 00059 00060 rGen.Accessible(); 00061 if (rGen.Size() == 0) { 00062 FD_DF("StateMin: generator size 0. returning given generator"); 00063 rResGen = rGen; 00064 return; 00065 } 00066 if (rGen.Size() == 1) { 00067 FD_DF("StateMin: generator size 1. returning given generator"); 00068 rResGen = rGen; 00069 rSubsets.push_back(rGen.States() ); 00070 rNewIndices.push_back(*( rResGen.States().Begin() ) ); 00071 return; 00072 } 00073 00074 // ensure generator is deterministic 00075 if (! rGen.IsDeterministic()) { 00076 throw Exception("StateMin", "input automaton nondeterministic", 101); 00077 } 00078 00079 // use pointer pResGen to result rResGen; if rResGen is identical to 00080 // one of the parameters, allocate temporary object and copy back later 00081 vGenerator* pResGen = &rResGen; 00082 if(&rResGen==&rGen) { 00083 pResGen= pResGen->New(); 00084 } 00085 00086 // prepare result 00087 pResGen->Clear(); 00088 pResGen->Name(rGen.Name()+" [minstate]"); 00089 pResGen->InjectAlphabet(rGen.Alphabet()); 00090 bool stateNames= pResGen->StateNamesEnabled() && rGen.StateNamesEnabled(); 00091 // blocks B[i] 00092 std::vector<StateSet>& b = rSubsets; // convenience notation "b" 00093 Idx i, j; 00094 // set of active b (iterators) 00095 std::set<Idx> active; 00096 std::set<Idx>::iterator ait; 00097 // reverse transrel 00098 TransSetEvX2X1 rtransrel; 00099 rGen.TransRel(rtransrel); 00100 TransSetEvX2X1::Iterator rtit, rtit_end; 00101 // other stuff 00102 StateSet::Iterator lit; 00103 TransSet::Iterator tit; 00104 00105 // set up b "B[i]" 00106 i = 0; 00107 if (rGen.Size() - rGen.MarkedStatesSize() > 0) { 00108 StateSet notmarked=rGen.States() - rGen.MarkedStates(); 00109 notmarked.Name("B[i]"); 00110 FD_DF("StateMin: new block B[" << i << "] = {" << notmarked.ToString() << "}"); 00111 b.push_back(notmarked); //X -Xm 00112 active.insert(i++); 00113 } 00114 if (rGen.MarkedStatesSize() > 0) { // tmoor 20090915: conditional to prevent emty block 00115 FD_DF("StateMin: new block B[" << i << "] = {" << rGen.MarkedStates().ToString() << "}"); 00116 b.push_back(rGen.MarkedStates()); // Xm 00117 active.insert(i++); 00118 } 00119 00120 // while there is a active block B 00121 while (! active.empty()) { 00122 FD_WP("StateMin: blocks/active: " << b.size() << " / " << active.size()); 00123 #ifdef FAUDES_DEBUG_FUNCTION 00124 FD_DF("StateMin: while there is an active block B..."); 00125 std::set<Idx>::iterator _it1; 00126 std::stringstream str; 00127 for (_it1 = active.begin(); _it1 != active.end(); ++_it1) { 00128 str << *_it1 << " "; 00129 } 00130 FD_DF("StateMin: active: "+str.str()); 00131 std::vector<StateSet>::iterator _it2; 00132 str.clear(); 00133 str.str(""); 00134 for (_it2 = b.begin(); _it2 != b.end(); ++_it2) { 00135 str << "{" << _it2->ToString() << "} "<<std::endl; 00136 } 00137 str << std::endl; 00138 FD_DF("B: "+str.str()); 00139 #endif 00140 // current block B[i] 00141 i = *(active.begin()); 00142 // inactivate B[i] 00143 active.erase(active.begin()); 00144 FD_DF("StateMin: getting active block B[" << i << "] = {" << 00145 b.at(i).ToString() << "}"); 00146 // b_current <- B[i] 00147 StateSet b_current = b.at(i); 00148 00149 // compute C = f^-1(B[i]) for every event in B[i] (as b_current) 00150 StateSet c; 00151 EventSet::Iterator eit; 00152 // iteration over alphabet 00153 for (eit = rGen.AlphabetBegin(); eit != rGen.AlphabetEnd(); ++eit) { 00154 c.Clear(); 00155 // iteration over states in current block 00156 for (lit = b_current.Begin(); lit != b_current.End(); ++lit) { 00157 // find predecessor states by current ev + x2 00158 rtit = rtransrel.BeginByEvX2(*eit, *lit); 00159 rtit_end = rtransrel.EndByEvX2(*eit, *lit); 00160 for (; rtit != rtit_end; ++rtit) { 00161 c.Insert(rtit->X1); 00162 } 00163 } 00164 // if predecessor states where found 00165 if (! c.Empty()) { 00166 // search for new block on next event or coming end of rtransrel with 00167 // x1 as *lit 00168 FD_DF("StateMin: computed predecessor states C = {" << c.ToString() 00169 << "} for event " << rGen.EventName(*eit)); 00170 // foreach block D 00171 for (j=0; j < b.size(); ++j) { 00172 FD_DF("StateMin: examining block B[" << j << "] = {" << 00173 b.at(j).ToString() << "}"); 00174 // compute D' = D intersection C 00175 StateSet d_ = b.at(j) * c; 00176 d_.Name("D'"); 00177 // compute D'' = D - D'; remove D, add D'' 00178 StateSet d__ = b.at(j) - d_; 00179 d__.Name("D''"); 00180 // check D split by B 00181 if (d_.Empty() || d__.Empty()) { 00182 FD_DF("StateMin: -> no split"); 00183 continue; 00184 } 00185 FD_DF("StateMin: -> split:"); 00186 b[j] = d_; 00187 FD_DF("StateMin: new block B[" << j << "] = {" 00188 << d_.ToString() << "}"); 00189 b.push_back(d__); 00190 FD_DF("StateMin: new block B[" << b.size()-1 << "] = {" 00191 << d__.ToString() << "}"); 00192 // if D was active 00193 if (active.count(j) > 0) { 00194 // then mark both D', D'' active 00195 active.insert((Idx)b.size()- 1); 00196 FD_DF("StateMin: mark active: " << b.size()-1); 00197 } 00198 // else mark smaller of D', D'' active 00199 else { 00200 if (d_.Size() < d__.Size()) { 00201 active.insert(j); 00202 FD_DF("StateMin: mark active: " << j); 00203 } 00204 else { 00205 active.insert((Idx)b.size()-1); 00206 FD_DF("StateMin: mark active: " << b.size()-1); 00207 } 00208 } 00209 } // foreach block D 00210 c.Clear(); 00211 } 00212 } 00213 } 00214 00215 FD_DF("StateMin: *** building minimized generator ***"); 00216 // build minimized generator 00217 std::map<Idx,Idx> minstatemap; 00218 Idx newstate; 00219 // loop over all blocks B 00220 for (i = 0; i < b.size(); ++i) { 00221 // create state in new generator for every block 00222 newstate = pResGen->InsState(); 00223 rNewIndices.push_back(newstate); 00224 FD_DF("StateMin: block {" << b.at(i).ToString() 00225 << "} -> new state " << newstate); 00226 std::ostringstream ostr; 00227 for (lit = b.at(i).Begin(); lit != b.at(i).End(); ++lit) { 00228 // set minstatemap entry for every state in gen 00229 minstatemap[*lit] = newstate; 00230 if(stateNames) { 00231 if (rGen.StateName(*lit) == "") { 00232 ostr << ToStringInteger(*lit) << ","; 00233 } 00234 else { 00235 ostr << rGen.StateName(*lit) << ","; 00236 } 00237 } 00238 // set istates 00239 if (rGen.ExistsInitState(*lit)) { 00240 pResGen->SetInitState(newstate); 00241 FD_DF("StateMin: -> initial state"); 00242 } 00243 // set mstates 00244 if (rGen.ExistsMarkedState(*lit)) { 00245 pResGen->SetMarkedState(newstate); 00246 FD_DF("StatMmin: -> marked state"); 00247 } 00248 } 00249 if (stateNames) { 00250 std::string statename = ostr.str(); 00251 if(statename!="") statename.erase(statename.length()-1); 00252 statename = "{" + statename + "}"; 00253 pResGen->StateName(newstate, statename); 00254 } 00255 } 00256 // create transition relation 00257 for (tit = rGen.TransRelBegin(); tit != rGen.TransRelEnd(); ++tit) { 00258 pResGen->SetTransition(minstatemap[tit->X1], tit->Ev, minstatemap[tit->X2]); 00259 FD_DF("statemin: adding transition: " 00260 << minstatemap[tit->X1] << "-" << tit->Ev << "-" 00261 << minstatemap[tit->X2]); 00262 } 00263 00264 // if necessary, move pResGen to rResGen 00265 if(pResGen != &rResGen) { 00266 pResGen->Move(rResGen); 00267 delete pResGen; 00268 } 00269 } 00270 00271 } // namespace faudes |
libFAUDES 2.14g --- 2009-12-3 --- c++ source docu by doxygen 1.5.6