mtc_statemin.cpp
Go to the documentation of this file.
1 /** @file mtc_statemin.cpp
2 
3 State 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 
29 namespace faudes {
30 
31 // mtcStateMin(rGen, rResGen)
32 void 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)
39 void 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  //rGen.Copy(rResGen); changed !! test
59  rResGen = rGen;
60  rSubsets.push_back(rGen.States() );
61  rNewIndices.push_back(*( rResGen.States().Begin() ) );
62  return;
63  }
64 
65  // ensure generator is deterministic
66  if (! rGen.IsDeterministic()) {
67  throw Exception("mtcStateMin", "input automaton nondeterministic", 505);
68  }
69 
70  // prepare result
71  rResGen.Clear();
72  rResGen.Name(rGen.Name()+" [mtc minstate]");
73 
74  rResGen.ClearStateAttributes();
75  rResGen.InjectAlphabet(rGen.Alphabet());
76 
77  rResGen.SetControllable(rGen.ControllableEvents());
78  rResGen.SetForcible(rGen.ForcibleEvents());
79  rResGen.ClrObservable(rGen.UnobservableEvents());
80 
81 
82  // blocks B[i]
83  std::vector<StateSet>& b = rSubsets; // convenience notation "b"
84  Idx i, j;
85  // set of active b (iterators)
86  std::set<Idx> active;
87  std::set<Idx>::iterator ait;
88  // reverse transrel
89  TransSetEvX2X1 rtransrel;
90  rGen.TransRel(rtransrel);
91  TransSetEvX2X1::Iterator rtit, rtit_end;
92  // other stuff
93  StateSet::Iterator lit;
95 
96  // set up b "B[i]"
97  i = 0;
98 
99 #ifdef FAUDES_DEBUG_FUNCTION
100  FD_WARN("mtcStateMin: debug out: states");
101  rGen.States().Write();
102  FD_WARN("mtcStateMin: debug out: colored states");
103  rGen.ColoredStates().Write();
104  FD_WARN("mtcStateMin: debug out: unolored states");
105  rGen.UncoloredStates().Write();
106 #endif
107 
108  if (rGen.UncoloredStates().Size() > 0) {
109  b.push_back(rGen.UncoloredStates());
110  active.insert(i++);
111  FD_DF("statemin: new block B[" << i-1 << "] = {" <<
112  (rGen.UncoloredStates()).ToString() << "}");
113  }
114  // find states that have the same associated colors
115  std::map<Idx,ColorSet> stateColorMap = rGen.StateColorMap();
116  std::map<Idx,ColorSet>::const_iterator sit_end = stateColorMap.end();
117  std::map<ColorSet,StateSet> SameColors;
118  std::map<ColorSet,StateSet>::iterator csit;
119  std::map<Idx,ColorSet>::const_iterator sit;
120 
121  for(sit = stateColorMap.begin(); sit != sit_end; ++sit){
122  csit = SameColors.find(sit->second);
123  FD_DF("stateColorMap, state: " << ToStringInteger(sit->first) << ", colors: " << (sit->second).ToString());
124  if(csit != SameColors.end() )
125  csit->second.Insert(sit->first);
126  else{
127  StateSet NewStateSet;
128  NewStateSet.Insert(sit->first);
129  SameColors[sit->second] = NewStateSet;
130  }
131  }
132 
133  // create the initial set of equivalence classes
134  std::map<ColorSet,StateSet>::const_iterator csit_end = SameColors.end();
135  for(csit = SameColors.begin(); csit != csit_end; ++csit){
136  b.push_back(csit->second); // Colored StateSets
137  active.insert(i++);
138  FD_DF("statemin: new block B[" << i-1 << "] = {" <<
139  csit->second.ToString() << "}");
140  }
141 
142  // while there is an active block B
143  while (! active.empty()) {
144  FD_WP("mtcStateMin: blocks/active: " << b.size() << " / " << active.size());
145 #ifdef FD_DF
146  FD_DF("statemin: if there is an active block B...");
147  std::set<Idx>::iterator _it1;
148  std::stringstream str;
149  for (_it1 = active.begin(); _it1 != active.end(); ++_it1) {
150  str << *_it1 << " ";
151  }
152  FD_DF("active: "+str.str());
153  std::vector<StateSet>::iterator _it2;
154  str.clear();
155  for (_it2 = b.begin(); _it2 != b.end(); ++_it2) {
156  str << "{" << _it2->ToString() << "} ";
157  }
158  str << std::endl;
159  FD_DF("B: "+str.str());
160 #endif
161  // current block B[i]
162  i = *(active.begin());
163  // inactivate B[i]
164  active.erase(active.begin());
165  FD_DF("statemin: getting active block B[" << i << "] = {" <<
166  b.at(i).ToString() << "}");
167  // b_current <- B[i]
168  StateSet b_current = b.at(i);
169 
170  // compute C = f^-1(B[i]) for every event in B[i] (as b_current)
171  StateSet c;
172  EventSet::Iterator eit;
173  // iteration over alphabet
174  for (eit = rGen.AlphabetBegin(); eit != rGen.AlphabetEnd(); ++eit) {
175  c.Clear();
176  // iteration over states in current block
177  for (lit = b_current.Begin(); lit != b_current.End(); ++lit) {
178  // find predecessor states by current ev + x2
179  rtit = rtransrel.BeginByEvX2(*eit, *lit);
180  rtit_end = rtransrel.EndByEvX2(*eit, *lit);
181  for (; rtit != rtit_end; ++rtit) {
182  c.Insert(rtit->X1);
183  }
184  }
185  // if predecessor states where found
186  if (! c.Empty()) {
187  // search for new block on next event or coming end of rtransrel with
188  // x1 as *lit
189  FD_DF("statemin: computed predecessor states C = {" << c.ToString()
190  << "} for event " << rGen.EventName(*eit));
191 
192  // foreach block D
193  for (j=0; j < b.size(); ++j) {
194  FD_DF("statemin: examining block B[" << j << "] = {" <<
195  b.at(j).ToString() << "}");
196  // compute D' = D intersection C
197  StateSet d_ = b.at(j) * c;
198  // compute D'' = D - D'; remove D, add D''
199  StateSet d__ = b.at(j) - d_;
200  // check D split by B
201  if (d_.Empty() || d__.Empty()) {
202  FD_DF("statemin: -> no split");
203  continue;
204  }
205  FD_DF("statemin: -> split:");
206  b[j] = d_;
207  FD_DF("statemin: new block B[" << j << "] = {"
208  << d_.ToString() << "}");
209  b.push_back(d__);
210  FD_DF("statemin: new block B[" << b.size()-1 << "] = {"
211  << d__.ToString() << "}");
212  // if D was active
213  if (active.count(j) > 0) {
214  // then mark both D', D'' active
215  active.insert((Idx)b.size()- 1);
216  FD_DF("statemin: mark active: " << b.size()-1);
217  }
218  // else mark smaller of D', D'' active
219  else {
220  if (d_.Size() < d__.Size()) {
221  active.insert(j);
222  FD_DF("statemin: mark active: " << j);
223  }
224  else {
225  active.insert((Idx)b.size()-1);
226  FD_DF("statemin: mark active: " << b.size()-1);
227  }
228  }
229  } // foreach block D
230  c.Clear();
231  }
232  }
233  }
234 
235  FD_DF("statemin: *** building minimized generator ***");
236  // build minimized generator
237  std::map<Idx,Idx> minstatemap;
238  Idx newstate;
239  // loop over all blocks B
240  for (i = 0; i < b.size(); i++) {
241  // create state in new generator for every block
242  newstate = rResGen.InsState();
243  rNewIndices.push_back(newstate);
244  FD_DF("statemin: block {" << b.at(i).ToString()
245  << "} -> new state " << newstate);
246  std::ostringstream ostr;
247  Idx count = 0;
248  for (lit = b.at(i).Begin(); lit != b.at(i).End(); lit++) {
249  count++;
250  // set minstatemap entry for every state in gen
251  minstatemap[*lit] = newstate;
252  if (rResGen.StateNamesEnabled()) {
253  FD_DF("StateNamesEnabled: index: \""<< ToStringInteger(*lit) << "\", name: \"" << rGen.StateName(*lit) << "\"");
254  if (rGen.StateName(*lit) == "") {
255  ostr << ToStringInteger(*lit) << ",";
256  FD_DF("StateName \"\", ostr = " << ostr.str());
257  }
258  else {
259  ostr << rGen.StateName(*lit) << ",";
260  FD_DF("StateName exists, ostr = " << ostr.str());
261  }
262  }
263  // set istates
264  if (rGen.ExistsInitState(*lit)) {
265  rResGen.SetInitState(newstate);
266  FD_DF("statemin: -> initial state");
267  }
268  if(count == 1){ //all states in b.at(i) have the same colors
269  std::map<Idx,ColorSet>::const_iterator col_it;
270  col_it = stateColorMap.find(*lit);
271  // are there any colors to set for the current state?
272  if (col_it != stateColorMap.end()) {
273  // insert corresponding colors if they are not already set for the current state
274  FD_DF("mtcStateMin: insert colors " << col_it->second.ToString() << " to state " << newstate);
275  rResGen.InsColors(newstate, col_it->second);
276  }
277  }
278  }
279  if (rResGen.StateNamesEnabled()) {
280  std::string statename = ostr.str();
281  statename.erase(statename.length()-1);
282  statename = "{" + statename + "}";
283  FD_DF("Set state name: name: \"" << statename << "\", index: \"" << newstate << "\"");
284  rResGen.StateName(newstate, statename);
285  }
286  }
287  // create transition relation
288  for (tit = rGen.TransRelBegin(); tit != rGen.TransRelEnd(); ++tit) {
289  rResGen.SetTransition(minstatemap[tit->X1], tit->Ev, minstatemap[tit->X2]);
290  FD_DF("statemin: adding transition: "
291  << minstatemap[tit->X1] << "-" << tit->Ev << "-"
292  << minstatemap[tit->X2]);
293  }
294 #ifdef FAUDES_DEBUG_FUNCTION
295  FD_WARN("mtcStateMin: debug out: result")
296  rResGen.Write("tmp_smin_r.gen");
297 #endif
298 }
299 
300 // RTI wrapper
301 void mtcStateMin(const MtcSystem& rGen, MtcSystem& rResGen) {
302  MtcSystem gen(rGen);
303  mtcStateMin(gen,rResGen);
304 
305  FD_WARN("mtcStateMin: debug out")
306  rGen.GraphWrite("tmp_smin_w.png");
307  rGen.DotWrite("tmp_smin_w.dot");
308 
309 }
310 
311 } // namespace faudes
#define FD_WARN(message)
#define FD_DF(message)
#define FD_WP(message)
Iterator EndByEvX2(Idx ev, Idx x2) const
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
Definition: cfl_transset.h:273
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
Definition: cfl_types.cpp:170
void Write(const Type *pContext=0) const
Definition: cfl_types.cpp:140
TransSet::Iterator TransRelBegin(void) const
EventSet::Iterator AlphabetBegin(void) const
void SetInitState(Idx index)
std::string StateName(Idx index) const
void Name(const std::string &rName)
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
Definition: cfl_baseset.h:1841
virtual void Clear(void)
Definition: cfl_baseset.h:1919
Iterator End(void) const
Definition: cfl_baseset.h:1913
Iterator Begin(void) const
Definition: cfl_baseset.h:1908
Idx Size(void) const
Definition: cfl_baseset.h:1836
uint32_t Idx
void mtcStateMin(MtcSystem &rGen, MtcSystem &rResGen)
std::string ToStringInteger(Int number)
Definition: cfl_utils.cpp:43

libFAUDES 2.33b --- 2025.05.07 --- c++ api documentaion by doxygen