Vaucanson 1.4
normalized_composition.hxx
Go to the documentation of this file.
00001 // normalized_composition.hxx: this file is part of the Vaucanson project.
00002 //
00003 // Vaucanson, a generic library for finite state machines.
00004 //
00005 // Copyright (C) 2005, 2006, 2011 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_NORMALIZED_COMPOSITION_HXX
00018 # define VCSN_ALGORITHMS_NORMALIZED_COMPOSITION_HXX
00019 
00033 # include <set>
00034 # include <queue>
00035 # include <vaucanson/algorithms/normalized_composition.hh>
00036 # include <vaucanson/algorithms/internal/outsplitting.hh>
00037 # include <vaucanson/algebra/concept/freemonoid_product.hh>
00038 # include <vaucanson/algebra/implementation/series/series.hh>
00039 # include <vaucanson/automata/concept/automata.hh>
00040 
00041 
00042 namespace vcsn {
00043 
00044   template <typename S, typename M1, typename M2, typename lhs_t,
00045             typename rhs_t, typename res_t>
00046   struct composer
00047   {
00048     AUTOMATON_TYPES(res_t);
00049     AUTOMATON_TYPES_(lhs_t, lhs_);
00050     AUTOMATON_TYPES_(rhs_t, rhs_);
00051 
00052    #define SPECIFIC_TYPES(Auto) \
00053       typedef std::list<typename Auto##_t::htransition_t>      Auto##_delta_ret_t; \
00054 
00055     SPECIFIC_TYPES(lhs);
00056     SPECIFIC_TYPES(rhs);
00057     SPECIFIC_TYPES(res);
00058 
00059     #undef SPECIFIC_TYPES
00060     typedef std::pair<lhs_hstate_t, rhs_hstate_t>       pair_hstate_t;
00061     typedef std::map<pair_hstate_t, hstate_t>           visited_t;
00062     typedef std::map<hstate_t, pair_hstate_t>           map_of_states_t;
00063     typedef std::queue<pair_hstate_t>                   to_process_t;
00064 
00065     typedef std::list<htransition_t>                    delta_ret_t;
00066     typedef typename series_set_elt_t::support_t        support_t;
00067     typedef typename lhs_series_set_elt_t::support_t    lhs_support_t;
00068     typedef typename rhs_series_set_elt_t::support_t    rhs_support_t;
00069 
00070     typedef typename lhs_monoid_t::first_monoid_t
00071     lhs_first_monoid_t;
00072     typedef typename lhs_monoid_elt_value_t::first_type
00073     lhs_first_monoid_elt_value_t;
00074     typedef Element<lhs_first_monoid_t, lhs_first_monoid_elt_value_t>
00075     lhs_first_monoid_elt_t;
00076 
00077     typedef typename rhs_monoid_t::first_monoid_t
00078     rhs_first_monoid_t;
00079     typedef typename rhs_monoid_elt_value_t::first_type
00080     rhs_first_monoid_elt_value_t;
00081     typedef Element<rhs_first_monoid_t, rhs_first_monoid_elt_value_t>
00082     rhs_first_monoid_elt_t;
00083 
00084     typedef typename lhs_monoid_t::second_monoid_t
00085     lhs_second_monoid_t;
00086     typedef typename lhs_monoid_elt_value_t::second_type
00087     lhs_second_monoid_elt_value_t;
00088     typedef Element<lhs_second_monoid_t, lhs_second_monoid_elt_value_t>
00089     lhs_second_monoid_elt_t;
00090 
00091     typedef typename rhs_monoid_t::second_monoid_t
00092     rhs_second_monoid_t;
00093     typedef typename rhs_monoid_elt_value_t::second_type
00094     rhs_second_monoid_elt_value_t;
00095     typedef Element<rhs_second_monoid_t, rhs_second_monoid_elt_value_t>
00096     rhs_second_monoid_elt_t;
00097 
00098     visited_t visited;
00099     to_process_t to_process;
00100     map_of_states_t m;
00101 
00102     const lhs_t&                 lhs;
00103     const rhs_t&                 rhs;
00104     res_t&                       output;
00105     std::set<typename lhs_t::hstate_t>& lhs_black_states;
00106     std::set<typename rhs_t::hstate_t>& rhs_black_states;
00107 
00108     const series_set_t& series;
00109     const monoid_t&     monoid;
00110 
00111     const lhs_series_set_t&     lhs_series;
00112     const lhs_monoid_t&         lhs_monoid;
00113 
00114     const rhs_series_set_t&     rhs_series;
00115     const rhs_monoid_t&         rhs_monoid;
00116 
00117     lhs_first_monoid_elt_t lhs_first_identity;
00118     rhs_first_monoid_elt_t rhs_first_identity;
00119     lhs_second_monoid_elt_t lhs_second_identity;
00120     rhs_second_monoid_elt_t rhs_second_identity;
00121 
00122     composer (const AutomataBase<S>&,
00123               const algebra::FreeMonoidProduct<M1, M2>&,
00124               const lhs_t&                        aLhs,
00125               const rhs_t&                        aRhs,
00126               res_t&                              aOutput,
00127               std::set<typename lhs_t::hstate_t>& aLhs_states,
00128               std::set<typename rhs_t::hstate_t>& aRhs_states)
00129       : lhs (aLhs),
00130         rhs (aRhs),
00131         output (aOutput),
00132         lhs_black_states (aLhs_states),
00133         rhs_black_states (aRhs_states),
00134 
00135         series (output.structure().series()),
00136         monoid (series.monoid()),
00137 
00138         lhs_series (lhs.structure().series()),
00139         lhs_monoid (lhs_series.monoid()),
00140 
00141         rhs_series (rhs.structure().series()),
00142         rhs_monoid (rhs_series.monoid()),
00143 
00144         lhs_first_identity (algebra::identity_as<lhs_first_monoid_elt_value_t>::
00145                             of(lhs_monoid.first_monoid())),
00146         rhs_first_identity (algebra::identity_as<rhs_first_monoid_elt_value_t>::
00147                             of(rhs_monoid.first_monoid())),
00148         lhs_second_identity (algebra::identity_as<lhs_second_monoid_elt_value_t>::
00149                              of(lhs_monoid.second_monoid())),
00150         rhs_second_identity (algebra::identity_as<rhs_second_monoid_elt_value_t>::
00151                              of(rhs_monoid.second_monoid()))
00152     {
00153     }
00154 
00155     // - Add a transition between current_state and the state
00156     //   corresponding to the pair (from,to).
00157     // - If the state (from,to) does not exist, then it is created.
00158     // - The transition is labelled by prod_series.
00159     void
00160     add_transition(const hstate_t current_state,
00161                    const hstate_t from,
00162                    const hstate_t to,
00163                    typename res_t::series_set_elt_t& prod_series)
00164     {
00165       if (lhs_black_states.find(from) == lhs_black_states.end()
00166           or rhs_black_states.find(to) == rhs_black_states.end())
00167         {
00168           const pair_hstate_t new_pair (from, to);
00169 
00170           typename visited_t::const_iterator found =
00171             visited.find(new_pair);
00172           hstate_t dst;
00173           if (found == visited.end())
00174             {
00175               dst = output.add_state();
00176               visited[new_pair] = dst;
00177               m[dst] = new_pair;
00178               to_process.push(new_pair);
00179             }
00180           else
00181             dst = found->second;
00182           output.add_series_transition(current_state, dst, prod_series);
00183         }
00184     }
00185 
00186     typename res_t::series_set_elt_t
00187     series_product (typename monoid_elt_value_t::first_type l1,
00188                     typename monoid_elt_value_t::second_type l2,
00189                     semiring_elt_t w)
00190     {
00191       typename res_t::series_set_elt_t res (series);
00192       const monoid_elt_value_t word (l1, l2);
00193       res.assoc(word, w.value());
00194       return res;
00195     }
00196 
00197 
00198     // Compute the series for an initial or a final state, on the
00199     // empty word.
00200     typename res_t::series_set_elt_t
00201     state_series (lhs_series_set_elt_t l,
00202                   rhs_series_set_elt_t r)
00203     {
00204       series_set_elt_t res(series);
00205       res.assoc(monoid_elt_t(monoid,
00206                              algebra::identity_as<monoid_elt_value_t>::
00207                              of(monoid).value()),
00208                 l.get(*l.supp().begin()) * r.get(*r.supp().begin()));
00209       return res;
00210     }
00211 
00212     void process_one_pair (const hstate_t current_state,
00213                            const typename lhs_t::hstate_t lhs_s,
00214                            const hstate_t rhs_s)
00215     {
00216 
00217       if (lhs.is_initial(lhs_s) and rhs.is_initial(rhs_s))
00218         output.set_initial(current_state,
00219                            state_series (lhs.get_initial(lhs_s),
00220                                          rhs.get_initial(rhs_s)));
00221 
00222       if (lhs.is_final(lhs_s) and rhs.is_final(rhs_s))
00223         output.set_final(current_state,
00224                          state_series (lhs.get_final(lhs_s),
00225                                        rhs.get_final(rhs_s)));
00226 
00227       for (delta_iterator l(lhs.value(), lhs_s); ! l.done(); l.next())
00228         {
00229           const lhs_series_set_elt_t left_series = lhs.series_of(*l);
00230           const lhs_monoid_elt_t left_supp_elt (lhs_monoid,
00231                                                 *left_series.supp().begin());
00232 
00233           // (i)
00234           // If the outgoing transition is of type (*, 1).
00235           if (left_supp_elt.value().second == lhs_second_identity.value())
00236             {
00237               series_set_elt_t s =
00238                 series_product (left_supp_elt.value().first,
00239                                 rhs_second_identity.value(),
00240                                 left_series.get(left_supp_elt));
00241               add_transition (current_state,
00242                               lhs.dst_of(*l), rhs_s, s);
00243             }
00244           // (iii')
00245           else
00246             {
00247               for (delta_iterator r(rhs.value(), rhs_s); ! r.done(); r.next())
00248                 {
00249                   const rhs_series_set_elt_t right_series =
00250                     rhs.series_of(*r);
00251                   const rhs_monoid_elt_t right_supp_elt
00252                     (rhs_monoid, *right_series.supp().begin());
00253 
00254                   // If the incoming transition is not of type (1, *).
00255                   if (right_supp_elt.value().first !=
00256                       rhs_first_identity.value())
00257                     //  we try to connect a transition of lhs and
00258                     // a transition of rhs.
00259                     if (left_supp_elt.value().second ==
00260                         right_supp_elt.value().first)
00261                       {
00262                         series_set_elt_t s =
00263                           series_product (left_supp_elt.value().first,
00264                                           right_supp_elt.value().second,
00265                                           left_series.get(left_supp_elt)
00266                                           * right_series.get(right_supp_elt));
00267                         add_transition
00268                           (current_state,
00269                            lhs.dst_of(*l), rhs.dst_of(*r),
00270                            s);
00271                       }
00272                 }
00273             }
00274         }
00275 
00276       for (delta_iterator r(rhs.value(), rhs_s); ! r.done(); r.next())
00277         {
00278           const rhs_series_set_elt_t right_series = rhs.series_of(*r);
00279           const rhs_monoid_elt_t right_supp_elt (rhs_monoid,
00280                                                  *right_series.supp().begin());
00281 
00282           // (ii)
00283           if (right_supp_elt.value().first == rhs_first_identity.value())
00284             {
00285               series_set_elt_t s =
00286                 series_product (lhs_first_identity.value(),
00287                                 right_supp_elt.value().second,
00288                                 right_series.get(right_supp_elt));
00289               add_transition (current_state,
00290                               lhs_s, rhs.dst_of(*r), s);
00291             }
00292         }
00293 
00294     }
00295 
00296 
00297     void operator() ()
00298     {
00299 
00300       /*----------------------------------.
00301       | Get initial states of the product |
00302       `----------------------------------*/
00303       for_all_const_initial_states(lhs_s, lhs)
00304         for_all_const_initial_states(rhs_s, rhs)
00305         {
00306           if (lhs_black_states.find(*lhs_s) == lhs_black_states.end() or
00307               rhs_black_states.find(*rhs_s) == rhs_black_states.end())
00308             {
00309               const hstate_t      new_state = output.add_state();
00310               const pair_hstate_t new_pair (*lhs_s, *rhs_s);
00311 
00312               m[new_state] = new_pair;
00313               visited[new_pair] = new_state;
00314               to_process.push(new_pair);
00315             }
00316         }
00317 
00318       /*-----------.
00319       | Processing |
00320       `-----------*/
00321       while (not to_process.empty())
00322         {
00323           const pair_hstate_t p = to_process.front();
00324           to_process.pop();
00325           process_one_pair (visited[p], p.first, p.second);
00326         }
00327     }
00328   };
00329 
00330 
00331 
00334   template <typename S, typename M1, typename M2, typename lhs_t,
00335             typename rhs_t, typename res_t>
00336   void
00337   do_compose(const AutomataBase<S>&,
00338              const algebra::FreeMonoidProduct<M1, M2>&,
00339              const lhs_t& lhs,
00340              const rhs_t& rhs,
00341              res_t& ret)
00342   {
00343     AUTOMATON_TYPES(res_t);
00344 
00345     std::set<typename lhs_t::hstate_t> lhs_states;
00346     std::set<typename rhs_t::hstate_t> rhs_states;
00347 
00348     composer<S, M1, M2, lhs_t, rhs_t, res_t>
00349       compose (ret.structure(), ret.structure().series().monoid(),
00350                lhs, rhs, ret, lhs_states, rhs_states);
00351     compose ();
00352     eps_removal_here (ret);
00353   }
00354 
00357   template <typename S, typename M1, typename M2, typename lhs_t,
00358             typename rhs_t, typename res_t>
00359   void
00360   do_u_compose(const AutomataBase<S>&,
00361                const algebra::FreeMonoidProduct<M1, M2>&,
00362                const lhs_t& lhs,
00363                const rhs_t& rhs,
00364                res_t& ret)
00365   {
00366     AUTOMATON_TYPES(res_t);
00367 
00368     std::set<typename lhs_t::hstate_t> lhs_states;
00369     std::set<typename rhs_t::hstate_t> rhs_states;
00370 
00371     lhs_t lhs_cov = splitting::outsplitting(lhs, lhs_states);
00372     rhs_t rhs_cov = splitting::insplitting(rhs, rhs_states);
00373 
00374     composer<S, M1, M2, lhs_t, rhs_t, res_t>
00375       compose (ret.structure(), ret.structure().series().monoid(),
00376                lhs_cov, rhs_cov, ret, lhs_states, rhs_states);
00377     compose ();
00378 
00379     eps_removal_here (ret);
00380     sub_automaton_here (ret, useful_states (ret));
00381   }
00382 
00383 
00384 
00385   // Compose dispatchers
00386   template <typename S, typename M1, typename M2, typename lhs_t,
00387             typename rhs_t, typename res_t>
00388   void
00389   do_compose_dispatcher(const AutomataBase<S>&,
00390                         const algebra::FreeMonoidProduct<M1, M2>&,
00391                         SELECTOR(bool),
00392                         const lhs_t& lhs,
00393                         const rhs_t& rhs,
00394                         res_t& ret)
00395   {
00396     do_compose (ret.structure(),
00397                 ret.structure().series().monoid(),
00398                 lhs, rhs, ret);
00399   }
00400 
00401 
00402   template <typename S, typename M1, typename M2, typename lhs_t,
00403             typename rhs_t, typename res_t, typename weight_t>
00404   void
00405   do_compose_dispatcher(const AutomataBase<S>&,
00406                         const algebra::FreeMonoidProduct<M1, M2>&,
00407                         const weight_t&,
00408                         const lhs_t& lhs,
00409                         const rhs_t& rhs,
00410                         res_t& ret)
00411   {
00412     do_u_compose (ret.structure(),
00413                   ret.structure().series().monoid(),
00414                   lhs, rhs, ret);
00415   }
00416 
00417   // Facade for compose
00418 
00419   template <typename S, typename T>
00420   void
00421   compose(const Element<S, T>& lhs,
00422           const Element<S, T>& rhs,
00423           Element<S, T>& ret)
00424   {
00425     typedef Element<S, T> auto_t;
00426     AUTOMATON_TYPES(auto_t);
00427 
00428     for_all_states (s, ret)
00429       ret.del_state (*s);
00430 
00431     do_compose_dispatcher (ret.structure(),
00432                            ret.structure().series().monoid(),
00433                            SELECT(semiring_elt_value_t),
00434                            lhs, rhs, ret);
00435   }
00436 
00437 
00438 
00439   template <typename S, typename T>
00440   Element<S, T>
00441   compose(const Element<S, T>& lhs,
00442           const Element<S, T>& rhs)
00443   {
00444     typedef Element<S, T> auto_t;
00445     AUTOMATON_TYPES(auto_t);
00446 
00447     typedef algebra::FreeMonoidProduct<
00448     typename auto_t::series_set_t::monoid_t::first_monoid_t,
00449       typename auto_t::series_set_t::monoid_t::second_monoid_t> res_monoid_t;
00450 
00451     typedef algebra::Series<typename auto_t::series_set_t::semiring_t,
00452       res_monoid_t>
00453       res_series_set_t;
00454 
00455     res_monoid_t monoid(lhs.structure().series().monoid().first_monoid(),
00456                         rhs.structure().series().monoid().second_monoid());
00457 
00458 
00459     res_series_set_t series(lhs.structure().series().semiring(), monoid);
00460 
00461     Automata<series_set_t, kind_t> aut_set(series);
00462 
00463     Element< Automata<series_set_t, kind_t>, T> ret(aut_set);
00464     do_compose_dispatcher(ret.structure(),
00465                           ret.structure().series().monoid(),
00466                           SELECT(semiring_elt_value_t),
00467                           lhs, rhs, ret);
00468     return ret;
00469   }
00470 
00471 
00472   // Facade for unambiguous composition
00473   template <typename S, typename T>
00474   void
00475   u_compose(const Element<S, T>& lhs,
00476             const Element<S, T>& rhs,
00477             Element<S, T>& ret)
00478   {
00479     typedef Element<S, T> auto_t;
00480     AUTOMATON_TYPES(auto_t);
00481 
00482     for_all_states (s, ret)
00483       ret.del_state (*s);
00484 
00485     do_u_compose (ret.structure(),
00486                   ret.structure().series().monoid(),
00487                   lhs, rhs, ret);
00488   }
00489 
00490   template <typename S, typename T>
00491   Element<S, T>
00492   u_compose(const Element<S, T>& lhs,
00493             const Element<S, T>& rhs)
00494   {
00495     typedef Element<S, T> auto_t;
00496     AUTOMATON_TYPES(auto_t);
00497 
00498     typedef algebra::FreeMonoidProduct<
00499     typename auto_t::series_set_t::monoid_t::first_monoid_t,
00500       typename auto_t::series_set_t::monoid_t::second_monoid_t> res_monoid_t;
00501 
00502     typedef algebra::Series<typename auto_t::series_set_t::semiring_t,
00503       res_monoid_t>
00504       res_series_set_t;
00505 
00506     res_monoid_t monoid(lhs.structure().series().monoid().first_monoid(),
00507                         rhs.structure().series().monoid().second_monoid());
00508 
00509 
00510     res_series_set_t series(lhs.structure().series().semiring(), monoid);
00511 
00512     Automata<series_set_t, kind_t> aut_set(series);
00513 
00514     Element< Automata<series_set_t, kind_t>, T> ret(aut_set);
00515     do_u_compose(ret.structure(),
00516                  ret.structure().series().monoid(),
00517                  lhs, rhs, ret);
00518     return ret;
00519   }
00520 
00521 } // vcsn
00522 
00523 #endif // ! VCSN_ALGORITHMS_NORMALIZED_COMPOSITION_HXX