00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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 # ifndef VCSN_NDEBUG
00028 # include <vaucanson/algorithms/realtime.hh>
00029 # endif // ! VCSN_NDEBUG
00030
00031 # include <vaucanson/automata/concept/automata_base.hh>
00032 # include <vaucanson/misc/usual_macros.hh>
00033 # include <vaucanson/automata/implementation/geometry.hh>
00034 # include <vaucanson/misc/static.hh>
00035
00036 namespace vcsn
00037 {
00038
00039
00040
00041
00042 template<typename A, typename T, typename U>
00043 class Product
00044 {
00045 public:
00046 typedef AutomataBase<A> structure_t;
00047 typedef Element<A, T> lhs_t;
00048 typedef Element<A, U> rhs_t;
00049 typedef lhs_t output_t;
00050 typedef std::map<typename output_t::hstate_t,
00051 std::pair<typename lhs_t::hstate_t, typename rhs_t::hstate_t> >
00052 pair_map_t;
00053
00054 Product (const structure_t& structure,
00055 const bool use_geometry)
00056 : use_geometry_(use_geometry),
00057 series_(structure.series()),
00058 monoid_(series_.monoid()),
00059 semiring_zero_(series_.semiring().zero(SELECT(semiring_elt_value_t)))
00060 {
00061 }
00062
00063
00064 output_t&
00065 operator() (output_t& output,
00066 const lhs_t& lhs,
00067 const rhs_t& rhs,
00068 pair_map_t& m)
00069 {
00070 TIMER_SCOPED("product");
00071 visited_.clear();
00072
00073 precondition(is_realtime(lhs));
00074 precondition(is_realtime(rhs));
00075
00076 this->initialize_queue(output, lhs, rhs, m);
00077
00078 delta_ret_t transition_lhs;
00079 delta_ret_t transition_rhs;
00080 while (not to_process_.empty())
00081 {
00082 const pair_hstate_t current_pair = to_process_.front();
00083 to_process_.pop();
00084
00085 const hstate_t lhs_s = current_pair.first;
00086 const hstate_t rhs_s = current_pair.second;
00087 const hstate_t current_state = visited_[current_pair];
00088
00089 output.set_initial(current_state,
00090 lhs.get_initial(lhs_s) * rhs.get_initial(rhs_s));
00091 output.set_final(current_state,
00092 lhs.get_final(lhs_s) * rhs.get_final(rhs_s));
00093
00094 transition_lhs.clear();
00095 transition_rhs.clear();
00096 lhs.deltac(transition_lhs, lhs_s, delta_kind::transitions());
00097 rhs.deltac(transition_rhs, rhs_s, delta_kind::transitions());
00098
00099 for_all_const_(delta_ret_t, l, transition_lhs)
00100 for_all_const_(delta_ret_t, r, transition_rhs)
00101 {
00102 series_set_elt_t prod_series(series_);
00103
00104 if (is_product_not_null(lhs, rhs, l, r, prod_series))
00105 {
00106 const pair_hstate_t new_pair(lhs.dst_of(*l), rhs.dst_of(*r));
00107 typename visited_t::const_iterator found = visited_.find(new_pair);
00108
00109 hstate_t dst;
00110 if (found == visited_.end())
00111 {
00112 dst = output.add_state();
00113
00114 this->add_state_to_process(output, lhs, rhs, m, dst, new_pair);
00115 }
00116 else
00117 dst = found->second;
00118 output.add_series_transition(current_state, dst, prod_series);
00119 }
00120 }
00121 }
00122 return output;
00123 }
00124
00125 private:
00126
00127 class grphx
00128 {
00129 public:
00130 template <typename Output, typename Lhs, typename Rhs>
00131 static void
00132 setcoordfrom (Output& a,
00133 const Lhs& lhs,
00134 const Rhs& rhs,
00135 const typename Output::hstate_t state,
00136 const typename Lhs::hstate_t x_state,
00137 const typename Rhs::hstate_t y_state)
00138 {
00139 typename std::map<typename Lhs::hstate_t,
00140 typename Lhs::geometry_t::coords_t>::const_iterator iter;
00141 typename std::map<typename Rhs::hstate_t,
00142 typename Rhs::geometry_t::coords_t>::const_iterator iter2;
00143 double x = 0, y = 0;
00144
00145 iter = lhs.geometry().states().find(x_state);
00146 if (iter != lhs.geometry().states().end())
00147 x = iter->second.first;
00148
00149 iter2 = rhs.geometry().states().find(y_state);
00150 if (iter2 != rhs.geometry().states().end())
00151 y = iter2->second.second;
00152
00153 a.geometry().states()[state] = std::make_pair(x, y);
00154 }
00155 private:
00156
00157 template<typename I>
00158 void
00159 align (const I& a)
00160 {
00161 AUTOMATON_TYPES(I);
00162 std::map<hstate_t,bool> visited;
00163 std::stack<hstate_t> stack;
00164
00165 for_all_const_states(i, a)
00166 {
00167 visited[*i] = false;
00168
00169 stack.push(*i);
00170 }
00171
00172 for_all_const_initial_states(i, a)
00173 stack.push(*i);
00174
00175 int x = 0;
00176 while (!stack.empty())
00177 {
00178 hstate_t i = stack.top();
00179 stack.pop();
00180
00181 if (!visited[i])
00182 {
00183 visited[i] = true;
00184
00185 a.geometry()[i] = std::make_pair(x, x);
00186 x++;
00187
00188 std::vector<htransition_t> dst;
00189 a.deltac(dst, i, delta_kind::transitions());
00190 for_all_const_(std::vector<htransition_t>, j, dst)
00191 stack.push(a.dst_of(*j));
00192 }
00193 }
00194 }
00195
00196 };
00197 class no_grphx
00198 {
00199 public:
00200 template <typename Output, typename Lhs, typename Rhs>
00201 static void
00202 setcoordfrom (Output& a,
00203 const Lhs& lhs,
00204 const Rhs& rhs,
00205 const typename Output::hstate_t state,
00206 const typename Lhs::hstate_t x_state,
00207 const typename Rhs::hstate_t y_state) {};
00208 };
00209
00210
00211 AUTOMATON_TYPES(output_t);
00212
00213 typedef std::pair<typename lhs_t::hstate_t, typename rhs_t::hstate_t>
00214 pair_hstate_t;
00215 typedef std::list<htransition_t> delta_ret_t;
00216 typedef std::map<pair_hstate_t, hstate_t> visited_t;
00217 typedef typename series_set_elt_t::support_t support_t;
00218
00219
00220 inline void
00221 add_state_to_process (output_t& output,
00222 const lhs_t& lhs,
00223 const rhs_t& rhs,
00224 pair_map_t& m,
00225 const hstate_t& new_state,
00226 const pair_hstate_t& new_pair)
00227 {
00228 m[new_state] = new_pair;
00229 visited_[new_pair] = new_state;
00230 to_process_.push(new_pair);
00231
00232 # define if_(Cond, ThenClause, ElseClause) \
00233 misc::static_if_simple<Cond, ThenClause, ElseClause>::t
00234 # define eq_(Type1, Type2) \
00235 misc::static_eq<Type1, Type2>::value
00236 # define DECLARE_GEOMETRY(Type) \
00237 typedef geometry<typename Type::hstate_t, typename Type::htransition_t, typename Type::geometry_coords_t> geometry_ ## Type ;
00238
00239 DECLARE_GEOMETRY(output_t)
00240 DECLARE_GEOMETRY(lhs_t)
00241 DECLARE_GEOMETRY(rhs_t)
00242 if (use_geometry_)
00243 if_(eq_(typename output_t::geometry_t, geometry_output_t) and \
00244 eq_(typename rhs_t::geometry_t, geometry_rhs_t) and \
00245 eq_(typename lhs_t::geometry_t, geometry_lhs_t), \
00246 grphx, no_grphx)
00247 ::setcoordfrom(output, lhs, rhs,
00248 new_state, new_pair.first, new_pair.second);
00249 # undef if_
00250 # undef eq_
00251 }
00252
00253
00254 inline void
00255 initialize_queue (output_t& output,
00256 const lhs_t& lhs,
00257 const rhs_t& rhs,
00258 pair_map_t& m)
00259 {
00260 for_all_const_initial_states(lhs_s, lhs)
00261 for_all_const_initial_states(rhs_s, rhs)
00262 {
00263 const pair_hstate_t new_pair(*lhs_s, *rhs_s);
00264 const hstate_t new_state = output.add_state();
00265
00266 this->add_state_to_process(output, lhs, rhs, m, new_state, new_pair);
00267 }
00268 }
00269
00270 inline bool
00271 is_product_not_null (const lhs_t& lhs,
00272 const rhs_t& rhs,
00273 const typename delta_ret_t::const_iterator& l,
00274 const typename delta_ret_t::const_iterator& r,
00275 series_set_elt_t& prod_series) const
00276 {
00277 const series_set_elt_t left_series = lhs.series_of(*l);
00278 const series_set_elt_t right_series = rhs.series_of(*r);
00279
00280 bool prod_is_not_null = false;
00281 for_all_(support_t, supp, left_series.supp())
00282 {
00283 const monoid_elt_t supp_elt (monoid_, *supp);
00284 const semiring_elt_t l = left_series.get(supp_elt);
00285 const semiring_elt_t r = right_series.get(supp_elt);
00286 const semiring_elt_t p = l * r;
00287 if (p != semiring_zero_)
00288 {
00289 prod_series.assoc(*supp, p.value());
00290 prod_is_not_null = true;
00291 }
00292 }
00293 return (prod_is_not_null);
00294 }
00295
00296
00297 const bool use_geometry_;
00298
00299
00300 visited_t visited_;
00301
00302 std::queue<pair_hstate_t> to_process_;
00303
00304
00305 const series_set_t& series_;
00306 const monoid_t& monoid_;
00307
00308 const semiring_elt_t semiring_zero_;
00309 };
00310
00311
00312
00313
00314
00315 template<typename A, typename T, typename U>
00316 Element<A, T>
00317 product (const Element<A, T>& lhs, const Element<A, U>& rhs,
00318 std::map<typename T::hstate_t,
00319 std::pair<typename T::hstate_t, typename U::hstate_t> >& m,
00320 const bool use_geometry)
00321 {
00322 Element<A, T> ret(rhs.structure());
00323 Product<A, T, U> do_product(ret.structure(), use_geometry);
00324 return do_product (ret, lhs, rhs, m);
00325 }
00326
00327 template<typename A, typename T, typename U>
00328 Element<A, T>
00329 product (const Element<A, T>& lhs, const Element<A, U>& rhs,
00330 const bool use_geometry)
00331 {
00332 std::map<typename T::hstate_t,
00333 std::pair<typename T::hstate_t, typename U::hstate_t> > m;
00334 return product (lhs, rhs, m, use_geometry);
00335 }
00336
00337 }
00338
00339 #endif // ! VCSN_ALGORITHMS_PRODUCT_HXX