Vaucanson 1.4
thompson.hxx
00001 // thompson.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, 2006, 2007, 2008, 2009 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_THOMPSON_HXX
00018 # define VCSN_ALGORITHMS_THOMPSON_HXX
00019 
00020 # include <utility>
00021 
00022 # include <vaucanson/algorithms/thompson.hh>
00023 
00024 # include <vaucanson/automata/concept/automata_base.hh>
00025 # include <vaucanson/misc/usual_macros.hh>
00026 
00027 namespace vcsn {
00028 
00029   /*----------------.
00030   | ThompsonVisitor |
00031   `----------------*/
00032   // FIXME : from now, it is only working over LetterAutomaton
00033 
00034   template <class Auto_, class Monoid_, class Semiring_>
00035   class ThompsonVisitor :
00036       public rat::ConstNodeVisitor<Monoid_, Semiring_>
00037   {
00038     public :
00039       typedef Auto_                                     automaton_t;
00040       typedef typename automaton_t::hstate_t            hstate_t;
00041       typedef typename automaton_t::set_t               automata_set_t;
00042       typedef typename automaton_t::series_set_t        series_set_t;
00043       typedef typename automaton_t::series_set_elt_t    series_set_elt_t;
00044       typedef typename series_set_elt_t::semiring_elt_t semiring_elt_t;
00045       typedef Monoid_                                   monoid_elt_value_t;
00046       typedef Semiring_                                 semiring_elt_value_t;
00047       typedef rat::Node<monoid_elt_value_t, semiring_elt_value_t> node_t;
00048 
00049     public :
00050 
00051       ThompsonVisitor(automaton_t &a)
00052         : auto_ (a)
00053       {}
00054 
00055       virtual
00056       ~ThompsonVisitor()
00057       {}
00058 
00059       virtual void
00060       product(const node_t* lhs, const node_t* rhs)
00061       {
00062         // Visit left tree
00063         lhs->accept(*this);
00064         // Store results
00065         std::pair<hstate_t, hstate_t>     left_ini_fin = ini_fin_;
00066         // Visit right tree
00067         rhs->accept(*this);
00068         // Create spontaneous link between
00069         // final of left automaton and initial of right automaton.
00070         auto_.add_spontaneous(left_ini_fin.second, ini_fin_.first);
00071 
00072         // Save new initial state.
00073         ini_fin_.first = left_ini_fin.first;
00074       }
00075 
00076       virtual void
00077       sum(const node_t* lhs, const node_t* rhs)
00078       {
00079         lhs->accept(*this);
00080 
00081         std::pair<hstate_t, hstate_t>     left_ini_fin = ini_fin_;
00082         hstate_t new_i = auto_.add_state();
00083         hstate_t new_f = auto_.add_state();
00084 
00085         auto_.add_spontaneous(new_i, left_ini_fin.first);
00086         auto_.add_spontaneous(left_ini_fin.second, new_f);
00087 
00088         rhs->accept(*this);
00089 
00090         auto_.add_spontaneous(new_i, ini_fin_.first);
00091         auto_.add_spontaneous(ini_fin_.second, new_f);
00092 
00093         ini_fin_.first = new_i;
00094         ini_fin_.second = new_f;
00095       }
00096 
00097       virtual void
00098       star(const node_t* node)
00099       {
00100         node->accept(*this);
00101         auto_.add_spontaneous(ini_fin_.second, ini_fin_.first);
00102 
00103         hstate_t new_i = auto_.add_state();
00104         hstate_t new_f = auto_.add_state();
00105 
00106         auto_.add_spontaneous(new_i, new_f);
00107         auto_.add_spontaneous(new_i, ini_fin_.first);
00108         auto_.add_spontaneous(ini_fin_.second, new_f);
00109 
00110         ini_fin_.first = new_i;
00111         ini_fin_.second = new_f;
00112       }
00113 
00114       virtual void
00115       left_weight(const semiring_elt_value_t& w, const node_t* node)
00116       {
00117         node->accept(*this);
00118 
00119         hstate_t new_i = auto_.add_state();
00120         hstate_t new_f = auto_.add_state();
00121 
00122         series_set_elt_t t = auto_.series().zero_;
00123         t.assoc(auto_.series().monoid().identity(SELECT(monoid_elt_value_t)), w);
00124         auto_.add_series_transition(new_i, ini_fin_.first, t);
00125 
00126         auto_.add_spontaneous(ini_fin_.second, new_f);
00127 
00128         ini_fin_.first = new_i;
00129         ini_fin_.second = new_f;
00130       }
00131 
00132       virtual void
00133       right_weight(const semiring_elt_value_t& w, const node_t* node)
00134       {
00135         node->accept(*this);
00136 
00137         hstate_t new_i = auto_.add_state();
00138         hstate_t new_f = auto_.add_state();
00139 
00140         auto_.add_spontaneous(new_i, ini_fin_.first);
00141 
00142         series_set_elt_t t = auto_.series().zero_;
00143         t.assoc(auto_.series().monoid().identity(SELECT(monoid_elt_value_t)), w);
00144         auto_.add_series_transition(ini_fin_.second, new_f, t);
00145 
00146         ini_fin_.first = new_i;
00147         ini_fin_.second = new_f;
00148       }
00149 
00150       virtual void
00151       constant(const monoid_elt_value_t& m)
00152       {
00153         ini_fin_.first = auto_.add_state();
00154         hstate_t link_state;
00155 
00156         typename monoid_elt_value_t::const_iterator i = m.begin();
00157 
00158         ini_fin_.second = auto_.add_state();
00159         auto_.add_letter_transition(ini_fin_.first, ini_fin_.second, *i);
00160         ++i;
00161 
00162         while (i != m.end())
00163         {
00164           link_state = auto_.add_state();
00165           auto_.add_spontaneous(ini_fin_.second, link_state);
00166           ini_fin_.second = auto_.add_state();
00167           auto_.add_letter_transition(link_state, ini_fin_.second, *i);
00168           ++i;
00169         }
00170       }
00171 
00172       virtual void
00173       zero()
00174       {
00175         ini_fin_.first = auto_.add_state();
00176         ini_fin_.second = auto_.add_state();
00177       }
00178 
00179       virtual void
00180       one()
00181       {
00182         ini_fin_.first = auto_.add_state();
00183         ini_fin_.second = auto_.add_state();
00184         auto_.add_spontaneous(ini_fin_.first, ini_fin_.second);
00185       }
00186 
00187       const automaton_t         &get_auto() const
00188       {
00189         auto_.clear_initial();
00190         auto_.clear_final();
00191         auto_.set_initial(ini_fin_.first);
00192         auto_.set_final(ini_fin_.second);
00193         return auto_;
00194       }
00195 
00196       // finalize is used to only set initial and final states of auto_
00197       // only once (to spare the multiple set and unset required elsewise).
00198       void
00199       finalize() const
00200       {
00201         auto_.set_initial(ini_fin_.first);
00202         auto_.set_final(ini_fin_.second);
00203       }
00204 
00205     private :
00206       automaton_t                       &auto_;
00207       std::pair<hstate_t, hstate_t>     ini_fin_;
00208   };
00209 
00210   template <typename A, typename auto_t,
00211             typename Letter, typename Weight>
00212   void
00213   do_thompson_of(const AutomataBase<A>&,
00214                  auto_t& output,
00215                  const rat::exp<Letter, Weight>& kexp)
00216   {
00217     // You should provide an empty automaton as output.
00218     ThompsonVisitor<auto_t, Letter, Weight> visitor(output);
00219     // FIXME :
00220     // Static assert : Letter = monoid_elt_value_t,
00221     //                 Weight = semiring_elt_value_t
00222     kexp.accept(visitor);
00223     visitor.finalize();
00224   }
00225 
00226   template<typename A,      typename T,
00227            typename Letter, typename Weight>
00228   void
00229   thompson_of(Element<A, T>& out,
00230               const rat::exp<Letter, Weight>& kexp)
00231   {
00232     do_thompson_of(out.structure(), out, kexp);
00233   }
00234 
00235   template <typename AutoType, typename S, typename K, typename T>
00236   Element<Automata<S, K>, AutoType>
00237   thompson_of(const Element<S, T>& exp)
00238   {
00239     Automata<S, K>                      automata_set(exp.structure());
00240     Element<Automata<S, K>, AutoType>   automata(automata_set);
00241 
00242     thompson_of(automata, exp.value());
00243     return automata;
00244   }
00245 } // vcsn
00246 
00247 #endif // ! VCSN_ALGORITHMS_THOMPSON_HXX