statemin.cpp

Go to the documentation of this file.
00001 
00003 /* FAU Discrete Event Systems Library (libfaudes)
00004 
00005 Copyright (C) 2006  Bernd Opitz
00006 Exclusive copyright is granted to Klaus Schmidt
00007 
00008 This library is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU Lesser General Public
00010 License as published by the Free Software Foundation; either
00011 version 2.1 of the License, or (at your option) any later version.
00012 
00013 This library is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 Lesser General Public License for more details.
00017 
00018 You should have received a copy of the GNU Lesser General Public
00019 License along with this library; if not, write to the Free Software
00020 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00021 
00022   
00023 #include "statemin.h"
00024 #include "exception.h"
00025 #include "project.h"
00026 
00027 namespace faudes {
00028 
00029   // StateMin(rGen, rResGen)
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   // StateMin(rGen, rResGen, rSubSets, rNewIndices)
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     // ensure generator is deterministic
00057     if (! rGen.IsDeterministic()) {
00058       throw Exception("StateMin", "input automaton nondeterministic", 101);
00059     }
00060 
00061     // prepare result
00062     rResGen.Clear();
00063     rResGen.Name(rGen.Name()+" [minstate]");
00064     rResGen.InjectAlphabet(rGen.Alphabet());
00065     bool stateNames= rResGen.StateNamesEnabled() && rGen.StateNamesEnabled();
00066     // blocks B[i]
00067     std::vector<StateSet>& b = rSubsets; // convenience notation "b"
00068     Idx i, j;
00069     // set of active b (iterators)
00070     std::set<Idx> active;
00071     std::set<Idx>::iterator ait;
00072     // reverse transrel
00073     TransSetEvX2X1 rtransrel;
00074     rGen.TransRel(rtransrel);
00075     TransSetEvX2X1::Iterator rtit, rtit_end;
00076     // other stuff
00077     StateSet::Iterator lit; 
00078     TransSet::Iterator tit;
00079 
00080     // set up b "B[i]"
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);  //X -Xm
00088       active.insert(i++);
00089     }
00090     FD_DF("StateMin: new block B[" << i << "] = {" << 
00091     rGen.MarkedStates().ToString() << "}");
00092     b.push_back(rGen.MarkedStates()); // Xm
00093     active.insert(i++);
00094 
00095     // while there is a active block B
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       // current block B[i]
00116       i = *(active.begin());
00117       // inactivate B[i]
00118       active.erase(active.begin());
00119       FD_DF("StateMin: getting active block B[" << i << "] = {" <<
00120       b.at(i).ToString() << "}");
00121       // b_current <- B[i]
00122       StateSet b_current = b.at(i);
00123 
00124       // compute C = f^-1(B[i]) for every event in B[i] (as b_current)
00125       StateSet c;
00126       EventSet::Iterator eit;
00127       // iteration over alphabet
00128       for (eit = rGen.AlphabetBegin(); eit != rGen.AlphabetEnd(); ++eit) {
00129   c.Clear();
00130   // iteration over states in current block
00131   for (lit = b_current.Begin(); lit != b_current.End(); ++lit) {
00132     // find predecessor states by current ev + x2
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   // if predecessor states where found
00140   if (! c.Empty()) {
00141     // search for new block on next event or coming end of rtransrel with
00142     // x1 as *lit
00143     FD_DF("StateMin: computed predecessor states C = {" << c.ToString() 
00144     << "} for event " << rGen.EventName(*eit));
00145     // foreach block D 
00146     for (j=0; j < b.size(); ++j) {
00147       FD_DF("StateMin: examining block B[" << j << "] = {" << 
00148       b.at(j).ToString() << "}");
00149       // compute D' = D intersection C
00150       StateSet d_ = b.at(j) * c;
00151             d_.Name("D'");
00152       // compute D'' = D - D'; remove D, add D''
00153       StateSet d__ = b.at(j) - d_;
00154             d__.Name("D''");
00155       // check D split by B
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       // if D was active
00168       if (active.count(j) > 0) {
00169         // then mark both D', D'' active
00170         active.insert((Idx)b.size()- 1);
00171         FD_DF("StateMin: mark active: " << b.size()-1);
00172       }
00173       // else mark smaller of D', D'' active
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     } // foreach block D
00185     c.Clear();
00186   }
00187       }
00188     }
00189 
00190     FD_DF("StateMin: *** building minimized generator ***");
00191     // build minimized generator
00192     std::map<Idx,Idx> minstatemap;
00193     Idx newstate;
00194     // loop over all blocks B
00195     for (i = 0; i < b.size(); ++i) {
00196       // create state in new generator for every block
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   // set minstatemap entry for every state in gen
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   // set istates
00214   if (rGen.ExistsInitState(*lit)) {
00215     rResGen.SetInitState(newstate);
00216     FD_DF("StateMin: -> initial state");
00217   }
00218   // set mstates
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     // create transition relation
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 } // namespace faudes

Generated on Fri May 9 11:26:47 2008 for libFAUDES 2.09b by  doxygen 1.4.4