00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 #ifndef VCSN_ALGORITHMS_LETTER_TO_LETTER_COMPOSITION_HXX
00018 # define VCSN_ALGORITHMS_LETTER_TO_LETTER_COMPOSITION_HXX
00019 
00020 # include <vaucanson/automata/concept/transducer_base.hh>
00021 # include <vaucanson/misc/usual_macros.hh>
00022 
00023 # include <set>
00024 # include <map>
00025 
00026 namespace vcsn {
00027 
00028 
00029   template <class Self, class T>
00030   Element<Self, T>
00031   do_letter_to_letter_composition(const TransducerBase<Self>& s,
00032                                   const Element<Self, T>& f,
00033                                   const Element<Self, T>& g)
00034   {
00035     typedef Element<Self, T> transducer_t;
00036     AUTOMATON_TYPES(transducer_t);
00037     typedef std::map<std::pair<hstate_t, hstate_t>, hstate_t> assoc_t;
00038     typedef std::set<htransition_t> delta_ret_t;
00039 
00040     semiring_t output_series(f.series().semiring().semiring(),
00041                              f.series().semiring().monoid());
00042     series_set_t series(output_series, g.series().monoid());
00043     automata_set_t structure(series);
00044     transducer_t output(s);
00045     delta_ret_t f_delta_ret, g_delta_ret;
00046     assoc_t conv;
00047     series_set_elt_t zero =
00048       algebra::zero_as<series_set_elt_value_t>::of(output.series());
00049 
00050     for_all_states(s, f)
00051       for_all_states(t, g)
00052     {
00053       hstate_t ns = output.add_state();
00054       conv[std::make_pair(*s, *t)] = ns;
00055       output.set_initial(ns,
00056                          f.get_initial(*s) * g.get_initial(*t));
00057       output.set_final(ns,
00058                        f.get_final(*s) * g.get_final(*t));
00059 
00060     }
00061 
00062     for_all_states(s, f)
00063       for_all_states(t, g)
00064     {
00065       f_delta_ret.clear();
00066       g_delta_ret.clear();
00067 
00068       f.deltac(f_delta_ret, *s, delta_kind::transitions());
00069       g.deltac(g_delta_ret, *t, delta_kind::transitions());
00070 
00071       for_all_const_(delta_ret_t, lhs_e, f_delta_ret)
00072       {
00073         series_set_elt_t l = f.series_of(*lhs_e);
00074         for_all_const_(delta_ret_t, rhs_e, g_delta_ret)
00075         {
00076           series_set_elt_t l_ = g.series_of(*rhs_e);
00077           series_set_elt_t l__(series);
00078           typedef typename series_set_t::support_t support_t;
00079           for_all_const_(support_t, supp, l.supp())
00080           {
00081             semiring_elt_t ol = l.get(*supp);
00082             typedef typename semiring_elt_t::support_t wsupport_t;
00083             wsupport_t wsupp = ol.supp();
00084             series_set_t ts(series, monoid_elt_t(*supp));
00085             for_all_const_(wsupport_t, ss, wsupp)
00086               l__ += ts * l_.get(*ss);
00087           }
00088           if (l__ != zero)
00089           {
00090             output.add_series_transition(conv[std::make_pair(*s, *t)],
00091                                          conv[std::make_pair(f.dst_of(*lhs_e),
00092                                                              g.dst_of(*rhs_e))
00093                                            ],
00094                                          l__);
00095           }
00096         }
00097       }
00098     }
00099     return output;
00100   }
00101 
00102   template <class S, class T>
00103   Element<S, T>
00104   letter_to_letter_composition(const Element<S, T>& lhs,
00105                                const Element<S, T>& rhs)
00106   {
00107     TIMER_SCOPED("letter_to_letter_composition");
00108     return do_letter_to_letter_composition(lhs.structure(), lhs, rhs);
00109   }
00110 
00111 } 
00112 
00113 #endif // ! VCSN_ALGORITHMS_LETTER_TO_LETTER_COMPOSITION_HXX