Vaucanson 1.4
one_eps_closure.hxx
00001 // one_eps_closure.hxx: this file is part of the Vaucanson project.
00002 //
00003 // Vaucanson, a generic library for finite state machines.
00004 //
00005 // Copyright (C) 2010 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_ONE_EPS_CLOSURE_HXX
00018 # define VCSN_ALGORITHMS_ONE_EPS_CLOSURE_HXX
00019 
00020 # include <vaucanson/algorithms/one_eps_closure.hh>
00021 
00022 # include <vaucanson/automata/concept/automata_base.hh>
00023 # include <vaucanson/misc/usual_macros.hh>
00024 # include <list>
00025 
00026 namespace vcsn
00027 {
00028 
00029   template<typename A, typename AI, typename S, typename V>
00030   void
00031   workaround_add_series_transition(const AutomataBase<A>& a_set,
00032                                    Element<A, AI>&   a,
00033                                    S& src, S& dst, V& val)
00034   {
00035     typedef Element<A, AI> automaton_t;
00036     AUTOMATON_TYPES(automaton_t)
00037     // We cannot update a transition with the current interface.
00038     // Instead...
00039     // Find the first transitions going from source to target,
00040     // labelled by K.  If it exists, remove it and add
00041     // its label K to the series we wanted to create.
00042     for (delta_iterator j(a.value(), src); !j.done(); j.next())
00043       {
00044         if (a.dst_of(*j) != dst)
00045           {
00046             continue;
00047           }
00048         else
00049           {
00050             val += a.series_of(*j);
00051             a.del_transition(*j);
00052             break;
00053           }
00054       }
00055     a.add_series_transition(src, dst, val);
00056   }
00057 
00058   /*-------------------------------------------.
00059   | One Epsilon Closure for weighted automaton |
00060   `--------------------------------------------*/
00061 
00062 
00063   template<class A, typename AI, typename EPS>
00064   void
00065   do_backward_one_eps_closure(const AutomataBase<A>& a_set,
00066                               Element<A, AI>&   a,
00067                               const EPS& eps)
00068   {
00069     typedef Element<A, AI> automaton_t;
00070     AUTOMATON_TYPES(automaton_t)
00071 
00072     hstate_t source = eps.src();
00073     hstate_t dest = eps.dst();
00074 
00075     precondition(source != dest);
00076 
00077     // Computation of the list of transitions which follow 'eps' This
00078     // list has to be computed before creating any new transition.
00079     // Otherwise, if add_to_transition() deletes a transition, it
00080     // makes the delta_iterator invalid.
00081     std::list<htransition_t> transition_list;
00082     for (delta_iterator it(a.value(), dest); !it.done(); it.next())
00083       transition_list.push_back(*it);
00084 
00085     // Creation of the new transitions.
00086     for(typename std::list<htransition_t>::iterator it =
00087           transition_list.begin(); it != transition_list.end(); ++it)
00088       {
00089         series_set_elt_t series = eps.weight() * a.series_of(*it);
00090 
00091         if (series == a.series().zero_)
00092           continue;
00093 
00094         hstate_t target = a.dst_of(*it);
00095 
00096         workaround_add_series_transition(a.structure(), a,
00097                                          source, target, series);
00098       }
00099 
00100 
00101     // Handling final functions.
00102     series_set_elt_t fin_weight =
00103       a.get_final(source) + eps.weight() * a.get_final(dest);
00104 
00105     a.set_final(source, fin_weight);
00106   }
00107 
00108   template<class A, typename AI, typename EPS>
00109   void
00110   do_forward_one_eps_closure(const AutomataBase<A>& a_set,
00111                       Element<A, AI>&   a,
00112                       const EPS& eps)
00113   {
00114     typedef Element<A, AI> automaton_t;
00115     AUTOMATON_TYPES(automaton_t);
00116 
00117     hstate_t source = eps.src();
00118     hstate_t dest = eps.dst();
00119 
00120     precondition(source != dest);
00121 
00122     // Computation of the list of transitions which precede 'eps'.
00123     // This list has to be coumputed before creating any new
00124     // transition.  Otherwise, if add_to_transition deletes a
00125     // transition, it makes the delta_iterator invalid.
00126     std::list<htransition_t> transition_list;
00127     for (rdelta_iterator it(a.value(), source); ! it.done(); it.next())
00128       transition_list.push_back(*it);
00129 
00130     // Creation of the new transitions.
00131     for(typename std::list<htransition_t>::iterator it =
00132           transition_list.begin(); it != transition_list.end(); ++it)
00133       {
00134         series_set_elt_t series = a.series_of(*it) * eps.weight();
00135 
00136         if (series == a.series().zero_)
00137           continue;
00138 
00139         hstate_t target = a.dst_of(*it);
00140 
00141         workaround_add_series_transition(a.structure(), a,
00142                                          source, target, series);
00143       }
00144 
00145     // Handling initial functions.
00146     series_set_elt_t ini_weight =
00147       a.get_initial(source) * eps.weight() + a.get_initial(dest);
00148     a.set_initial(dest, ini_weight);
00149   }
00150 
00151   template<typename A, typename AI, typename EPS>
00152   void
00153   backward_one_eps_closure(Element<A, AI>& a, const EPS& eps)
00154   {
00155     typedef Element<A, AI> automaton_t;
00156     AUTOMATON_TYPES(automaton_t);
00157     do_backward_one_eps_closure(a.structure(), a, eps);
00158   }
00159 
00160   template<typename A, typename AI, typename EPS>
00161   void
00162   forward_one_eps_closure(Element<A, AI>& a, const EPS& eps)
00163   {
00164     typedef Element<A, AI> automaton_t;
00165     AUTOMATON_TYPES(automaton_t);
00166     do_forward_one_eps_closure(a.structure(), a, eps);
00167   }
00168 
00169   template<typename A, typename AI, typename EPS>
00170   void
00171   one_eps_closure(Element<A, AI>& a, const EPS& eps, misc::direction_type dir)
00172   {
00173     typedef Element<A, AI> automaton_t;
00174     AUTOMATON_TYPES(automaton_t);
00175     switch(dir){
00176     case misc::backward :
00177       do_backward_one_eps_closure(a.structure(), a, eps);
00178       break;
00179     case misc::forward :
00180       do_forward_one_eps_closure(a.structure(), a, eps);
00181       break;
00182     }
00183   }
00184 
00185 } // vcsn
00186 
00187 #endif // ! VCSN_ALGORITHMS_ONE_EPS_CLOSURE_HXX