Vaucanson 1.4
|
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