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