cfl_determin.cppGo to the documentation of this file.00001 /** @file cfl_determin.cpp powerset construction */ 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 "cfl_determin.h" 00024 00025 namespace faudes { 00026 00027 // UniqueInit(rGen&) 00028 void UniqueInit(Generator& rGen) { 00029 Idx inituni; 00030 StateSet::Iterator lit; 00031 TransSet::Iterator tit; 00032 // check number of initial states 00033 if(rGen.InitStatesSize() == 1) return; 00034 // introduce new initial state 00035 if(rGen.StateNamesEnabled()) { 00036 std::string initname=rGen.UniqueStateName("InitUni"); 00037 inituni = rGen.InsState(initname); 00038 } else { 00039 inituni = rGen.InsState(); 00040 } 00041 FD_DF("UniqueInit: introducing new initial state: " << inituni); 00042 // introduce outgoing transitions from initial state 00043 FD_DF("UniqueInit: introduce outgoing transitions: "); 00044 for (lit = rGen.InitStatesBegin(); lit != rGen.InitStatesEnd(); ++lit) { 00045 for (tit = rGen.TransRelBegin(*lit); tit != rGen.TransRelEnd(*lit); ++tit) { 00046 rGen.SetTransition(inituni, tit->Ev, tit->X2); 00047 FD_DF("UniqueInit: " << inituni << "-" << tit->Ev << "-" << tit->X2); 00048 } 00049 } 00050 // mark the new init state if there exists an originally marked init state (tm 20101206) 00051 if(!(rGen.InitStates() * rGen.MarkedStates()).Empty()){ 00052 rGen.SetMarkedState(inituni); 00053 FD_DF("UniqueInit: set marked state: " << inituni); 00054 } 00055 // delete old istates 00056 rGen.ClearInitStates(); 00057 // set inituni as new initial state 00058 rGen.SetInitState(inituni); 00059 } 00060 00061 // UniqueInit(rGen&,rResGen&) 00062 void UniqueInit(const Generator& rGen, Generator& rResGen) { 00063 rResGen.Assign(rGen); 00064 UniqueInit(rResGen); 00065 } 00066 00067 // Deterministic(rGen&, rResGen&) 00068 void Deterministic(const Generator& rGen, Generator& rResGen) { 00069 // temporary vectors 00070 std::vector<StateSet> power_states; 00071 std::vector<Idx> det_states; 00072 Deterministic(rGen, power_states, det_states, rResGen); 00073 } 00074 00075 00076 // aDeterministic(rGen&, rResGen&) 00077 void aDeterministic(const Generator& rGen, Generator& rResGen) { 00078 // prepare result to keep original alphabet 00079 Generator* pResGen = &rResGen; 00080 if(&rResGen==&rGen) { 00081 pResGen= rResGen.New(); 00082 } 00083 // perform op 00084 Deterministic(rGen,*pResGen); 00085 // set old attributes 00086 pResGen->EventAttributes(rGen.Alphabet()); 00087 // copy result 00088 if(pResGen != &rResGen) { 00089 pResGen->Move(rResGen); 00090 delete pResGen; 00091 } 00092 } 00093 00094 00095 // Deterministic(rGen&, rEntryStatesMap&, rResGen&) 00096 void Deterministic(const Generator& rGen, std::map<Idx,StateSet>& rEntryStatesMap, 00097 Generator& rResGen) { 00098 // prepare result: 00099 rEntryStatesMap.clear(); 00100 // helpers: 00101 std::vector<StateSet> power_states; 00102 std::vector<Idx> det_states; 00103 // call Deterministic function 00104 Deterministic(rGen, power_states, det_states, rResGen); 00105 // build entry states map 00106 std::vector<StateSet>::size_type i; 00107 for (i = 0; i < power_states.size(); ++i) { 00108 rEntryStatesMap.insert(std::pair<Idx,StateSet>(det_states[i], power_states[i])); 00109 } 00110 } 00111 00112 00113 void Deterministic(const Generator& rGen, std::vector<StateSet>& rPowerStates, 00114 std::vector<Idx>& rDetStates, Generator& rResGen) { 00115 00116 // note: there is a demonstrative description of the multiway merge 00117 // algorithm in the master thesis. (Bernd Opitz) 00118 00119 FD_DF("Deterministic(): core function #" << rGen.Size()); 00120 00121 // use pointer pResGen to result rResGen 00122 Generator* pResGen = &rResGen; 00123 if(&rResGen== &rGen) { 00124 pResGen= rResGen.New(); 00125 } 00126 00127 // prepare result 00128 pResGen->Clear(); 00129 rPowerStates.clear(); 00130 rDetStates.clear(); 00131 // set the name 00132 pResGen->Name(CollapsString("Det(" + rGen.Name() + ")")); 00133 // copy alphabet 00134 FD_DF("Deterministic A " << rGen.Alphabet().ToString()); 00135 pResGen->InjectAlphabet(rGen.Alphabet()); 00136 FD_DF("Deterministic B"); 00137 00138 // bail out on empty input 00139 if(rGen.InitStatesEmpty()) { 00140 if(pResGen != &rResGen) { 00141 pResGen->Move(rResGen); 00142 delete pResGen; 00143 } 00144 FD_DF("Deterministic(): done (empty)"); 00145 return; 00146 } 00147 00148 // helpers 00149 typedef std::multimap< Idx,std::vector<StateSet>::size_type > T_HASHMAP; 00150 T_HASHMAP hashmap; 00151 std::vector<StateSet>::size_type current_vecindex; 00152 std::pair< std::map<StateSet,Idx>::iterator,bool > result; 00153 TransSet::Iterator transrel_end = rGen.TransRelEnd(); 00154 StateSet newset; 00155 StateSet::Iterator lit; 00156 const Idx max_idx = std::numeric_limits<Idx>::max(); 00157 00158 // lock transrel to prevent iterator tracking (tmoor 201403) 00159 rGen.TransRel().Lock(); 00160 00161 // initialize rPowerStates with subset of initial states 00162 Idx newstate = pResGen->InsInitState(); 00163 for (lit = rGen.InitStatesBegin(); lit != rGen.InitStatesEnd(); ++lit) { 00164 // clear set and insert single state 00165 newset.Insert(*lit); 00166 // if marked state set in res generator 00167 if (rGen.ExistsMarkedState(*lit)) { 00168 pResGen->SetMarkedState(newstate); 00169 FD_DF("Deterministic: setting as mstate: " << rGen.SStr(newstate)); 00170 } 00171 } 00172 FD_DF("Deterministic: created subset of initial states {" 00173 << newset.ToString() << "} with deterministic state index " 00174 << rGen.SStr(newstate)); 00175 // internally record newset 00176 rPowerStates.push_back(newset); 00177 rDetStates.push_back(newstate); 00178 hashmap.insert(std::make_pair(newset.Signature(), (Idx)rPowerStates.size() - 1)); 00179 00180 // iteration over all states 00181 for (current_vecindex = 0; current_vecindex < rPowerStates.size(); 00182 ++current_vecindex) { 00183 FD_WPC(current_vecindex,rPowerStates.size(), "Deterministic(): current/size: "<< current_vecindex << " / " << rPowerStates.size()); 00184 FD_DF("Deterministic: current power set: {" 00185 << rPowerStates[current_vecindex].ToString() << "} -> " 00186 << rDetStates[current_vecindex]); 00187 00188 std::vector<StateSet> newset_vec; 00189 std::vector<Idx> event_vec; 00190 00191 // multiway merge begin 00192 FD_DF("Deterministic: starting multiway merge..."); 00193 std::list<TransSet::Iterator> merge_iterators; 00194 std::vector<Transition> trans_vec; 00195 00196 // add transset iterator at begin of each state's transitions 00197 TransSet::Iterator tit; 00198 for (lit = rPowerStates[current_vecindex].Begin(); 00199 lit != rPowerStates[current_vecindex].End(); ++lit) { 00200 tit = rGen.TransRelBegin(*lit); 00201 if (tit != rGen.TransRelEnd(*lit)) { 00202 merge_iterators.push_back(tit); 00203 FD_DF("Deterministic: added merge iterator: " << rGen.SStr(tit->X1) 00204 << "-" << rGen.EStr(tit->Ev) << "-" << rGen.SStr(tit->X2)); 00205 } 00206 } 00207 00208 // find first iterator with lowest event 00209 while (! merge_iterators.empty()) { 00210 Idx currentevent = max_idx; 00211 std::list<TransSet::Iterator>::iterator i; 00212 std::list<TransSet::Iterator>::iterator currentit = merge_iterators.end(); 00213 for (i = merge_iterators.begin(); i != merge_iterators.end(); ++i) { 00214 if ((*i)->Ev < currentevent) { 00215 currentevent = (*i)->Ev; 00216 currentit = i; 00217 } 00218 } 00219 // currentit now holds the iterator 00220 // currentevent holds the lowest event (lowest Idx) 00221 00222 // merge all transitions with currentevent at each iterator in a row; 00223 // this is a modification of multiway merge as after projection the 00224 // automaton most likely holds states with many transitions that share 00225 // the same event; only merging the lowest transition and continue with 00226 // search for the lowest event again would be to slow here (because 00227 // of too much iterator dereferencing). 00228 Idx currentstate; 00229 while (currentit != merge_iterators.end()) { 00230 currentstate = (*currentit)->X1; 00231 TransSet::Iterator& j = *currentit; 00232 while (1) { 00233 // remove iterator if it reaches the end of the transition set 00234 if (j == transrel_end) { 00235 merge_iterators.erase(currentit++); 00236 break; 00237 } 00238 // if current iterator is in its original state 00239 else if (j->X1 == currentstate) { 00240 // if the event is still the same add the transition 00241 if (j->Ev == currentevent) { 00242 trans_vec.push_back(*j); 00243 FD_DF("Deterine: adding transition to list: " 00244 << rGen.SStr(j->X1) << "-" << rGen.EStr(j->Ev) << "-" 00245 << rGen.SStr(j->X2)); 00246 } 00247 // else go to next iterator 00248 else { 00249 ++currentit; 00250 break; 00251 } 00252 } 00253 // if the iterator is beyond its original state remove it 00254 else { 00255 merge_iterators.erase(currentit++); 00256 break; 00257 } 00258 ++j; 00259 } 00260 } 00261 } 00262 00263 // partition transition vector by events. optimizable? 00264 FD_DF("Deterministic: partitioning the transition vector..."); 00265 std::vector<Transition>::iterator tv_it; 00266 StateSet newset; 00267 Idx lastevent = 0; 00268 for (tv_it = trans_vec.begin(); tv_it != trans_vec.end(); ++tv_it) { 00269 if ((tv_it->Ev == lastevent) || (lastevent == 0)) { 00270 newset.Insert(tv_it->X2); 00271 lastevent = tv_it->Ev; 00272 } 00273 else { 00274 FD_DF("Deterministic: partition: {" << newset.ToString() 00275 << "} with event " << rGen.EStr(lastevent)); 00276 newset_vec.push_back(newset); 00277 event_vec.push_back(lastevent); 00278 newset.Clear(); 00279 newset.Insert(tv_it->X2); 00280 lastevent = tv_it->Ev; 00281 } 00282 } 00283 if (! newset.Empty()) { 00284 FD_DF("Deterministic: partition: {" << newset.ToString() 00285 << "} with event " << rGen.EStr(lastevent)); 00286 newset_vec.push_back(newset); 00287 event_vec.push_back(lastevent); 00288 } 00289 FD_DF("Deterministic: partitioning the transition vector finished"); 00290 FD_DF("Deterministic: multiway merge finished"); 00291 // multiway merge end 00292 00293 00294 std::vector<StateSet>::size_type nsv_index; 00295 for (nsv_index = 0; nsv_index < newset_vec.size(); ++nsv_index) { 00296 StateSet& currentset = newset_vec[nsv_index]; 00297 Idx currentevent = event_vec[nsv_index]; 00298 Idx tmp_x2 = 0; 00299 Idx sig = currentset.Signature(); 00300 // test if newset signature is already known 00301 std::pair<T_HASHMAP::iterator,T_HASHMAP::iterator> phit 00302 = hashmap.equal_range(sig); 00303 T_HASHMAP::iterator hit = phit.first; 00304 for (hit = phit.first; hit != phit.second; ++hit) { 00305 // test set of every matching signature for equality 00306 if (currentset == rPowerStates[hit->second]) { 00307 tmp_x2 = rDetStates[hit->second]; 00308 break; 00309 } 00310 } 00311 00312 // if new set is unique within the existing power sets 00313 if (tmp_x2 == 0) { 00314 // create new state in res generator 00315 tmp_x2 = pResGen->InsState(); 00316 // insert newset in rPowerStates and get iterator,bool pair 00317 rPowerStates.push_back(currentset); 00318 rDetStates.push_back(tmp_x2); 00319 hashmap.insert(std::make_pair(sig, (Idx)rPowerStates.size() - 1)); 00320 FD_DF("Deterministic: added new state " 00321 << rGen.SStr(tmp_x2) 00322 << " for new subset {" << currentset.ToString() << "}"); 00323 // set marked if one of the states in current set is marked 00324 for (lit = currentset.Begin(); lit != currentset.End(); ++lit) { 00325 if (rGen.ExistsMarkedState(*lit)) { 00326 pResGen->SetMarkedState(tmp_x2); 00327 break; 00328 } 00329 } 00330 } 00331 // introduce transition 00332 pResGen->SetTransition(rDetStates[current_vecindex], currentevent, tmp_x2); 00333 } 00334 } 00335 00336 00337 // fix names 00338 if (rGen.StateNamesEnabled() && pResGen->StateNamesEnabled()) { 00339 FD_DF("Deterministic: fixing names..."); 00340 // rPowerStates / rDetStates index "iterator" 00341 std::vector<StateSet>::size_type i; 00342 // deterministic states iterator 00343 std::vector<Idx>::const_iterator dit; 00344 for (i = 0; i < rPowerStates.size(); ++i) { 00345 // temporary state name 00346 std::string name = "{"; 00347 for (lit = rPowerStates[i].Begin(); lit != rPowerStates[i].End(); ++lit) { 00348 if (rGen.StateName(*lit) != "") name = name + rGen.StateName(*lit) + ","; 00349 else name = name + ToStringInteger(*lit) + ","; 00350 } 00351 name.erase(name.length() - 1); 00352 name = name + "}"; 00353 FD_DF("Deterministic: setting state name \"" << name << "\" for index " 00354 << rDetStates[i]); 00355 pResGen->StateName(rDetStates[i], name); 00356 } 00357 } 00358 00359 // move pResGen to rResGen 00360 if(pResGen != &rResGen) { 00361 pResGen->Move(rResGen); 00362 delete pResGen; 00363 } 00364 00365 FD_DF("Deterministic(): core function: done"); 00366 00367 } 00368 00369 00370 00371 } // namespace faudes libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen |