00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "statemin.h"
00024 #include "exception.h"
00025 #include "project.h"
00026
00027 namespace faudes {
00028
00029
00030 void StateMin(vGenerator& rGen, vGenerator& rResGen) {
00031 std::vector<StateSet> subsets;
00032 std::vector<Idx> newindices;
00033 StateMin(rGen, rResGen, subsets, newindices);
00034 }
00035
00036
00037 void StateMin(vGenerator& rGen, vGenerator& rResGen,
00038 std::vector<StateSet>& rSubsets, std::vector<Idx>& rNewIndices) {
00039 FD_DF("StateMin: *** computing state space minimization of generator "
00040 << &rGen << " ***");
00041 FD_DF("StateMin: making generator accessible");
00042
00043 rGen.Accessible();
00044 if (rGen.Size() == 0) {
00045 FD_DF("StateMin: generator size 0. returning given generator");
00046 rResGen = rGen;
00047 return;
00048 }
00049 if (rGen.Size() == 1) {
00050 FD_DF("StateMin: generator size 1. returning given generator");
00051 rResGen = rGen;
00052 rSubsets.push_back(rGen.States() );
00053 rNewIndices.push_back(*( rResGen.States().Begin() ) );
00054 return;
00055 }
00056
00057
00058 if (! rGen.IsDeterministic()) {
00059 throw Exception("StateMin", "input automaton nondeterministic", 101);
00060 }
00061
00062
00063
00064 vGenerator* pResGen = &rResGen;
00065 if(&rResGen==&rGen) {
00066 pResGen= pResGen->NewP();
00067 }
00068
00069
00070 pResGen->Clear();
00071 pResGen->Name(rGen.Name()+" [minstate]");
00072 pResGen->InjectAlphabet(rGen.Alphabet());
00073 bool stateNames= pResGen->StateNamesEnabled() && rGen.StateNamesEnabled();
00074
00075 std::vector<StateSet>& b = rSubsets;
00076 Idx i, j;
00077
00078 std::set<Idx> active;
00079 std::set<Idx>::iterator ait;
00080
00081 TransSetEvX2X1 rtransrel;
00082 rGen.TransRel(rtransrel);
00083 TransSetEvX2X1::Iterator rtit, rtit_end;
00084
00085 StateSet::Iterator lit;
00086 TransSet::Iterator tit;
00087
00088
00089 i = 0;
00090 if (rGen.Size() - rGen.MarkedStatesSize() > 0) {
00091 StateSet notmarked=rGen.States() - rGen.MarkedStates();
00092 notmarked.Name("B[i]");
00093 FD_DF("StateMin: new block B[" << i << "] = {" <<
00094 notmarked.ToString() << "}");
00095 b.push_back(notmarked);
00096 active.insert(i++);
00097 }
00098 FD_DF("StateMin: new block B[" << i << "] = {" <<
00099 rGen.MarkedStates().ToString() << "}");
00100 b.push_back(rGen.MarkedStates());
00101 active.insert(i++);
00102
00103
00104 while (! active.empty()) {
00105 FD_WP("StateMin: blocks/active: " << b.size() << " / " << active.size());
00106 #ifdef FAUDES_DEBUG_FUNCTION
00107 FD_DF("StateMin: while there is an active block B...");
00108 std::set<Idx>::iterator _it1;
00109 std::stringstream str;
00110 for (_it1 = active.begin(); _it1 != active.end(); ++_it1) {
00111 str << *_it1 << " ";
00112 }
00113 FD_DF("StateMin: active: "+str.str());
00114 std::vector<StateSet>::iterator _it2;
00115 str.clear();
00116 str.str("");
00117 for (_it2 = b.begin(); _it2 != b.end(); ++_it2) {
00118 str << "{" << _it2->ToString() << "} "<<std::endl;
00119 }
00120 str << std::endl;
00121 FD_DF("B: "+str.str());
00122 #endif
00123
00124 i = *(active.begin());
00125
00126 active.erase(active.begin());
00127 FD_DF("StateMin: getting active block B[" << i << "] = {" <<
00128 b.at(i).ToString() << "}");
00129
00130 StateSet b_current = b.at(i);
00131
00132
00133 StateSet c;
00134 EventSet::Iterator eit;
00135
00136 for (eit = rGen.AlphabetBegin(); eit != rGen.AlphabetEnd(); ++eit) {
00137 c.Clear();
00138
00139 for (lit = b_current.Begin(); lit != b_current.End(); ++lit) {
00140
00141 rtit = rtransrel.BeginByEvX2(*eit, *lit);
00142 rtit_end = rtransrel.EndByEvX2(*eit, *lit);
00143 for (; rtit != rtit_end; ++rtit) {
00144 c.Insert(rtit->X1);
00145 }
00146 }
00147
00148 if (! c.Empty()) {
00149
00150
00151 FD_DF("StateMin: computed predecessor states C = {" << c.ToString()
00152 << "} for event " << rGen.EventName(*eit));
00153
00154 for (j=0; j < b.size(); ++j) {
00155 FD_DF("StateMin: examining block B[" << j << "] = {" <<
00156 b.at(j).ToString() << "}");
00157
00158 StateSet d_ = b.at(j) * c;
00159 d_.Name("D'");
00160
00161 StateSet d__ = b.at(j) - d_;
00162 d__.Name("D''");
00163
00164 if (d_.Empty() || d__.Empty()) {
00165 FD_DF("StateMin: -> no split");
00166 continue;
00167 }
00168 FD_DF("StateMin: -> split:");
00169 b[j] = d_;
00170 FD_DF("StateMin: new block B[" << j << "] = {"
00171 << d_.ToString() << "}");
00172 b.push_back(d__);
00173 FD_DF("StateMin: new block B[" << b.size()-1 << "] = {"
00174 << d__.ToString() << "}");
00175
00176 if (active.count(j) > 0) {
00177
00178 active.insert((Idx)b.size()- 1);
00179 FD_DF("StateMin: mark active: " << b.size()-1);
00180 }
00181
00182 else {
00183 if (d_.Size() < d__.Size()) {
00184 active.insert(j);
00185 FD_DF("StateMin: mark active: " << j);
00186 }
00187 else {
00188 active.insert((Idx)b.size()-1);
00189 FD_DF("StateMin: mark active: " << b.size()-1);
00190 }
00191 }
00192 }
00193 c.Clear();
00194 }
00195 }
00196 }
00197
00198 FD_DF("StateMin: *** building minimized generator ***");
00199
00200 std::map<Idx,Idx> minstatemap;
00201 Idx newstate;
00202
00203 for (i = 0; i < b.size(); ++i) {
00204
00205 newstate = pResGen->InsState();
00206 rNewIndices.push_back(newstate);
00207 FD_DF("StateMin: block {" << b.at(i).ToString()
00208 << "} -> new state " << newstate);
00209 std::ostringstream ostr;
00210 for (lit = b.at(i).Begin(); lit != b.at(i).End(); ++lit) {
00211
00212 minstatemap[*lit] = newstate;
00213 if(stateNames) {
00214 if (rGen.StateName(*lit) == "") {
00215 ostr << ToStringInteger(*lit) << ",";
00216 }
00217 else {
00218 ostr << rGen.StateName(*lit) << ",";
00219 }
00220 }
00221
00222 if (rGen.ExistsInitState(*lit)) {
00223 pResGen->SetInitState(newstate);
00224 FD_DF("StateMin: -> initial state");
00225 }
00226
00227 if (rGen.ExistsMarkedState(*lit)) {
00228 pResGen->SetMarkedState(newstate);
00229 FD_DF("StatMmin: -> marked state");
00230 }
00231 }
00232 if (stateNames) {
00233 std::string statename = ostr.str();
00234 if(statename!="") statename.erase(statename.length()-1);
00235 statename = "{" + statename + "}";
00236 pResGen->StateName(newstate, statename);
00237 }
00238 }
00239
00240 for (tit = rGen.TransRelBegin(); tit != rGen.TransRelEnd(); ++tit) {
00241 pResGen->SetTransition(minstatemap[tit->X1], tit->Ev, minstatemap[tit->X2]);
00242 FD_DF("statemin: adding transition: "
00243 << minstatemap[tit->X1] << "-" << tit->Ev << "-"
00244 << minstatemap[tit->X2]);
00245 }
00246
00247
00248 if(pResGen != &rResGen) {
00249 pResGen->Move(rResGen);
00250 delete pResGen;
00251 }
00252 }
00253
00254 }