Vaucanson 1.4
|
00001 // eps_removal_sp.hxx: this file is part of the Vaucanson project. 00002 // 00003 // Vaucanson, a generic library for finite state machines. 00004 // 00005 // Copyright (C) 2004, 2005, 2006, 2008 The Vaucanson Group. 00006 // 00007 // This program is free software; you can redistribute it and/or 00008 // modify it under the terms of the GNU General Public License 00009 // as published by the Free Software Foundation; either version 2 00010 // of the License, or (at your option) any later version. 00011 // 00012 // The complete GNU General Public Licence Notice can be found as the 00013 // `COPYING' file in the root directory. 00014 // 00015 // The Vaucanson Group consists of people listed in the `AUTHORS' file. 00016 // 00017 #ifndef VCSN_ALGORITHMS_EPS_REMOVAL_SP_HXX 00018 # define VCSN_ALGORITHMS_EPS_REMOVAL_SP_HXX 00019 00020 # include <vaucanson/algorithms/eps_removal.hh> 00021 00022 # include <vaucanson/automata/concept/automata_base.hh> 00023 # include <vaucanson/misc/usual_macros.hh> 00024 00025 # include <boost/multi_index_container.hpp> 00026 # include <boost/multi_index/member.hpp> 00027 # include <boost/multi_index/hashed_index.hpp> 00028 # include <boost/multi_index/composite_key.hpp> 00029 # include <boost/functional/hash/hash.hpp> 00030 # include <boost/tuple/tuple.hpp> 00031 # include <vector> 00032 # include <list> 00033 # include <queue> 00034 # include <map> 00035 # include <utility> 00036 # include <set> 00037 # include <stack> 00038 00039 namespace vcsn { 00040 00041 /*----------------------------------------. 00042 | EpsilonRemoverSp for weighted automaton | 00043 `----------------------------------------*/ 00044 00045 template 00046 <class A_, typename Auto, typename Weight> 00047 class EpsilonRemoverSp 00048 { 00049 AUTOMATON_TYPES(Auto); 00050 public: 00051 struct tr_t 00052 { 00053 tr_t(hstate_t src_, hstate_t dst_, series_set_elt_t series_) 00054 : src(src_), 00055 dst(dst_), 00056 series(series_) 00057 {} 00058 00059 hstate_t src; 00060 hstate_t dst; 00061 series_set_elt_t series; 00062 }; 00063 00064 struct s_shortest 00065 { 00066 s_shortest(const hstate_t src_, const hstate_t dst_, semiring_elt_t& d_, semiring_elt_t& r_) 00067 : src(src_), 00068 dst(dst_), 00069 dist(d_), 00070 rel(r_) 00071 {} 00072 00073 const hstate_t src; 00074 const hstate_t dst; 00075 semiring_elt_t dist; 00076 semiring_elt_t rel; 00077 }; 00078 00079 struct change_rel 00080 { 00081 change_rel(const semiring_elt_t& new_rel) 00082 : new_rel(new_rel) 00083 {} 00084 00085 void operator() (s_shortest& s) 00086 { 00087 s.rel = new_rel; 00088 } 00089 private: 00090 semiring_elt_t new_rel; 00091 }; 00092 00093 struct change_dist 00094 { 00095 change_dist(const semiring_elt_t& new_dist) 00096 : new_dist(new_dist) 00097 {} 00098 00099 void operator() (s_shortest& s) 00100 { 00101 s.dist = new_dist; 00102 } 00103 private: 00104 semiring_elt_t new_dist; 00105 }; 00106 00107 struct add_dr 00108 { 00109 add_dr(const semiring_elt_t& new_dist, const semiring_elt_t& new_rel) 00110 : new_dist(new_dist), 00111 new_rel(new_rel) 00112 {} 00113 00114 void operator() (s_shortest& s) 00115 { 00116 s.dist += new_dist; 00117 s.rel += new_rel; 00118 } 00119 private: 00120 semiring_elt_t new_dist; 00121 semiring_elt_t new_rel; 00122 }; 00123 00124 typedef boost::multi_index_container 00125 < 00126 s_shortest, 00127 boost::multi_index::indexed_by 00128 < 00129 boost::multi_index::hashed_unique 00130 < 00131 boost::multi_index::composite_key 00132 < 00133 s_shortest, 00134 BOOST_MULTI_INDEX_MEMBER(s_shortest, const hstate_t, src), 00135 BOOST_MULTI_INDEX_MEMBER(s_shortest, const hstate_t, dst) 00136 > 00137 > 00138 > 00139 > s_shortest_hash; 00140 00141 EpsilonRemoverSp(const AutomataBase<A_>&, 00142 Auto& aut) 00143 : a(aut), 00144 null_series(aut.series().zero_), 00145 semiring_elt_zero(aut.series().semiring().wzero_), 00146 semiring_elt_one(aut.series().semiring().wone_), 00147 monoid_identity(aut.series().monoid().VCSN_EMPTY_) 00148 { 00149 shortest_eps_distance(); 00150 } 00151 00152 void operator() (misc::direction_type dir) 00153 { 00154 // Remove epsilon-transitions 00155 for_all_transitions(e,a) 00156 { 00157 series_set_elt_t t = a.series_of(*e); 00158 if (t.get(monoid_identity) != semiring_elt_zero) 00159 { 00160 t.assoc(monoid_identity.value(), semiring_elt_zero.value()); 00161 if (t != null_series) 00162 a.add_series_transition(a.src_of(*e), a.dst_of(*e), t); 00163 a.del_transition(*e); 00164 } 00165 } 00166 00167 if (dir == misc::backward) 00168 backward_remove(); 00169 else 00170 forward_remove(); 00171 } 00172 00173 private: 00174 void shortest_eps_distance() 00175 { 00176 for_all_const_states(s, a) 00177 { 00178 typename s_shortest_hash::iterator it; 00179 shortest_hash.insert(s_shortest(*s, *s, semiring_elt_one, semiring_elt_one)); 00180 squeue.insert(*s); 00181 while (!squeue.empty()) 00182 { 00183 hstate_t curr = *squeue.begin(); 00184 squeue.erase(squeue.begin()); 00185 semiring_elt_t R = semiring_elt_zero; 00186 it = shortest_hash.find(boost::make_tuple(*s, curr)); 00187 if (it != shortest_hash.end()) 00188 { 00189 R = it->rel; 00190 shortest_hash.modify(it, change_rel(semiring_elt_zero)); 00191 } 00192 00193 for (delta_iterator e(a.value(), curr); ! e.done(); e.next()) 00194 if (a.is_spontaneous(*e)) 00195 { 00196 semiring_elt_t dist = semiring_elt_zero; 00197 it = shortest_hash.find(boost::make_tuple(*s, a.dst_of(*e))); 00198 if (it != shortest_hash.end()) 00199 dist = it->dist; 00200 semiring_elt_t we = a.series_of(*e).get(monoid_identity); 00201 we = R * we; 00202 if (dist != dist + we) 00203 { 00204 if (it != shortest_hash.end()) 00205 { 00206 shortest_hash.modify(it, add_dr(we, we)); 00207 squeue.insert(a.dst_of(*e)); 00208 } 00209 else 00210 { 00211 shortest_hash.insert(s_shortest(*s, a.dst_of(*e), we, we)); 00212 squeue.insert(a.dst_of(*e)); 00213 } 00214 } 00215 } 00216 } 00217 } 00218 } 00219 00220 void backward_remove() 00221 { 00222 std::list<std::pair<htransition_t, semiring_elt_t> > tr_l; 00223 std::list<std::pair<hstate_t, semiring_elt_t> > fin_l; 00224 std::stack<tr_t> tr_st; 00225 std::stack<std::pair<hstate_t, series_set_elt_t> > fin_st; 00226 00227 for_all_(s_shortest_hash, it, shortest_hash) 00228 if (it->src != it->dst) 00229 { 00230 for (delta_iterator e(a.value(), it->dst); ! e.done(); e.next()) 00231 tr_st.push(tr_t(it->src, a.dst_of(*e), it->dist * a.series_of(*e))); 00232 if (a.is_final(it->dst)) 00233 fin_st.push(make_pair(it->src, it->dist * a.get_final(it->dst))); 00234 } 00235 else 00236 { 00237 if (it->dist != semiring_elt_one) 00238 { 00239 for (delta_iterator e(a.value(), it->dst); ! e.done(); e.next()) 00240 tr_l.push_front(std::pair<htransition_t, semiring_elt_t>(*e, it->dist)); // associate each e with it->dist 00241 if (a.is_final(it->dst)) 00242 fin_l.push_front(std::pair<hstate_t, semiring_elt_t>(it->src, it->dist));// store what we need to multiply w(final(it->src)) by it->dist 00243 } 00244 } 00245 00246 for (typename std::list<std::pair<htransition_t, semiring_elt_t> >::iterator it = tr_l.begin(); 00247 it != tr_l.end(); ++it) 00248 { 00249 series_set_elt_t s = a.series_of(it->first) * it->second; 00250 if (s != null_series) 00251 a.add_series_transition(a.src_of(it->first), a.dst_of(it->first), s); 00252 a.del_transition(it->first); 00253 } 00254 00255 for (typename std::list<std::pair<hstate_t, semiring_elt_t> >::iterator it = fin_l.begin(); 00256 it != fin_l.end(); ++it) 00257 a.set_final(it->first, it->second * a.get_final(it->first)); 00258 00259 while (!tr_st.empty()) 00260 { 00261 a.add_series_transition(tr_st.top().src, tr_st.top().dst, tr_st.top().series); 00262 tr_st.pop(); 00263 } 00264 00265 while (!fin_st.empty()) 00266 { 00267 a.set_final(fin_st.top().first, a.get_final(fin_st.top().first) + 00268 fin_st.top().second); 00269 fin_st.pop(); 00270 } 00271 } 00272 00273 void forward_remove() 00274 { 00275 std::list<std::pair<htransition_t, semiring_elt_t> > tr_l; 00276 std::list<std::pair<hstate_t, semiring_elt_t> > fin_l; 00277 std::stack<tr_t> tr_st; 00278 std::stack<std::pair<hstate_t, series_set_elt_t> > init_st; 00279 00280 for_all_(s_shortest_hash, it, shortest_hash) 00281 if (it->src != it->dst) 00282 { 00283 for (rdelta_iterator e(a.value(), it->dst); ! e.done(); e.next()) 00284 tr_st.push(tr_t(a.src_of(*e), it->dst, a.series_of(*e) * it->dist)); 00285 if (a.is_initial(it->src)) 00286 init_st.push(make_pair(it->dst, a.get_initial(it->src) * it->dist)); 00287 } 00288 else 00289 { 00290 if (it->dist != semiring_elt_one) 00291 { 00292 for (rdelta_iterator e(a.value(), it->dst); ! e.done(); e.next()) 00293 tr_l.push_front(std::pair<htransition_t, semiring_elt_t>(*e, it->dist)); // associate each e with it->dist 00294 if (a.is_initial(it->src)) 00295 fin_l.push_front(std::pair<hstate_t, semiring_elt_t>(it->dst, it->dist));// store what we need to multiply w(final(it->src)) by it->dist 00296 } 00297 } 00298 00299 for (typename std::list<std::pair<htransition_t, semiring_elt_t> >::iterator it = tr_l.begin(); 00300 it != tr_l.end(); ++it) 00301 { 00302 series_set_elt_t s = a.series_of(it->first) * it->second; 00303 if (s != null_series) 00304 a.add_series_transition(a.src_of(it->first), a.dst_of(it->first), s); 00305 a.del_transition(it->first); 00306 } 00307 00308 for (typename std::list<std::pair<hstate_t, semiring_elt_t> >::iterator it = fin_l.begin(); 00309 it != fin_l.end(); ++it) 00310 a.set_initial(it->first, it->second * a.get_initial(it->first)); 00311 00312 while (!tr_st.empty()) 00313 { 00314 a.add_series_transition(tr_st.top().src, tr_st.top().dst, tr_st.top().series); 00315 tr_st.pop(); 00316 } 00317 00318 while (!init_st.empty()) 00319 { 00320 a.set_initial(init_st.top().first, a.get_initial(init_st.top().first) + 00321 init_st.top().second); 00322 init_st.pop(); 00323 } 00324 } 00325 00326 automaton_t& a; 00327 00328 // zero and identity of used algebraic structure. 00329 series_set_elt_t null_series; 00330 semiring_elt_t semiring_elt_zero; 00331 semiring_elt_t semiring_elt_one; 00332 monoid_elt_t monoid_identity; 00333 00334 // Shortest distance structures 00335 s_shortest_hash shortest_hash; 00336 std::set<hstate_t> squeue; 00337 }; 00338 00339 /*--------------. 00340 | eps_removal. | 00341 `--------------*/ 00342 00343 template<class A_, typename Auto, typename Weight> 00344 void 00345 do_eps_removal_here_sp(const AutomataBase<A_>& a_set, 00346 const Weight&, 00347 Auto& a, 00348 misc::direction_type dir) 00349 { 00350 BENCH_TASK_SCOPED("eps_removal"); 00351 00352 EpsilonRemoverSp<A_, Auto, Weight> algo(a_set, a); 00353 algo(dir); 00354 } 00355 00356 template<typename A, typename AI> 00357 void 00358 eps_removal_here_sp(Element<A, AI>& a, misc::direction_type dir) 00359 { 00360 typedef Element<A, AI> automaton_t; 00361 AUTOMATON_TYPES(automaton_t); 00362 00363 do_eps_removal_here_sp(a.structure(), 00364 SELECT(semiring_elt_value_t), 00365 a, dir); 00366 } 00367 00368 template<typename A, typename AI> 00369 Element<A, AI> 00370 eps_removal_sp(const Element<A, AI>& a, misc::direction_type dir) 00371 { 00372 typedef Element<A, AI> automaton_t; 00373 AUTOMATON_TYPES(automaton_t); 00374 00375 automaton_t ret(a); 00376 do_eps_removal_here_sp(ret.structure(), 00377 SELECT(semiring_elt_value_t), 00378 ret, dir); 00379 return ret; 00380 } 00381 00382 template<typename A, typename AI> 00383 void 00384 backward_eps_removal_here_sp(Element<A, AI>& a) 00385 { 00386 typedef Element<A, AI> automaton_t; 00387 AUTOMATON_TYPES(automaton_t); 00388 00389 do_eps_removal_here_sp(a.structure(), 00390 SELECT(semiring_elt_value_t), 00391 a, misc::backward); 00392 } 00393 00394 template<typename A, typename AI> 00395 Element<A, AI> 00396 backward_eps_removal_sp(const Element<A, AI>& a) 00397 { 00398 typedef Element<A, AI> automaton_t; 00399 AUTOMATON_TYPES(automaton_t); 00400 00401 automaton_t ret(a); 00402 do_eps_removal_here_sp(ret.structure(), 00403 SELECT(semiring_elt_value_t), 00404 ret, misc::backward); 00405 return ret; 00406 } 00407 00408 template<typename A, typename AI> 00409 void 00410 forward_eps_removal_here_sp(Element<A, AI>& a) 00411 { 00412 typedef Element<A, AI> automaton_t; 00413 AUTOMATON_TYPES(automaton_t); 00414 00415 do_eps_removal_here_sp(a.structure(), 00416 SELECT(semiring_elt_value_t), 00417 a, misc::forward); 00418 } 00419 00420 template<typename A, typename AI> 00421 Element<A, AI> 00422 forward_eps_removal_sp(const Element<A, AI>& a) 00423 { 00424 typedef Element<A, AI> automaton_t; 00425 AUTOMATON_TYPES(automaton_t); 00426 00427 automaton_t ret(a); 00428 do_eps_removal_here_sp(ret.structure(), 00429 SELECT(semiring_elt_value_t), 00430 ret, misc::forward); 00431 return ret; 00432 } 00433 00434 } // vcsn 00435 00436 #endif // ! VCSN_ALGORITHMS_EPS_REMOVAL_HXX