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

- File List
- File Members

# standard.hxx

    00001 // standard.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,
    00006 // 2010, 2011 The 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_ALGORITHMS_STANDARD_HXX
    00019 # define VCSN_ALGORITHMS_STANDARD_HXX
    00020
    00021 # include <vaucanson/algorithms/standard.hh>
    00022 # include <vaucanson/algorithms/one_eps_closure.hh>
    00023 # include <vaucanson/algorithms/internal/has_neighbour.hh>
    00024 # include <vaucanson/algorithms/internal/build_pattern.hh>
    00025
    00026 # include <vaucanson/algorithms/accessible.hh>
    00027 # include <vaucanson/automata/concept/automata_base.hh>
    00028 # include <vaucanson/automata/concept/automata.hh>
    00029 # include <vaucanson/misc/usual_macros.hh>
    00030
    00031 # include <set>
    00032
    00033 namespace vcsn {
    00034
    00035   /*------------.
    00036   | basic_sptr  |
    00037   `------------*/
    00038
    00039   template<typename HSTATE, typename WEIGHT>
    00040   struct basic_sptr
    00041   {
    00042   private:
    00043     const HSTATE& src_;
    00044     const HSTATE& dst_;
    00045     const WEIGHT& weight_;
    00046
    00047   public:
    00048     basic_sptr(const HSTATE& src, const HSTATE& dst, const WEIGHT& weight) :
    00049       src_(src), dst_(dst), weight_(weight) {}
    00050
    00051     HSTATE src() const {
    00052       return src_;
    00053     }
    00054
    00055     HSTATE dst() const {
    00056       return dst_;
    00057     }
    00058
    00059     WEIGHT weight() const {
    00060       return weight_;
    00061     }
    00062   };
    00063
    00064
    00065   /*--------.
    00066   |  union  |
    00067   `--------*/
    00068
    00069   template <typename A, typename AI1, typename AI2>
    00070   void
    00071   do_union_here(const AutomataBase<A>&,
    00072                 Element<A, AI1>& lhs,
    00073                 const Element<A, AI2>& rhs)
    00074   {
    00075     typedef Element<A, AI1> lhs_t;
    00076     AUTOMATON_TYPES(lhs_t);
    00077     typedef Element<A, AI2> rhs_t;
    00078     typedef typename rhs_t::hstate_t r_hstate_t;
    00079
    00080     std::map<r_hstate_t, hstate_t> states_map;
    00081
    00082     //  union of states
    00083     for_all_states(it, rhs)
    00084       {
    00085         hstate_t    new_state = lhs.add_state();
    00086         states_map[*it] = new_state;
    00087
    00088         lhs.set_initial(new_state, rhs.get_initial(*it));
    00089         lhs.set_final(new_state, rhs.get_final(*it));
    00090       }
    00091
    00092       //  union of transitions.
    00093     for_all_transitions(it, rhs)
    00094       {
    00095         lhs.add_transition(states_map[rhs.src_of(*it)],
    00096                            states_map[rhs.dst_of(*it)],
    00097                            rhs.label_of(*it));
    00098       }
    00099   }
    00100
    00101   //  wrappers for union
    00102   template<typename A, typename AI1, typename AI2>
    00103   void
    00104   union_here(Element<A, AI1>& lhs, const Element<A, AI2>& rhs)
    00105   {
    00106     do_union_here(lhs.structure(), lhs, rhs);
    00107   }
    00108
    00109
    00110   template<typename A, typename AI1, typename AI2>
    00111   Element<A, AI1>
    00112   union_(const Element<A, AI1>& lhs, const Element<A, AI2>& rhs)
    00113   {
    00114     Element<A, AI1> ret(lhs);
    00115     do_union_here(ret.structure(), ret, rhs);
    00116     return ret;
    00117   }
    00118
    00119   //   same as union, but keeps track of two states in the union
    00120   //   (will be used for initial states)
    00121   template <typename A, typename AI1, typename AI2>
    00122   void
    00123   marked_union_here(const AutomataBase<A>&,
    00124                     Element<A, AI1>& lhs,
    00125                     const Element<A, AI2>& rhs,
    00126                     const typename Element<A, AI1>::hstate_t& lhs_stt,
    00127                     typename Element<A, AI1>::hstate_t& mrk_stt,
    00128                     const typename Element<A, AI2>::hstate_t& rhs_stt)
    00129   {
    00130     typedef Element<A, AI1> lhs_t;
    00131     AUTOMATON_TYPES(lhs_t);
    00132     typedef Element<A, AI2> rhs_t;
    00133     typedef typename rhs_t::hstate_t   r_hstate_t;
    00134     std::map<r_hstate_t, hstate_t>     states_map;
    00135
    00136     //   copy of rhs states into lhs
    00137     for_all_states(it, rhs)
    00138       {
    00139         hstate_t    new_state = lhs.add_state();
    00140         states_map[*it] = new_state;
    00141
    00142         lhs.set_initial(new_state, rhs.get_initial(*it));
    00143         lhs.set_final(new_state, rhs.get_final(*it));
    00144       }
    00145     mrk_stt = states_map[rhs_stt];  //  mark copy of rhs_stt
    00146
    00147     // copy of rhs transitions into lhs
    00148     for_all_transitions(it, rhs)
    00149       {
    00150         lhs.add_transition(states_map[rhs.src_of(*it)],
    00151                            states_map[rhs.dst_of(*it)],
    00152                            rhs.label_of(*it));
    00153       }
    00154   }
    00155
    00156   /*--------------.
    00157   | is_standard.  |
    00158   `--------------*/
    00159   template<typename A, typename AI>
    00160   bool
    00161   do_is_standard(const AutomataBase<A>&, const Element<A, AI>& a)
    00162   {
    00163     BENCH_TASK_SCOPED("is_standard");
    00164     typedef Element<A, AI> automaton_t;
    00165     typedef typename automaton_t::series_set_elt_value_t series_set_elt_value_t;
    00166
    00167     // Check there is only one initial state.
    00168     if (a.initial().size() != 1)
    00169       return false;
    00170
    00171     // Check the multiplicity of the initial state.
    00172     typename automaton_t::hstate_t s = *a.initial().begin();
    00173     if (a.get_initial(s)
    00174         != a.series().identity(SELECT(series_set_elt_value_t)))
    00175       return false;
    00176
    00177     // Check that there is no input transition on the initial state.
    00178     return !has_predecessors(a, s);
    00179   }
    00180
    00181   template<typename A, typename AI>
    00182   bool
    00183   is_standard(const Element<A, AI>& a)
    00184   {
    00185     return do_is_standard(a.structure(), a);
    00186   }
    00187
    00188   /*------------.
    00189   | standardize |
    00190   `------------*/
    00191
    00192   template<typename S, typename AI>
    00193   void
    00194   do_standardize(const AutomataBase<S>&, Element<S, AI>& a)
    00195   {
    00196     BENCH_TASK_SCOPED("standardize");
    00197     typedef Element<S, AI> automaton_t;
    00198     AUTOMATON_TYPES(automaton_t);
    00199     typedef basic_sptr<hstate_t, series_set_elt_t> sptr_t;
    00200     typedef typename std::list<hstate_t> stt_lst_t;
    00201
    00202     stt_lst_t  stt_list;
    00203     series_set_elt_t fin_wgt =
    00204       algebra::zero_as<series_set_elt_value_t>::of(a.series());
    00205
    00206     if (is_standard(a)) return;
    00207
    00208     hstate_t i = a.add_state();  // add a new state that will be the
    00209                                  // initial state
    00210     //  put all initial states of a in a list
    00211     for_all_initial_states(it, a)   stt_list.push_back(*it);
    00212
    00213     for_all(typename stt_lst_t, it, stt_list)
    00214       {
    00215         hstate_t ini_stt = *it;
    00216         series_set_elt_t ini_wgt = a.get_initial(ini_stt);
    00217
    00218         //  emulates closure with respect of a spt transition between i and ini_stt
    00219         sptr_t t(i, ini_stt, ini_wgt);
    00220         one_eps_closure(a, t, misc::backward);
    00221         //  computes the final weight of the new initial state
    00222         a.unset_initial(ini_stt);
    00223         //  delete state if there is zero incoming transitions
    00224         if (!has_predecessors(a, ini_stt))
    00225           a.del_state(ini_stt);
    00226       }
    00227
    00228     a.set_initial(i);
    00229
    00230     return;
    00231   }
    00232
    00233   // standardize is always 'here'
    00234   template<typename A, typename AI>
    00235   void
    00236   standardize(Element<A, AI>& a)
    00237   {
    00238     do_standardize(a.structure(), a);
    00239   }
    00240
    00241   /*-----------------.
    00242   | sum_of_standard  |
    00243   `-----------------*/
    00244
    00245   template <typename A, typename AI>
    00246   void
    00247   sum_of_standard_inside(const AutomataBase<A>&,   Element<A, AI>& aut,
    00248                          const typename Element<A, AI>::hstate_t& aut_stt,
    00249                                typename Element<A, AI>::hstate_t& mrk_stt)
    00250   {
    00251     typedef Element<A, AI> automaton_t;    AUTOMATON_TYPES(automaton_t);
    00252     typedef series_set_elt_t                    weight_t;
    00253     typedef basic_sptr<hstate_t, weight_t>   sptr_t;
    00254
    00255     weight_t unit = aut.series().identity(SELECT(series_set_elt_value_t));
    00256
    00257     sptr_t t(aut_stt, mrk_stt, unit);
    00258     one_eps_closure(aut, t, misc::backward);
    00259     aut.del_state(mrk_stt);
    00260   }
    00261
    00262
    00263   template <typename A, typename AI1, typename AI2>
    00264   void
    00265   do_sum_of_standard_here(const AutomataBase<A>&,
    00266                                 Element<A, AI1>& lhs,
    00267                           const Element<A, AI2>& rhs)
    00268   {
    00269     BENCH_TASK_SCOPED("sum_of_standard");
    00270
    00271     typedef Element<A, AI1> lhs_t;
    00272     AUTOMATON_TYPES(lhs_t);
    00273     typedef Element<A, AI2> rhs_t;
    00274     typedef typename rhs_t::hstate_t     r_hstate_t;
    00275
    00276     hstate_t mrk_stt;
    00277
    00278     // Mark the initial states
    00279     hstate_t    lhs_stt = *lhs.initial().begin();
    00280     r_hstate_t  rhs_stt = *rhs.initial().begin();
    00281
    00282     marked_union_here(lhs.structure(), lhs, rhs, lhs_stt, mrk_stt, rhs_stt);
    00283
    00284     sum_of_standard_inside(lhs.structure(), lhs, lhs_stt, mrk_stt);
    00285   }
    00286
    00287
    00288   template<typename A, typename AI1, typename AI2>
    00289   void
    00290   sum_of_standard_here(Element<A, AI1>& lhs, const Element<A, AI2>& rhs)
    00291   {
    00292     precondition(is_standard(lhs));
    00293     precondition(is_standard(rhs));
    00294     do_sum_of_standard_here(lhs.structure(), lhs, rhs);
    00295   }
    00296
    00297   template<typename A, typename AI1, typename AI2>
    00298   Element<A, AI1>
    00299   sum_of_standard(const Element<A, AI1>& lhs, const Element<A, AI2>& rhs)
    00300   {
    00301     precondition(is_standard(lhs));
    00302     precondition(is_standard(rhs));
    00303     Element<A, AI1> ret(lhs);
    00304     sum_of_standard_here(ret, rhs);
    00305     return ret;
    00306   }
    00307
    00308   /*---------------------.
    00309   | concat_of_standard.  |
    00310   `---------------------*/
    00311
    00312
    00313   template <typename A, typename AI>
    00314   void
    00315   concat_of_standard_inside(const AutomataBase<A>&,   Element<A, AI>& aut,
    00316                             typename std::list<typename Element<A, AI>::hstate_t>& stt_list,
    00317                             typename Element<A, AI>::hstate_t& mrk_stt)
    00318   {
    00319     typedef Element<A, AI> aut_t;
    00320     AUTOMATON_TYPES(aut_t);
    00321     typedef series_set_elt_t                    weight_t;
    00322     typedef typename std::list<hstate_t>        stt_lst_t;
    00323     typedef basic_sptr<hstate_t, weight_t>      sptr_t;
    00324
    00325     weight_t    mrk_wgt = aut.get_final(mrk_stt);
    00326
    00327     for_all(typename stt_lst_t, it, stt_list)
    00328       {
    00329         hstate_t   fin_stt = *it;
    00330         weight_t   fin_wgt = aut.get_final(fin_stt);
    00331         aut.unset_final(fin_stt);
    00332         sptr_t t(fin_stt, mrk_stt, fin_wgt);
    00333         one_eps_closure(aut, t, misc::backward);
    00334       }
    00335     aut.del_state(mrk_stt);
    00336   }
    00337
    00338
    00339   template <typename A, typename AI1, typename AI2>
    00340   void
    00341   do_concat_of_standard_here(const AutomataBase<A>&,
    00342                              Element<A, AI1>& lhs,
    00343                              const Element<A, AI2>& rhs)
    00344   {
    00345     BENCH_TASK_SCOPED("concat_of_standard");
    00346
    00347     typedef Element<A, AI1> lhs_t;
    00348     AUTOMATON_TYPES(lhs_t);
    00349     typedef std::list<hstate_t>              stt_lst_t;
    00350     typedef Element<A, AI2> rhs_t;
    00351     typedef typename rhs_t::hstate_t r_hstate_t;
    00352
    00353     // Remember list of final states in lhs
    00354     stt_lst_t    stt_list;
    00355     for_all_final_states(it, lhs)  stt_list.push_back(*it);
    00356
    00357     // Mark the initial states and perform marked union of states
    00358     hstate_t    mrk_stt;
    00359     hstate_t    lhs_stt = *lhs.initial().begin();
    00360     r_hstate_t  rhs_stt = *rhs.initial().begin();
    00361     marked_union_here(lhs.structure(), lhs, rhs, lhs_stt, mrk_stt, rhs_stt);
    00362
    00363     concat_of_standard_inside(lhs.structure(), lhs, stt_list, mrk_stt);
    00364   }
    00365
    00366
    00367   template<typename A, typename AI1, typename AI2>
    00368   void
    00369   concat_of_standard_here(Element<A, AI1>& lhs, const Element<A, AI2>& rhs)
    00370   {
    00371     precondition(is_standard(lhs));
    00372     precondition(is_standard(rhs));
    00373     do_concat_of_standard_here(lhs.structure(), lhs, rhs);
    00374   }
    00375
    00376   template<typename A, typename AI1, typename AI2>
    00377   Element<A, AI1>
    00378   concat_of_standard(const Element<A, AI1>& lhs,
    00379                      const Element<A, AI2>& rhs)
    00380   {
    00381     precondition(is_standard(lhs));
    00382     precondition(is_standard(rhs));
    00383     Element<A, AI1> ret(lhs);
    00384     do_concat_of_standard_here(ret.structure(), ret, rhs);
    00385     return ret;
    00386   }
    00387
    00388
    00389    /*----------------------------------.
    00390    | left_ext_mult_of_standard_inside  |
    00391    `----------------------------------*/
    00392
    00393   template <typename A, typename AI>
    00394   void
    00395   left_ext_mult_of_standard_inside(const AutomataBase<A>&,
    00396                                    Element<A, AI>& aut,
    00397                                    const typename Element<A, AI>::hstate_t& ini_stt,
    00398                                    const typename Element<A, AI>::series_set_elt_t& k)
    00399   {
    00400     typedef Element<A, AI> automaton_t;  AUTOMATON_TYPES(automaton_t);
    00401     typedef series_set_elt_t                      weight_t;
    00402     typedef typename std::list<htransition_t>   trn_lst_t;
    00403
    00404     weight_t     zero(aut.series().zero_);
    00405     trn_lst_t    ini_out_list;
    00406
    00407     // Build the list of outgoing transitions from ini_stt
    00408     for (delta_iterator it(aut.value(), ini_stt); !it.done(); it.next())
    00409       ini_out_list.push_back(*it);
    00410
    00411     // In case of multiplication by zero (this cannot happen if we are
    00412     // working from a rational expression, but we check it nonetheless
    00413     // in case one day this function is used with a used-supplied
    00414     // weight).
    00415     if (k == zero)
    00416       {
    00417         // erase all outgoing transitions from ini_stt
    00418         for_all(typename trn_lst_t, it, ini_out_list)
    00419            aut.del_transition(*it);
    00420         // make ini_stt non final
    00421         aut.unset_final(ini_stt);
    00422       }
    00423     // In all other cases
    00424     else
    00425       {
    00426         for_all(typename trn_lst_t, it, ini_out_list)
    00427           { // multiply by k the series of all outgoing transitions from ini_stt
    00428             hstate_t dest = aut.dst_of(*it);
    00429             weight_t wgt = k * aut.series_of(*it);
    00430             aut.del_transition(*it);
    00431             aut.add_series_transition(ini_stt, dest, wgt);
    00432           }
    00433         // multiply by k the final weight of ini_stt
    00434         aut.set_final(ini_stt, k * aut.get_final(ini_stt));
    00435       }
    00436   }
    00437
    00438   template <typename A, typename AI>
    00439   void
    00440   left_mult_of_standard_here(Element<A, AI>& aut,
    00441                              const typename Element<A, AI>::series_set_elt_t& k)
    00442   {
    00443     precondition(is_standard(aut));
    00444     left_ext_mult_of_standard_inside(aut.structure(), aut,
    00445                                      *aut.initial().begin(), k);
    00446   }
    00447
    00448   /*----------------------------------.
    00449   | right_ext_mult_of_standard_inside  |
    00450   `----------------------------------*/
    00451
    00452   template <typename A, typename AI>
    00453   void
    00454   right_ext_mult_of_standard_inside
    00455   (const AutomataBase<A>&, Element<A, AI>& aut,
    00456    typename std::list<typename Element<A, AI>::hstate_t>& stt_list,
    00457    const typename Element<A, AI>::series_set_elt_t& k)
    00458   {
    00459     typedef Element<A, AI> automaton_t;  AUTOMATON_TYPES(automaton_t);
    00460     typedef typename std::list<hstate_t> stt_lst_t;
    00461
    00462     // multiply by k (on the right) the final weight of of every state
    00463     // in stt_list
    00464     for_all(typename stt_lst_t, it, stt_list)
    00465       aut.set_final(*it, aut.get_final(*it) * k);
    00466   }
    00467
    00468   template <typename A, typename AI>
    00469   void
    00470   right_mult_of_standard_here(Element<A, AI>& aut,
    00471                               const typename Element<A, AI>::series_set_elt_t& k)
    00472   {
    00473     typedef Element<A, AI> automaton_t;
    00474     AUTOMATON_TYPES(automaton_t);
    00475
    00476     precondition(is_standard(aut));
    00477     std::list<hstate_t> finals;
    00478     for_all_final_states(it, aut)  finals.push_back(*it);
    00479
    00480     right_ext_mult_of_standard_inside(aut.structure(), aut,
    00481                                       finals, k);
    00482   }
    00483
    00484   /*------------------.
    00485   | star_of_standard  |
    00486   `------------------*/
    00487
    00488   template <typename A, typename AI>
    00489   void
    00490   star_of_standard_inside(const AutomataBase<A>&, Element<A, AI>& aut,
    00491                           const typename Element<A, AI>::hstate_t& ini_stt,
    00492                           typename std::list<typename Element<A, AI>::hstate_t>& stt_list)
    00493   {
    00494     typedef Element<A, AI> automaton_t;   AUTOMATON_TYPES(automaton_t);
    00495     typedef series_set_elt_t                    weight_t;
    00496     typedef typename std::list<hstate_t>        stt_lst_t;
    00497     typedef basic_sptr<hstate_t, weight_t>      sptr_t;
    00498     weight_t unit = aut.series().identity(SELECT(series_set_elt_value_t));
    00499
    00500     // compute the star of the final weight of ini_stt (starable has
    00501     // already been called)
    00502     weight_t    fin_wgt = aut.get_final(ini_stt);  fin_wgt.star();
    00503
    00504     // multiply on the left by that coefficient
    00505     aut.set_final(ini_stt, unit);
    00506     left_ext_mult_of_standard_inside(aut.structure(), aut, ini_stt, fin_wgt);
    00507
    00508     // emulates closure of spt transition from every
    00509     // state in stt_list to ini_stt
    00510     for_all(typename stt_lst_t, it, stt_list)
    00511       {
    00512         hstate_t   crn_stt = *it;
    00513         weight_t   crn_fin_wgt = aut.get_final(crn_stt);
    00514         aut.unset_final(crn_stt);
    00515
    00516         sptr_t t(crn_stt, ini_stt, crn_fin_wgt);
    00517         one_eps_closure(aut, t, misc::backward);
    00518       }
    00519   }
    00520
    00521
    00522   template <typename A, typename AI>
    00523   void
    00524   do_star_of_standard_here(const AutomataBase<A>&, Element<A, AI>& a)
    00525   {
    00526     BENCH_TASK_SCOPED("star_of_standard");
    00527     typedef Element<A, AI> automaton_t;   AUTOMATON_TYPES(automaton_t);
    00528     typedef series_set_elt_t              weight_t;
    00529     typedef std::list<hstate_t>           stt_lst_t;
    00530
    00531     hstate_t    ini_stt = *a.initial().begin();
    00532     weight_t    fin_wgt = a.get_final(ini_stt);
    00533
    00534     precondition(fin_wgt.starable());
    00535
    00536     stt_lst_t  stt_list;
    00537     for_all_final_states(it, a)
    00538       if (*it != ini_stt)
    00539         stt_list.push_back(*it);
    00540
    00541     star_of_standard_inside(a.structure(), a, ini_stt, stt_list);
    00542   }
    00543
    00544   template<typename A, typename AI>
    00545   void
    00546   star_of_standard_here(Element<A, AI>& a)
    00547   {
    00548     precondition(is_standard(a));
    00549     do_star_of_standard_here(a.structure(), a);
    00550   }
    00551
    00552   template<typename A, typename AI>
    00553   Element<A, AI>
    00554   star_of_standard(const Element<A, AI>& a)
    00555   {
    00556     precondition(is_standard(a));
    00557     Element<A, AI> ret(a);
    00558     do_star_of_standard_here(ret.structure(), ret);
    00559     return ret;
    00560   }
    00561
    00562 } // vcsn
    00563
    00564 #endif // ! VCSN_ALGORITHMS_STANDARD_HXX