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

# eps_removal_sp.hxx

    00001 // eps_removal.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 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 <queue>
    00033 # include <map>
    00034 # include <utility>
    00035 # include <set>
    00036 # include <stack>
    00037
    00038 namespace vcsn {
    00039
    00040   /*----------------------------------------.
    00041   | EpsilonRemoverSp for weighted automaton |
    00042   `----------------------------------------*/
    00043
    00044   template
    00045   <class A_, typename Auto, typename Weight>
    00046   class EpsilonRemoverSp
    00047   {
    00048     AUTOMATON_TYPES(Auto);
    00049   public:
    00050     struct tr_t
    00051     {
    00052       tr_t(hstate_t src_, hstate_t dst_, series_set_elt_t series_)
    00053           : src(src_),
    00054             dst(dst_),
    00055             series(series_)
    00056       {}
    00057
    00058       hstate_t src;
    00059       hstate_t dst;
    00060       series_set_elt_t series;
    00061     };
    00062
    00063     struct s_shortest
    00064     {
    00065       s_shortest(const hstate_t src_, const hstate_t dst_, semiring_elt_t& d_, semiring_elt_t& r_)
    00066         : src(src_),
    00067           dst(dst_),
    00068           dist(d_),
    00069           rel(r_)
    00070       {}
    00071
    00072       const hstate_t src;
    00073       const hstate_t dst;
    00074       semiring_elt_t dist;
    00075       semiring_elt_t rel;
    00076     };
    00077
    00078     struct change_rel
    00079     {
    00080       change_rel(const semiring_elt_t& new_rel)
    00081         : new_rel(new_rel)
    00082       {}
    00083
    00084       void operator() (s_shortest& s)
    00085       {
    00086         s.rel = new_rel;
    00087       }
    00088       private:
    00089       semiring_elt_t new_rel;
    00090     };
    00091
    00092     struct change_dist
    00093     {
    00094       change_dist(const semiring_elt_t& new_dist)
    00095         : new_dist(new_dist)
    00096       {}
    00097
    00098       void operator() (s_shortest& s)
    00099       {
    00100         s.dist = new_dist;
    00101       }
    00102       private:
    00103       semiring_elt_t new_dist;
    00104     };
    00105
    00106     struct add_dr
    00107     {
    00108       add_dr(const semiring_elt_t& new_dist, const semiring_elt_t& new_rel)
    00109         : new_dist(new_dist),
    00110           new_rel(new_rel)
    00111       {}
    00112
    00113       void operator() (s_shortest& s)
    00114       {
    00115         s.dist += new_dist;
    00116         s.rel += new_rel;
    00117       }
    00118       private:
    00119       semiring_elt_t new_dist;
    00120       semiring_elt_t new_rel;
    00121     };
    00122
    00123     typedef boost::multi_index_container
    00124     <
    00125       s_shortest,
    00126       boost::multi_index::indexed_by
    00127       <
    00128         boost::multi_index::hashed_unique
    00129         <
    00130           boost::multi_index::composite_key
    00131           <
    00132             s_shortest,
    00133             BOOST_MULTI_INDEX_MEMBER(s_shortest, const hstate_t, src),
    00134             BOOST_MULTI_INDEX_MEMBER(s_shortest, const hstate_t, dst)
    00135           >
    00136         >
    00137       >
    00138     > s_shortest_hash;
    00139
    00140     EpsilonRemoverSp(const AutomataBase<A_>&,
    00141                      Auto& aut)
    00142       : a(aut),
    00143         null_series(aut.series().zero_),
    00144         semiring_elt_zero(aut.series().semiring().wzero_),
    00145         semiring_elt_one(aut.series().semiring().wone_),
    00146         monoid_identity(aut.series().monoid().vcsn_empty)
    00147     {
    00148       shortest_eps_distance();
    00149     }
    00150
    00151     void operator() (misc::direction_type dir)
    00152     {
    00153       // Remove epsilon-transitions
    00154       for_all_transitions(e,a)
    00155       {
    00156         series_set_elt_t t = a.series_of(*e);
    00157         if (t.get(monoid_identity) != semiring_elt_zero)
    00158         {
    00159           t.assoc(monoid_identity.value(), semiring_elt_zero.value());
    00160           if (t != null_series)
    00161             a.add_series_transition(a.src_of(*e), a.dst_of(*e), t);
    00162           a.del_transition(*e);
    00163         }
    00164       }
    00165
    00166       if (dir == misc::backward)
    00167         backward_remove();
    00168       else
    00169         forward_remove();
    00170     }
    00171
    00172   private:
    00173     void shortest_eps_distance()
    00174     {
    00175       for_all_states(s, a)
    00176       {
    00177         typename s_shortest_hash::iterator it;
    00178         shortest_hash.insert(s_shortest(*s, *s, semiring_elt_one, semiring_elt_one));
    00179         squeue.insert(*s);
    00180         while (!squeue.empty())
    00181         {
    00182           hstate_t curr = *squeue.begin();
    00183           squeue.erase(squeue.begin());
    00184           semiring_elt_t R = semiring_elt_zero;
    00185           it = shortest_hash.find(boost::make_tuple(*s, curr));
    00186           if (it != shortest_hash.end())
    00187           {
    00188             R = it->rel;
    00189             shortest_hash.modify(it, change_rel(semiring_elt_zero));
    00190           }
    00191
    00192           std::list<htransition_t> transition_list;
    00193           a.spontaneous_deltac(transition_list, curr, delta_kind::transitions());
    00194           for_all_const_(std::list<htransition_t>, e, transition_list)
    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               if (it != shortest_hash.end())
    00204               {
    00205                 shortest_hash.modify(it, add_dr(we, we));
    00206                 squeue.insert(a.dst_of(*e));
    00207               }
    00208               else
    00209               {
    00210                 shortest_hash.insert(s_shortest(*s, a.dst_of(*e), we, we));
    00211                 squeue.insert(a.dst_of(*e));
    00212               }
    00213           }
    00214          //it = shortest_hash.find(boost::make_tuple(*s, *s));
    00215          //result_not_computable_if(!it->rel.starable());
    00216         }
    00217       }
    00218     }
    00219
    00220     void backward_remove()
    00221     {
    00222       std::stack<tr_t> tr_st;
    00223       std::stack<std::pair<hstate_t, series_set_elt_t> > fin_st;
    00224
    00225       std::list<htransition_t> transition_list;
    00226       for_all_(s_shortest_hash, it, shortest_hash)
    00227       {
    00228         transition_list.clear();
    00229         a.deltac(transition_list, it->dst, delta_kind::transitions());
    00230         for_all_const_(std::list<htransition_t>, e, transition_list)
    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
    00236       while (!tr_st.empty())
    00237       {
    00238         a.add_series_transition(tr_st.top().src, tr_st.top().dst, tr_st.top().series);
    00239         tr_st.pop();
    00240       }
    00241
    00242       while (!fin_st.empty())
    00243       {
    00244         a.set_final(fin_st.top().first, a.get_final(fin_st.top().first) +
    00245                                              fin_st.top().second);
    00246         fin_st.pop();
    00247       }
    00248     }
    00249
    00250     void forward_remove()
    00251     {
    00252       std::stack<tr_t> tr_st;
    00253       std::stack<std::pair<hstate_t, series_set_elt_t> > init_st;
    00254
    00255       std::list<htransition_t> transition_list;
    00256       for_all_(s_shortest_hash, it, shortest_hash)
    00257       {
    00258         transition_list.clear();
    00259         a.rdeltac(transition_list, it->src, delta_kind::transitions());
    00260         for_all_const_(std::list<htransition_t>, e, transition_list)
    00261           tr_st.push(tr_t(a.src_of(*e), it->dst, a.series_of(*e) * it->dist));
    00262         if (a.is_initial(it->src))
    00263           init_st.push(make_pair(it->dst, a.get_initial(it->src) * it->dist));
    00264       }
    00265
    00266       while (!tr_st.empty())
    00267       {
    00268         a.add_series_transition(tr_st.top().src, tr_st.top().dst, tr_st.top().series);
    00269         tr_st.pop();
    00270       }
    00271
    00272       while (!init_st.empty())
    00273       {
    00274         a.set_initial(init_st.top().first, a.get_initial(init_st.top().first) +
    00275                                              init_st.top().second);
    00276         init_st.pop();
    00277       }
    00278     }
    00279
    00280     automaton_t&        a;
    00281
    00282     // zero and identity of used algebraic structure.
    00283     series_set_elt_t    null_series;
    00284     semiring_elt_t      semiring_elt_zero;
    00285     semiring_elt_t      semiring_elt_one;
    00286     monoid_elt_t        monoid_identity;
    00287
    00288     // Shortest distance structures
    00289     s_shortest_hash     shortest_hash;
    00290     std::set<hstate_t>  squeue;
    00291   };
    00292
    00293   /*--------------.
    00294   | eps_removal.  |
    00295   `--------------*/
    00296
    00297   template<class A_, typename Auto, typename Weight>
    00298   void
    00299   do_eps_removal_here_sp(const AutomataBase<A_>& a_set,
    00300                       const Weight&,
    00301                       Auto& a,
    00302                       misc::direction_type dir)
    00303   {
    00304     TIMER_SCOPED("eps_removal");
    00305
    00306     EpsilonRemoverSp<A_, Auto, Weight> algo(a_set, a);
    00307     algo(dir);
    00308   }
    00309
    00310   template<typename  A, typename  T>
    00311   void
    00312   eps_removal_here_sp(Element<A, T>& a, misc::direction_type dir)
    00313   {
    00314     typedef Element<A, T> auto_t;
    00315     AUTOMATON_TYPES(auto_t);
    00316
    00317     do_eps_removal_here_sp(a.structure(),
    00318                            SELECT(semiring_elt_value_t),
    00319                            a, dir);
    00320   }
    00321
    00322   template<typename  A, typename  T>
    00323   Element<A, T>
    00324   eps_removal_sp(const Element<A, T>& a, misc::direction_type dir)
    00325   {
    00326     typedef Element<A, T> auto_t;
    00327     AUTOMATON_TYPES(auto_t);
    00328
    00329     Element<A, T> ret(a);
    00330     do_eps_removal_here_sp(ret.structure(),
    00331                            SELECT(semiring_elt_value_t),
    00332                            ret, dir);
    00333     return ret;
    00334   }
    00335
    00336   template<typename  A, typename  T>
    00337   void
    00338   backward_eps_removal_here_sp(Element<A, T>& a)
    00339   {
    00340     typedef Element<A, T> auto_t;
    00341     AUTOMATON_TYPES(auto_t);
    00342
    00343     do_eps_removal_here_sp(a.structure(),
    00344                            SELECT(semiring_elt_value_t),
    00345                            a, misc::backward);
    00346   }
    00347
    00348   template<typename  A, typename  T>
    00349   Element<A, T>
    00350   backward_eps_removal_sp(const Element<A, T>& a)
    00351   {
    00352     typedef Element<A, T> auto_t;
    00353     AUTOMATON_TYPES(auto_t);
    00354
    00355     Element<A, T> ret(a);
    00356     do_eps_removal_here_sp(ret.structure(),
    00357                            SELECT(semiring_elt_value_t),
    00358                            ret, misc::backward);
    00359     return ret;
    00360   }
    00361
    00362   template<typename  A, typename  T>
    00363   void
    00364   forward_eps_removal_here_sp(Element<A, T>& a)
    00365   {
    00366     typedef Element<A, T> auto_t;
    00367     AUTOMATON_TYPES(auto_t);
    00368
    00369     do_eps_removal_here_sp(a.structure(),
    00370                            SELECT(semiring_elt_value_t),
    00371                            a, misc::forward);
    00372   }
    00373
    00374   template<typename  A, typename  T>
    00375   Element<A, T>
    00376   forward_eps_removal_sp(const Element<A, T>& a)
    00377   {
    00378     typedef Element<A, T> auto_t;
    00379     AUTOMATON_TYPES(auto_t);
    00380
    00381     Element<A, T> ret(a);
    00382     do_eps_removal_here_sp(ret.structure(),
    00383                            SELECT(semiring_elt_value_t),
    00384                            ret, misc::forward);
    00385     return ret;
    00386   }
    00387
    00388 } // vcsn
    00389
    00390 #endif // ! VCSN_ALGORITHMS_EPS_REMOVAL_HXX