Vaucanson 1.4
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