- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

# 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