Vaucanson 1.4
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 = misc::limits<unsigned int>::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       for (typename Auto_::delta_iterator j(a.value(), *i);
00129            ! j.done();
00130            j.next())
00131         delta_out.push_back(*j);
00132       for (typename Auto_::rdelta_iterator j(a.value(), *i);
00133            ! j.done();
00134            j.next())
00135         delta_in.push_back(*j);
00136       for (typename std::list<typename Auto_::htransition_t>::iterator j = delta_out.begin();
00137            j != delta_out.end();
00138            ++j)
00139         if (*i == a.dst_of(*j))
00140           has_loop = true;
00141 
00142       //FIXME : If the state has several loops
00143       if (has_loop)
00144         d_in = delta_in.size() - 1;
00145       else
00146         d_in = delta_in.size();
00147       d_out = delta_out.size();
00148 
00149       //We prefer to delete a state that has no loop transition
00150       if (d_in * d_out < max ||
00151           (d_in * d_out == max &&
00152            has_loop_old && not has_loop))
00153       {
00154         s = i;
00155         max = d_in * d_out;
00156         has_loop_old = has_loop;
00157       }
00158       delta_out.clear();
00159       delta_in.clear();
00160     }
00161     return *s;
00162   }
00163 
00164   /*-------------------------.
00165   | Heuristic chooser:       |
00166   | from Delgado & Morais    |
00167   | (Proposed in CIAA 2004)  |
00168   `-------------------------*/
00169 
00170   template <class Auto_>
00171   typename Auto_::hstate_t
00172   DMChooser::operator()(const Auto_& a) const
00173   {
00174     assertion(a.states().size() > 0);
00175 
00176     std::list<typename Auto_::htransition_t> delta_in;
00177     std::list<typename Auto_::htransition_t> delta_out;
00178     typename Auto_::state_iterator s = a.states().begin();
00179 
00180     int weight_min = misc::limits<int>::max();
00181     for (typename Auto_::state_iterator i = a.states().begin();
00182          i != a.states().end();
00183          ++i)
00184     {
00185       if (a.is_final(*i) || a.is_initial(*i))
00186         continue;
00187       unsigned int n_loops = 0;
00188       unsigned int in = 0;
00189       unsigned int out = 0;
00190 
00191       int weight = 0;
00192 
00193       delta_in.clear();
00194       delta_out.clear();
00195       for (typename Auto_::delta_iterator j(a.value(), *i);
00196            ! j.done();
00197            j.next())
00198         delta_out.push_back(*j);
00199       for (typename Auto_::rdelta_iterator j(a.value(), *i);
00200            ! j.done();
00201            j.next())
00202         delta_in.push_back(*j);
00203 
00204       for (typename std::list<typename Auto_::htransition_t>::iterator j = delta_out.begin();
00205            j != delta_out.end();
00206            ++j)
00207         if (*i == a.dst_of(*j))
00208           ++n_loops;
00209 
00210       in = delta_in.size() - n_loops;
00211       out = delta_out.size() - n_loops;
00212 
00213       // Compute SUM(Win(k) * (Out - 1))
00214       for (typename std::list<typename Auto_::htransition_t>::iterator j = delta_in.begin();
00215            j != delta_in.end();
00216            ++j)
00217         if (*i != a.dst_of(*j))
00218         {
00219           weight += a.series_value_of(*j).length() * (out - 1);
00220         }
00221 
00222       // Compute SUM(Wout(k) * (In - 1))
00223       for (typename std::list<typename Auto_::htransition_t>::iterator j = delta_out.begin();
00224            j != delta_out.end();
00225            ++j)
00226         if (*i != a.dst_of(*j))
00227         {
00228           weight += a.series_value_of(*j).length() * (in - 1);
00229         }
00230 
00231       // Compute Wloop * (In * Out - 1)
00232       for (typename std::list<typename Auto_::htransition_t>::iterator j = delta_out.begin();
00233            j != delta_out.end();
00234            ++j)
00235         if (*i == a.dst_of(*j))
00236         {
00237           weight += a.series_value_of(*j).length() * (in  * out - 1);
00238         }
00239 
00240       if (weight < weight_min)
00241       {
00242         s = i;
00243         weight_min = weight;
00244       }
00245     }
00246     return *s;
00247   }
00248 
00249   /*------------.
00250   | ListChooser |
00251   `------------*/
00252 
00253   inline ListChooser::ListChooser(const std::list<unsigned int>& l) :
00254       list_(l),
00255       pos_(l.begin())
00256   {
00257   }
00258 
00259   template <class Auto_>
00260   typename Auto_::hstate_t
00261   ListChooser::operator() (const Auto_& a)
00262   {
00263     assertion(pos_ != list_.end());
00264     return a.get_state(*pos_++);
00265   }
00266 
00267   /*-----------.
00268   | aut_to_exp |
00269   `-----------*/
00270 
00271   template <class A, typename AI, typename Chooser>
00272   typename Element<A, AI>::series_set_elt_t
00273   do_in_aut_to_exp(const AutomataBase<A>&  a_set,
00274                    Element<A, AI>&         a,
00275                    Chooser                 chooser)
00276   {
00277     typedef Element<A, AI>                              automaton_t;
00278     AUTOMATON_TYPES(automaton_t);
00279     typedef typename automaton_t::series_set_t          series_set_t;
00280     typedef typename automaton_t::series_set_elt_t      series_set_elt_t;
00281 
00282     typedef typename std::list<htransition_t>           htransition_set_t;
00283     typedef std::map<hstate_t, series_set_elt_t>        sums_t;
00284 
00285     typename htransition_set_t::const_iterator          i, j;
00286     hstate_t                                            q;
00287     htransition_set_t                                   transitions;
00288     std::list<htransition_t>                            transitions_to_remove;
00289     normalize_here(a);
00290     // assertion(is_normalized(a)); // FIXME To remove
00291 
00292     while (a.states().size() != 2)
00293     {
00294       series_set_elt_t loop_sum(a_set.series());
00295       sums_t       in_sums, out_sums;
00296 
00297       q = chooser(a);
00298       if (a.is_initial(q) || a.is_final(q))
00299         continue;
00300 
00301       transitions.clear();
00302       for (delta_iterator e(a.value(), q); ! e.done(); e.next())
00303         transitions.push_back(*e);
00304       for (i = transitions.begin(); i != transitions.end(); i = j)
00305       {
00306         j = i; ++j;
00307 
00308         if (a.dst_of(*i) == q)
00309           loop_sum += a.series_of(*i);
00310         else
00311         {
00312           typename sums_t::iterator f = out_sums.find(a.dst_of(*i));
00313           if (f == out_sums.end())
00314             f = out_sums.insert
00315               (std::make_pair(a.dst_of(*i),
00316                               series_set_elt_t(a_set.series()))).first;
00317           f->second += a.series_of(*i);
00318         }
00319         a.del_transition(*i);
00320       }
00321       transitions.clear();
00322       for (rdelta_iterator e(a.value(), q); ! e.done(); e.next())
00323         transitions.push_back(*e);
00324       for (i = transitions.begin(); i != transitions.end(); i = j)
00325       {
00326         j = i; ++j;
00327         // Here all loops have already been removed.
00328         typename sums_t::iterator f = in_sums.find(a.src_of(*i));
00329         if (f == in_sums.end())
00330           f = in_sums.insert
00331             (std::make_pair(a.src_of(*i),
00332                             series_set_elt_t(a_set.series()))).first;
00333 
00334         f->second += a.series_of(*i);
00335         a.del_transition(*i);
00336       }
00337       loop_sum.star();
00338       //Slow
00339       for_all_const_(sums_t, in, in_sums)
00340         for_all_const_(sums_t, out, out_sums)
00341         {
00342           series_set_elt_t res = in->second * loop_sum * out->second;
00343           a.add_series_transition(in->first, out->first, res);
00344         }
00345       a.del_state(q);
00346     }
00347     series_set_elt_t final(a_set.series());
00348     for_all_const_transitions(i, a)
00349       final += a.label_of(*i);
00350     return final;
00351   }
00352 
00353   /*-----------.
00354   | aut_to_exp |
00355   `-----------*/
00356 
00357   template<typename A, typename AI, typename Chooser>
00358   typename Element<A, AI>::series_set_elt_t
00359   aut_to_exp(const Element<A, AI>& a, const Chooser& c)
00360   {
00361     BENCH_TASK_SCOPED("aut_to_exp");
00362     Element<A, AI> ret(a);
00363     return do_in_aut_to_exp(ret.structure(), ret, c);
00364   }
00365 
00366   template<typename A, typename AI>
00367   typename Element<A, AI>::series_set_elt_t
00368   aut_to_exp(const Element<A, AI>& a)
00369   {
00370     return aut_to_exp(a, DefaultChooser());
00371   }
00372 
00373 } // vcsn
00374 
00375 #endif // ! VCSN_ALGORITHMS_AUT_TO_EXP_HXX