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 
00043     rGen.Accessible();
00044     if (rGen.Size() == 0) {
00045       FD_DF("StateMin: generator size 0. returning given generator");
00046       rResGen = rGen;
00047       return;
00048     }
00049     if (rGen.Size() == 1) {
00050       FD_DF("StateMin: generator size 1. returning given generator");
00051       rResGen = rGen;
00052       rSubsets.push_back(rGen.States() );
00053       rNewIndices.push_back(*( rResGen.States().Begin() ) );
00054       return;
00055     }
00056 
00057     // ensure generator is deterministic
00058     if (! rGen.IsDeterministic()) {
00059       throw Exception("StateMin", "input automaton nondeterministic", 101);
00060     }
00061     
00062     // use pointer pResGen to result rResGen; if rResGen is identical to
00063     // one of the parameters, allocate temporary object and copy back later
00064     vGenerator* pResGen = &rResGen;
00065     if(&rResGen==&rGen) {
00066         pResGen= pResGen->NewP();
00067     }
00068 
00069     // prepare result
00070     pResGen->Clear();
00071     pResGen->Name(rGen.Name()+" [minstate]");
00072     pResGen->InjectAlphabet(rGen.Alphabet());
00073     bool stateNames= pResGen->StateNamesEnabled() && rGen.StateNamesEnabled();
00074     // blocks B[i]
00075     std::vector<StateSet>& b = rSubsets; // convenience notation "b"
00076     Idx i, j;
00077     // set of active b (iterators)
00078     std::set<Idx> active;
00079     std::set<Idx>::iterator ait;
00080     // reverse transrel
00081     TransSetEvX2X1 rtransrel;
00082     rGen.TransRel(rtransrel);
00083     TransSetEvX2X1::Iterator rtit, rtit_end;
00084     // other stuff
00085     StateSet::Iterator lit; 
00086     TransSet::Iterator tit;
00087 
00088     // set up b "B[i]"
00089     i = 0;
00090     if (rGen.Size() - rGen.MarkedStatesSize() > 0) {
00091       StateSet notmarked=rGen.States() - rGen.MarkedStates();
00092       notmarked.Name("B[i]"); 
00093       FD_DF("StateMin: new block B[" << i << "] = {" << 
00094       notmarked.ToString() << "}");
00095       b.push_back(notmarked);  //X -Xm
00096       active.insert(i++);
00097     }
00098     FD_DF("StateMin: new block B[" << i << "] = {" << 
00099     rGen.MarkedStates().ToString() << "}");
00100     b.push_back(rGen.MarkedStates()); // Xm
00101     active.insert(i++);
00102 
00103     // while there is a active block B
00104     while (! active.empty()) {
00105       FD_WP("StateMin: blocks/active:   " << b.size() << " / " << active.size());
00106 #ifdef FAUDES_DEBUG_FUNCTION
00107       FD_DF("StateMin: while there is an active block B...");
00108       std::set<Idx>::iterator _it1;
00109       std::stringstream str;
00110       for (_it1 = active.begin(); _it1 != active.end(); ++_it1) {
00111   str << *_it1 << " ";
00112       }
00113       FD_DF("StateMin: active: "+str.str());
00114       std::vector<StateSet>::iterator _it2;
00115       str.clear();
00116       str.str("");
00117       for (_it2 = b.begin(); _it2 != b.end(); ++_it2) {
00118   str << "{" << _it2->ToString() << "} "<<std::endl;
00119       }
00120       str << std::endl;
00121       FD_DF("B: "+str.str());
00122 #endif
00123       // current block B[i]
00124       i = *(active.begin());
00125       // inactivate B[i]
00126       active.erase(active.begin());
00127       FD_DF("StateMin: getting active block B[" << i << "] = {" <<
00128       b.at(i).ToString() << "}");
00129       // b_current <- B[i]
00130       StateSet b_current = b.at(i);
00131 
00132       // compute C = f^-1(B[i]) for every event in B[i] (as b_current)
00133       StateSet c;
00134       EventSet::Iterator eit;
00135       // iteration over alphabet
00136       for (eit = rGen.AlphabetBegin(); eit != rGen.AlphabetEnd(); ++eit) {
00137   c.Clear();
00138   // iteration over states in current block
00139   for (lit = b_current.Begin(); lit != b_current.End(); ++lit) {
00140     // find predecessor states by current ev + x2
00141     rtit = rtransrel.BeginByEvX2(*eit, *lit);
00142     rtit_end = rtransrel.EndByEvX2(*eit, *lit);
00143     for (; rtit != rtit_end; ++rtit) {
00144       c.Insert(rtit->X1);
00145     }
00146   }
00147   // if predecessor states where found
00148   if (! c.Empty()) {
00149     // search for new block on next event or coming end of rtransrel with
00150     // x1 as *lit
00151     FD_DF("StateMin: computed predecessor states C = {" << c.ToString() 
00152     << "} for event " << rGen.EventName(*eit));
00153     // foreach block D 
00154     for (j=0; j < b.size(); ++j) {
00155       FD_DF("StateMin: examining block B[" << j << "] = {" << 
00156       b.at(j).ToString() << "}");
00157       // compute D' = D intersection C
00158       StateSet d_ = b.at(j) * c;
00159             d_.Name("D'");
00160       // compute D'' = D - D'; remove D, add D''
00161       StateSet d__ = b.at(j) - d_;
00162             d__.Name("D''");
00163       // check D split by B
00164       if (d_.Empty() || d__.Empty()) {
00165         FD_DF("StateMin: -> no split");  
00166         continue;
00167       }
00168       FD_DF("StateMin: -> split:");  
00169       b[j] = d_;
00170       FD_DF("StateMin: new block B[" << j << "] = {" 
00171       << d_.ToString() << "}");
00172       b.push_back(d__);
00173       FD_DF("StateMin: new block B[" << b.size()-1 << "] = {"
00174       << d__.ToString() << "}");
00175       // if D was active
00176       if (active.count(j) > 0) {
00177         // then mark both D', D'' active
00178         active.insert((Idx)b.size()- 1);
00179         FD_DF("StateMin: mark active: " << b.size()-1);
00180       }
00181       // else mark smaller of D', D'' active
00182       else {
00183         if (d_.Size() < d__.Size()) {
00184     active.insert(j);
00185     FD_DF("StateMin: mark active: " << j);
00186         }
00187         else {
00188     active.insert((Idx)b.size()-1);
00189     FD_DF("StateMin: mark active: " << b.size()-1);
00190         }
00191       }
00192     } // foreach block D
00193     c.Clear();
00194   }
00195       }
00196     }
00197 
00198     FD_DF("StateMin: *** building minimized generator ***");
00199     // build minimized generator
00200     std::map<Idx,Idx> minstatemap;
00201     Idx newstate;
00202     // loop over all blocks B
00203     for (i = 0; i < b.size(); ++i) {
00204       // create state in new generator for every block
00205       newstate = pResGen->InsState();
00206       rNewIndices.push_back(newstate);
00207       FD_DF("StateMin: block {" << b.at(i).ToString() 
00208       << "} -> new state " << newstate);
00209       std::ostringstream ostr; 
00210       for (lit = b.at(i).Begin(); lit != b.at(i).End(); ++lit) {
00211   // set minstatemap entry for every state in gen
00212   minstatemap[*lit] = newstate;
00213   if(stateNames) {
00214     if (rGen.StateName(*lit) == "") {
00215       ostr << ToStringInteger(*lit) << ",";
00216     }
00217     else {
00218       ostr << rGen.StateName(*lit) << ",";
00219     }
00220   }
00221   // set istates
00222   if (rGen.ExistsInitState(*lit)) {
00223     pResGen->SetInitState(newstate);
00224     FD_DF("StateMin: -> initial state");
00225   }
00226   // set mstates
00227   if (rGen.ExistsMarkedState(*lit)) {
00228     pResGen->SetMarkedState(newstate);
00229     FD_DF("StatMmin: -> marked state");
00230   }
00231       }
00232       if (stateNames) {
00233   std::string statename = ostr.str();
00234   if(statename!="") statename.erase(statename.length()-1);
00235   statename = "{" + statename + "}";
00236   pResGen->StateName(newstate, statename);
00237       }
00238     }
00239     // create transition relation
00240     for (tit = rGen.TransRelBegin(); tit != rGen.TransRelEnd(); ++tit) {
00241       pResGen->SetTransition(minstatemap[tit->X1], tit->Ev, minstatemap[tit->X2]);
00242       FD_DF("statemin: adding transition: " 
00243       << minstatemap[tit->X1] << "-" << tit->Ev << "-" 
00244       << minstatemap[tit->X2]);
00245     }
00246     
00247     // if necessary, move pResGen to rResGen
00248     if(pResGen != &rResGen) {
00249     pResGen->Move(rResGen);
00250     delete pResGen;
00251     }
00252   }
00253   
00254 } // namespace faudes

Generated on Mon Nov 10 08:13:15 2008 for libFAUDES 2.11v by  doxygen 1.4.4