- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

# eps_removal_sp.hxx

    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