product.hxx

00001 // product.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 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_PRODUCT_HXX
00018 # define VCSN_ALGORITHMS_PRODUCT_HXX
00019 
00020 # include <set>
00021 # include <map>
00022 # include <queue>
00023 # include <stack>
00024 
00025 # include <vaucanson/algorithms/product.hh>
00026 
00027 # include <vaucanson/automata/concept/automata_base.hh>
00028 # include <vaucanson/tools/usual_macros.hh>
00029 # include <vaucanson/automata/implementation/geometry.hh>
00030 # include <vaucanson/misc/static.hh>
00031 
00032 # define if_(cond, then_clause, else_clause)                    \
00033   utility::static_if_simple<cond, then_clause, else_clause>::t
00034 
00035 # define eq_(type1, type2)                      \
00036   utility::static_eq<type1, type2>::value
00037 
00038 
00039 namespace vcsn {
00040 
00041   namespace geom {
00042 
00043     // Some little graphic tools
00044     struct grphx {
00045 
00046         // Diagonal alignement with a depth-first traversal
00047         template<typename I>
00048         static
00049         void align(const I& a)
00050         {
00051           AUTOMATON_TYPES(I);
00052           int x = 0;
00053           std::map<hstate_t,bool> visited;
00054           std::stack<hstate_t> stack;
00055 
00056           for_each_state(i, a) {
00057             visited[*i] = false;
00058             // ensure inaccessible states will be visited
00059             stack.push(*i);
00060           }
00061 
00062           for_each_initial_state(i, a)
00063             stack.push(*i);
00064 
00065           while (!stack.empty()) {
00066             hstate_t i = stack.top();
00067             stack.pop();
00068 
00069             if (!visited[i]) {
00070               visited[i] = true;
00071 
00072               a.geometry()[i] = std::make_pair(x, x);
00073               x++;
00074 
00075               std::list<htransition_t> aim;
00076               a.deltac(aim, i, delta_kind::transitions());
00077               for_all_const_(std::list<htransition_t>, j, aim)
00078                 stack.push(a.dst_of(*j));
00079             }
00080           }
00081         }
00082 
00083 
00084         template <typename Output, typename Lhs, typename Rhs>
00085         static
00086         void setcoordfrom(Output& a,
00087                           const Lhs& lhs,
00088                           const Rhs& rhs,
00089                           const hstate_t state,
00090                           const hstate_t x_state,
00091                           const hstate_t y_state)
00092         {
00093           std::map<hstate_t, std::pair<double, double> >::const_iterator iter;
00094           double x = 0, y = 0;
00095 
00096           iter = lhs.geometry().states().find(x_state);
00097           if (iter != lhs.geometry().states().end())
00098             x = iter->second.first;
00099 
00100           iter = rhs.geometry().states().find(y_state);
00101           if (iter != rhs.geometry().states().end())
00102             y = iter->second.second;
00103 
00104           a.geometry().states()[state] = std::make_pair(x, y);
00105         }
00106 
00107     };
00108 
00109     struct no_grphx
00110     {
00111         template <typename Output, typename Lhs, typename Rhs>
00112         static
00113         void setcoordfrom(Output& a,
00114                           const Lhs& lhs,
00115                           const Rhs& rhs,
00116                           const hstate_t state,
00117                           const hstate_t x_state,
00118                           const hstate_t y_state)
00119         {}
00120 
00121     };
00122 
00123   } // ! geom
00124 
00125 
00126   /*--------.
00127   | product |
00128   `--------*/
00129 
00130   template <typename A, typename lhs_t, typename rhs_t, typename output_t>
00131   void
00132   product(const AutomataBase<A>&,
00133           output_t&                     output,
00134           const lhs_t&                  lhs,
00135           const rhs_t&                  rhs,
00136           std::map< hstate_t, std::pair<hstate_t, hstate_t> >& m,
00137           const bool use_geometry = false)
00138   {
00139     AUTOMATON_TYPES(output_t);
00140 
00141     typedef std::pair<hstate_t, hstate_t>               pair_hstate_t;
00142     typedef std::set<htransition_t>                             delta_ret_t;
00143     typedef std::map<pair_hstate_t, hstate_t>           visited_t;
00144     typedef typename series_set_elt_t::support_t        support_t;
00145 
00146     const series_set_t& series   = output.structure().series();
00147     const monoid_t&     monoid   = series.monoid();
00148     const semiring_t&   semiring = series.semiring();
00149 
00150     const semiring_elt_t  semiring_zero =
00151       semiring.zero(SELECT(semiring_elt_value_t));
00152 
00153     visited_t                   visited;
00154     std::queue<pair_hstate_t>   to_process;
00155 
00156 
00157     /*----------------------------------.
00158     | Get initial states of the product |
00159     `----------------------------------*/
00160     for_each_initial_state(lhs_s, lhs)
00161       for_each_initial_state(rhs_s, rhs)
00162     {
00163       const hstate_t            new_state = output.add_state();
00164       const pair_hstate_t       new_pair (*lhs_s, *rhs_s);
00165 
00166       m[new_state] = new_pair;
00167       visited[new_pair] = new_state;
00168       to_process.push(new_pair);
00169 
00170       if (use_geometry)
00171         if_(eq_(typename output_t::geometry_t, geometry) and    \
00172             eq_(typename rhs_t::geometry_t, geometry) and       \
00173             eq_(typename lhs_t::geometry_t, geometry),  \
00174             geom::grphx, geom::no_grphx)
00175           ::setcoordfrom(output, lhs, rhs, new_state, *lhs_s, *rhs_s);
00176     }
00177 
00178     /*-----------.
00179     | Processing |
00180     `-----------*/
00181     while (not to_process.empty())
00182     {
00183       const pair_hstate_t current_pair  = to_process.front();
00184       to_process.pop();
00185 
00186       const hstate_t lhs_s           = current_pair.first;
00187       const hstate_t rhs_s           = current_pair.second;
00188       const hstate_t current_state = visited[current_pair];
00189 
00190       output.set_initial(current_state,
00191                          lhs.get_initial(lhs_s) * rhs.get_initial(rhs_s));
00192       output.set_final(current_state,
00193                        lhs.get_final(lhs_s) * rhs.get_final(rhs_s));
00194 
00195       delta_ret_t transition_lhs;
00196       delta_ret_t transition_rhs;
00197       lhs.deltac(transition_lhs, lhs_s, delta_kind::transitions());
00198       rhs.deltac(transition_rhs, rhs_s, delta_kind::transitions());
00199 
00200       for_all_const_(delta_ret_t, l, transition_lhs)
00201         for_all_const_(delta_ret_t, r, transition_rhs)
00202       {
00203         const series_set_elt_t  left_series  = lhs.series_of(*l);
00204         const series_set_elt_t  right_series = rhs.series_of(*r);
00205         series_set_elt_t            prod_series (series);
00206 
00207         bool                prod_is_null (true);
00208         for_all_(support_t, supp, left_series.supp())
00209         {
00210           const monoid_elt_t   supp_elt (monoid, *supp);
00211           const semiring_elt_t l = left_series.get(supp_elt);
00212           const semiring_elt_t r = right_series.get(supp_elt);
00213           const semiring_elt_t p = l * r;
00214           if (p != semiring_zero)
00215           {
00216             prod_series.assoc(*supp, p.value());
00217             prod_is_null = false;
00218           }
00219         }
00220 
00221         if (not prod_is_null)
00222         {
00223           const pair_hstate_t new_pair (lhs.dst_of(*l), rhs.dst_of(*r));
00224 
00225           typename visited_t::const_iterator found =
00226             visited.find(new_pair);
00227 
00228           hstate_t aim;
00229           if (found == visited.end())
00230           {
00231             aim = output.add_state();
00232             visited[new_pair] = aim;
00233             m[aim] = new_pair;
00234             to_process.push(new_pair);
00235 
00236             if (use_geometry)
00237               if_(eq_(typename output_t::geometry_t, geometry) and  \
00238                   eq_(typename rhs_t::geometry_t, geometry) and     \
00239                   eq_(typename lhs_t::geometry_t, geometry),        \
00240                   geom::grphx, geom::no_grphx)
00241                 ::setcoordfrom(output, lhs, rhs, aim,
00242                                new_pair.first, new_pair.second);
00243           }
00244           else
00245             aim = found->second;
00246           output.add_series_transition(current_state, aim, prod_series);
00247         }
00248       }
00249     }
00250   }
00251 
00252   // wrappers
00253   template<typename A, typename T, typename U>
00254   Element<A, T>
00255   product(const Element<A, T>& lhs, const Element<A, U>& rhs,
00256           const bool use_geometry)
00257   {
00258     std::map<hstate_t, std::pair<hstate_t, hstate_t> > m;
00259     // assertion(lhs.structure() == rhs.structure())
00260     Element<A, T> ret(rhs.structure());
00261     product(ret.structure(), ret, lhs, rhs, m, use_geometry);
00262     return ret;
00263   }
00264 
00265   template<typename A, typename T, typename U>
00266   Element<A, T>
00267   product(const Element<A, T>& lhs, const Element<A, U>& rhs,
00268           std::map<hstate_t, std::pair<hstate_t, hstate_t> >& m,
00269           const bool use_geometry)
00270   {
00271     Element<A, T> ret(rhs.structure());
00272     product(ret.structure(), ret, lhs, rhs, m, use_geometry);
00273     return ret;
00274   }
00275 
00276 } // End of namespace vcsn.
00277 
00278 
00279 #undef if_
00280 #undef eq_
00281 
00282 
00283 #endif // ! VCSN_ALGORITHMS_PRODUCT_HXX

Generated on Fri Jul 28 12:18:51 2006 for Vaucanson by  doxygen 1.4.6