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

- File List
- File Members

# eps_removal.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, 2008, 2010, 2011 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_HXX
    00018 # define VCSN_ALGORITHMS_EPS_REMOVAL_HXX
    00019
    00020 # include <vaucanson/algorithms/eps_removal.hh>
    00021
    00022 # include <vaucanson/automata/concept/automata_base.hh>
    00023 # include <vaucanson/algebra/concept/freemonoid_product.hh>
    00024 # include <vaucanson/misc/usual_macros.hh>
    00025
    00026 # include <list>
    00027 # include <map>
    00028 # include <utility>
    00029
    00030 namespace vcsn {
    00031
    00032   // For automata.
    00033   template <class A, typename M, typename AI>
    00034   bool
    00035   do_is_proper(const AutomataBase<A>&, const M&, const Element<A, AI>& a)
    00036   {
    00037     BENCH_TASK_SCOPED("is_proper (automaton)");
    00038     typedef Element<A, AI> automaton_t;
    00039     AUTOMATON_TYPES(automaton_t);
    00040
    00041     for_all_const_transitions(e, a)
    00042       {
    00043         // A transition labelled by "1+a" is not considered to be
    00044         // spontaneous by is_spontaneous(), yet it cannot belong to a
    00045         // proper automaton.
    00046         series_set_elt_t label = a.series_of(*e);
    00047         for_all_const_(series_set_elt_t::support_t, it, label.supp())
    00048           if ((*it).empty())
    00049             return false;
    00050       }
    00051     return true;
    00052   }
    00053
    00054   // For FMP.
    00055   template <class A, typename F, typename S, typename AI>
    00056   bool
    00057   do_is_proper(const AutomataBase<A>&,
    00058                const algebra::FreeMonoidProduct<F, S>&,
    00059                const Element<A, AI>& a)
    00060   {
    00061     BENCH_TASK_SCOPED("is_proper (FMP)");
    00062     typedef Element<A, AI> automaton_t;
    00063     AUTOMATON_TYPES(automaton_t);
    00064
    00065     for_all_const_transitions(e, a)
    00066       {
    00067         series_set_elt_t label = a.series_of(*e);
    00068         for_all_const_(series_set_elt_t::support_t, it, label.supp())
    00069           if ((*it).first.empty() && (*it).second.empty())
    00070             return false;
    00071       }
    00072     return true;
    00073   }
    00074
    00075   template <typename A, typename AI>
    00076   bool
    00077   is_proper(const Element<A, AI>& a)
    00078   {
    00079     return do_is_proper(a.structure(), a.series().monoid(), a);
    00080   }
    00081
    00082
    00083   // Forward declaration.
    00084   template <class A_, typename Auto, typename Weight>
    00085   class EpsilonRemover;
    00086
    00087   template <class A_, typename Auto, typename Weight, int>
    00088   struct test_for_non_positive_semiring
    00089   {
    00090     bool run(const Auto&) const
    00091     {
    00092       return true;
    00093     }
    00094   };
    00095
    00096   template <class A_, typename Auto, typename Weight>
    00097   struct test_for_non_positive_semiring<A_, Auto, Weight, 0>
    00098   {
    00099     bool run(const Auto& a) const; // See After the EpsilonRemover declaration.
    00100   };
    00101
    00102   /*--------------------------------------.
    00103   | EpsilonRemover for weighted automaton |
    00104   `--------------------------------------*/
    00105
    00106   template <class A_, typename Auto, typename Weight>
    00107   class EpsilonRemover
    00108   {
    00109     AUTOMATON_TYPES(Auto);
    00110         typedef typename series_set_elt_t::support_t support_t;
    00111
    00112     friend struct test_for_non_positive_semiring
    00113     <A_, Auto, Weight, semiring_traits<semiring_t,
    00114                                        semiring_elt_value_t>::is_positive>;
    00115
    00116
    00117     automaton_t&        a;
    00118     // zero and identity of used algebraic structure.
    00119     series_set_elt_t    null_series;
    00120     semiring_elt_t      semiring_elt_zero,
    00121       semiring_elt_unit;
    00122     monoid_elt_t        monoid_identity;
    00123
    00124
    00125   public:
    00126     EpsilonRemover(const AutomataBase<A_>&,
    00127                    Auto& aut)
    00128       : a(aut),
    00129         null_series(aut.series().zero_),
    00130         semiring_elt_zero(aut.series().semiring().wzero_),
    00131         semiring_elt_unit(aut.series().semiring().wone_),
    00132         monoid_identity(aut.series().monoid().VCSN_EMPTY_)
    00133     {}
    00134
    00135     void operator()(misc::direction_type dir)
    00136     {
    00137       test_for_non_positive_semiring
    00138         <A_, Auto, Weight, semiring_traits<semiring_t,
    00139                                            semiring_elt_value_t>::is_positive>
    00140         nps;
    00141       result_not_computable_if(!nps.run(a));
    00142
    00143       std::list<hstate_t> eps_states;
    00144        if (dir == misc::backward)
    00145         this->epsilon_covering(eps_states);
    00146       else
    00147         this->epsilon_co_covering(eps_states);
    00148       result_not_computable_if(!spontaneous_suppression(eps_states));
    00149       merge_transitions();
    00150     }
    00151
    00152     private:
    00153
    00154         /* This method computes a covering of the automaton such
    00155            that, in this covering, there are two kinds of states:
    00156            -- states whose incoming transitions are not spontaneous;
    00157            -- non initial states whose incoming transitions are spontaneous.
    00158            The argument is filled with the states which belong to the second kind.
    00159         */
    00160     void epsilon_covering(std::list<hstate_t>& spontaneous_states)
    00161     {
    00162       //list of states to split
    00163       std::list<hstate_t> split_states;
    00164       for_all_states(s, a)
    00165         {
    00166           bool eps_in = false;
    00167           bool other_in = a.is_initial(*s);
    00168
    00169           // Test whether there are different types of incoming transitions.
    00170
    00171           std::list<htransition_t> transitions;
    00172           for (rdelta_iterator e(a.value(), *s); ! e.done(); e.next())
    00173             transitions.push_back(*e);
    00174           for_all_(std::list<htransition_t>, e, transitions)
    00175             {
    00176               series_set_elt_t t = a.series_of(*e);
    00177               semiring_elt_t eps_weight= t.get(monoid_identity);
    00178               if (eps_weight == semiring_elt_zero)
    00179                 other_in = true ;
    00180               else
    00181                 {
    00182                   eps_in=true;
    00183                   if (t.supp().size() > 1)
    00184                     other_in = true;
    00185                 }
    00186             }
    00187           if (eps_in)
    00188             {
    00189               if (other_in)
    00190                 split_states.push_back(*s);
    00191               else
    00192                 spontaneous_states.push_back(*s);
    00193             }
    00194         }
    00195       //Split the states which have to
    00196       for_all_(std::list<hstate_t>, s, split_states)
    00197         {
    00198           hstate_t eps_state = a.add_state();
    00199           spontaneous_states.push_back(eps_state);
    00200           //incoming transitions (the original state remains initial if it is)
    00201           std::list<htransition_t> transitions;
    00202           for (rdelta_iterator e(a.value(), *s); ! e.done(); e.next())
    00203             transitions.push_back(*e);
    00204           for_all_(std::list<htransition_t>, e, transitions)
    00205             {
    00206               series_set_elt_t t = a.series_of(*e);
    00207               semiring_elt_t eps_weight= t.get(monoid_identity);
    00208               if (eps_weight == semiring_elt_zero)
    00209                 continue;
    00210               series_set_elt_t eps_label(a.structure().series());
    00211               eps_label.assoc(monoid_identity.value(), eps_weight.value());
    00212               //which remains on the transition without epsilon:
    00213               t.assoc(monoid_identity.value(), semiring_elt_zero.value());
    00214               hstate_t source=a.src_of(*e);
    00215               a.add_series_transition(source, eps_state, eps_label);
    00216               if (t != null_series)
    00217                 a.add_series_transition(source, *s, t);
    00218               a.del_transition(*e);
    00219             }
    00220           //outgoing transitions and final states
    00221           if (a.is_final(*s))
    00222             a.set_final(eps_state,a.get_final(*s));
    00223           for (delta_iterator e(a.value(), *s); ! e.done(); e.next())
    00224             a.add_series_transition(eps_state, a.dst_of(*e), a.series_of(*e));
    00225           /* Notice that if there is a loop on *s, with label a+1, the
    00226              step "incoming transitions" turns it into a loop with
    00227              label 'a' and a transition from *s to eps_state with
    00228              label 1, and the step "outgoing transitions" build a
    00229              transition from eps_state to *s with label '1' and a loop
    00230              on eps_state with label 1, which is what it is
    00231              expected */
    00232         }
    00233     }
    00234
    00235     /* Initial and final cleaner. This method adds if necessary an
    00236        initial and/or a final state such that series labelling initial
    00237        and final arrows are constant. This method is presently unused.
    00238     */
    00239     void initial_final_cleaner()
    00240     {
    00241       {
    00242         //Initial
    00243         std::list<hstate_t> initial_states;
    00244         for_all_initial_states(s, a)
    00245           initial_states.push_back(*s);
    00246         hstate_t new_initial=a.add_state();
    00247         for_all_(std::list<hstate_t>, s, initial_states)
    00248           {
    00249             series_set_elt_t t = a.get_initial(*s);
    00250             semiring_elt_t eps_weight= t.get(monoid_identity);
    00251             t.assoc(monoid_identity, semiring_elt_zero.value());
    00252             if (t != null_series)
    00253               {
    00254                 a.unset_initial(*s);
    00255                 a.add_series_transition(new_initial, *s, t);
    00256                 if (eps_weight != semiring_elt_zero)
    00257                   {
    00258                     series_set_elt_t cst(a.structure().series());
    00259                     cst.assoc(monoid_identity, eps_weight.value());
    00260                     a.set_initial(*s, cst);
    00261                   }
    00262               }
    00263           }
    00264         delta_iterator test(a.value(), new_initial);
    00265         if (test.done())
    00266           a.del_state(new_initial);
    00267         else
    00268           a.set_initial(new_initial);
    00269       }
    00270       {
    00271         //Final
    00272         std::list<hstate_t> final_states;
    00273         for_all_final_states(s, a)
    00274           final_states.push_back(*s);
    00275         hstate_t new_final=a.add_state();
    00276         for_all_(std::list<hstate_t>, s, final_states)
    00277           {
    00278             series_set_elt_t t = a.get_final(*s);
    00279             semiring_elt_t eps_weight= t.get(monoid_identity);
    00280             t.assoc(monoid_identity, semiring_elt_zero.value());
    00281             if (t != null_series)
    00282               {
    00283                 a.unset_final(*s);
    00284                 a.add_series_transition(*s, new_final, t);
    00285                 if(eps_weight != semiring_elt_zero)
    00286                   {
    00287                     series_set_elt_t cst(a.structure().series());
    00288                     cst.assoc(monoid_identity, eps_weight.value());
    00289                     a.set_final(*s, cst);
    00290                   }
    00291               }
    00292           }
    00293         rdelta_iterator test(a.value(), new_final);
    00294         if (test.done())
    00295           a.del_state(new_final);
    00296         else
    00297           a.set_final(new_final);
    00298       }
    00299     }
    00300
    00301     /* This method computes a co-covering of the automaton such
    00302        that, in this co-covering, there are two kinds of states:
    00303        -- states whose outgoing transitions are not spontaneous;
    00304        -- non final states whose outgoing transitions are spontaneous.
    00305        The argument is filled with the states which belong to the second kind.
    00306     */
    00307     void epsilon_co_covering(std::list<hstate_t>& spontaneous_states)
    00308     {
    00309       //list of states to split
    00310       std::list<hstate_t> split_states;
    00311       for_all_states(s, a)
    00312         {
    00313           bool eps_out = false;
    00314           bool other_out = a.is_final(*s);
    00315
    00316           // Test whether there are different types of outgoing transitions.
    00317
    00318           std::list<htransition_t> transitions;
    00319           for (delta_iterator e(a.value(), *s); !e.done(); e.next())
    00320             transitions.push_back(*e);
    00321           for_all_(std::list<htransition_t>, e, transitions)
    00322             {
    00323               series_set_elt_t t = a.series_of(*e);
    00324               semiring_elt_t eps_weight= t.get(monoid_identity);
    00325               if(eps_weight == semiring_elt_zero)
    00326                 other_out=true ;
    00327               else
    00328                 {
    00329                   eps_out=true;
    00330                   if (t.supp().size() > 1)
    00331                     other_out=true;
    00332                 }
    00333             }
    00334           if (eps_out)
    00335             {
    00336               if (other_out)
    00337                 split_states.push_back(*s);
    00338               else
    00339                 spontaneous_states.push_back(*s);
    00340             }
    00341         }
    00342       //Split the states which have to
    00343       for_all_(std::list<hstate_t>, s, split_states)
    00344         {
    00345           hstate_t eps_state = a.add_state();
    00346           spontaneous_states.push_back(eps_state);
    00347           //outgoing transitions (the original state remains final if it is)
    00348           std::list<htransition_t> transitions;
    00349           for (delta_iterator e(a.value(), *s); !e.done(); e.next())
    00350             transitions.push_back(*e);
    00351           for_all_(std::list<htransition_t>, e, transitions)
    00352             {
    00353               series_set_elt_t t = a.series_of(*e);
    00354               semiring_elt_t eps_weight= t.get(monoid_identity);
    00355               if (eps_weight == semiring_elt_zero)
    00356                 continue;
    00357               series_set_elt_t eps_label(a.structure().series());
    00358               eps_label.assoc(monoid_identity.value(), eps_weight.value());
    00359               //which remains on the transition without epsilon:
    00360               t.assoc(monoid_identity.value(), semiring_elt_zero.value());
    00361               hstate_t target=a.dst_of(*e);
    00362               a.add_series_transition(eps_state, target, eps_label);
    00363               if (t != null_series)
    00364                 a.add_series_transition(*s, target, t);
    00365               a.del_transition(*e);
    00366             }
    00367           //incoming transitions and initial states
    00368           if (a.is_initial(*s))
    00369             a.set_initial(eps_state,a.get_initial(*s));
    00370           for (rdelta_iterator e(a.value(), *s); ! e.done(); e.next())
    00371             a.add_series_transition(a.src_of(*e), eps_state, a.series_of(*e));
    00372           /* Notice that if there is a loop on *s, with label a+1, the
    00373              step "outgoing transitions" turns it into a loop with
    00374              label 'a' and a transition from eps_state to *s with
    00375              label 1, and the step "incoming transitions" build a
    00376              transition from *s to eps_state with label '1' and a loop
    00377              on eps_state with label 1, which is what it is
    00378              expected */
    00379         }
    00380     }
    00381
    00382     /* This method computes an equivalent K-automaton with only
    00383        positive transitions (excepted final arrows).  A second copy of
    00384        the automaton is built, a negative weight makes switch from a
    00385        copy to another.  Two final states are added, one where
    00386        positive paths end, the other one where negative paths end. In
    00387        the result, all the edges have positive weight; the two final
    00388        states have resp.  weights equal to 1 and -1.
    00389     */
    00390     void positive_path_covering()
    00391     {
    00392       std::map<hstate_t,hstate_t> clones;
    00393       std::list<hstate_t> states;
    00394       for_all_states(s, a)
    00395         states.push_back(*s);
    00396       for_all_(std::list<hstate_t>, s, states)
    00397         clones[*s]=a.add_state();
    00398       hstate_t pos_final_state=a.add_state();
    00399       hstate_t neg_final_state=a.add_state();
    00400       std::list<htransition_t> transitions;
    00401       for_all_transitions(e, a)
    00402         transitions.push_back(*e);
    00403       for_all_(std::list<htransition_t>, e, transitions)
    00404         {
    00405           series_set_elt_t posit = a.series_of(*e);
    00406           series_set_elt_t negat(a.structure().series());
    00407           support_t su = posit.supp();
    00408           for_all_(support_t, x, su)
    00409             {
    00410               semiring_elt_t weight=posit.get(*x);
    00411               if (weight < semiring_elt_zero)
    00412                 {
    00413                   negat.assoc(*x,-weight.value());
    00414                   posit.assoc(*x,semiring_elt_zero.value());
    00415                 }
    00416             }
    00417           hstate_t src=a.src_of(*e), dst=a.dst_of(*e);
    00418           if (posit != null_series)
    00419             a.add_series_transition(clones[src], clones[dst], posit);
    00420           if (negat != null_series)
    00421             {
    00422               a.add_series_transition(src, clones[dst], negat);
    00423               a.add_series_transition(clones[src], dst, negat);
    00424               if (posit != null_series)
    00425                 a.add_series_transition(src, dst, posit);
    00426               a.del_transition(*e);
    00427             }
    00428         }
    00429       states.clear();
    00430       for_all_initial_states(s, a)
    00431         states.push_back(*s);
    00432       for_all_(std::list<hstate_t>, s, states)
    00433         {
    00434           series_set_elt_t posit = a.get_initial(*s);
    00435           series_set_elt_t negat(a.structure().series());
    00436           support_t su = posit.supp();
    00437           for_all_(support_t, x, su)
    00438             {
    00439               semiring_elt_t weight = posit.get(*x);
    00440               if (weight < semiring_elt_zero)
    00441                 {
    00442                   negat.assoc(*x,-weight.value());
    00443                   posit.assoc(*x,semiring_elt_zero.value());
    00444                 }
    00445             }
    00446           if (negat != null_series)
    00447             {
    00448               a.set_initial(clones[*s], negat);
    00449               a.unset_initial(*s);
    00450               if (posit != null_series)
    00451                 a.set_initial(*s,posit);
    00452             }
    00453         }
    00454       states.clear();
    00455       for_all_final_states(s, a)
    00456         states.push_back(*s);
    00457       for_all_(std::list<hstate_t>, s, states)
    00458         {
    00459           series_set_elt_t posit = a.get_final(*s);
    00460           series_set_elt_t negat(a.structure().series());
    00461           support_t su = posit.supp();
    00462           for_all_(support_t, x, su)
    00463             {
    00464               semiring_elt_t weight=posit.get(*x);
    00465               if (weight < semiring_elt_zero)
    00466                 {
    00467                   negat.assoc(*x,-weight.value());
    00468                   posit.assoc(*x,semiring_elt_zero.value());
    00469                 }
    00470             }
    00471           if (negat != null_series)
    00472             {
    00473               a.add_series_transition(*s, neg_final_state, negat);
    00474               a.add_series_transition(clones[*s], pos_final_state, negat);
    00475             }
    00476           a.unset_final(*s);
    00477           if (posit != null_series)
    00478             {
    00479               a.add_series_transition(*s, pos_final_state, posit);
    00480               a.add_series_transition(clones[*s], neg_final_state, posit);
    00481             }
    00482         }
    00483       a.set_final(pos_final_state);
    00484       series_set_elt_t mss = a.get_final(pos_final_state);
    00485       mss.assoc(monoid_identity,-semiring_elt_unit.value());
    00486       a.set_final(neg_final_state,mss);
    00487       accessible_here(a);
    00488     }
    00489
    00490     /*supression of "epsilon-states"
    00491       epsilon_covering should have been called before
    00492       This part of the algorithm is symmetrical and is exactly
    00493       the "elimination state method" applicated to a list of states.
    00494       We consider the case where the state is initial or final, even if
    00495       in the backward case the 'epsilon state' cannot be initial for instance
    00496      */
    00497     bool spontaneous_suppression(std::list<hstate_t>& sp_states)
    00498     {
    00499       for_all_(std::list<hstate_t>, s, sp_states)
    00500         {
    00501           std::list<htransition_t> incoming_transitions;
    00502           //list of incoming transitions, beginning with loops
    00503           for (rdelta_iterator e(a.value(), *s); ! e.done(); e.next())
    00504             {
    00505               if (a.src_of(*e) == a.dst_of(*e))
    00506                 incoming_transitions.push_front(*e);
    00507               else
    00508                 incoming_transitions.push_back(*e);
    00509             }
    00510           bool hasloop=false;
    00511           series_set_elt_t loop_series(a.structure().series());
    00512           //loops are removed from incoming transitions;
    00513           while (!incoming_transitions.empty())
    00514             {
    00515               htransition_t& loop=incoming_transitions.front();
    00516               if(a.src_of(loop)==a.dst_of(loop))
    00517                 {
    00518                   hasloop=true;
    00519                   loop_series += a.series_of(loop);
    00520                   incoming_transitions.pop_front();
    00521                 }
    00522               else
    00523                 break;
    00524             }
    00525           if (hasloop)
    00526             {
    00527               if (!loop_series.get(monoid_identity).starable())
    00528                 return false;
    00529               loop_series = loop_series.star();
    00530             }
    00531           std::list<htransition_t> outgoing_transitions;
    00532           for (delta_iterator e(a.value(), *s); ! e.done(); e.next())
    00533               if (a.src_of(*e)!=a.dst_of(*e))
    00534                 outgoing_transitions.push_back(*e);
    00535           for_all_(std::list<htransition_t>, e, incoming_transitions)
    00536             for_all_(std::list<htransition_t>, f, outgoing_transitions)
    00537               if (hasloop)
    00538                 a.add_series_transition(a.src_of(*e), a.dst_of(*f),
    00539                                         a.series_of(*e)*loop_series*a.series_of(*f));
    00540               else
    00541                 a.add_series_transition(a.src_of(*e), a.dst_of(*f),
    00542                                         a.series_of(*e)*a.series_of(*f));
    00543           if (a.is_final(*s))
    00544             {
    00545               series_set_elt_t final_s = a.get_final(*s);
    00546               for_all_(std::list<htransition_t>, e, incoming_transitions)
    00547                 {
    00548                   hstate_t p = a.src_of(*e);
    00549                   series_set_elt_t t = a.get_final(p);
    00550                   if (hasloop)
    00551                     t += a.series_of(*e)*loop_series*final_s;
    00552                   else
    00553                     t += a.series_of(*e)*final_s;
    00554                   a.unset_final(p);
    00555                   if (t != null_series)
    00556                     a.set_final(p,t);
    00557                 }
    00558             }
    00559           if (a.is_initial(*s))
    00560             {
    00561               series_set_elt_t initial_s=a.get_initial(*s);
    00562               for_all_(std::list<htransition_t>, f, outgoing_transitions)
    00563                 {
    00564                   hstate_t p = a.dst_of(*f);
    00565                   series_set_elt_t t = a.get_initial(p);
    00566                   if (hasloop)
    00567                     t += initial_s*loop_series*a.series_of(*f);
    00568                   else
    00569                     t += initial_s*a.series_of(*f);
    00570                   a.unset_initial(p);
    00571                   if (t != null_series)
    00572                     a.set_initial(p,t);
    00573                 }
    00574             }
    00575           a.del_state(*s);
    00576         }
    00577       return true;
    00578     }
    00579
    00580     //merge transitions with the same ends
    00581     void merge_transitions()
    00582     {
    00583       typedef std::map<hstate_t, series_set_elt_t> map_t;
    00584       for_all_states(s, a)
    00585         {
    00586           map_t map;
    00587           std::list<htransition_t> transitions;
    00588           for (delta_iterator e(a.value(), *s); ! e.done(); e.next())
    00589             {
    00590               hstate_t target = a.dst_of(*e);
    00591               transitions.push_back(*e);
    00592               typename map_t::iterator it = map.find(target);
    00593               if (it == map.end())
    00594                 map.insert(std::pair<hstate_t, series_set_elt_t>(target,
    00595                                                                  a.series_of(*e)));
    00596               else
    00597                 it->second += a.series_of(*e);
    00598             }
    00599           for_all_(std::list<htransition_t>, e, transitions)
    00600             a.del_transition(*e);
    00601           for_all_(map_t, it, map)
    00602             a.add_series_transition(*s, it->first, it->second);
    00603         }
    00604     }
    00605
    00606   };
    00607
    00608
    00609   template <class A_, typename Auto, typename Weight>
    00610   bool test_for_non_positive_semiring<A_, Auto, Weight, 0>::run(const Auto& a) const
    00611   {
    00612     AUTOMATON_TYPES(Auto);
    00613
    00614     std::list<hstate_t> eps_states;
    00615     automaton_t test(a);
    00616     EpsilonRemover<A_, Auto, Weight> epsTest(test.structure(), test);
    00617     epsTest.positive_path_covering();
    00618     epsTest.epsilon_covering(eps_states);
    00619     return epsTest.spontaneous_suppression(eps_states);
    00620   }
    00621
    00622
    00623
    00624
    00625   /*--------------.
    00626     | eps_removal.  |
    00627     `--------------*/
    00628
    00629   template<class A_, typename Auto, typename Weight>
    00630   void
    00631   do_eps_removal_here(const AutomataBase<A_>& a_set,
    00632                       const Weight&,
    00633                       Auto& a,
    00634                       misc::direction_type dir)
    00635   {
    00636     BENCH_TASK_SCOPED("eps_removal");
    00637     AUTOMATON_TYPES(Auto);
    00638     EpsilonRemover<A_, Auto, Weight> algo(a_set, a);
    00639     algo(dir);
    00640   }
    00641
    00642   template<typename  A, typename  AI>
    00643   void
    00644   eps_removal_here(Element<A, AI>& a, misc::direction_type dir)
    00645   {
    00646     typedef Element<A, AI> automaton_t;
    00647     AUTOMATON_TYPES(automaton_t);
    00648
    00649     do_eps_removal_here(a.structure(),
    00650                         SELECT(semiring_elt_value_t),
    00651                         a, dir);
    00652   }
    00653
    00654   template<typename  A, typename  AI>
    00655   Element<A, AI>
    00656   eps_removal(const Element<A, AI>& a, misc::direction_type dir)
    00657   {
    00658     typedef Element<A, AI> automaton_t;
    00659     AUTOMATON_TYPES(automaton_t);
    00660
    00661     automaton_t ret(a);
    00662     do_eps_removal_here(ret.structure(),
    00663                         SELECT(semiring_elt_value_t),
    00664                         ret, dir);
    00665     return ret;
    00666   }
    00667
    00668   template<typename  A, typename  AI>
    00669   void
    00670   backward_eps_removal_here(Element<A, AI>& a)
    00671   {
    00672     typedef Element<A, AI> automaton_t;
    00673     AUTOMATON_TYPES(automaton_t);
    00674
    00675     do_eps_removal_here(a.structure(),
    00676                         SELECT(semiring_elt_value_t),
    00677                         a, misc::backward);
    00678   }
    00679
    00680   template<typename  A, typename  AI>
    00681   Element<A, AI>
    00682   backward_eps_removal(const Element<A, AI>& a)
    00683   {
    00684     typedef Element<A, AI> automaton_t;
    00685     AUTOMATON_TYPES(automaton_t);
    00686
    00687     automaton_t ret(a);
    00688     do_eps_removal_here(ret.structure(),
    00689                         SELECT(semiring_elt_value_t),
    00690                         ret, misc::backward);
    00691     return ret;
    00692   }
    00693
    00694   template<typename  A, typename  AI>
    00695   void
    00696   forward_eps_removal_here(Element<A, AI>& a)
    00697   {
    00698     typedef Element<A, AI> automaton_t;
    00699     AUTOMATON_TYPES(automaton_t);
    00700
    00701     do_eps_removal_here(a.structure(),
    00702                         SELECT(semiring_elt_value_t),
    00703                         a, misc::forward);
    00704   }
    00705
    00706   template<typename  A, typename  AI>
    00707   Element<A, AI>
    00708   forward_eps_removal(const Element<A, AI>& a)
    00709   {
    00710     typedef Element<A, AI> automaton_t;
    00711     AUTOMATON_TYPES(automaton_t);
    00712
    00713     automaton_t ret(a);
    00714     do_eps_removal_here(ret.structure(),
    00715                         SELECT(semiring_elt_value_t),
    00716                         ret, misc::forward);
    00717     return ret;
    00718   }
    00719
    00720 } // vcsn
    00721
    00722 #endif // ! VCSN_ALGORITHMS_EPS_REMOVAL_HXX