00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef VCSN_ALGORITHMS_SHUFFLE_HXX
00018 # define VCSN_ALGORITHMS_SHUFFLE_HXX
00019
00020 # include <set>
00021 # include <map>
00022 # include <queue>
00023 # include <stack>
00024
00025 # include <vaucanson/algorithms/shuffle.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 Shuffle
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 Shuffle (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 BENCH_TASK_SCOPED("shuffle");
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 while (not to_process_.empty())
00079 {
00080 const pair_hstate_t current_pair = to_process_.front();
00081 to_process_.pop();
00082
00083 const hstate_t lhs_s = current_pair.first;
00084 const hstate_t rhs_s = current_pair.second;
00085 const hstate_t current_state = visited_[current_pair];
00086
00087 output.set_initial(current_state,
00088 lhs.get_initial(lhs_s) * rhs.get_initial(rhs_s));
00089 output.set_final(current_state,
00090 lhs.get_final(lhs_s) * rhs.get_final(rhs_s));
00091
00092 for (typename lhs_t::delta_iterator l(lhs.value(), lhs_s);
00093 ! l.done();
00094 l.next())
00095 {
00096 const pair_hstate_t new_pair(lhs.dst_of(*l), rhs_s);
00097 typename visited_t::const_iterator found = visited_.find(new_pair);
00098
00099 hstate_t dst;
00100 if (found == visited_.end())
00101 {
00102 dst = output.add_state();
00103
00104 this->add_state_to_process(output, lhs, rhs, m, dst, new_pair);
00105 }
00106 else
00107 dst = found->second;
00108 output.add_series_transition(current_state, dst, lhs.series_of(*l));
00109 }
00110 for (typename rhs_t::delta_iterator r(rhs.value(), rhs_s);
00111 ! r.done();
00112 r.next())
00113 {
00114 const pair_hstate_t new_pair(lhs_s, rhs.dst_of(*r));
00115 typename visited_t::const_iterator found = visited_.find(new_pair);
00116
00117 hstate_t dst;
00118 if (found == visited_.end())
00119 {
00120 dst = output.add_state();
00121
00122 this->add_state_to_process(output, lhs, rhs, m, dst, new_pair);
00123 }
00124 else
00125 dst = found->second;
00126 output.add_series_transition(current_state, dst, rhs.series_of(*r));
00127 }
00128
00129
00130
00131 }
00132 return output;
00133 }
00134
00135 private:
00136
00137 class grphx
00138 {
00139 public:
00140 template <typename Output, typename Lhs, typename Rhs>
00141 static void
00142 setcoordfrom (Output& a,
00143 const Lhs& lhs,
00144 const Rhs& rhs,
00145 const typename Output::hstate_t state,
00146 const typename Lhs::hstate_t x_state,
00147 const typename Rhs::hstate_t y_state)
00148 {
00149 typename std::map<typename Lhs::hstate_t,
00150 typename Lhs::geometry_t::coords_t>::const_iterator iter;
00151 typename std::map<typename Rhs::hstate_t,
00152 typename Rhs::geometry_t::coords_t>::const_iterator iter2;
00153 double x = 0, y = 0;
00154
00155 iter = lhs.geometry().states().find(x_state);
00156 if (iter != lhs.geometry().states().end())
00157 x = iter->second.first;
00158
00159 iter2 = rhs.geometry().states().find(y_state);
00160 if (iter2 != rhs.geometry().states().end())
00161 y = iter2->second.second;
00162
00163 a.geometry().states()[state] = std::make_pair(x, y);
00164 }
00165 private:
00166
00167 template<typename I>
00168 void
00169 align (const I& a)
00170 {
00171 AUTOMATON_TYPES(I);
00172 std::map<hstate_t,bool> visited;
00173 std::stack<hstate_t> stack;
00174
00175 for_all_const_states(i, a)
00176 {
00177 visited[*i] = false;
00178
00179 stack.push(*i);
00180 }
00181
00182 for_all_const_initial_states(i, a)
00183 stack.push(*i);
00184
00185 int x = 0;
00186 while (!stack.empty())
00187 {
00188 hstate_t i = stack.top();
00189 stack.pop();
00190
00191 if (!visited[i])
00192 {
00193 visited[i] = true;
00194
00195 a.geometry()[i] = std::make_pair(x, x);
00196 x++;
00197
00198 for (delta_iterator j(a.value(), i);
00199 ! j.done();
00200 j.next())
00201 stack.push(a.dst_of(*j));
00202 }
00203 }
00204 }
00205
00206 };
00207 class no_grphx
00208 {
00209 public:
00210 template <typename Output, typename Lhs, typename Rhs>
00211 static void
00212 setcoordfrom (Output& a,
00213 const Lhs& lhs,
00214 const Rhs& rhs,
00215 const typename Output::hstate_t state,
00216 const typename Lhs::hstate_t x_state,
00217 const typename Rhs::hstate_t y_state) {};
00218 };
00219
00220
00221 AUTOMATON_TYPES(output_t);
00222
00223 typedef std::pair<typename lhs_t::hstate_t, typename rhs_t::hstate_t>
00224 pair_hstate_t;
00225 typedef std::list<htransition_t> delta_ret_t;
00226 typedef std::map<pair_hstate_t, hstate_t> visited_t;
00227 typedef typename series_set_elt_t::support_t support_t;
00228
00229
00230 inline void
00231 add_state_to_process (output_t& output,
00232 const lhs_t& lhs,
00233 const rhs_t& rhs,
00234 pair_map_t& m,
00235 const hstate_t& new_state,
00236 const pair_hstate_t& new_pair)
00237 {
00238 m[new_state] = new_pair;
00239 visited_[new_pair] = new_state;
00240 to_process_.push(new_pair);
00241
00242 # define if_(Cond, ThenClause, ElseClause) \
00243 misc::static_if_simple<Cond, ThenClause, ElseClause>::t
00244 # define eq_(Type1, Type2) \
00245 misc::static_eq<Type1, Type2>::value
00246 # define DECLARE_GEOMETRY(Type) \
00247 typedef geometry<typename Type::hstate_t, typename Type::htransition_t, typename Type::geometry_coords_t> geometry_ ## Type ;
00248
00249 DECLARE_GEOMETRY(output_t)
00250 DECLARE_GEOMETRY(lhs_t)
00251 DECLARE_GEOMETRY(rhs_t)
00252 if (use_geometry_)
00253 if_(eq_(typename output_t::geometry_t, geometry_output_t) and \
00254 eq_(typename rhs_t::geometry_t, geometry_rhs_t) and \
00255 eq_(typename lhs_t::geometry_t, geometry_lhs_t), \
00256 grphx, no_grphx)
00257 ::setcoordfrom(output, lhs, rhs,
00258 new_state, new_pair.first, new_pair.second);
00259 # undef if_
00260 # undef eq_
00261 }
00262
00263
00264 inline void
00265 initialize_queue (output_t& output,
00266 const lhs_t& lhs,
00267 const rhs_t& rhs,
00268 pair_map_t& m)
00269 {
00270 for_all_const_initial_states(lhs_s, lhs)
00271 for_all_const_initial_states(rhs_s, rhs)
00272 {
00273 const pair_hstate_t new_pair(*lhs_s, *rhs_s);
00274 const hstate_t new_state = output.add_state();
00275
00276 this->add_state_to_process(output, lhs, rhs, m, new_state, new_pair);
00277 }
00278 }
00279
00280 inline bool
00281 is_shuffle_not_null (const lhs_t& lhs,
00282 const rhs_t& rhs,
00283 const typename lhs_t::delta_iterator& l,
00284 const typename rhs_t::delta_iterator& r,
00285 series_set_elt_t& prod_series) const
00286 {
00287 const series_set_elt_t left_series = lhs.series_of(*l);
00288 const series_set_elt_t right_series = rhs.series_of(*r);
00289
00290 bool prod_is_not_null = false;
00291 for_all_(support_t, supp, left_series.supp())
00292 {
00293 const monoid_elt_t supp_elt (monoid_, *supp);
00294 const semiring_elt_t l = left_series.get(supp_elt);
00295 const semiring_elt_t r = right_series.get(supp_elt);
00296 const semiring_elt_t p = l * r;
00297 if (p != semiring_zero_)
00298 {
00299 prod_series.assoc(*supp, p.value());
00300 prod_is_not_null = true;
00301 }
00302 }
00303 return (prod_is_not_null);
00304 }
00305
00306
00307 const bool use_geometry_;
00308
00309
00310 visited_t visited_;
00311
00312 std::queue<pair_hstate_t> to_process_;
00313
00314
00315 const series_set_t& series_;
00316 const monoid_t& monoid_;
00317
00318 const semiring_elt_t semiring_zero_;
00319 };
00320
00321
00322
00323
00324
00325 template<typename A, typename T, typename U>
00326 Element<A, T>
00327 shuffle (const Element<A, T>& lhs, const Element<A, U>& rhs,
00328 std::map<typename T::hstate_t,
00329 std::pair<typename T::hstate_t, typename U::hstate_t> >& m,
00330 const bool use_geometry)
00331 {
00332 Element<A, T> ret(rhs.structure());
00333 Shuffle<A, T, U> do_shuffle(ret.structure(), use_geometry);
00334 return do_shuffle (ret, lhs, rhs, m);
00335 }
00336
00337 template<typename A, typename T, typename U>
00338 Element<A, T>
00339 shuffle (const Element<A, T>& lhs, const Element<A, U>& rhs,
00340 const bool use_geometry)
00341 {
00342 std::map<typename T::hstate_t,
00343 std::pair<typename T::hstate_t, typename U::hstate_t> > m;
00344 return shuffle (lhs, rhs, m, use_geometry);
00345 }
00346
00347 }
00348
00349 #endif // ! VCSN_ALGORITHMS_SHUFFLE_HXX