• 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

Generated on Fri Jul 8 2011 22:06:58 for Vaucanson by  doxygen 1.7.1