Vaucanson  1.4.1
derived_term_automaton.hxx
1 // derived_term_automaton.hxx: this file is part of the Vaucanson project.
2 //
3 // Vaucanson, a generic library for finite state machines.
4 //
5 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2011 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_DERIVED_TERM_AUTOMATON_HXX
18 # define VCSN_ALGORITHMS_DERIVED_TERM_AUTOMATON_HXX
19 
21 
22 # include <vaucanson/algorithms/internal/build_pattern.hh>
26 
28 # include <vaucanson/misc/usual_macros.hh>
30 
31 # ifdef DEBUG
32 
33 namespace std
34 {
35  template <typename T>
36  std::ostream& operator << (std::ostream& o, const std::list<T>& l)
37  {
38  typename std::list<T>::const_iterator i = l.begin();
39 
40  o << '{';
41  if (i != l.end())
42  {
43  o << *i;
44  for (i++; i != l.end(); ++i)
45  o << ", " << *i;
46  }
47  return o << '}';
48  }
49 }
50 
51 # define DERIVATES_TRACE_DEBUG(undef, e, l, s) \
52  if (!undef) \
53  { \
54  std::cerr << "Deriv " \
55  << e \
56  << " by " \
57  << l \
58  << " =" \
59  << std::endl; \
60  std::cerr << s << std::endl; \
61  std::cerr << std::endl; \
62  }
63 
64 # else
65 
66 # define DERIVATES_TRACE_DEBUG(undef, e, l, s)
67 
68 # endif
69 
70 namespace vcsn {
71 
72  using namespace algorithm_patterns;
73 
74  // In order to avoid re-calculation, the algorithm building
75  // derivatives automaton is implemented in a incremental way
76  template <typename T_auto, typename S, typename T>
77  struct DerivativesAlgo : public IncAutomataConstructor <
78  DerivativesAlgo<T_auto, S, T>,
79  T_auto,
80  PartialExp<S, T> >
81  {
82  typedef PartialExp<S, T> exp_t;
83  typedef std::list<exp_t> exp_list_t;
84  typedef typename exp_list_t::iterator exp_list_iterator;
85  AUTOMATON_TYPES(T_auto);
86  AUTOMATON_FREEMONOID_TYPES(T_auto);
87 
88  // Contructor -> initialize mother class and undefined attributes,
89  // which indicate if the resulting automaton is valid
90  DerivativesAlgo(const series_set_t& series, const Element<S, T>& exp):
91  IncAutomataConstructor<DerivativesAlgo, T_auto, PartialExp<S, T> >
92  (series, prat_exp_convert(exp)),
93  undefined(false)
94  {}
95 
96  // List Contructor -> initialize mother class and undefined attributes,
97  // which indicate if the resulting automaton is valid.
98  // This is used for the broken_derived_term_automaton algorithm.
99  DerivativesAlgo(const series_set_t& series,
100  const std::list<Element<S, T> >& listexp):
101  IncAutomataConstructor<DerivativesAlgo, T_auto, PartialExp<S, T> >
102  (series, prat_exp_convert(listexp)),
103  undefined(false)
104  {}
105 
106  // Function applied on each state
107  void on_state(const PartialExp<S, T>& e)
108  {
109  alphabet_t alpha = this->get()->series().monoid().alphabet();
110 
111  // Test the constant term of current expression
112  // If it is not zero, it is a final state
113  std::pair<semiring_elt_t, bool> c_term = constant_term(e);
114  if (!c_term.second)
115  undefined = true;
116  if (c_term.first !=
117  e.exp_structure().semiring().zero(SELECT(semiring_elt_value_t)))
118  this->set_final(series_set_elt_t (e.exp_structure(), c_term.first));
119 
120  // Create links between current state and states corresponding to
121  // partial derivatives of current expression
122  for (alphabet_iterator a = alpha.begin(); a != alpha.end(); ++a)
123  {
124  std::pair<std::list<PartialExp<S, T> >, bool>
125  s = prat_exp_derivate(e, *a);
126  if (!s.second)
127  undefined = true;
128  DERIVATES_TRACE_DEBUG(undefined, e, *a, s.first);
129  for (exp_list_iterator i = s.first.begin(); i != s.first.end(); ++i)
130  {
131  PartialExp<S, T> p_exp = *i;
132  series_set_elt_t s_elt (e.exp_structure(),
133  monoid_elt_t(e.exp_structure().monoid(), *a));
134  s_elt = p_exp.begin().semiring_elt() * s_elt;
135  p_exp.begin().semiring_elt() =
136  e.exp_structure().semiring().identity(SELECT(semiring_elt_value_t));
137  this->link_to(p_exp, s_elt);
138  }
139  }
140  }
141 
142  bool undefined;
143  };
144 
145  template<typename T_auto, typename S, typename T>
146  T_auto*
147  do_derived_term_automaton(const T_auto& out,
148  const Element<S, T>& kexp)
149  {
150  Element<S, T> exp = realtime(kexp);
151  DerivativesAlgo<T_auto, S, T> derivatives_algo(out.series(), exp);
152  derivatives_algo.run();
153  if (derivatives_algo.undefined)
154  {
155  delete derivatives_algo.get();
156  return NULL;
157  }
158  else
159  return derivatives_algo.get();
160  }
161 
162  template<typename A, typename T, typename Exp>
163  void
164  derived_term_automaton(Element<A, T>& out, const Exp& kexp)
165  {
166  BENCH_TASK_SCOPED("derived_term_automaton");
167  Element<A, T>* res = do_derived_term_automaton(out, kexp);
168  if (res)
169  out = *res;
170  }
171 
172  template<typename A, typename T, typename Exp>
173  Element<A, T>
174  derived_term_automaton(const Exp& kexp)
175  {
176  A a_structure(kexp.structure());
177  Element<A, T> out (a_structure);
178  derived_term_automaton (out, kexp);
179  return out;
180  }
181 
182  // broken_derived_term_automaton implementation
183  template<typename T_auto, typename S, typename T>
184  T_auto*
185  do_broken_derived_term_automaton(const T_auto& out,
186  const Element<S, T>& kexp)
187  {
188  Element<S, T> exp = realtime(kexp);
189  KRatExpInitialDerivation< S, T, algebra::DispatchFunction<T> >
190  matcher(exp);
191  std::list< Element<S, T> > listexp = matcher.match(exp.value());
192  DerivativesAlgo<T_auto, S, T> derivatives_algo(out.series(),
193  listexp);
194  derivatives_algo.run();
195  if (derivatives_algo.undefined)
196  {
197  delete derivatives_algo.get();
198  return NULL;
199  }
200  else
201  return derivatives_algo.get();
202  }
203 
204  template<typename A, typename T, typename Exp>
205  void
206  broken_derived_term_automaton(Element<A, T>& out, const Exp& kexp)
207  {
208  Element<A, T>* result = do_broken_derived_term_automaton(out, kexp);
209  if (result != NULL)
210  out = *result;
211  }
212 
213  template<typename A, typename T, typename Exp>
214  Element<A, T>
215  broken_derived_term_automaton(const Exp& kexp)
216  {
217  A a_structure(kexp.structure());
218  Element<A, T> out (a_structure);
219  Element<A, T>* result = do_broken_derived_term_automaton(out, kexp);
220  if (result != NULL)
221  out = *result;
222  return out;
223  }
224 
225 
226 
227 } // vcsn
228 
229 #endif // ! VCSN_ALGORITHMS_DERIVED_TERM_AUTOMATON_HXX