Vaucanson  1.4.1
one_eps_closure.hxx
1 // one_eps_closure.hxx: this file is part of the Vaucanson project.
2 //
3 // Vaucanson, a generic library for finite state machines.
4 //
5 // Copyright (C) 2010 The Vaucanson Group.
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
11 //
12 // The complete GNU General Public Licence Notice can be found as the
13 // `COPYING' file in the root directory.
14 //
15 // The Vaucanson Group consists of people listed in the `AUTHORS' file.
16 //
17 #ifndef VCSN_ALGORITHMS_ONE_EPS_CLOSURE_HXX
18 # define VCSN_ALGORITHMS_ONE_EPS_CLOSURE_HXX
19 
21 
22 # include <vaucanson/automata/concept/automata_base.hh>
23 # include <vaucanson/misc/usual_macros.hh>
24 # include <list>
25 
26 namespace vcsn
27 {
28 
29  template<typename A, typename AI, typename S, typename V>
30  void
31  workaround_add_series_transition(const AutomataBase<A>& a_set,
32  Element<A, AI>& a,
33  S& src, S& dst, V& val)
34  {
35  typedef Element<A, AI> automaton_t;
36  AUTOMATON_TYPES(automaton_t)
37  // We cannot update a transition with the current interface.
38  // Instead...
39  // Find the first transitions going from source to target,
40  // labelled by K. If it exists, remove it and add
41  // its label K to the series we wanted to create.
42  for (delta_iterator j(a.value(), src); !j.done(); j.next())
43  {
44  if (a.dst_of(*j) != dst)
45  {
46  continue;
47  }
48  else
49  {
50  val += a.series_of(*j);
51  a.del_transition(*j);
52  break;
53  }
54  }
55  if (val != a.series().zero_)
56  a.add_series_transition(src, dst, val);
57  }
58 
59  /*-------------------------------------------.
60  | One Epsilon Closure for weighted automaton |
61  `--------------------------------------------*/
62 
63 
64  template<class A, typename AI, typename EPS>
65  void
66  do_backward_one_eps_closure(const AutomataBase<A>& a_set,
67  Element<A, AI>& a,
68  const EPS& eps)
69  {
70  typedef Element<A, AI> automaton_t;
71  AUTOMATON_TYPES(automaton_t)
72 
73  hstate_t source = eps.src();
74  hstate_t dest = eps.dst();
75 
76  precondition(source != dest);
77 
78  // Computation of the list of transitions which follow 'eps' This
79  // list has to be computed before creating any new transition.
80  // Otherwise, if add_to_transition() deletes a transition, it
81  // makes the delta_iterator invalid.
82  std::list<htransition_t> transition_list;
83  for (delta_iterator it(a.value(), dest); !it.done(); it.next())
84  transition_list.push_back(*it);
85 
86  // Creation of the new transitions.
87  for(typename std::list<htransition_t>::iterator it =
88  transition_list.begin(); it != transition_list.end(); ++it)
89  {
90  series_set_elt_t series = eps.weight() * a.series_of(*it);
91 
92  if (series == a.series().zero_)
93  continue;
94 
95  hstate_t target = a.dst_of(*it);
96 
97  workaround_add_series_transition(a.structure(), a,
98  source, target, series);
99  }
100 
101 
102  // Handling final functions.
103  series_set_elt_t fin_weight =
104  a.get_final(source) + eps.weight() * a.get_final(dest);
105 
106  a.set_final(source, fin_weight);
107  }
108 
109  template<class A, typename AI, typename EPS>
110  void
111  do_forward_one_eps_closure(const AutomataBase<A>& a_set,
112  Element<A, AI>& a,
113  const EPS& eps)
114  {
115  typedef Element<A, AI> automaton_t;
116  AUTOMATON_TYPES(automaton_t);
117 
118  hstate_t source = eps.src();
119  hstate_t dest = eps.dst();
120 
121  precondition(source != dest);
122 
123  // Computation of the list of transitions which precede 'eps'.
124  // This list has to be coumputed before creating any new
125  // transition. Otherwise, if add_to_transition deletes a
126  // transition, it makes the delta_iterator invalid.
127  std::list<htransition_t> transition_list;
128  for (rdelta_iterator it(a.value(), source); ! it.done(); it.next())
129  transition_list.push_back(*it);
130 
131  // Creation of the new transitions.
132  for(typename std::list<htransition_t>::iterator it =
133  transition_list.begin(); it != transition_list.end(); ++it)
134  {
135  series_set_elt_t series = a.series_of(*it) * eps.weight();
136 
137  if (series == a.series().zero_)
138  continue;
139 
140  hstate_t target = a.dst_of(*it);
141 
142  workaround_add_series_transition(a.structure(), a,
143  source, target, series);
144  }
145 
146  // Handling initial functions.
147  series_set_elt_t ini_weight =
148  a.get_initial(source) * eps.weight() + a.get_initial(dest);
149  a.set_initial(dest, ini_weight);
150  }
151 
152  template<typename A, typename AI, typename EPS>
153  void
155  {
156  typedef Element<A, AI> automaton_t;
157  AUTOMATON_TYPES(automaton_t);
158  do_backward_one_eps_closure(a.structure(), a, eps);
159  }
160 
161  template<typename A, typename AI, typename EPS>
162  void
164  {
165  typedef Element<A, AI> automaton_t;
166  AUTOMATON_TYPES(automaton_t);
167  do_forward_one_eps_closure(a.structure(), a, eps);
168  }
169 
170  template<typename A, typename AI, typename EPS>
171  void
173  {
174  typedef Element<A, AI> automaton_t;
175  AUTOMATON_TYPES(automaton_t);
176  switch(dir){
177  case misc::backward :
178  do_backward_one_eps_closure(a.structure(), a, eps);
179  break;
180  case misc::forward :
181  do_forward_one_eps_closure(a.structure(), a, eps);
182  break;
183  }
184  }
185 
186 } // vcsn
187 
188 #endif // ! VCSN_ALGORITHMS_ONE_EPS_CLOSURE_HXX