- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

# 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