Vaucanson 1.4
evaluation.hxx
00001 // evaluation.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, 2009 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_EVALUATION_HXX
00018 # define VCSN_ALGORITHMS_EVALUATION_HXX
00019 
00020 # include <vaucanson/algorithms/internal/evaluation.hh>
00021 
00022 # include <vaucanson/misc/usual_macros.hh>
00023 # include <vaucanson/automata/concept/transducer_base.hh>
00024 
00025 // FIXME: check dead code
00026 //# include <vaucanson/algorithms/standard.hh>
00027 
00028 # include <vaucanson/algorithms/standard_of.hh>
00029 
00030 // Required by DefaultChooser.
00031 # include <vaucanson/algorithms/aut_to_exp.hh>
00032 
00033 # include <vaucanson/algorithms/extension.hh>
00034 # include <vaucanson/algorithms/product.hh>
00035 # include <vaucanson/algorithms/trim.hh>
00036 # include <vaucanson/algorithms/image.hh>
00037 
00038 namespace vcsn
00039 {
00040   template<typename SS, typename SM, typename V,
00041            typename Series_t, typename Trans_t,
00042            typename M>
00043   void
00044   do_partial_evaluation(const algebra::Series<SS, SM>&,
00045                         const Series_t& E,
00046                         const TransducerBase<V>&,
00047                         const Trans_t& S,
00048                         const typename Trans_t::hstate_t& p,
00049                         M& res)
00050   {
00051     // Type helpers.
00052     typedef typename Trans_t::value_t W;
00053     typedef typename output_projection_helper<V, W>::ret Auto_t;
00054     AUTOMATON_TYPES(Auto_t);
00055     AUTOMATON_TYPES_(Trans_t, t_);
00056     typedef typename Auto_t::set_t Auto_set_t;
00057     typedef typename Auto_set_t::series_set_t Auto_series_set_t;
00058     typedef series_set_elt_t exp_t;
00059     typedef t_series_set_elt_t t_exp_t;
00060     typedef std::map<t_hstate_t, std::pair<t_hstate_t, t_hstate_t> >
00061     state_pair_map_t;
00062     typedef std::map<t_hstate_t, hstate_t> state_state_map_t;
00063     typedef std::pair<t_hstate_t, exp_t> se_pair_t;
00064     Auto_set_t auto_structure(Auto_series_set_t(S.structure().series().semiring()));
00065 
00066     //
00067     // Part 1.
00068     // Construct A = standard_of(E).
00069     //
00070 
00071     // Hold standard_of(E).
00072     Auto_t A(auto_structure);
00073     standard_of(A, E.value());
00074 
00075     //
00076     // Part 2.
00077     // Sp construction.
00078     //
00079 
00080     // Does a copy of S,
00081     Trans_t Sp = S;
00082     state_state_map_t Sp_to_S;
00083     for_all_const_states_(t_, q, Sp)
00084     {
00085       hstate_t pSp = Sp_to_S[*q] = S.get_state(size_t(*q));
00086       if (pSp == p)
00087         Sp.set_initial(*q);
00088       else
00089         Sp.unset_initial(*q);
00090     }
00091 
00092     //
00093     // evaluation(A, Sp)
00094     // Evaluation: we keep some information for later.
00095     //
00096 
00097     // extension
00098     Trans_t tmp_trans(Sp.structure());
00099     tmp_trans = extension(A, Sp);
00100 
00101     // product
00102     Trans_t pro(Sp.structure());
00103     state_pair_map_t sp_m;
00104     pro = product(tmp_trans, Sp, sp_m);
00105 
00106     // build map we will reuse later
00107     std::map<typename Trans_t::hstate_t, typename Trans_t::hstate_t>    states_map_for_sp_m;
00108     for_all_iterator (typename state_pair_map_t::iterator, i, sp_m)
00109     states_map_for_sp_m.insert(std::make_pair(pro.get_state(size_t(i->first)), i->first));
00110 
00111     // image
00112     Auto_t G(auto_structure);
00113     state_state_map_t proj_m;
00114     G = image(pro, proj_m);
00115 
00116     std::map<typename Trans_t::hstate_t, typename Trans_t::hstate_t>    states_map_for_proj_m;
00117     for_all_iterator (typename state_state_map_t::iterator, i, proj_m)
00118     states_map_for_proj_m.insert(std::make_pair(G.get_state(size_t(i->first)), i->first));
00119 
00120     // add i state
00121     const hstate_t i = G.add_state();
00122     for_all_const_initial_states(r, G)
00123     {
00124       exp_t old_label = G.get_initial(*r);
00125       G.add_series_transition(i, *r, old_label);
00126       G.unset_initial(*r);
00127     }
00128     G.set_initial(i);
00129 
00130     //
00131     // Part 3.
00132     // Initialize map.
00133     //
00134 
00135     G.clear_final();
00136     state_state_map_t state_of, is_state_of;
00137     for_all_const_states_(t_, u, Sp)
00138     {
00139       hstate_t new_state = G.add_state();
00140       state_of[*u] = new_state;
00141       is_state_of[new_state] = *u;
00142       G.set_final(new_state);
00143     }
00144 
00145     //
00146     // Part 4.
00147     // Create spontaneous transitions.
00148     //
00149 
00150     for_all_const_states(ig, G)
00151     {
00152       if (*ig != i && !G.is_final(*ig))
00153       {
00154         t_hstate_t t = sp_m[states_map_for_sp_m[proj_m[states_map_for_proj_m[*ig]]]].first;
00155         t_hstate_t u = sp_m[states_map_for_sp_m[proj_m[states_map_for_proj_m[*ig]]]].second;
00156 
00157         if (tmp_trans.is_final(t))
00158           G.add_spontaneous(*ig, state_of[u]);
00159       }
00160     }
00161 
00162     //
00163     // Part 5.
00164     // Construct the output map.
00165     //
00166 
00167     M se;
00168     partial_elimination(G, se);
00169 
00170     for_all_(M, p, se)
00171     {
00172       se_pair_t my_pair = std::make_pair(Sp_to_S[is_state_of[(*p).first]], p->second);
00173       res.insert(my_pair);
00174     }
00175   }
00176 
00177   template <typename S1, typename T1,
00178             typename S2, typename T2,
00179             typename M>
00180   void
00181   partial_evaluation(const Element<S1, T1>& E,
00182                      const Element<S2, T2>& S,
00183                      const typename Element<S2, T2>::hstate_t& p,
00184                      M& res)
00185   {
00186     do_partial_evaluation(E.structure(), E, S.structure(), S, p, res);
00187   }
00188 
00189   template<typename S, typename Auto_t, typename M, typename Chooser_t>
00190   void
00191   do_partial_elimination(const AutomataBase<S>&,
00192                          const Auto_t& a,
00193                          Chooser_t chooser,
00194                          M& state_exp_pair_set)
00195   {
00196     AUTOMATON_TYPES(Auto_t);
00197     typedef typename std::set<htransition_t>            htransition_set_t;
00198     typedef typename Auto_t::hstate_t                   hstate_t;
00199     typedef std::map<hstate_t, series_set_elt_t>        sums_t;
00200 
00201     typename htransition_set_t::const_iterator          i, j;
00202     hstate_t                                            q;
00203     htransition_set_t                                   transitions;
00204 
00205     Auto_t b = a;
00206 
00207     // Save a map linking hstates between automata a and b.
00208     // This is needed to be able to fill state_exp_pair_set with correct hstates.
00209     std::map<hstate_t, hstate_t>                        states_map;
00210     for (state_iterator i = a.states().begin(), j = b.states().begin(),
00211          end_ = a.states().end();
00212          i != end_;
00213          ++i, ++j)
00214       states_map.insert(std::make_pair(*j, *i));
00215 
00216     // FIXME: check dead code
00217 //    standardize(b);
00218 
00219     // all final states and the initial state.
00220     int num = b.final().size() + b.initial().size();
00221 
00222     while (int(b.states().size()) != num)
00223     {
00224       series_set_elt_t loop_sum(b.series());
00225       sums_t       in_sums, out_sums;
00226       typename sums_t::iterator f;
00227       q = chooser(b);
00228       if (b.is_initial(q) || b.is_final(q))
00229         continue;
00230 
00231       transitions.clear();
00232       for (delta_iterator e(b.value(), q); ! e.done(); e.next())
00233         transitions.insert(*e);
00234       for (i = transitions.begin(); i != transitions.end(); i = j)
00235       {
00236         j = i; ++j;
00237 
00238         if (b.dst_of(*i) == q)
00239           loop_sum += b.series_of(*i);
00240         else if ((f = out_sums.find(b.dst_of(*i))) !=
00241                  out_sums.end())
00242           f->second += b.series_of(*i);
00243         else
00244           out_sums.insert(std::make_pair(b.dst_of(*i), b.series_of(*i)));
00245         b.del_transition(*i);
00246       }
00247       transitions.clear();
00248       for (rdelta_iterator e(b.value(), q); ! e.done(); e.next())
00249         transitions.insert(*e);
00250       for (i = transitions.begin(); i != transitions.end(); i = j)
00251       {
00252         j = i; ++j;
00253         // here all loops have already been removed
00254         if ((f = in_sums.find(b.src_of(*i))) !=
00255             in_sums.end())
00256           f->second += b.series_of(*i);
00257         else
00258           in_sums.insert(std::make_pair(b.src_of(*i), b.series_of(*i)));
00259         b.del_transition(*i);
00260       }
00261       loop_sum.star();
00262       for_all_const_(sums_t, in, in_sums)
00263         for_all_const_(sums_t, out, out_sums)
00264         {
00265           series_set_elt_t res = in->second * loop_sum * out->second;
00266           b.add_series_transition(in->first, out->first, res);
00267         }
00268       b.del_state(q);
00269     }
00270 
00271     typedef std::map<hstate_t, series_set_elt_t>   se_map_t;
00272     typedef std::pair<hstate_t, series_set_elt_t>  state_exp_pair_t;
00273     se_map_t se_m;
00274 
00275     // maybe there are more than one transition comming to one final state
00276     // we must sum the labels
00277     for_all_transitions(e, b)
00278     {
00279       hstate_t dst = b.dst_of(*e);
00280       typename se_map_t::iterator i = se_m.find(dst);
00281       if (i == se_m.end())
00282         se_m.insert(std::make_pair(dst,
00283                                    series_set_elt_t (b.structure().series(),
00284                                                      b.label_of(*e))));
00285       else
00286         i->second += b.label_of(*e);
00287     }
00288 
00289     for_all_final_states(p, b)
00290     {
00291       typename se_map_t::iterator i = se_m.find(*p);
00292       if (i != se_m.end())
00293         state_exp_pair_set.insert(std::make_pair(states_map[*p], i->second));
00294     }
00295   }
00296 
00297   /*------------.
00298   | elimination |
00299   `------------*/
00300   // FIXME: add the generalized automaton precondition
00301   // preconditions :
00302   //   - hope that automaton's labels are sufficient to support "star"
00303   //     => in fact, generalized automaton are generally expected here.
00304   template<typename A, typename T, typename M>
00305   void
00306   partial_elimination(const Element<A, T>& a,
00307                       M& state_exp_pair_set)
00308   {
00309     do_partial_elimination(a.structure(),
00310                            a,
00311                            DefaultChooser(),
00312                            state_exp_pair_set);
00313   }
00314 
00315 } // ! vcsn
00316 
00317 #endif // ! VCSN_ALGORITHMS_EVALUATION_HXX