Vaucanson 1.4
krat.hxx
00001 // krat.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, 2008, 2010, 2011 The
00006 // Vaucanson Group.
00007 //
00008 // This program is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU General Public License
00010 // as published by the Free Software Foundation; either version 2
00011 // of the License, or (at your option) any later version.
00012 //
00013 // The complete GNU General Public Licence Notice can be found as the
00014 // `COPYING' file in the root directory.
00015 //
00016 // The Vaucanson Group consists of people listed in the `AUTHORS' file.
00017 //
00018 #ifndef VCSN_ALGEBRA_IMPLEMENTATION_SERIES_KRAT_HXX
00019 # define VCSN_ALGEBRA_IMPLEMENTATION_SERIES_KRAT_HXX
00020 
00021 # include <utility>
00022 # include <list>
00023 
00024 # include <vaucanson/algebra/implementation/series/series.hh>
00025 # include <vaucanson/algebra/implementation/series/rat/exp.hh>
00026 # include <vaucanson/algebra/implementation/series/rat/random_visitor.hh>
00027 # include <vaucanson/misc/usual_macros.hh>
00028 
00029 # include <vaucanson/algebra/implementation/series/krat_exp_is_finite_app.hxx>
00030 # include <vaucanson/algebra/implementation/series/krat_exp_support.hxx>
00031 # include <vaucanson/algebra/implementation/series/krat_exp_transpose.hxx>
00032 
00033 # include <vaucanson/algorithms/eval.hh>
00034 # include <vaucanson/algorithms/standard_of.hh>
00035 
00036 # include <vaucanson/algebra/implementation/series/polynoms.hh>
00037 # include <vaucanson/automata/concept/automata.hh>
00038 
00039 # include <vaucanson/misc/contract.hh>
00040 
00041 namespace vcsn
00042 {
00043   namespace algebra
00044   {
00059     template<typename W, typename M, typename Tm, typename Tw>
00060     bool op_contains(const algebra::Series<W, M>&, const rat::exp<Tm, Tw>&)
00061     {
00062       pure_service_call ("default version of op_contains(Series<W,M>, exp<Tm,Tw>)");
00063       return true;
00064     }
00065 
00066     template<typename W, typename M, typename Tm, typename Tw>
00067     bool op_is_finite_app(const algebra::Series<W, M>&,
00068                           const rat::exp<Tm, Tw>& m)
00069     {
00070       vcsn::IsFiniteAppMatcher<
00071         algebra::Series<W, M>,
00072         vcsn::rat::exp<Tm, Tw>,
00073         algebra::DispatchFunction<vcsn::rat::exp<Tm, Tw> >
00074         > matcher;
00075       return matcher.match(m);
00076     }
00077 
00078     template<typename W, typename M, typename Tm, typename Tw>
00079     typename algebra::series_traits<rat::exp<Tm, Tw> >::support_t
00080     op_support(const algebra::Series<W, M>& s, const rat::exp<Tm, Tw>& m)
00081     {
00082       vcsn::SupportMatcher<
00083         algebra::Series<W, M>, rat::exp<Tm, Tw>,
00084         algebra::DispatchFunction<rat::exp<Tm, Tw> >
00085         > matcher(s);
00086       matcher.match(m);
00087       return matcher.get();
00088     }
00089 
00090     template <typename W, typename M, typename Tm, typename Tw>
00091     Tm op_choose_from_supp(const algebra::Series<W, M>&,
00092                            const rat::exp<Tm, Tw>& m)
00093     {
00094       rat::RandomVisitor<Tm, Tw> v;
00095       m.accept(v);
00096       return v.get();
00097     }
00098 
00099     template<typename W, typename M, typename Tm, typename Tw>
00100     const rat::exp<Tm, Tw>& identity_value(SELECTOR2(algebra::Series<W, M>),
00101                                            SELECTOR2(rat::exp<Tm, Tw>))
00102     {
00103       static const rat::exp<Tm, Tw> instance = rat::exp<Tm, Tw>::one();
00104       return instance;
00105     }
00106 
00107     template<typename W, typename M, typename Tm, typename Tw>
00108     bool show_identity_value(SELECTOR2(algebra::Series<W, M>),
00109                              SELECTOR2(rat::exp<Tm, Tw>))
00110     {
00111       return true;
00112     }
00113 
00114     template<typename W, typename M, typename Tm, typename Tw>
00115     const rat::exp<Tm, Tw>& zero_value(SELECTOR2(algebra::Series<W, M>),
00116                                        SELECTOR2(rat::exp<Tm, Tw>))
00117     {
00118       static const rat::exp<Tm, Tw> instance = rat::exp<Tm, Tw>::zero();
00119       return instance;
00120     }
00121 
00122     template <typename W, typename M, typename Tm, typename Tw>
00123     void op_in_transpose(const algebra::Series<W, M>& s,
00124                          rat::exp<Tm, Tw>& exp)
00125     {
00126       Element<algebra::Series<W, M>,
00127       rat::exp<Tm, Tw> > elt(s, exp);
00128 
00129       vcsn::algebra::KRatExpTranspose<
00130         algebra::Series<W, M>,
00131         rat::exp<Tm, Tw>,
00132         algebra::DispatchFunction<vcsn::rat::exp<Tm, Tw> >
00133         > matcher(elt);
00134 
00135       elt = matcher.match(exp);
00136       exp = elt.value();
00137     }
00138 
00139     template<typename W, typename M, typename Tm, typename Tw>
00140     void op_in_add(const algebra::Series<W, M>&,
00141                    rat::exp<Tm, Tw>& dst,
00142                    const rat::exp<Tm, Tw>& arg)
00143     {
00144       // case E + 0
00145       if (arg.base()->what() == rat::Node<Tm, Tw>::zero)
00146         return ;
00147 
00148       // case 0 + E
00149       if (dst.base()->what() == rat::Node<Tm, Tw>::zero)
00150       {
00151         delete dst.base();
00152         dst.base() = arg.base()->clone();
00153         return;
00154       }
00155 
00156       dst.base() = new rat::Sum<Tm, Tw>(dst.base(), arg.base()->clone());
00157     }
00158 
00159     template<typename W, typename M, typename Tm, typename Tw>
00160     rat::exp<Tm, Tw> op_add(const algebra::Series<W, M>& s,
00161                             const rat::exp<Tm, Tw>& a,
00162                             const rat::exp<Tm, Tw>& b)
00163     {
00164       rat::exp<Tm, Tw> ret(a);
00165       op_in_add(s, ret, b);
00166       return ret;
00167     }
00168 
00169     template<typename W, typename M, typename Tm, typename Tw>
00170     void op_in_mul(const algebra::Series<W, M>& s,
00171                    rat::exp<Tm, Tw>& dst,
00172                    const rat::exp<Tm, Tw>& arg)
00173     {
00174       typedef rat::Node<Tm, Tw>                 node_t;
00175       typedef typename  rat::Node<Tm, Tw>::type type;
00176       typedef rat::One<Tm, Tw>                  n_one_t;
00177       typedef rat::Constant<Tm, Tw>             n_const_t;
00178       typedef rat::Zero<Tm, Tw>                 n_zero_t;
00179       typedef rat::Star<Tm, Tw>                 n_star_t;
00180       typedef rat::LeftWeighted<Tm, Tw>         n_lweight_t;
00181       typedef rat::RightWeighted<Tm, Tw>        n_rweight_t;
00182       typedef rat::Sum<Tm, Tw>                  n_sum_t;
00183       typedef rat::Product<Tm, Tw>              n_prod_t;
00184 
00185       type this_type = dst.base()->what();
00186       type arg_type  = arg.base()->what();
00187 
00188       // case 0 . E -> 0
00189       if (this_type == node_t::zero)
00190         return;
00191 
00192       // case E . 0 -> 0
00193       if (arg_type == node_t::zero)
00194       {
00195         delete dst.base();
00196         dst.base() = new n_zero_t;
00197         return;
00198       }
00199 
00200       // case 1 . E -> E
00201       if (this_type == node_t::one)
00202       {
00203         delete dst.base();
00204         dst.base() = arg.base()->clone();
00205         return;
00206       }
00207 
00208       // case E . 1 -> E
00209       if (arg_type == node_t::one)
00210       {
00211         return;
00212       }
00213 
00214       // case E . {k'} 1 -> E {k'}
00215       if (arg_type == node_t::lweight)
00216       {
00217         n_lweight_t *p = dynamic_cast<n_lweight_t*>(arg.base());
00218         if (p->child_->what() == node_t::one)
00219         {
00220           op_in_mul(s, s.semiring(), dst, p->weight_);
00221           return;
00222         }
00223       }
00224 
00225       // case {k} 1 . E -> {k} E
00226       if (this_type == node_t::lweight)
00227       {
00228         n_lweight_t *p = dynamic_cast<n_lweight_t*>(dst.base());
00229         if (p->child_->what() == node_t::one)
00230         {
00231           dst = op_mul(s.semiring(), s, p->weight_, arg);
00232           return;
00233         }
00234       }
00235 
00236       // general case : {k} E . E'
00237       dst.base() = new n_prod_t(dst.base(), arg.base()->clone());
00238       return;
00239     }
00240 
00241     template<typename W, typename M, typename Tm, typename Tw>
00242     rat::exp<Tm, Tw> op_mul(const algebra::Series<W, M>& s,
00243                             const rat::exp<Tm, Tw>& a,
00244                             const rat::exp<Tm, Tw>& b)
00245     {
00246       rat::exp<Tm, Tw> ret(a);
00247       op_in_mul(s, ret, b);
00248       return ret;
00249     }
00250 
00251     template <typename W, typename M, typename Tm, typename Tw, typename St>
00252     St&
00253     op_rout(const algebra::Series<W, M>& s,
00254             St& st,
00255             const rat::exp<Tm, Tw>& e)
00256     {
00257       rat::DumpVisitor<Tm, Tw, W, M> v (st, s.monoid(), s.representation());
00258       e.accept(v);
00259       return st;
00260     }
00261 
00262     /*---------------------.
00263     | foreign constructors |
00264     `---------------------*/
00265 
00266     template<typename Tm, typename Tw, typename M, typename W>
00267     rat::exp<Tm, Tw> op_convert(SELECTOR2(algebra::Series<M, W>),
00268                                 SELECTOR2(rat::exp<Tm, Tw>),
00269                                 const Tm& m_value)
00270     {
00271       return new rat::Constant<Tm, Tw>(m_value);
00272     }
00273 
00274     template<typename Tm, typename Tw, typename M, typename W>
00275     rat::exp<Tm, Tw> op_convert(SELECTOR2(algebra::Series<M, W>),
00276                                 SELECTOR2(rat::exp<Tm, Tw>),
00277                                 char m_value)
00278     {
00279       const char str[] = {m_value, '\0'};
00280       return new rat::Constant<Tm, Tw>(str);
00281     }
00282 
00283     template<typename Tm, typename Tw, typename W, typename M, typename oTm>
00284     rat::exp<Tm, Tw> op_convert(SELECTOR2(algebra::Series<W, M>) s,
00285                                 SELECTOR2(rat::exp<Tm, Tw>),
00286                                 SELECTOR(M),
00287                                 const oTm& m_value)
00288     {
00289       if (m_value == identity_value(SELECT(M), SELECT(oTm)))
00290         return rat::exp<Tm, Tw>::one();
00291 
00292       return rat::exp<Tm, Tw>::constant(op_convert(s.monoid(), SELECT(Tm),
00293                                                    m_value));
00294     }
00295 
00296     template<typename Tm, typename Tw, typename W, typename M, typename oTw>
00297     rat::exp<Tm, Tw> op_convert(SELECTOR2(algebra::Series<W, M>),
00298                                 SELECTOR2(rat::exp<Tm, Tw>),
00299                                 SELECTOR(W),
00300                                 const oTw& w_value)
00301     {
00302       if (w_value == identity_value(SELECT(W), SELECT(oTw)))
00303         return rat::exp<Tm, Tw>::one();
00304       if (w_value == zero_value(SELECT(W), SELECT(oTw)))
00305         return rat::exp<Tm, Tw>::zero();
00306       rat::exp<Tm, Tw> ret = rat::exp<Tm, Tw>::one();
00307       ret.base() = new rat::LeftWeighted<Tm, Tw>
00308       (op_convert(SELECT(W), SELECT(Tw),
00309                   w_value), ret.base());
00310       return ret;
00311     }
00312 
00313     template <typename W, typename M, typename Tm, typename Tw, typename oTm>
00314     void op_assign(SELECTOR2(algebra::Series<W, M>) s,
00315                    SELECTOR(M),
00316                    rat::exp<Tm, Tw>& dst,
00317                    const oTm& src)
00318     {
00319       dst = op_convert(s,
00320                        SELECT2(rat::exp<Tm, Tw>),
00321                        SELECT(M), src);
00322     }
00323 
00324     template <typename W, typename M, typename Tm, typename Tw, typename oTw>
00325     void op_assign(SELECTOR2(algebra::Series<W, M>) s,
00326                    SELECTOR(W),
00327                    rat::exp<Tm, Tw>& dst,
00328                    const oTw& src)
00329     {
00330       dst = op_convert(s,
00331                        SELECT2(rat::exp<Tm, Tw>),
00332                        SELECT(W), src);
00333     }
00334 
00335     /*-----.
00336     | star |
00337     `-----*/
00338 
00339     template<typename W, typename M, typename Tm, typename Tw>
00340     bool op_starable(const algebra::Series<W, M>&,
00341                      const rat::exp<Tm, Tw>&)
00342     {
00343       return true;
00344     }
00345 
00346     template<typename W, typename M, typename Tm, typename Tw>
00347     void op_in_star(const algebra::Series<W, M>&,
00348                     rat::exp<Tm, Tw>& dst)
00349     {
00350       // rewrite 0* as 1
00351       if (dst.base()->what() == rat::Node<Tm, Tw>::zero)
00352         dst = rat::exp<Tm, Tw>::one();
00353       else
00354         dst.base() = new rat::Star<Tm, Tw>(dst.base());
00355     }
00356 
00357     template<typename W, typename M, typename Tm, typename Tw>
00358     rat::exp<Tm, Tw>
00359     op_star(const algebra::Series<W, M>& s,
00360             const rat::exp<Tm, Tw>& src)
00361     {
00362       rat::exp<Tm, Tw> ret(src);
00363       op_in_star(s, ret);
00364       return ret;
00365     }
00366 
00367     /*--------------------------------------.
00368     | foreign addition with monoid elements |
00369     `--------------------------------------*/
00370 
00371     template<typename W, typename M, typename Tm, typename Tw, typename oTm>
00372     void op_in_add(const algebra::Series<W, M>& s,
00373                    const M& monoid,
00374                    rat::exp<Tm, Tw>& dst,
00375                    const oTm& src)
00376     {
00377       op_in_add(s, dst, op_convert(s,
00378                                    SELECT2(rat::exp<Tm, Tw>),
00379                                    SELECT(M),
00380                                    src));
00381     }
00382 
00383     template<typename W, typename M, typename Tm, typename Tw, typename oTm>
00384     rat::exp<Tm, Tw> op_add(const algebra::Series<W, M>& s,
00385                             const M& monoid,
00386                             const rat::exp<Tm, Tw>& a,
00387                             const oTm& b)
00388     {
00389       rat::exp<Tm, Tw> ret(a);
00390       op_in_add(s, monoid, ret, b);
00391       return ret;
00392     }
00393 
00394     template<typename M, typename W, typename oTm, typename Tm, typename Tw>
00395     rat::exp<Tm, Tw> op_add(const M& monoid,
00396                             const algebra::Series<W, M>& s,
00397                             const oTm& a,
00398                             const rat::exp<Tm, Tw>& b)
00399     {
00400       rat::exp<Tm, Tw> ret(b);
00401       op_in_add(s, monoid, ret, a);
00402       return ret;
00403     }
00404 
00405     /*----------------------------------------.
00406     | foreign addition with semiring elements |
00407     `----------------------------------------*/
00408 
00409     template<typename W, typename M, typename Tm, typename Tw, typename oTw>
00410     void op_in_add(const algebra::Series<W, M>& s,
00411                    const W& semiring,
00412                    rat::exp<Tm, Tw>& dst,
00413                    const oTw& src)
00414     {
00415       precondition(& s.semiring() == & semiring);
00416       op_in_add(s, dst, op_convert(s,
00417                                    SELECT2(rat::exp<Tm, Tw>),
00418                                    SELECT(W),
00419                                    src));
00420     }
00421 
00422     template<typename W, typename M, typename Tm, typename Tw, typename oTw>
00423     rat::exp<Tm, Tw> op_add(const algebra::Series<W, M>& s,
00424                             const W& semiring,
00425                             const rat::exp<Tm, Tw>& a,
00426                             const oTw& b)
00427     {
00428       rat::exp<Tm, Tw> ret(a);
00429       op_in_add(s, semiring, ret, b);
00430       return ret;
00431     }
00432 
00433     template<typename W, typename M, typename oTw, typename Tm, typename Tw>
00434     rat::exp<Tm, Tw> op_add(const W& semiring,
00435                             const algebra::Series<W, M>& s,
00436                             const oTw& a,
00437                             const rat::exp<Tm, Tw>& b)
00438     {
00439       rat::exp<Tm, Tw> ret(b);
00440       op_in_add(s, semiring, ret, a);
00441       return ret;
00442     }
00443 
00444     /*--------------------------------------------.
00445     | foreign multiplication by semiring elements |
00446     `--------------------------------------------*/
00447 
00448     template<typename W, typename M, typename Tm, typename Tw, typename oTw>
00449     void op_in_mul(const algebra::Series<W, M>& s,
00450                    const W& semiring,
00451                    rat::exp<Tm, Tw>& ret,
00452                    const oTw& w)
00453     {
00454       precondition(& s.semiring() == & semiring);
00455       (void) s; (void) semiring;
00456 
00457       typedef rat::Node<Tm, Tw>                         node_t;
00458       typedef typename rat::Node<Tm, Tw>::type          type;
00459       typedef rat::One<Tm, Tw>                          n_one_t;
00460       typedef rat::Constant<Tm, Tw>                     n_const_t;
00461       typedef rat::Zero<Tm, Tw>                         n_zero_t;
00462       typedef rat::Star<Tm, Tw>                         n_star_t;
00463       typedef rat::LeftWeighted<Tm, Tw>                 n_lweight_t;
00464       typedef rat::RightWeighted<Tm, Tw>                n_rweight_t;
00465       typedef rat::Sum<Tm, Tw>                          n_sum_t;
00466       typedef rat::Product<Tm, Tw>                      n_prod_t;
00467 
00468       type this_type = ret.base()->what();
00469 
00470       // case 0 {k} -> 0
00471       if (this_type == node_t::zero)
00472         return;
00473 
00474       // case E {1} -> E
00475       if (w == identity_value(SELECT(W), SELECT(oTw)))
00476         return;
00477 
00478       // case E {0} -> 0
00479       if (w == zero_value(SELECT(W), SELECT(oTw)))
00480       {
00481         delete ret.base();
00482         ret.base() = new n_zero_t;
00483         return;
00484       }
00485 
00486       // case 1 {k} -> {k} 1
00487       if (this_type == node_t::one)
00488       {
00489         ret.base() = new n_lweight_t
00490         (op_convert(SELECT(W), SELECT(Tw), w), ret.base());
00491         return;
00492       }
00493 
00494       // case c {k} -> {k} c  (where c is an atom)
00495       if ((this_type == node_t::constant)
00496           && op_is_atom(s.monoid(),
00497                         dynamic_cast<n_const_t*>(ret.base())->value_))
00498         {
00499           ret.base() = new n_lweight_t
00500             (op_convert(SELECT(W), SELECT(Tw), w), ret.base());
00501           return;
00502         }
00503 
00504       // case (E {k'}) {k} -> E {k'k}
00505       if (this_type == node_t::rweight)
00506       {
00507         op_in_mul(s.semiring(),
00508                   dynamic_cast<n_rweight_t* >(ret.base())->weight_,
00509                   op_convert(SELECT(W), SELECT(Tw), w));
00510         return;
00511       }
00512 
00513       // [1] case ({k'} c) {k} -> {k'k} c  if c is an atom or a constant
00514       // (Note: case [2] is like if you had applied case [1]
00515       // followed by the c {k} -> {k} c, and then the
00516       // {k'} (E  {k}) -> {k'k} E rewritings.)
00517       // [2] case ({k'} E) {k} -> {k'} (E {k})
00518       // subcase: ({k'} (E {k''}) {k} -> {k'} (E {k''k})
00519       if (this_type == node_t::lweight)
00520       {
00521         // [1]
00522         n_lweight_t* p = dynamic_cast<n_lweight_t*>(ret.base());
00523         if ((p->child_->what() == node_t::constant
00524              && op_is_atom(s.monoid(),
00525                            dynamic_cast<n_const_t*>(p->child_)->value_))
00526             || p->child_->what() == node_t::one)
00527           {
00528             p->weight_ = op_mul (s.semiring(), p->weight_,
00529                                  op_convert(SELECT(W), SELECT(Tw), w));
00530           }
00531         else // [2]
00532           {
00533             // subcase
00534             if (p->child_->what() == node_t::rweight)
00535               {
00536                 n_rweight_t* q = dynamic_cast<n_rweight_t*>(p->child_);
00537                 assert(q);
00538                 q->weight_ = op_mul (s.semiring(),
00539                                      q->weight_,
00540                                      op_convert(SELECT(W), SELECT(Tw), w));
00541               }
00542             else // general case
00543               {
00544                 p->child_ =
00545                   new n_rweight_t(op_convert(SELECT(W), SELECT(Tw), w),
00546                                   p->child_);
00547               }
00548           }
00549         return;
00550       }
00551 
00552       // case ({k'} E) {k} -> general case
00553       ret.base() =
00554       new n_rweight_t(op_convert(SELECT(W), SELECT(Tw), w), ret.base());
00555       return;
00556     }
00557 
00558     template<typename W, typename M, typename Tm, typename Tw, typename oTw>
00559     rat::exp<Tm, Tw> op_mul(const algebra::Series<W, M>& s,
00560                             const W& semiring,
00561                             const rat::exp<Tm, Tw>& a,
00562                             const oTw& w)
00563     {
00564       rat::exp<Tm, Tw> ret(a);
00565       op_in_mul(s, semiring, ret, w);
00566       return ret;
00567     }
00568 
00569     template<typename W, typename M, typename oTw, typename Tm, typename Tw>
00570     rat::exp<Tm, Tw> op_mul(const W& semiring,
00571                             const algebra::Series<W, M>& s,
00572                             const oTw& w,
00573                             const rat::exp<Tm, Tw>& b)
00574     {
00575       precondition(& s.semiring() == & semiring);
00576       (void) s; (void) semiring;
00577 
00578       typedef rat::Node<Tm, Tw>                         node_t;
00579       typedef typename rat::Node<Tm, Tw>::type          type;
00580       typedef rat::One<Tm, Tw>                          n_one_t;
00581       typedef rat::Constant<Tm, Tw>                     n_const_t;
00582       typedef rat::Zero<Tm, Tw>                         n_zero_t;
00583       typedef rat::Star<Tm, Tw>                         n_star_t;
00584       typedef rat::LeftWeighted<Tm, Tw>                 n_lweight_t;
00585       typedef rat::RightWeighted<Tm, Tw>                n_rweight_t;
00586       typedef rat::Sum<Tm, Tw>                          n_sum_t;
00587       typedef rat::Product<Tm, Tw>                      n_prod_t;
00588 
00589       rat::exp<Tm, Tw> ret(b);
00590 
00591       type this_type = ret.base()->what();
00592 
00593       // case {k} 0 -> 0
00594       if (this_type == node_t::zero)
00595         return ret;
00596 
00597       // case {k} 1 -> general case
00598 
00599       // case {0} E -> 0
00600       if (w == zero_value(SELECT(W), SELECT(oTw)))
00601       { return rat::exp<Tm, Tw>::zero(); }
00602 
00603       // case {1} E -> E
00604       if (w == identity_value(SELECT(W), SELECT(oTw)))
00605         return ret;
00606 
00607       // case {k} ({k'} E) -> {k k'} E
00608       if (this_type == node_t::lweight)
00609       {
00610         n_lweight_t* p = dynamic_cast<n_lweight_t*>(ret.base());
00611         p->weight_ = op_mul
00612           (s.semiring(), op_convert(SELECT(W), SELECT(Tw), w), p->weight_);
00613         return ret;
00614       }
00615 
00616       // general case {k} E
00617       ret.base() = new n_lweight_t(w, ret.base());
00618       return ret;
00619     }
00620 
00621     template<typename W, typename M, typename Tm, typename Tw, typename oTm>
00622     Tw op_series_get(const algebra::Series<W, M>& s,
00623                      const rat::exp<Tm, Tw>& p,
00624                      const oTm& m)
00625     {
00626       typedef typename standard_of_traits<algebra::Series<W, M>,
00627                                           rat::exp<Tm, Tw> >::
00628                                           automaton_t automaton_t;
00629 
00630       typename automaton_t::set_t       automata (s);
00631       automaton_t                       a (automata);
00632       standard_of(a, p);
00633       return eval(a, m).value();
00634     }
00635 
00636     template<typename W, typename M, typename Tm, typename Tw,
00637     typename oTm, typename oTw>
00638     void op_series_set(const algebra::Series<W, M>& s,
00639                        rat::exp<Tm, Tw>& p,
00640                        const oTm& m,
00641                        const oTw& w)
00642     {
00643       if ((m == algebra::identity_as<oTm>::of(s.monoid())) &&
00644           (w == algebra::identity_as<oTw>::of(s.semiring())) &&
00645           (p == algebra::zero_as<rat::exp<Tm, Tw> >::of(s)))
00646       {
00647         p = algebra::identity_as<rat::exp<Tm, Tw> >::of(s).value();
00648         return ;
00649       }
00650 
00651       typedef Element<algebra::Series<W, M>, rat::exp<Tm, Tw> > series_set_elt_t;
00652       typedef typename series_set_elt_t::monoid_elt_t           monoid_elt_t;
00653       typedef typename monoid_elt_t::value_t                    monoid_elt_value_t;
00654       typedef std::list<monoid_elt_value_t>                     support_t;
00655 
00656       rat::exp<Tm, Tw> pp = p;
00657       p = algebra::zero_as<rat::exp<Tm, Tw> >::of(s).value();
00658 
00659       // FIXME Should not rebuild the serie from stratch
00660       // Should use some kind of visitor and update the tree
00661       support_t supp = op_support(s, pp);
00662       oTw sw;
00663       bool exist = false;
00664       for_all_const_(support_t, e, supp)
00665       {
00666         rat::exp<Tm, Tw> ret = op_convert(s,
00667                                           SELECT2(rat::exp<Tm, Tw>),
00668                                           SELECT(M), *e);
00669         if (*e == m)
00670         {
00671           exist = true;
00672           sw = w;
00673         }
00674         else
00675           sw = op_series_get(s, pp, *e);
00676 
00677         op_in_add(s, p, op_mul(s.semiring(), s, sw, ret));
00678       }
00679       if (!exist)
00680         op_in_add(s, p, op_mul(s.semiring(), s, w,
00681                                op_convert(s,
00682                                           SELECT2(rat::exp<Tm, Tw>),
00683                                           SELECT(M), m)));
00684     }
00685 
00686   } // ! algebra
00687 
00688   /*----------------------------------------------------------------------------.
00689   | MetaElement<algebra::SeriesBase<algebra::Series<W, M> >, rat::exp<Tm, Tw> > |
00690   `----------------------------------------------------------------------------*/
00691 
00692   template <typename W, typename M, typename Tm, typename Tw>
00693   void
00694   MetaElement<algebra::Series<W, M>, rat::exp<Tm, Tw> >::accept
00695   (const rat::ConstNodeVisitor<Tm, Tw>& v) const
00696   {
00697     this->value().accept(v);
00698   }
00699 
00700   template <typename W, typename M, typename Tm, typename Tw>
00701   size_t
00702   MetaElement<algebra::Series<W, M>, rat::exp<Tm, Tw> >::depth() const
00703   {
00704     return this->value().depth();
00705   }
00706 
00707   namespace algebra
00708   {
00709     template <class W, class M, class Tm, class Tw>
00710     Element<algebra::Series<W,M>, rat::exp<Tm,Tw> >
00711     op_choose(const algebra::Series<W,M>& s,
00712               SELECTOR2(rat::exp<Tm,Tw>))
00713     {
00714       Element<algebra::Series<W,M>, rat::exp<Tm, Tw> > e(s);
00715       // FIXME : add global constants to do this !
00716       unsigned nb = RAND___(10);
00717       while (nb != 0)
00718       {
00719         --nb;
00720         unsigned t = RAND___(3);
00721         switch (t)
00722         {
00723           // star
00724           case 0 :
00725             {
00726               e = e.star();
00727               continue;
00728             }
00729             // plus
00730           case 1 :
00731             {
00732               Element<algebra::Series<W,M>, rat::exp<Tm,Tw> >
00733                       ep(s, s.monoid().choose(SELECT(Tm)));
00734               ep = ep * s.semiring().choose(SELECT(Tw));
00735               unsigned t = RAND___(2);
00736               if (t < 1)
00737                 e = e + ep;
00738               else
00739                 e = ep + e;
00740               continue;
00741             }
00742             // mult
00743           case 2 :
00744             {
00745               Element<algebra::Series<W,M>, rat::exp<Tm,Tw> >
00746                       ep(s, s.monoid().choose(SELECT(Tm)));
00747               ep = ep * s.semiring().choose(SELECT(Tw));
00748               unsigned t = RAND___(2);
00749               if (t < 1)
00750                 e = e * ep;
00751               else
00752                 e = ep * e;
00753               continue;
00754             }
00755         }
00756       }
00757       return Element<algebra::Series<W,M>, rat::exp<Tm,Tw> >(s, e);
00758     }
00759 
00760   } // ! algebra
00761 
00762 } // ! vcsn
00763 
00764 #endif // ! VCSN_ALGEBRA_IMPLEMENTATION_SERIES_KRAT_HXX