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