derived_term_automaton.hxx

00001 // derived_term_automaton.hxx: this file is part of the Vaucanson project.
00002 //
00003 // Vaucanson, a generic library for finite state machines.
00004 //
00005 // Copyright (C) 2001, 2002, 2003, 2004, 2005 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_DERIVED_TERM_AUTOMATON_HXX
00018 # define VCSN_ALGORITHMS_DERIVED_TERM_AUTOMATON_HXX
00019 
00020 # include <vaucanson/algorithms/derived_term_automaton.hh>
00021 
00022 # include <vaucanson/algorithms/internal/build_pattern.hh>
00023 # include <vaucanson/algorithms/internal/partial_rat_exp.hh>
00024 # include <vaucanson/algorithms/internal/partial_rat_exp_constant_term.hh>
00025 # include <vaucanson/algorithms/internal/partial_rat_exp_derivation.hh>
00026 
00027 # include <vaucanson/algorithms/krat_exp_realtime.hh>
00028 # include <vaucanson/misc/usual_macros.hh>
00029 # include <vaucanson/algorithms/initial_derivation.hh>
00030 
00031 # ifdef DEBUG
00032 
00033 namespace std
00034 {
00035   template <typename T>
00036   std::ostream& operator << (std::ostream& o, const std::list<T>& l)
00037   {
00038     typename std::list<T>::const_iterator       i = l.begin();
00039 
00040     o << '{';
00041     if (i != l.end())
00042     {
00043       o << *i;
00044       for (i++; i != l.end(); ++i)
00045         o << ", " << *i;
00046     }
00047     return o << '}';
00048   }
00049 }
00050 
00051 #  define DERIVATES_TRACE_DEBUG(undef, e, l, s)         \
00052      if (!undef)                                        \
00053      {                                                  \
00054        std::cout << "Deriv "                            \
00055                  << e                                   \
00056                  << " by "                              \
00057                  << l                                   \
00058                  << " ="                                \
00059                  << std::endl;                          \
00060        std::cout << s << std::endl;                     \
00061        std::cout << std::endl;                          \
00062      }
00063 
00064 # else
00065 
00066 #  define DERIVATES_TRACE_DEBUG(undef, e, l, s)
00067 
00068 # endif
00069 
00070 namespace vcsn {
00071 
00072   using namespace algorithm_patterns;
00073 
00074   // In order to avoid re-calculation, the algorithm building
00075   // derivatives automaton is implemented in a incremental way
00076   template <typename T_auto, typename S, typename T>
00077   struct DerivativesAlgo : public IncAutomataConstructor <
00078     DerivativesAlgo<T_auto, S, T>,
00079     T_auto,
00080     PartialExp<S, T> >
00081   {
00082     typedef PartialExp<S, T>                            exp_t;
00083     typedef std::list<exp_t>                            exp_list_t;
00084     typedef typename exp_list_t::iterator               exp_list_iterator;
00085     AUTOMATON_TYPES(T_auto);
00086     AUTOMATON_FREEMONOID_TYPES(T_auto);
00087 
00088     // Contructor -> initialize mother class and undefined attributes,
00089     // which indicate if the resulting automaton is valid
00090     DerivativesAlgo(const series_set_t& series, const Element<S, T>& exp):
00091       IncAutomataConstructor<DerivativesAlgo, T_auto, PartialExp<S, T> >
00092         (series, prat_exp_convert(exp)),
00093       undefined(false)
00094     {}
00095 
00096     // List Contructor -> initialize mother class and undefined attributes,
00097     // which indicate if the resulting automaton is valid.
00098     // This is used for the broken_derived_term_automaton algorithm.
00099     DerivativesAlgo(const series_set_t& series,
00100                     const std::list<Element<S, T> >& listexp):
00101       IncAutomataConstructor<DerivativesAlgo, T_auto, PartialExp<S, T> >
00102         (series, prat_exp_convert(listexp)),
00103        undefined(false)
00104      {}
00105 
00106     // Function applied on each state
00107     void on_state(const PartialExp<S, T>& e)
00108     {
00109       alphabet_t alpha = this->get()->series().monoid().alphabet();
00110 
00111       // Test the constant term of current expression
00112       // If it is not zero, it is a final state
00113       std::pair<semiring_elt_t, bool>   c_term = constant_term(e);
00114       if (!c_term.second)
00115         undefined = true;
00116       if (c_term.first !=
00117           e.exp_structure().semiring().zero(SELECT(semiring_elt_value_t)))
00118         set_final(series_set_elt_t (e.exp_structure(), c_term.first));
00119 
00120       // Create links between current state and states corresponding to
00121       // partial derivatives of current expression
00122       for (alphabet_iterator a = alpha.begin(); a != alpha.end(); ++a)
00123       {
00124         std::pair<std::list<PartialExp<S, T> >, bool>
00125           s = prat_exp_derivate(e, *a);
00126         if (!s.second)
00127           undefined = true;
00128         DERIVATES_TRACE_DEBUG(undefined, e, *a, s.first);
00129         for (exp_list_iterator i = s.first.begin(); i != s.first.end(); ++i)
00130         {
00131           PartialExp<S, T> p_exp = *i;
00132           series_set_elt_t s_elt (e.exp_structure(),
00133                               monoid_elt_t(e.exp_structure().monoid(), *a));
00134           s_elt = p_exp.begin().semiring_elt() * s_elt;
00135           p_exp.begin().semiring_elt() =
00136             e.exp_structure().semiring().identity(SELECT(semiring_elt_value_t));
00137           link_to(p_exp, s_elt);
00138         }
00139       }
00140     }
00141 
00142     bool undefined;
00143   };
00144 
00145   template<typename T_auto, typename S, typename T>
00146   T_auto*
00147   do_derived_term_automaton(const T_auto& out,
00148                            const Element<S, T>& kexp)
00149   {
00150     Element<S, T>                       exp = realtime(kexp);
00151     DerivativesAlgo<T_auto, S, T>       derivatives_algo(out.series(), exp);
00152     derivatives_algo.run();
00153     if (derivatives_algo.undefined)
00154     {
00155       delete derivatives_algo.get();
00156       return NULL;
00157     }
00158     else
00159       return derivatives_algo.get();
00160   }
00161 
00162   template<typename A, typename T, typename Exp>
00163   void
00164   derived_term_automaton(Element<A, T>& out, const Exp& kexp)
00165   {
00166     Element<A, T>*      result = do_derived_term_automaton(out, kexp);
00167     if (result != NULL)
00168       out = *result;
00169   }
00170 
00171   template<typename A, typename T, typename Exp>
00172   Element<A, T>
00173   derived_term_automaton(const Exp& kexp)
00174   {
00175     A                   a_structure(kexp.structure());
00176     Element<A, T>       out (a_structure);
00177     Element<A, T>*      result = do_derived_term_automaton(out, kexp);
00178     if (result != NULL)
00179       out = *result;
00180     return out;
00181   }
00182 
00183 // broken_derived_term_automaton implementation
00184   template<typename T_auto, typename S, typename T>
00185   T_auto*
00186   do_broken_derived_term_automaton(const T_auto& out,
00187                            const Element<S, T>& kexp)
00188   {
00189     Element<S, T>                       exp = realtime(kexp);
00190     KRatExpInitialDerivation< S, T, algebra::DispatchFunction<T> >
00191       matcher(exp);
00192     std::list< Element<S, T> > listexp = matcher.match(exp.value());
00193     DerivativesAlgo<T_auto, S, T> derivatives_algo(out.series(),
00194                                                    listexp);
00195     derivatives_algo.run();
00196     if (derivatives_algo.undefined)
00197     {
00198       delete derivatives_algo.get();
00199       return NULL;
00200     }
00201     else
00202       return derivatives_algo.get();
00203   }
00204 
00205   template<typename A, typename T, typename Exp>
00206   void
00207   broken_derived_term_automaton(Element<A, T>& out, const Exp& kexp)
00208   {
00209     Element<A, T>*      result = do_broken_derived_term_automaton(out, kexp);
00210     if (result != NULL)
00211       out = *result;
00212   }
00213 
00214   template<typename A, typename T, typename Exp>
00215   Element<A, T>
00216   broken_derived_term_automaton(const Exp& kexp)
00217   {
00218     A                   a_structure(kexp.structure());
00219     Element<A, T>       out (a_structure);
00220     Element<A, T>*      result = do_broken_derived_term_automaton(out, kexp);
00221     if (result != NULL)
00222       out = *result;
00223     return out;
00224   }
00225 
00226 
00227 
00228 } // vcsn
00229 
00230 #endif // ! VCSN_ALGORITHMS_DERIVED_TERM_AUTOMATON_HXX

Generated on Sat Jul 29 17:12:58 2006 for Vaucanson by  doxygen 1.4.6