aut_to_exp.hxx

00001 // aut_to_exp.hxx: this file is part of the Vaucanson project.
00002 //
00003 // Vaucanson, a generic library for finite state machines.
00004 //
00005 // Copyright (C) 2004, 2005, 2006, 2008 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_AUT_TO_EXP_HXX
00018 # define VCSN_ALGORITHMS_AUT_TO_EXP_HXX
00019 
00020 # include <vaucanson/algorithms/aut_to_exp.hh>
00021 
00022 # include <vaucanson/automata/concept/handlers.hh>
00023 # include <vaucanson/algorithms/normalized.hh>
00024 # include <vaucanson/misc/usual_macros.hh>
00025 # include <vaucanson/misc/contract.hh>
00026 # include <vaucanson/misc/limits.hh>
00027 # include <vaucanson/misc/random.hh>
00028 # include <vaucanson/automata/concept/automata_base.hh>
00029 
00030 # include <list>
00031 # include <set>
00032 # include <vector>
00033 
00034 # include <stdlib.h>
00035 # include <time.h>
00036 
00037 namespace vcsn {
00038 
00039   /*---------------.
00040   | DefaultChooser |
00041   `---------------*/
00042 
00043   template <class Auto_>
00044   typename Auto_::hstate_t
00045   DefaultChooser::operator()(const Auto_& a) const
00046   {
00047     assertion(a.states().size() > 0);
00048     typename Auto_::state_iterator s = a.states().begin();
00049     typename Auto_::state_iterator k = s;
00050     while ((k != a.states().end()) &&
00051            ((a.is_initial(*k)) || (a.is_final(*k))))
00052       ++k;
00053     s = k;
00054     return *s;
00055   }
00056 
00057   /*--------------.
00058   | RandomChooser |
00059   `--------------*/
00060 
00061   template <class Auto_>
00062   typename Auto_::hstate_t
00063   RandomChooser::operator()(const Auto_& a) const
00064   {
00065     assertion(a.states().size() > 0);
00066 
00067     int n_init = 0;
00068     int n_final = 0;
00069     for (typename Auto_::state_iterator i = a.states().begin();
00070          i != a.states().end();
00071          ++i)
00072     {
00073       if (a.is_initial(*i))
00074         ++n_init;
00075       if (a.is_final(*i))
00076         ++n_final;
00077     }
00078 
00079     unsigned n = misc::random::generate((unsigned) 0,
00080                                         a.states().size() -
00081                                         (n_init + n_final));
00082 
00083     typename Auto_::state_iterator k = a.states().begin();
00084     unsigned kk = 0;
00085     while (kk <= n || k == a.states().end() ||
00086            ((a.is_initial(*k)) || (a.is_final(*k))))
00087     {
00088       if (k == a.states().end())
00089       {
00090         k = a.states().begin();
00091         continue;
00092       }
00093       ++k;
00094       ++kk;
00095     }
00096     return *k;
00097   }
00098 
00099   /*----------------------------.
00100   |    Heuristic chooser:         |
00101   | Transition Number Heuristic |
00102   `----------------------------*/
00103 
00104   template <class Auto_>
00105   typename Auto_::hstate_t
00106   HChooser::operator()(const Auto_& a) const
00107   {
00108     assertion(a.states().size() > 0);
00109 
00110     std::list<typename Auto_::htransition_t> delta_in;
00111     std::list<typename Auto_::htransition_t> delta_out;
00112 
00113     typename Auto_::state_iterator s = a.states().begin();
00114     unsigned int d_in = 0;
00115     unsigned int d_out = 0;
00116     unsigned int max = UINT_MAX;
00117     bool has_loop = false;
00118     bool has_loop_old = false;
00119 
00120     for (typename Auto_::state_iterator i = a.states().begin();
00121          i != a.states().end();
00122          ++i)
00123     {
00124       if (a.is_final(*i) || a.is_initial(*i))
00125         continue;
00126       has_loop = false;
00127 
00128       a.deltac(delta_out, *i, delta_kind::transitions());
00129       a.rdeltac(delta_in, *i, delta_kind::transitions());
00130       for (typename std::list<typename Auto_::htransition_t>::iterator j = delta_out.begin();
00131            j != delta_out.end();
00132            ++j)
00133         if (*i == a.dst_of(*j))
00134           has_loop = true;
00135 
00136       //FIXME : If the state has several loops
00137       if (has_loop)
00138         d_in = delta_in.size() - 1;
00139       else
00140         d_in = delta_in.size();
00141       d_out = delta_out.size();
00142 
00143       //We prefer to delete a state that has no loop transition
00144       if (d_in * d_out < max ||
00145           (d_in * d_out == max &&
00146            has_loop_old && not has_loop))
00147       {
00148         s = i;
00149         max = d_in * d_out;
00150         has_loop_old = has_loop;
00151       }
00152       delta_out.clear();
00153       delta_in.clear();
00154     }
00155     return *s;
00156   }
00157 
00158   /*-------------------------.
00159   | Heuristic chooser:       |
00160   | from Delgado & Morais    |
00161   | (Proposed in CIAA 2004)  |
00162   `-------------------------*/
00163 
00164   template <class Auto_>
00165   typename Auto_::hstate_t
00166   DMChooser::operator()(const Auto_& a) const
00167   {
00168     assertion(a.states().size() > 0);
00169 
00170     std::list<typename Auto_::htransition_t> delta_in;
00171     std::list<typename Auto_::htransition_t> delta_out;
00172     typename Auto_::state_iterator s = a.states().begin();
00173 
00174     int weight_min = INT_MAX;
00175     for (typename Auto_::state_iterator i = a.states().begin();
00176          i != a.states().end();
00177          ++i)
00178     {
00179       if (a.is_final(*i) || a.is_initial(*i))
00180         continue;
00181       unsigned int n_loops = 0;
00182       unsigned int in = 0;
00183       unsigned int out = 0;
00184 
00185       int weight = 0;
00186 
00187       delta_in.clear();
00188       delta_out.clear();
00189       a.deltac(delta_out, *i, delta_kind::transitions());
00190       a.rdeltac(delta_in, *i, delta_kind::transitions());
00191 
00192       for (typename std::list<typename Auto_::htransition_t>::iterator j = delta_out.begin();
00193            j != delta_out.end();
00194            ++j)
00195         if (*i == a.dst_of(*j))
00196           ++n_loops;
00197 
00198       in = delta_in.size() - n_loops;
00199       out = delta_out.size() - n_loops;
00200 
00201       // Compute SUM(Win(k) * (Out - 1))
00202       for (typename std::list<typename Auto_::htransition_t>::iterator j = delta_in.begin();
00203            j != delta_in.end();
00204            ++j)
00205         if (*i != a.dst_of(*j))
00206         {
00207           weight += a.series_value_of(*j).length() * (out - 1);
00208         }
00209 
00210       // Compute SUM(Wout(k) * (In - 1))
00211       for (typename std::list<typename Auto_::htransition_t>::iterator j = delta_out.begin();
00212            j != delta_out.end();
00213            ++j)
00214         if (*i != a.dst_of(*j))
00215         {
00216           weight += a.series_value_of(*j).length() * (in - 1);
00217         }
00218 
00219       // Compute Wloop * (In * Out - 1)
00220       for (typename std::list<typename Auto_::htransition_t>::iterator j = delta_out.begin();
00221            j != delta_out.end();
00222            ++j)
00223         if (*i == a.dst_of(*j))
00224         {
00225           weight += a.series_value_of(*j).length() * (in  * out - 1);
00226         }
00227 
00228       if (weight < weight_min)
00229       {
00230         s = i;
00231         weight_min = weight;
00232       }
00233     }
00234     return *s;
00235   }
00236 
00237   /*------------.
00238   | ListChooser |
00239   `------------*/
00240 
00241   inline ListChooser::ListChooser(const std::list<unsigned int>& l) :
00242       list_(l),
00243       pos_(l.begin())
00244   {
00245   }
00246 
00247   template <class Auto_>
00248   typename Auto_::hstate_t
00249   ListChooser::operator() (const Auto_& a)
00250   {
00251     assertion(pos_ != list_.end());
00252     return a.get_state(*pos_++);
00253   }
00254 
00255   /*-----------.
00256   | aut_to_exp |
00257   `-----------*/
00258 
00259   template <class A, typename AI, typename Chooser>
00260   typename Element<A, AI>::series_set_elt_t
00261   do_in_aut_to_exp(const AutomataBase<A>&  a_set,
00262                    Element<A, AI>&         a,
00263                    Chooser                 chooser)
00264   {
00265     typedef Element<A, AI>                              automaton_t;
00266     AUTOMATON_TYPES(automaton_t);
00267     typedef typename automaton_t::series_set_t          series_set_t;
00268     typedef typename automaton_t::series_set_elt_t      series_set_elt_t;
00269 
00270     typedef typename std::list<htransition_t>           htransition_set_t;
00271     typedef std::map<hstate_t, series_set_elt_t>        sums_t;
00272 
00273     typename htransition_set_t::const_iterator          i, j;
00274     hstate_t                                            q;
00275     htransition_set_t                                   transitions;
00276     std::list<htransition_t>                            transitions_to_remove;
00277     normalize_here(a);
00278     // assertion(is_normalized(a)); // FIXME To remove
00279 
00280     while (a.states().size() != 2)
00281     {
00282       series_set_elt_t loop_sum(a_set.series());
00283       sums_t       in_sums, out_sums;
00284 
00285       q = chooser(a);
00286       if (a.is_initial(q) || a.is_final(q))
00287         continue;
00288 
00289       transitions.clear();
00290       // FIXME: use a new version of delta!
00291       a.deltac(transitions, q, delta_kind::transitions());
00292       for (i = transitions.begin(); i != transitions.end(); i = j)
00293       {
00294         j = i; ++j;
00295 
00296         if (a.dst_of(*i) == q)
00297           loop_sum += a.series_of(*i);
00298         else
00299         {
00300           typename sums_t::iterator f = out_sums.find(a.dst_of(*i));
00301           if (f == out_sums.end())
00302             f = out_sums.insert
00303               (std::make_pair(a.dst_of(*i),
00304                               series_set_elt_t(a_set.series()))).first;
00305           f->second += a.series_of(*i);
00306         }
00307         a.del_transition(*i);
00308       }
00309       transitions.clear();
00310       // FIXME: use a new version of delta!
00311       a.rdeltac(transitions, q, delta_kind::transitions());
00312       for (i = transitions.begin(); i != transitions.end(); i = j)
00313       {
00314         j = i; ++j;
00315         // Here all loops have already been removed.
00316         typename sums_t::iterator f = in_sums.find(a.src_of(*i));
00317         if (f == in_sums.end())
00318           f = in_sums.insert
00319             (std::make_pair(a.src_of(*i),
00320                             series_set_elt_t(a_set.series()))).first;
00321 
00322         f->second += a.series_of(*i);
00323         a.del_transition(*i);
00324       }
00325       loop_sum.star();
00326       //Slow
00327       for_all_const_(sums_t, in, in_sums)
00328         for_all_const_(sums_t, out, out_sums)
00329         {
00330           series_set_elt_t res = in->second * loop_sum * out->second;
00331           a.add_series_transition(in->first, out->first, res);
00332         }
00333       a.del_state(q);
00334     }
00335     series_set_elt_t final(a_set.series());
00336     for_all_const_transitions(i, a)
00337       final += a.label_of(*i);
00338     return final;
00339   }
00340 
00341   /*-----------.
00342   | aut_to_exp |
00343   `-----------*/
00344 
00345   template<typename A, typename AI, typename Chooser>
00346   typename Element<A, AI>::series_set_elt_t
00347   aut_to_exp(const Element<A, AI>& a, const Chooser& c)
00348   {
00349     TIMER_SCOPED("aut_to_exp");
00350     Element<A, AI> ret(a);
00351     return do_in_aut_to_exp(ret.structure(), ret, c);
00352   }
00353 
00354   template<typename A, typename AI>
00355   typename Element<A, AI>::series_set_elt_t
00356   aut_to_exp(const Element<A, AI>& a)
00357   {
00358     return aut_to_exp(a, DefaultChooser());
00359   }
00360 
00361 } // vcsn
00362 
00363 #endif // ! VCSN_ALGORITHMS_AUT_TO_EXP_HXX

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