mtc_statemin.cpp

Go to the documentation of this file.
00001 /** @file mtc_statemin.cpp
00002 
00003 State space minimization
00004 
00005 */
00006 
00007 /* FAU Discrete Event Systems Library (libfaudes)
00008 
00009    Copyright (C) 2008  Matthias Singer
00010    Copyright (C) 2006  Bernd Opitz
00011    Exclusive copyright is granted to Klaus Schmidt
00012 
00013    This library is free software; you can redistribute it and/or
00014    modify it under the terms of the GNU Lesser General Public
00015    License as published by the Free Software Foundation; either
00016    version 2.1 of the License, or (at your option) any later version.
00017 
00018    This library is distributed in the hope that it will be useful,
00019    but WITHOUT ANY WARRANTY; without even the implied warranty of
00020    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00021    Lesser General Public License for more details.
00022 
00023    You should have received a copy of the GNU Lesser General Public
00024    License along with this library; if not, write to the Free Software
00025    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00026 
00027 #include "mtc_statemin.h"  
00028 
00029 namespace faudes {
00030 
00031 // mtcStateMin(rGen, rResGen)
00032 void mtcStateMin(MtcSystem& rGen, MtcSystem& rResGen) {
00033   std::vector<StateSet> subsets;
00034   std::vector<Idx> newindices;
00035   mtcStateMin(rGen, rResGen, subsets, newindices);
00036 }
00037 
00038 // mtcStateMin(rGen, rResGen, rSubSets, rNewIndices)
00039 void mtcStateMin(MtcSystem& rGen, MtcSystem& rResGen,
00040     std::vector<StateSet>& rSubsets, std::vector<Idx>& rNewIndices) {
00041   FD_DF("statemin: *** computing state space minimization of multi-tasking generator " 
00042     << &rGen << " ***");
00043   FD_DF("statemin: making generator accessible");
00044 #ifdef FAUDES_DEBUG_FUNCTION
00045   FD_WARN("mtcStateMin: debug out")
00046   rGen.Write("tmp_smin_m.gen");
00047 #endif
00048   // make accessible
00049   rGen.Accessible();
00050 #ifdef FAUDES_DEBUG_FUNCTION
00051   FD_WARN("mtcStateMin: debug out")
00052   rGen.Write("tmp_smin_a.gen");
00053 #endif
00054 
00055 
00056   if (rGen.Size() < 2) {
00057     FD_DF("statemin: generator size < 2. returning given generator");
00058     //rGen.Copy(rResGen); changed !! test
00059     rResGen = rGen;
00060     rSubsets.push_back(rGen.States() );
00061     rNewIndices.push_back(*( rResGen.States().Begin() ) );
00062     return;
00063   }
00064 
00065   // ensure generator is deterministic
00066   if (! rGen.IsDeterministic()) {
00067     throw Exception("mtcStateMin", "input automaton nondeterministic", 505);
00068   }
00069 
00070   // prepare result
00071   rResGen.Clear();
00072   rResGen.Name(rGen.Name()+" [mtc minstate]");
00073 
00074   rResGen.ClearStateAttributes();
00075   rResGen.InjectAlphabet(rGen.Alphabet());
00076 
00077   rResGen.SetControllable(rGen.ControllableEvents());
00078   rResGen.SetForcible(rGen.ForcibleEvents());
00079   rResGen.ClrObservable(rGen.UnobservableEvents());
00080 
00081 
00082   // blocks B[i]
00083   std::vector<StateSet>& b = rSubsets; // convenience notation "b"
00084   Idx i, j;
00085   // set of active b (iterators)
00086   std::set<Idx> active;
00087   std::set<Idx>::iterator ait;
00088   // reverse transrel
00089   TransSetEvX2X1 rtransrel;
00090   rGen.TransRel(rtransrel);
00091   TransSetEvX2X1::Iterator rtit, rtit_end;
00092   // other stuff
00093   StateSet::Iterator lit; 
00094   TransSet::Iterator tit;
00095 
00096   // set up b "B[i]"
00097   i = 0;
00098 
00099 #ifdef FAUDES_DEBUG_FUNCTION
00100   FD_WARN("mtcStateMin: debug out: states");
00101   rGen.States().Write();
00102   FD_WARN("mtcStateMin: debug out: colored states");
00103   rGen.ColoredStates().Write();
00104   FD_WARN("mtcStateMin: debug out: unolored states");
00105   rGen.UncoloredStates().Write();
00106 #endif
00107 
00108   if (rGen.UncoloredStates().Size() > 0) {
00109     b.push_back(rGen.UncoloredStates());
00110     active.insert(i++);
00111     FD_DF("statemin: new block B[" << i-1 << "] = {" << 
00112       (rGen.UncoloredStates()).ToString() << "}");
00113   }
00114   // find states that have the same associated colors
00115   std::map<Idx,ColorSet> stateColorMap = rGen.StateColorMap();
00116   std::map<Idx,ColorSet>::const_iterator sit_end = stateColorMap.end();
00117   std::map<ColorSet,StateSet> SameColors;
00118   std::map<ColorSet,StateSet>::iterator csit;
00119   std::map<Idx,ColorSet>::const_iterator sit;
00120 
00121   for(sit = stateColorMap.begin(); sit != sit_end; ++sit){
00122     csit = SameColors.find(sit->second);
00123     FD_DF("stateColorMap, state: " << ToStringInteger(sit->first) << ", colors: " << (sit->second).ToString());
00124     if(csit != SameColors.end() )
00125         csit->second.Insert(sit->first);
00126     else{
00127         StateSet NewStateSet;
00128         NewStateSet.Insert(sit->first);
00129         SameColors[sit->second] = NewStateSet;
00130     }
00131   }
00132 
00133   // create the initial set of equivalence classes
00134   std::map<ColorSet,StateSet>::const_iterator csit_end = SameColors.end();
00135   for(csit = SameColors.begin(); csit != csit_end; ++csit){
00136       b.push_back(csit->second); // Colored StateSets
00137       active.insert(i++);
00138       FD_DF("statemin: new block B[" << i-1 << "] = {" << 
00139             csit->second.ToString() << "}");
00140   }
00141 
00142   // while there is an active block B
00143   while (! active.empty()) {
00144     FD_WP("mtcStateMin: blocks/active:   " << b.size() << " / " << active.size());
00145 #ifdef FD_DF
00146     FD_DF("statemin: if there is an active block B...");
00147     std::set<Idx>::iterator _it1;
00148     std::stringstream str;
00149     for (_it1 = active.begin(); _it1 != active.end(); ++_it1) {
00150       str << *_it1 << " ";
00151     }
00152     FD_DF("active: "+str.str());
00153     std::vector<StateSet>::iterator _it2;
00154     str.clear();
00155     for (_it2 = b.begin(); _it2 != b.end(); ++_it2) {
00156       str << "{" << _it2->ToString() << "} ";
00157     }
00158     str << std::endl;
00159     FD_DF("B: "+str.str());
00160 #endif
00161     // current block B[i]
00162     i = *(active.begin());
00163     // inactivate B[i]
00164     active.erase(active.begin());
00165     FD_DF("statemin: getting active block B[" << i << "] = {" <<
00166         b.at(i).ToString() << "}");
00167     // b_current <- B[i]
00168     StateSet b_current = b.at(i);
00169 
00170     // compute C = f^-1(B[i]) for every event in B[i] (as b_current)
00171     StateSet c;
00172     EventSet::Iterator eit;
00173     // iteration over alphabet
00174     for (eit = rGen.AlphabetBegin(); eit != rGen.AlphabetEnd(); ++eit) {
00175       c.Clear();
00176       // iteration over states in current block
00177       for (lit = b_current.Begin(); lit != b_current.End(); ++lit) {
00178         // find predecessor states by current ev + x2
00179         rtit = rtransrel.BeginByEvX2(*eit, *lit);
00180         rtit_end = rtransrel.EndByEvX2(*eit, *lit);
00181         for (; rtit != rtit_end; ++rtit) {
00182           c.Insert(rtit->X1);
00183         }
00184       }
00185       // if predecessor states where found
00186       if (! c.Empty()) {
00187         // search for new block on next event or coming end of rtransrel with
00188         // x1 as *lit
00189         FD_DF("statemin: computed predecessor states C = {" << c.ToString() 
00190             << "} for event " << rGen.EventName(*eit));
00191 
00192         // foreach block D 
00193         for (j=0; j < b.size(); ++j) {
00194           FD_DF("statemin: examining block B[" << j << "] = {" << 
00195               b.at(j).ToString() << "}");
00196           // compute D' = D intersection C
00197           StateSet d_ = b.at(j) * c;
00198           // compute D'' = D - D'; remove D, add D''
00199           StateSet d__ = b.at(j) - d_;
00200           // check D split by B
00201           if (d_.Empty() || d__.Empty()) {
00202             FD_DF("statemin: -> no split");  
00203             continue;
00204           }
00205           FD_DF("statemin: -> split:");  
00206           b[j] = d_;
00207           FD_DF("statemin: new block B[" << j << "] = {" 
00208               << d_.ToString() << "}");
00209           b.push_back(d__);
00210           FD_DF("statemin: new block B[" << b.size()-1 << "] = {"
00211               << d__.ToString() << "}");
00212           // if D was active
00213           if (active.count(j) > 0) {
00214             // then mark both D', D'' active
00215             active.insert((Idx)b.size()- 1);
00216             FD_DF("statemin: mark active: " << b.size()-1);
00217           }
00218           // else mark smaller of D', D'' active
00219           else {
00220             if (d_.Size() < d__.Size()) {
00221               active.insert(j);
00222               FD_DF("statemin: mark active: " << j);
00223             }
00224             else {
00225               active.insert((Idx)b.size()-1);
00226               FD_DF("statemin: mark active: " << b.size()-1);
00227             }
00228           }
00229         } // foreach block D
00230         c.Clear();
00231       }
00232     }
00233   }
00234 
00235   FD_DF("statemin: *** building minimized generator ***");
00236   // build minimized generator
00237   std::map<Idx,Idx> minstatemap;
00238   Idx newstate;
00239   // loop over all blocks B
00240   for (i = 0; i < b.size(); i++) {
00241     // create state in new generator for every block
00242     newstate = rResGen.InsState();
00243     rNewIndices.push_back(newstate);
00244     FD_DF("statemin: block {" << b.at(i).ToString() 
00245         << "} -> new state " << newstate);
00246     std::ostringstream ostr; 
00247     Idx count = 0;
00248     for (lit = b.at(i).Begin(); lit != b.at(i).End(); lit++) {
00249       count++;
00250       // set minstatemap entry for every state in gen
00251       minstatemap[*lit] = newstate;
00252       if (rResGen.StateNamesEnabled()) {
00253         FD_DF("StateNamesEnabled: index: \""<< ToStringInteger(*lit) << "\", name: \"" << rGen.StateName(*lit) << "\"");
00254         if (rGen.StateName(*lit) == "") {
00255           ostr << ToStringInteger(*lit) << ",";
00256           FD_DF("StateName \"\", ostr =  " << ostr.str());
00257         }
00258         else {
00259           ostr << rGen.StateName(*lit) << ",";
00260           FD_DF("StateName exists, ostr =  " << ostr.str());
00261         }
00262       }
00263       // set istates
00264       if (rGen.ExistsInitState(*lit)) {
00265         rResGen.SetInitState(newstate);
00266         FD_DF("statemin: -> initial state");
00267       }
00268       if(count == 1){ //all states in b.at(i) have the same colors
00269         std::map<Idx,ColorSet>::const_iterator col_it;
00270         col_it = stateColorMap.find(*lit);
00271         // are there any colors to set for the current state?
00272         if (col_it != stateColorMap.end()) {
00273           // insert corresponding colors if they are not already set for the current state
00274           FD_DF("mtcStateMin: insert colors " << col_it->second.ToString() << " to state " << newstate);
00275           rResGen.InsColors(newstate, col_it->second);
00276         }
00277       }
00278     }
00279     if (rResGen.StateNamesEnabled()) {
00280       std::string statename = ostr.str();
00281       statename.erase(statename.length()-1);
00282       statename = "{" + statename + "}";
00283       FD_DF("Set state name: name: \"" << statename << "\", index: \"" << newstate << "\"");
00284       rResGen.StateName(newstate, statename);
00285     }
00286   }
00287   // create transition relation
00288   for (tit = rGen.TransRelBegin(); tit != rGen.TransRelEnd(); ++tit) {
00289     rResGen.SetTransition(minstatemap[tit->X1], tit->Ev, minstatemap[tit->X2]);
00290     FD_DF("statemin: adding transition: " 
00291         << minstatemap[tit->X1] << "-" << tit->Ev << "-" 
00292         << minstatemap[tit->X2]);
00293   }
00294 #ifdef FAUDES_DEBUG_FUNCTION
00295   FD_WARN("mtcStateMin: debug out: result")
00296   rResGen.Write("tmp_smin_r.gen");
00297 #endif
00298 }
00299 
00300 // RTI wrapper
00301 void mtcStateMin(const MtcSystem& rGen, MtcSystem& rResGen) {
00302   MtcSystem gen(rGen);
00303   mtcStateMin(gen,rResGen);
00304 
00305   FD_WARN("mtcStateMin: debug out")
00306   rGen.GraphWrite("tmp_smin_w.png");
00307   rGen.DotWrite("tmp_smin_w.dot");
00308 
00309 }
00310 
00311 } // namespace faudes

libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen