Vaucanson 1.4
krat_exp_expand.hxx
00001 // krat_exp_expand.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, 2008, 2011 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_KRAT_EXP_EXPAND_HXX
00018 # define VCSN_ALGORITHMS_KRAT_EXP_EXPAND_HXX
00019 
00020 # include <list>
00021 # include <map>
00022 
00023 # include <vaucanson/algorithms/krat_exp_expand.hh>
00024 
00025 # include <vaucanson/algebra/implementation/series/krat_exp_pattern.hh>
00026 
00027 namespace vcsn
00028 {
00029 
00030   namespace algebra {
00031 
00032     // This is a trait to get more easily used types.
00033     template <typename S, typename T>
00034     struct pseudo_exp_list
00035     {
00036       typedef Element<S, T>                             exp_t;
00037       typedef std::list<exp_t>                          exp_list_t;
00038       typedef typename exp_t::semiring_elt_t            semiring_elt_t;
00039       typedef std::map<exp_list_t, semiring_elt_t>      ret_t;
00040     };
00041 
00042     // The Expander class. It breaks up the expression to build a map
00043     // and then rebuild it.
00044     template <class Series, class T, class Dispatch>
00045     struct KRatExpExpander : algebra::KRatExpMatcher<
00046       KRatExpExpander<Series, T, Dispatch>,
00047       T,
00048       typename pseudo_exp_list<Series, T>::ret_t,
00049       Dispatch
00050       >
00051     {
00052     public:
00053       typedef pseudo_exp_list<Series, T>                        trait;
00054       typedef typename trait::exp_t                             exp_t;
00055       typedef typename trait::ret_t                             return_type;
00056       typedef typename trait::exp_list_t                        exp_list_t;
00057       typedef KRatExpExpander<Series, T, Dispatch>              self_t;
00058       typedef typename Element<Series, T>::semiring_elt_t       semiring_elt_t;
00059       typedef typename semiring_elt_t::value_t                  semiring_elt_value_t;
00060       typedef typename Element<Series, T>::monoid_elt_t         monoid_elt_t;
00061       typedef typename monoid_elt_t::set_t                      monoid_t;
00062       typedef typename monoid_t::alphabet_t                     alphabet_t;
00063       typedef typename alphabet_t::letter_t                     letter_t;
00064       INHERIT_CONSTRUCTORS(self_t, T, semiring_elt_t, Dispatch);
00065 
00066       KRatExpExpander(const exp_t& exp) :
00067         exp_(exp)
00068       {}
00069 
00070       // Some useful internal functions.
00071     private:
00072       // Convert the return_type into a rational expression.
00073       exp_t convert(const return_type& l)
00074       {
00075         typedef typename return_type::const_iterator    iterator;
00076         typedef typename exp_list_t::const_iterator     sub_iterator;
00077 
00078         exp_t result = exp_.structure().zero(SELECT(T));
00079 
00080         for (iterator i = l.begin(); i != l.end(); ++i)
00081         {
00082           exp_list_t    l = i->first;
00083           exp_t         e = l.front();
00084           for (sub_iterator j = ++l.begin(); j != l.end(); ++j)
00085             e *= *j;
00086           result += i->second * e;
00087         }
00088 
00089         return result;
00090       }
00091 
00092       // Convert a standard expression into the corresponding breaked one.
00093       return_type convert(const exp_t& e)
00094       {
00095         exp_list_t      exp_list;
00096         exp_list.push_front(e);
00097 
00098         return_type     result;
00099         result[exp_list] =
00100           exp_.structure().semiring().identity(SELECT(semiring_elt_value_t));
00101 
00102         return result;
00103       }
00104 
00105       // The union of two lists implemented by a map. If an element is in the
00106       // two lists then the weights are added.
00107       return_type list_union(const return_type& left,
00108                              const return_type& right)
00109       {
00110         typedef typename return_type::const_iterator    const_iterator;
00111         typedef typename return_type::iterator          iterator;
00112 
00113         return_type     result(left);
00114         for (const_iterator i = right.begin(); i != right.end(); ++i)
00115         {
00116           iterator j = result.find(i->first);
00117 
00118           if (j != result.end())
00119             j->second += i->second;
00120           else
00121             result.insert(*i);
00122         }
00123 
00124         return result;
00125       }
00126 
00127       // Compute the concatenation of two lists
00128       exp_list_t list_concat(const exp_list_t& left, const exp_list_t& right)
00129       {
00130 
00131         typename T::node_t* lnode = left.back().value().base();
00132         typename T::node_t* rnode = right.front().value().base();
00133 
00134         // Handle concatenations when one operand is a constant (ONE or ZERO)
00135         if (dynamic_cast<typename T::n_one_t*>(lnode))
00136           return right;
00137         if (dynamic_cast<typename T::n_one_t*>(rnode))
00138           return left;
00139         if (dynamic_cast<typename T::n_zero_t*>(lnode))
00140           return left;
00141         if (dynamic_cast<typename T::n_zero_t*>(rnode))
00142           return right;
00143 
00144         typedef typename exp_list_t::const_iterator const_iterator;
00145         std::list<exp_t>        result(left);
00146 
00147         // If the last exp from left and the first exp from right
00148         // are words, concatenate them.
00149         typename T::n_const_t* left_node =
00150           dynamic_cast<typename T::n_const_t*>(lnode);
00151         typename T::n_const_t* right_node =
00152           dynamic_cast<typename T::n_const_t*>(rnode);
00153         if (left_node and right_node)
00154         {
00155           result.back() = exp_t(exp_.structure(),
00156                                 left_node->value_ + right_node->value_);
00157           for (const_iterator i = ++right.begin(); i != right.end(); ++i)
00158             result.push_back(*i);
00159         }
00160         else
00161           for (const_iterator i = right.begin(); i != right.end(); ++i)
00162             result.push_back(*i);
00163         return result;
00164       }
00165 
00166       // Public functions.
00167     public:
00168       // This function convert the result the original form.
00169       exp_t get()
00170       {
00171         return_type l = this->match(exp_.value());
00172         return convert(l);
00173       }
00174 
00175       // Match functions.
00176       MATCH__(Product, lhs, rhs)
00177       {
00178         typedef typename return_type::iterator          iterator;
00179 
00180         return_type llist = this->match(lhs);
00181         return_type rlist = this->match(rhs);
00182         return_type result;
00183 
00184         for (iterator i = llist.begin(); i != llist.end(); ++i)
00185           for (iterator j = rlist.begin(); j != rlist.end(); ++j)
00186             {
00187               exp_list_t p = list_concat(i->first, j->first);
00188 
00189               iterator pi = result.find(p);
00190               if (pi != result.end())
00191                 pi->second += i->second * j->second;
00192               else
00193                 result[p] = i->second * j->second;
00194             }
00195         return result;
00196       }
00197       END
00198 
00199       MATCH__(Sum, lhs, rhs)
00200       {
00201         return list_union(this->match(lhs), this->match(rhs));
00202       }
00203       END
00204 
00205       MATCH_(Star, e)
00206       {
00207         return_type l = this->match(e);
00208         return convert(convert(l).star());
00209       }
00210       END
00211 
00212       MATCH__(LeftWeight, w, e)
00213       {
00214         typedef typename return_type::iterator          iterator;
00215 
00216         return_type     l = this->match(e);
00217         return_type     result;
00218 
00219         for (iterator i = l.begin(); i != l.end(); ++i)
00220           result[i->first] = semiring_elt_t(w) * i->second;
00221         return result;
00222       }
00223       END
00224 
00225       MATCH__(RightWeight, e, w)
00226       {
00227         typedef typename return_type::iterator          iterator;
00228 
00229         return_type     l = this->match(e);
00230         return_type     result;
00231 
00232         for (iterator i = l.begin(); i != l.end(); ++i)
00233           result[i->first] = i->second * semiring_elt_t(w);
00234         return result;
00235       }
00236       END
00237 
00238       MATCH_(Constant, m)
00239       {
00240         return convert(exp_t(exp_.structure(), m));
00241       }
00242       END
00243 
00244       MATCH(Zero)
00245       {
00246         return convert(exp_.structure().zero(SELECT(T)));
00247       }
00248       END
00249 
00250       MATCH(One)
00251       {
00252         return convert(exp_.structure().identity(SELECT(T)));
00253       }
00254       END
00255 
00256     private:
00257         Element<Series, T>      exp_;
00258     };
00259 
00260   } // ! algebra
00261 
00262   template <class S, class E>
00263   E do_expand(const algebra::SeriesBase<S>&, const E& exp)
00264   {
00265     typedef typename E::value_t T;
00266 
00267     algebra::KRatExpExpander< S, T, algebra::DispatchFunction<T> >      matcher(exp);
00268     return matcher.get();
00269   }
00270 
00271   template <class Series, class T>
00272   Element<Series, T>
00273   expand(const Element<Series, T>& exp)
00274   {
00275     return do_expand(exp.structure(), exp);
00276   }
00277 
00278 } // ! vcsn
00279 
00280 #endif // ! VCSN_ALGORITHMS_KRAT_EXP_EXPAND_HXX