17 #ifndef VCSN_ALGORITHMS_EPS_REMOVAL_SP_HXX
18 # define VCSN_ALGORITHMS_EPS_REMOVAL_SP_HXX
22 # include <vaucanson/automata/concept/automata_base.hh>
23 # include <vaucanson/misc/usual_macros.hh>
25 # include <boost/multi_index_container.hpp>
26 # include <boost/multi_index/member.hpp>
27 # include <boost/multi_index/hashed_index.hpp>
28 # include <boost/multi_index/composite_key.hpp>
29 # include <boost/functional/hash/hash.hpp>
30 # include <boost/tuple/tuple.hpp>
46 <
class A_,
typename Auto,
typename Weight>
47 class EpsilonRemoverSp
49 AUTOMATON_TYPES(Auto);
53 tr_t(hstate_t src_, hstate_t dst_, series_set_elt_t series_)
61 series_set_elt_t series;
66 s_shortest(
const hstate_t src_,
const hstate_t dst_, semiring_elt_t& d_, semiring_elt_t& r_)
81 change_rel(
const semiring_elt_t& new_rel)
85 void operator() (s_shortest& s)
90 semiring_elt_t new_rel;
95 change_dist(
const semiring_elt_t& new_dist)
99 void operator() (s_shortest& s)
104 semiring_elt_t new_dist;
109 add_dr(
const semiring_elt_t& new_dist,
const semiring_elt_t& new_rel)
110 : new_dist(new_dist),
114 void operator() (s_shortest& s)
120 semiring_elt_t new_dist;
121 semiring_elt_t new_rel;
124 typedef boost::multi_index_container
127 boost::multi_index::indexed_by
129 boost::multi_index::hashed_unique
131 boost::multi_index::composite_key
134 BOOST_MULTI_INDEX_MEMBER(s_shortest,
const hstate_t, src),
135 BOOST_MULTI_INDEX_MEMBER(s_shortest,
const hstate_t, dst)
141 EpsilonRemoverSp(
const AutomataBase<A_>&,
144 null_series(aut.series().zero_),
145 semiring_elt_zero(aut.series().semiring().wzero_),
146 semiring_elt_one(aut.series().semiring().wone_),
147 monoid_identity(aut.series().monoid().VCSN_EMPTY_)
149 shortest_eps_distance();
155 for_all_transitions(e,a)
157 series_set_elt_t t = a.series_of(*e);
158 if (t.get(monoid_identity) != semiring_elt_zero)
160 t.assoc(monoid_identity.value(), semiring_elt_zero.value());
161 if (t != null_series)
162 a.add_series_transition(a.src_of(*e), a.dst_of(*e), t);
163 a.del_transition(*e);
167 if (dir == misc::backward)
174 void shortest_eps_distance()
176 for_all_const_states(s, a)
178 typename s_shortest_hash::iterator it;
179 shortest_hash.insert(s_shortest(*s, *s, semiring_elt_one, semiring_elt_one));
181 while (!squeue.empty())
183 hstate_t curr = *squeue.begin();
184 squeue.erase(squeue.begin());
185 semiring_elt_t R = semiring_elt_zero;
186 it = shortest_hash.find(boost::make_tuple(*s, curr));
187 if (it != shortest_hash.end())
190 shortest_hash.modify(it, change_rel(semiring_elt_zero));
193 for (delta_iterator e(a.value(), curr); ! e.done(); e.next())
194 if (a.is_spontaneous(*e))
196 semiring_elt_t dist = semiring_elt_zero;
197 it = shortest_hash.find(boost::make_tuple(*s, a.dst_of(*e)));
198 if (it != shortest_hash.end())
200 semiring_elt_t we = a.series_of(*e).get(monoid_identity);
202 if (dist != dist + we)
204 if (it != shortest_hash.end())
206 shortest_hash.modify(it, add_dr(we, we));
207 squeue.insert(a.dst_of(*e));
211 shortest_hash.insert(s_shortest(*s, a.dst_of(*e), we, we));
212 squeue.insert(a.dst_of(*e));
220 void backward_remove()
222 std::list<std::pair<htransition_t, semiring_elt_t> > tr_l;
223 std::list<std::pair<hstate_t, semiring_elt_t> > fin_l;
224 std::stack<tr_t> tr_st;
225 std::stack<std::pair<hstate_t, series_set_elt_t> > fin_st;
227 for_all_(s_shortest_hash, it, shortest_hash)
228 if (it->src != it->dst)
230 for (delta_iterator e(a.value(), it->dst); ! e.done(); e.next())
231 tr_st.push(tr_t(it->src, a.dst_of(*e), it->dist * a.series_of(*e)));
232 if (a.is_final(it->dst))
233 fin_st.push(make_pair(it->src, it->dist * a.get_final(it->dst)));
237 if (it->dist != semiring_elt_one)
239 for (delta_iterator e(a.value(), it->dst); ! e.done(); e.next())
240 tr_l.push_front(std::pair<htransition_t, semiring_elt_t>(*e, it->dist));
241 if (a.is_final(it->dst))
242 fin_l.push_front(std::pair<hstate_t, semiring_elt_t>(it->src, it->dist));
246 for (
typename std::list<std::pair<htransition_t, semiring_elt_t> >::iterator it = tr_l.begin();
247 it != tr_l.end(); ++it)
249 series_set_elt_t s = a.series_of(it->first) * it->second;
250 if (s != null_series)
251 a.add_series_transition(a.src_of(it->first), a.dst_of(it->first), s);
252 a.del_transition(it->first);
255 for (
typename std::list<std::pair<hstate_t, semiring_elt_t> >::iterator it = fin_l.begin();
256 it != fin_l.end(); ++it)
257 a.set_final(it->first, it->second * a.get_final(it->first));
259 while (!tr_st.empty())
261 a.add_series_transition(tr_st.top().src, tr_st.top().dst, tr_st.top().series);
265 while (!fin_st.empty())
267 a.set_final(fin_st.top().first, a.get_final(fin_st.top().first) +
268 fin_st.top().second);
273 void forward_remove()
275 std::list<std::pair<htransition_t, semiring_elt_t> > tr_l;
276 std::list<std::pair<hstate_t, semiring_elt_t> > fin_l;
277 std::stack<tr_t> tr_st;
278 std::stack<std::pair<hstate_t, series_set_elt_t> > init_st;
280 for_all_(s_shortest_hash, it, shortest_hash)
281 if (it->src != it->dst)
283 for (rdelta_iterator e(a.value(), it->dst); ! e.done(); e.next())
284 tr_st.push(tr_t(a.src_of(*e), it->dst, a.series_of(*e) * it->dist));
285 if (a.is_initial(it->src))
286 init_st.push(make_pair(it->dst, a.get_initial(it->src) * it->dist));
290 if (it->dist != semiring_elt_one)
292 for (rdelta_iterator e(a.value(), it->dst); ! e.done(); e.next())
293 tr_l.push_front(std::pair<htransition_t, semiring_elt_t>(*e, it->dist));
294 if (a.is_initial(it->src))
295 fin_l.push_front(std::pair<hstate_t, semiring_elt_t>(it->dst, it->dist));
299 for (
typename std::list<std::pair<htransition_t, semiring_elt_t> >::iterator it = tr_l.begin();
300 it != tr_l.end(); ++it)
302 series_set_elt_t s = a.series_of(it->first) * it->second;
303 if (s != null_series)
304 a.add_series_transition(a.src_of(it->first), a.dst_of(it->first), s);
305 a.del_transition(it->first);
308 for (
typename std::list<std::pair<hstate_t, semiring_elt_t> >::iterator it = fin_l.begin();
309 it != fin_l.end(); ++it)
310 a.set_initial(it->first, it->second * a.get_initial(it->first));
312 while (!tr_st.empty())
314 a.add_series_transition(tr_st.top().src, tr_st.top().dst, tr_st.top().series);
318 while (!init_st.empty())
320 a.set_initial(init_st.top().first, a.get_initial(init_st.top().first) +
321 init_st.top().second);
329 series_set_elt_t null_series;
330 semiring_elt_t semiring_elt_zero;
331 semiring_elt_t semiring_elt_one;
332 monoid_elt_t monoid_identity;
335 s_shortest_hash shortest_hash;
336 std::set<hstate_t> squeue;
343 template<
class A_,
typename Auto,
typename Weight>
345 do_eps_removal_here_sp(
const AutomataBase<A_>& a_set,
350 BENCH_TASK_SCOPED(
"eps_removal");
352 EpsilonRemoverSp<A_, Auto, Weight> algo(a_set, a);
356 template<
typename A,
typename AI>
361 AUTOMATON_TYPES(automaton_t);
364 SELECT(semiring_elt_value_t),
368 template<
typename A,
typename AI>
373 AUTOMATON_TYPES(automaton_t);
376 do_eps_removal_here_sp(ret.structure(),
377 SELECT(semiring_elt_value_t),
382 template<
typename A,
typename AI>
387 AUTOMATON_TYPES(automaton_t);
390 SELECT(semiring_elt_value_t),
394 template<
typename A,
typename AI>
399 AUTOMATON_TYPES(automaton_t);
402 do_eps_removal_here_sp(ret.structure(),
403 SELECT(semiring_elt_value_t),
404 ret, misc::backward);
408 template<
typename A,
typename AI>
413 AUTOMATON_TYPES(automaton_t);
416 SELECT(semiring_elt_value_t),
420 template<
typename A,
typename AI>
425 AUTOMATON_TYPES(automaton_t);
428 do_eps_removal_here_sp(ret.structure(),
429 SELECT(semiring_elt_value_t),
436 #endif // ! VCSN_ALGORITHMS_EPS_REMOVAL_HXX