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