mtc_statemin.cpp
Go to the documentation of this file.
1/** @file mtc_statemin.cpp
2
3State space minimization
4
5*/
6
7/* FAU Discrete Event Systems Library (libfaudes)
8
9 Copyright (C) 2008 Matthias Singer
10 Copyright (C) 2006 Bernd Opitz
11 Exclusive copyright is granted to Klaus Schmidt
12
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Lesser General Public
15 License as published by the Free Software Foundation; either
16 version 2.1 of the License, or (at your option) any later version.
17
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
22
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
26
27#include "mtc_statemin.h"
28
29namespace faudes {
30
31// mtcStateMin(rGen, rResGen)
32void mtcStateMin(MtcSystem& rGen, MtcSystem& rResGen) {
33 std::vector<StateSet> subsets;
34 std::vector<Idx> newindices;
35 mtcStateMin(rGen, rResGen, subsets, newindices);
36}
37
38// mtcStateMin(rGen, rResGen, rSubSets, rNewIndices)
39void mtcStateMin(MtcSystem& rGen, MtcSystem& rResGen,
40 std::vector<StateSet>& rSubsets, std::vector<Idx>& rNewIndices) {
41 FD_DF("statemin: *** computing state space minimization of multi-tasking generator "
42 << &rGen << " ***");
43 FD_DF("statemin: making generator accessible");
44#ifdef FAUDES_DEBUG_FUNCTION
45 FD_WARN("mtcStateMin: debug out")
46 rGen.Write("tmp_smin_m.gen");
47#endif
48 // make accessible
49 rGen.Accessible();
50#ifdef FAUDES_DEBUG_FUNCTION
51 FD_WARN("mtcStateMin: debug out")
52 rGen.Write("tmp_smin_a.gen");
53#endif
54
55
56 if (rGen.Size() < 2) {
57 FD_DF("statemin: generator size < 2. returning given generator");
58 rResGen = rGen;
59 rSubsets.push_back(rGen.States() );
60 rNewIndices.push_back(*( rResGen.States().Begin() ) );
61 return;
62 }
63
64 // ensure generator is deterministic
65 if (! rGen.IsDeterministic()) {
66 throw Exception("mtcStateMin", "input automaton nondeterministic", 505);
67 }
68
69 // prepare result
70 rResGen.Clear();
71 rResGen.Name(rGen.Name()+" [mtc minstate]");
72
73 rResGen.ClearStateAttributes();
74 rResGen.InjectAlphabet(rGen.Alphabet());
75
76 rResGen.SetControllable(rGen.ControllableEvents());
77 rResGen.SetForcible(rGen.ForcibleEvents());
78 rResGen.ClrObservable(rGen.UnobservableEvents());
79
80
81 // blocks B[i]
82 std::vector<StateSet>& b = rSubsets; // convenience notation "b"
83 Idx i, j;
84 // set of active b (iterators)
85 std::set<Idx> active;
86 std::set<Idx>::iterator ait;
87 // reverse transrel
88 TransSetEvX2X1 rtransrel;
89 rGen.TransRel(rtransrel);
90 TransSetEvX2X1::Iterator rtit, rtit_end;
91 // other stuff
92 StateSet::Iterator lit;
94
95 // set up b "B[i]"
96 i = 0;
97
98#ifdef FAUDES_DEBUG_FUNCTION
99 FD_WARN("mtcStateMin: debug out: states");
100 rGen.States().Write();
101 FD_WARN("mtcStateMin: debug out: colored states");
102 rGen.ColoredStates().Write();
103 FD_WARN("mtcStateMin: debug out: unolored states");
104 rGen.UncoloredStates().Write();
105#endif
106
107 if (rGen.UncoloredStates().Size() > 0) {
108 b.push_back(rGen.UncoloredStates());
109 active.insert(i++);
110 FD_DF("statemin: new block B[" << i-1 << "] = {" <<
111 (rGen.UncoloredStates()).ToString() << "}");
112 }
113 // find states that have the same associated colors
114 std::map<Idx,ColorSet> stateColorMap = rGen.StateColorMap();
115 std::map<Idx,ColorSet>::const_iterator sit_end = stateColorMap.end();
116 std::map<ColorSet,StateSet> SameColors;
117 std::map<ColorSet,StateSet>::iterator csit;
118 std::map<Idx,ColorSet>::const_iterator sit;
119
120 for(sit = stateColorMap.begin(); sit != sit_end; ++sit){
121 csit = SameColors.find(sit->second);
122 FD_DF("stateColorMap, state: " << ToStringInteger(sit->first) << ", colors: " << (sit->second).ToString());
123 if(csit != SameColors.end() )
124 csit->second.Insert(sit->first);
125 else{
126 StateSet NewStateSet;
127 NewStateSet.Insert(sit->first);
128 SameColors[sit->second] = NewStateSet;
129 }
130 }
131
132 // create the initial set of equivalence classes
133 std::map<ColorSet,StateSet>::const_iterator csit_end = SameColors.end();
134 for(csit = SameColors.begin(); csit != csit_end; ++csit){
135 b.push_back(csit->second); // Colored StateSets
136 active.insert(i++);
137 FD_DF("statemin: new block B[" << i-1 << "] = {" <<
138 csit->second.ToString() << "}");
139 }
140
141 // while there is an active block B
142 while (! active.empty()) {
143 FD_WP("mtcStateMin: blocks/active: " << b.size() << " / " << active.size());
144#ifdef FD_DF
145 FD_DF("statemin: if there is an active block B...");
146 std::set<Idx>::iterator _it1;
147 std::stringstream str;
148 for (_it1 = active.begin(); _it1 != active.end(); ++_it1) {
149 str << *_it1 << " ";
150 }
151 FD_DF("active: "+str.str());
152 std::vector<StateSet>::iterator _it2;
153 str.clear();
154 for (_it2 = b.begin(); _it2 != b.end(); ++_it2) {
155 str << "{" << _it2->ToString() << "} ";
156 }
157 str << std::endl;
158 FD_DF("B: "+str.str());
159#endif
160 // current block B[i]
161 i = *(active.begin());
162 // inactivate B[i]
163 active.erase(active.begin());
164 FD_DF("statemin: getting active block B[" << i << "] = {" <<
165 b.at(i).ToString() << "}");
166 // b_current <- B[i]
167 StateSet b_current = b.at(i);
168
169 // compute C = f^-1(B[i]) for every event in B[i] (as b_current)
170 StateSet c;
171 EventSet::Iterator eit;
172 // iteration over alphabet
173 for (eit = rGen.AlphabetBegin(); eit != rGen.AlphabetEnd(); ++eit) {
174 c.Clear();
175 // iteration over states in current block
176 for (lit = b_current.Begin(); lit != b_current.End(); ++lit) {
177 // find predecessor states by current ev + x2
178 rtit = rtransrel.BeginByEvX2(*eit, *lit);
179 rtit_end = rtransrel.EndByEvX2(*eit, *lit);
180 for (; rtit != rtit_end; ++rtit) {
181 c.Insert(rtit->X1);
182 }
183 }
184 // if predecessor states where found
185 if (! c.Empty()) {
186 // search for new block on next event or coming end of rtransrel with
187 // x1 as *lit
188 FD_DF("statemin: computed predecessor states C = {" << c.ToString()
189 << "} for event " << rGen.EventName(*eit));
190
191 // foreach block D
192 for (j=0; j < b.size(); ++j) {
193 FD_DF("statemin: examining block B[" << j << "] = {" <<
194 b.at(j).ToString() << "}");
195 // compute D' = D intersection C
196 StateSet d_ = b.at(j) * c;
197 // compute D'' = D - D'; remove D, add D''
198 StateSet d__ = b.at(j) - d_;
199 // check D split by B
200 if (d_.Empty() || d__.Empty()) {
201 FD_DF("statemin: -> no split");
202 continue;
203 }
204 FD_DF("statemin: -> split:");
205 b[j] = d_;
206 FD_DF("statemin: new block B[" << j << "] = {"
207 << d_.ToString() << "}");
208 b.push_back(d__);
209 FD_DF("statemin: new block B[" << b.size()-1 << "] = {"
210 << d__.ToString() << "}");
211 // if D was active
212 if (active.count(j) > 0) {
213 // then mark both D', D'' active
214 active.insert((Idx)b.size()- 1);
215 FD_DF("statemin: mark active: " << b.size()-1);
216 }
217 // else mark smaller of D', D'' active
218 else {
219 if (d_.Size() < d__.Size()) {
220 active.insert(j);
221 FD_DF("statemin: mark active: " << j);
222 }
223 else {
224 active.insert((Idx)b.size()-1);
225 FD_DF("statemin: mark active: " << b.size()-1);
226 }
227 }
228 } // foreach block D
229 c.Clear();
230 }
231 }
232 }
233
234 FD_DF("statemin: *** building minimized generator ***");
235 // build minimized generator
236 std::map<Idx,Idx> minstatemap;
237 Idx newstate;
238 // loop over all blocks B
239 for (i = 0; i < b.size(); i++) {
240 // create state in new generator for every block
241 newstate = rResGen.InsState();
242 rNewIndices.push_back(newstate);
243 FD_DF("statemin: block {" << b.at(i).ToString()
244 << "} -> new state " << newstate);
245 std::ostringstream ostr;
246 Idx count = 0;
247 for (lit = b.at(i).Begin(); lit != b.at(i).End(); lit++) {
248 count++;
249 // set minstatemap entry for every state in gen
250 minstatemap[*lit] = newstate;
251 if (rResGen.StateNamesEnabled()) {
252 FD_DF("StateNamesEnabled: index: \""<< ToStringInteger(*lit) << "\", name: \"" << rGen.StateName(*lit) << "\"");
253 if (rGen.StateName(*lit) == "") {
254 ostr << ToStringInteger(*lit) << ",";
255 FD_DF("StateName \"\", ostr = " << ostr.str());
256 }
257 else {
258 ostr << rGen.StateName(*lit) << ",";
259 FD_DF("StateName exists, ostr = " << ostr.str());
260 }
261 }
262 // set istates
263 if (rGen.ExistsInitState(*lit)) {
264 rResGen.SetInitState(newstate);
265 FD_DF("statemin: -> initial state");
266 }
267 if(count == 1){ //all states in b.at(i) have the same colors
268 std::map<Idx,ColorSet>::const_iterator col_it;
269 col_it = stateColorMap.find(*lit);
270 // are there any colors to set for the current state?
271 if (col_it != stateColorMap.end()) {
272 // insert corresponding colors if they are not already set for the current state
273 FD_DF("mtcStateMin: insert colors " << col_it->second.ToString() << " to state " << newstate);
274 rResGen.InsColors(newstate, col_it->second);
275 }
276 }
277 }
278 if (rResGen.StateNamesEnabled()) {
279 std::string statename = ostr.str();
280 statename.erase(statename.length()-1);
281 statename = "{" + statename + "}";
282 FD_DF("Set state name: name: \"" << statename << "\", index: \"" << newstate << "\"");
283 rResGen.StateName(newstate, statename);
284 }
285 }
286 // create transition relation
287 for (tit = rGen.TransRelBegin(); tit != rGen.TransRelEnd(); ++tit) {
288 rResGen.SetTransition(minstatemap[tit->X1], tit->Ev, minstatemap[tit->X2]);
289 FD_DF("statemin: adding transition: "
290 << minstatemap[tit->X1] << "-" << tit->Ev << "-"
291 << minstatemap[tit->X2]);
292 }
293#ifdef FAUDES_DEBUG_FUNCTION
294 FD_WARN("mtcStateMin: debug out: result")
295 rResGen.Write("tmp_smin_r.gen");
296#endif
297}
298
299// RTI wrapper
300void mtcStateMin(const MtcSystem& rGen, MtcSystem& rResGen) {
301 MtcSystem gen(rGen);
302 mtcStateMin(gen,rResGen);
303
304 FD_WARN("mtcStateMin: debug out")
305 rGen.GraphWrite("tmp_smin_w.png");
306 rGen.DotWrite("tmp_smin_w.dot");
307
308}
309
310} // namespace faudes
#define FD_WARN(message)
#define FD_DF(message)
#define FD_WP(message)
const std::string & Name(void) const
Iterator EndByEvX2(Idx ev, Idx x2) const
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
Iterator BeginByEvX2(Idx ev, Idx x2) const
virtual void Clear(void)
const TaStateSet< StateAttr > & States(void) const
const TaEventSet< EventAttr > & Alphabet(void) const
bool SetTransition(Idx x1, Idx ev, Idx x2)
const ATransSet & TransRel(void) const
void InjectAlphabet(const EventSet &rNewalphabet)
void ClrObservable(Idx index)
EventSet ControllableEvents(void) const
void SetControllable(Idx index)
EventSet ForcibleEvents(void) const
void SetForcible(Idx index)
EventSet UnobservableEvents(void) const
void InsColors(Idx stateIndex, const ColorSet &rColors)
StateSet ColoredStates(Idx colorIndex) const
virtual void DotWrite(const std::string &rFileName) const
std::map< Idx, ColorSet > StateColorMap(void) const
StateSet UncoloredStates() const
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
void Write(const Type *pContext=0) const
TransSet::Iterator TransRelBegin(void) const
EventSet::Iterator AlphabetBegin(void) const
void SetInitState(Idx index)
std::string StateName(Idx index) const
TransSet::Iterator TransRelEnd(void) const
bool IsDeterministic(void) const
bool StateNamesEnabled(void) const
void GraphWrite(const std::string &rFileName, const std::string &rOutFormat="", const std::string &rDotExec="dot") const
std::string EventName(Idx index) const
EventSet::Iterator AlphabetEnd(void) const
Idx Size(void) const
bool ExistsInitState(Idx index) const
bool Empty(void) const
virtual void Clear(void)
Iterator End(void) const
Iterator Begin(void) const
Idx Size(void) const
uint32_t Idx
void mtcStateMin(MtcSystem &rGen, MtcSystem &rResGen)
std::string ToStringInteger(Int number)
Definition cfl_utils.cpp:43

libFAUDES 2.34d --- 2026.03.11 --- c++ api documentaion by doxygen