libFAUDES

Sections

Index

statemin.cpp

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

libFAUDES 2.14g --- 2009-12-3 --- c++ source docu by doxygen 1.5.6