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

Generated on Thu Oct 9 20:22:41 2008 for Vaucanson by  doxygen 1.5.1