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 The Vaucanson Group.
00006 //
00007 // This program is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2
00010 // of the License, or (at your option) any later version.
00011 //
00012 // The complete GNU General Public Licence Notice can be found as the
00013 // `COPYING' file in the root directory.
00014 //
00015 // The Vaucanson Group consists of people listed in the `AUTHORS' file.
00016 //
00017 #ifndef VCSN_ALGORITHMS_STANDARD_HXX
00018 # define VCSN_ALGORITHMS_STANDARD_HXX
00019 
00020 # include <vaucanson/algorithms/standard.hh>
00021 # include <vaucanson/algorithms/internal/has_neighbour.hh>
00022 
00023 # include <vaucanson/algorithms/sum.hh>
00024 # include <vaucanson/algorithms/accessible.hh>
00025 # include <vaucanson/automata/concept/automata_base.hh>
00026 # include <vaucanson/misc/usual_macros.hh>
00027 
00028 # include <set>
00029 
00030 namespace vcsn {
00031 
00032   /*---------.
00033   | standard |
00034   `---------*/
00035   template <class A_, typename Auto_>
00036   void
00037   do_in_standardize(const AutomataBase<A_>& ,
00038                     Auto_&                  a)
00039   {
00040     TIMER_SCOPED("standardize");
00041     AUTOMATON_TYPES(Auto_);
00042 
00043     hstate_t i = a.add_state();
00044     std::set<htransition_t> transition_oi;
00045     series_set_elt_t final_series =
00046       algebra::zero_as<series_set_elt_value_t>::of(a.series());
00047 
00048     for_all_initial_states(oi, a)
00049     {
00050       series_set_elt_t s = a.get_initial(*oi);
00051 
00052       // Handle each transitions.
00053       transition_oi.clear();
00054       a.deltac(transition_oi, *oi, delta_kind::transitions());
00055       for_all_const_(std::set<htransition_t>, oil, transition_oi)
00056       {
00057         series_set_elt_t t = s * a.series_of(*oil);
00058         a.add_series_transition(i, a.dst_of(*oil), t);
00059       }
00060       // Accumulate final transition series of each initial state.
00061       final_series += s * a.get_final(*oi);
00062     }
00063 
00064     // Suppress initial states which are not accessible.  We don't use
00065     // @c accessible_here for efficienty issues, and because the
00066     // definition of a standard automaton does not imply the
00067     // admissible property.
00068     for (initial_iterator oi = a.initial().begin(), next = oi;
00069          oi != a.initial().end();
00070          oi = next)
00071     {
00072       ++next;
00073       if (!has_predecessors(a, *oi))
00074         a.del_state(*oi);
00075     }
00076     a.clear_initial();
00077     a.set_initial(i);
00078     a.set_final(i, final_series);
00079   }
00080 
00081   template<typename A, typename T>
00082   void
00083   standardize(Element<A, T>& a)
00084   {
00085     do_in_standardize(a.structure(), a);
00086   }
00087 
00088   /*-----------------.
00089   | standard_union.  |
00090   `-----------------*/
00091 
00092   template <typename A, typename lhs_t, typename rhs_t>
00093   void do_union_of_standard_here(const AutomataBase<A>&,
00094                                  lhs_t& lhs,
00095                                  const rhs_t& rhs)
00096   {
00097     precondition(is_standard(lhs));
00098     precondition(is_standard(rhs));
00099 
00100     TIMER_SCOPED("union_of_standard");
00101     typedef typename std::set<htransition_t> edelta_ret_t;
00102 
00103     // The resulting initial state is that of lhs.
00104     hstate_t new_i = *lhs.initial().begin();
00105     sum_here(lhs, rhs);
00106 
00107     // Adjust new_i, and handle old_i, the state that was the initial
00108     // state of rhs.
00109     typename lhs_t::initial_support_t initial = lhs.initial();
00110 
00111     // There are two initial states, old_i is the other.
00112     assertion (initial.size() == 2);
00113     typename lhs_t::initial_iterator i = initial.begin();
00114     hstate_t old_i = *i != new_i ? *i : *++i;
00115 
00116     lhs.set_final(new_i,
00117                   lhs.get_final(new_i) + lhs.get_final(old_i));
00118 
00119     // Add output transitions of old_i to new_i.
00120     edelta_ret_t dst;
00121     lhs.deltac(dst, old_i, delta_kind::transitions());
00122     for_all_const_(edelta_ret_t, d, dst)
00123     {
00124       lhs.add_transition(new_i,
00125                          lhs.dst_of(*d),
00126                          lhs.label_of(*d));
00127       lhs.del_transition(*d);
00128     }
00129     lhs.del_state(old_i);
00130   }
00131 
00132   template<typename A, typename T, typename U>
00133   void union_of_standard_here(Element<A, T>& lhs,
00134                               const Element<A, U>& rhs)
00135   {
00136     // assertion(lhs.structure() == rhs.structure())
00137     do_union_of_standard_here(lhs.structure(), lhs, rhs);
00138   }
00139 
00140   template<typename A, typename T, typename U>
00141   Element<A, T>
00142   union_of_standard(const Element<A, T>& lhs,
00143                     const Element<A, U>& rhs)
00144   {
00145     // assertion(lhs.structure() == rhs.structure())
00146     Element<A, T> ret(lhs);
00147     union_of_standard_here(ret, rhs);
00148     return ret;
00149   }
00150 
00151   /*--------------.
00152   | is_standard.  |
00153   `--------------*/
00154   template <typename A, typename auto_t>
00155   bool
00156   do_is_standard(const AutomataBase<A>& ,
00157                  const auto_t& a)
00158   {
00159     TIMER_SCOPED("is_standard");
00160     typedef typename auto_t::series_set_elt_value_t     series_set_elt_value_t;
00161 
00162     // Check there is only one initial state.
00163     if (a.initial().size() != 1)
00164       return false;
00165 
00166     // Check the multiplicity of the initial state.
00167     hstate_t s = *a.initial().begin();
00168     if (a.get_initial(s)
00169         != a.series().identity(SELECT(series_set_elt_value_t)))
00170       return false;
00171 
00172     // Check that there is no input transition on the initial state.
00173     return !has_predecessors(a, s);
00174   }
00175 
00176   template<typename A, typename T>
00177   bool
00178   is_standard(const Element<A, T>& a)
00179   {
00180     return do_is_standard(a.structure(), a);
00181   }
00182 
00183   /*---------------------.
00184   | concat_of_standard.  |
00185   `---------------------*/
00186   template <typename A, typename lhs_t, typename rhs_t>
00187   void do_concat_of_standard_here(const AutomataBase<A>& ,
00188                                   lhs_t& lhs,
00189                                   const rhs_t& rhs)
00190   {
00191     precondition(is_standard(lhs));
00192     precondition(is_standard(rhs));
00193 
00194     TIMER_SCOPED("concat_of_standard");
00195     AUTOMATON_TYPES(lhs_t);
00196     typedef std::map<hstate_t, hstate_t>        map_t;
00197     typedef std::set<htransition_t>             delta_ret_t;
00198 
00199     /*------------------.
00200     | Concat of states. |
00201     `------------------*/
00202     map_t       map_h;
00203     delta_ret_t dst;
00204     hstate_t    new_state;
00205 
00206     // Add states except the initial one.
00207     for (typename rhs_t::state_iterator s = rhs.states().begin();
00208          s != rhs.states().end();
00209          ++s)
00210       if (!rhs.is_initial(*s))
00211       {
00212         new_state = lhs.add_state();
00213         map_h[*s] = new_state;
00214       }
00215 
00216     // Add transitions.
00217     for (typename rhs_t::state_iterator i = rhs.states().begin();
00218          i != rhs.states().end();
00219          ++i)
00220       if (!rhs.is_initial(*i))
00221       {
00222         dst.clear();
00223         rhs.deltac(dst, *i, delta_kind::transitions());
00224         for_all_const_(delta_ret_t, d, dst)
00225           lhs.add_transition(map_h[*i],
00226                              map_h[rhs.dst_of(*d)],
00227                              rhs.label_of(*d));
00228       }
00229 
00230     // Concat final states of lhs to the initial state of rhs.
00231     hstate_t rhs_i = *rhs.initial().begin();
00232     dst.clear();
00233     rhs.deltac(dst, rhs_i, delta_kind::transitions());
00234     for_all_final_states(f, lhs)
00235     {
00236       typename lhs_t::series_set_elt_t weight = lhs.get_final(*f);
00237       for_all_const_(delta_ret_t, d, dst)
00238         lhs.add_series_transition(*f,
00239                                   map_h[rhs.dst_of(*d)],
00240                                   weight * rhs.label_of(*d));
00241     }
00242 
00243     // Multiply final transitions of lhs by the final multiplicity of the
00244     // initial state of rhs.
00245     typename lhs_t::series_set_elt_t rhs_iw = rhs.get_final(rhs_i);
00246     typename lhs_t::final_support_t support = lhs.final();
00247     for (typename lhs_t::final_iterator next = lhs.final().begin();
00248          next != lhs.final().end();)
00249     {
00250       typename lhs_t::final_iterator f = next;
00251       next++;
00252       lhs.set_final(*f, lhs.get_final(*f) * rhs_iw);
00253     }
00254 
00255     // Set transitions coming from rhs to final if needed.
00256     for_all_const_(map_t, nf, map_h)
00257       if (rhs.is_final(nf->first))
00258         lhs.set_final(nf->second, rhs.get_final(nf->first));
00259   }
00260 
00261   template<typename A, typename T, typename U>
00262   void concat_of_standard_here(Element<A, T>& lhs,
00263                                const Element<A, U>& rhs)
00264   {
00265     // assertion(lhs.structure() == rhs.structure())
00266     do_concat_of_standard_here(lhs.structure(), lhs, rhs);
00267   }
00268 
00269   template<typename A, typename T, typename U>
00270   Element<A, T>
00271   concat_of_standard(const Element<A, T>& lhs,
00272                      const Element<A, U>& rhs)
00273   {
00274     // assertion(lhs.structure() == rhs.structure())
00275     Element<A, T> ret(lhs);
00276     do_concat_of_standard_here(ret.structure(), ret, rhs);
00277     return ret;
00278   }
00279 
00280   /*----------------.
00281   | standard_star.  |
00282   `----------------*/
00283   template <typename A, typename auto_t>
00284   void do_star_of_standard_here(const AutomataBase<A>& ,
00285                                 auto_t& a)
00286   {
00287     precondition(is_standard(a));
00288 
00289     TIMER_SCOPED("star_of_standard");
00290     AUTOMATON_TYPES(auto_t);
00291     typedef std::set<htransition_t>             edelta_ret_t;
00292 
00293     edelta_ret_t                        dst;
00294     hstate_t                            new_i = *a.initial().begin();
00295     series_set_elt_t                    out_mult = a.get_final(new_i);
00296 
00297     out_mult.star();
00298     a.deltac(dst, new_i, delta_kind::transitions());
00299     for_all_final_states(f, a)
00300     {
00301       if (*f != new_i)
00302       {
00303         series_set_elt_t f_mult = a.get_final(*f) * out_mult;
00304         a.set_final(*f, f_mult);
00305         for_all_const_(edelta_ret_t, d, dst)
00306           a.add_series_transition(*f, a.dst_of(*d), f_mult * a.label_of(*d));
00307       }
00308     }
00309     a.set_final(new_i, out_mult);
00310   }
00311 
00312   template<typename A, typename T>
00313   void star_of_standard_here(Element<A, T>& a)
00314   {
00315     do_star_of_standard_here(a.structure(), a);
00316   }
00317 
00318   template<typename A, typename T>
00319   Element<A, T>
00320   star_of_standard(const Element<A, T>& a)
00321   {
00322     // assertion(lhs.structure() == rhs.structure())
00323     Element<A, T> ret(a);
00324     do_star_of_standard_here(ret.structure(), ret);
00325     return ret;
00326   }
00327 
00328 } // vcsn
00329 
00330 #endif // ! VCSN_ALGORITHMS_STANDARD_HXX

Generated on Thu Dec 13 16:03:01 2007 for Vaucanson by  doxygen 1.5.4