00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef VCSN_ALGORITHMS_INFILTRATION_HXX
00018 # define VCSN_ALGORITHMS_INFILTRATION_HXX
00019
00020 # include <set>
00021 # include <map>
00022 # include <queue>
00023 # include <stack>
00024
00025 # include <vaucanson/algorithms/infiltration.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 Infiltration
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 Infiltration (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("infiltration");
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 for (typename rhs_t::delta_iterator r(rhs.value(), rhs_s);
00096 ! r.done();
00097 r.next())
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 for (typename lhs_t::delta_iterator l(lhs.value(), lhs_s);
00119 ! l.done();
00120 l.next())
00121 {
00122 const pair_hstate_t new_pair(lhs.dst_of(*l), rhs_s);
00123 typename visited_t::const_iterator found = visited_.find(new_pair);
00124
00125 hstate_t dst;
00126 if (found == visited_.end())
00127 {
00128 dst = output.add_state();
00129
00130 this->add_state_to_process(output, lhs, rhs, m, dst, new_pair);
00131 }
00132 else
00133 dst = found->second;
00134 output.add_series_transition(current_state, dst, lhs.series_of(*l));
00135 }
00136 for (typename rhs_t::delta_iterator r(rhs.value(), rhs_s);
00137 ! r.done();
00138 r.next())
00139 {
00140 const pair_hstate_t new_pair(lhs_s, rhs.dst_of(*r));
00141 typename visited_t::const_iterator found = visited_.find(new_pair);
00142
00143 hstate_t dst;
00144 if (found == visited_.end())
00145 {
00146 dst = output.add_state();
00147
00148 this->add_state_to_process(output, lhs, rhs, m, dst, new_pair);
00149 }
00150 else
00151 dst = found->second;
00152 output.add_series_transition(current_state, dst, rhs.series_of(*r));
00153 }
00154
00155 }
00156 merge_transitions(output);
00157 return output;
00158 }
00159
00160 private:
00161
00162 void merge_transitions(output_t& a)
00163 {
00164 typedef std::map<hstate_t, series_set_elt_t> map_t;
00165 for_all_states(s, a)
00166 {
00167 map_t map;
00168 std::list<htransition_t> transitions;
00169 for (delta_iterator e(a.value(), *s); ! e.done(); e.next())
00170 {
00171 hstate_t target = a.dst_of(*e);
00172 transitions.push_back(*e);
00173 typename map_t::iterator it = map.find(target);
00174 if (it == map.end())
00175 map.insert(std::pair<hstate_t, series_set_elt_t>(target,
00176 a.series_of(*e)));
00177 else
00178 it->second += a.series_of(*e);
00179 }
00180 for_all_(std::list<htransition_t>, e, transitions)
00181 a.del_transition(*e);
00182 for_all_(map_t, it, map)
00183 if(it->second != a.series().zero_)
00184 a.add_series_transition(*s, it->first, it->second);
00185 }
00186 }
00187
00188
00189 class grphx
00190 {
00191 public:
00192 template <typename Output, typename Lhs, typename Rhs>
00193 static void
00194 setcoordfrom (Output& a,
00195 const Lhs& lhs,
00196 const Rhs& rhs,
00197 const typename Output::hstate_t state,
00198 const typename Lhs::hstate_t x_state,
00199 const typename Rhs::hstate_t y_state)
00200 {
00201 typename std::map<typename Lhs::hstate_t,
00202 typename Lhs::geometry_t::coords_t>::const_iterator iter;
00203 typename std::map<typename Rhs::hstate_t,
00204 typename Rhs::geometry_t::coords_t>::const_iterator iter2;
00205 double x = 0, y = 0;
00206
00207 iter = lhs.geometry().states().find(x_state);
00208 if (iter != lhs.geometry().states().end())
00209 x = iter->second.first;
00210
00211 iter2 = rhs.geometry().states().find(y_state);
00212 if (iter2 != rhs.geometry().states().end())
00213 y = iter2->second.second;
00214
00215 a.geometry().states()[state] = std::make_pair(x, y);
00216 }
00217 private:
00218
00219 template<typename I>
00220 void
00221 align (const I& a)
00222 {
00223 AUTOMATON_TYPES(I);
00224 std::map<hstate_t,bool> visited;
00225 std::stack<hstate_t> stack;
00226
00227 for_all_const_states(i, a)
00228 {
00229 visited[*i] = false;
00230
00231 stack.push(*i);
00232 }
00233
00234 for_all_const_initial_states(i, a)
00235 stack.push(*i);
00236
00237 int x = 0;
00238 while (!stack.empty())
00239 {
00240 hstate_t i = stack.top();
00241 stack.pop();
00242
00243 if (!visited[i])
00244 {
00245 visited[i] = true;
00246
00247 a.geometry()[i] = std::make_pair(x, x);
00248 x++;
00249
00250 for (delta_iterator j(a.value(), i);
00251 ! j.done();
00252 j.next())
00253 stack.push(a.dst_of(*j));
00254 }
00255 }
00256 }
00257
00258 };
00259 class no_grphx
00260 {
00261 public:
00262 template <typename Output, typename Lhs, typename Rhs>
00263 static void
00264 setcoordfrom (Output& a,
00265 const Lhs& lhs,
00266 const Rhs& rhs,
00267 const typename Output::hstate_t state,
00268 const typename Lhs::hstate_t x_state,
00269 const typename Rhs::hstate_t y_state) {};
00270 };
00271
00272
00273 AUTOMATON_TYPES(output_t);
00274
00275 typedef std::pair<typename lhs_t::hstate_t, typename rhs_t::hstate_t>
00276 pair_hstate_t;
00277 typedef std::list<htransition_t> delta_ret_t;
00278 typedef std::map<pair_hstate_t, hstate_t> visited_t;
00279 typedef typename series_set_elt_t::support_t support_t;
00280
00281
00282 inline void
00283 add_state_to_process (output_t& output,
00284 const lhs_t& lhs,
00285 const rhs_t& rhs,
00286 pair_map_t& m,
00287 const hstate_t& new_state,
00288 const pair_hstate_t& new_pair)
00289 {
00290 m[new_state] = new_pair;
00291 visited_[new_pair] = new_state;
00292 to_process_.push(new_pair);
00293
00294 # define if_(Cond, ThenClause, ElseClause) \
00295 misc::static_if_simple<Cond, ThenClause, ElseClause>::t
00296 # define eq_(Type1, Type2) \
00297 misc::static_eq<Type1, Type2>::value
00298 # define DECLARE_GEOMETRY(Type) \
00299 typedef geometry<typename Type::hstate_t, typename Type::htransition_t, typename Type::geometry_coords_t> geometry_ ## Type ;
00300
00301 DECLARE_GEOMETRY(output_t)
00302 DECLARE_GEOMETRY(lhs_t)
00303 DECLARE_GEOMETRY(rhs_t)
00304 if (use_geometry_)
00305 if_(eq_(typename output_t::geometry_t, geometry_output_t) and \
00306 eq_(typename rhs_t::geometry_t, geometry_rhs_t) and \
00307 eq_(typename lhs_t::geometry_t, geometry_lhs_t), \
00308 grphx, no_grphx)
00309 ::setcoordfrom(output, lhs, rhs,
00310 new_state, new_pair.first, new_pair.second);
00311 # undef if_
00312 # undef eq_
00313 }
00314
00315
00316 inline void
00317 initialize_queue (output_t& output,
00318 const lhs_t& lhs,
00319 const rhs_t& rhs,
00320 pair_map_t& m)
00321 {
00322 for_all_const_initial_states(lhs_s, lhs)
00323 for_all_const_initial_states(rhs_s, rhs)
00324 {
00325 const pair_hstate_t new_pair(*lhs_s, *rhs_s);
00326 const hstate_t new_state = output.add_state();
00327
00328 this->add_state_to_process(output, lhs, rhs, m, new_state, new_pair);
00329 }
00330 }
00331
00332 inline bool
00333 is_product_not_null (const lhs_t& lhs,
00334 const rhs_t& rhs,
00335 const typename lhs_t::delta_iterator& l,
00336 const typename rhs_t::delta_iterator& r,
00337 series_set_elt_t& prod_series) const
00338 {
00339 const series_set_elt_t left_series = lhs.series_of(*l);
00340 const series_set_elt_t right_series = rhs.series_of(*r);
00341
00342 bool prod_is_not_null = false;
00343 for_all_(support_t, supp, left_series.supp())
00344 {
00345 const monoid_elt_t supp_elt (monoid_, *supp);
00346 const semiring_elt_t l = left_series.get(supp_elt);
00347 const semiring_elt_t r = right_series.get(supp_elt);
00348 const semiring_elt_t p = l * r;
00349 if (p != semiring_zero_)
00350 {
00351 prod_series.assoc(*supp, p.value());
00352 prod_is_not_null = true;
00353 }
00354 }
00355 return (prod_is_not_null);
00356 }
00357
00358
00359 const bool use_geometry_;
00360
00361
00362 visited_t visited_;
00363
00364 std::queue<pair_hstate_t> to_process_;
00365
00366
00367 const series_set_t& series_;
00368 const monoid_t& monoid_;
00369
00370 const semiring_elt_t semiring_zero_;
00371 };
00372
00373
00374
00375
00376
00377 template<typename A, typename T, typename U>
00378 Element<A, T>
00379 infiltration (const Element<A, T>& lhs, const Element<A, U>& rhs,
00380 std::map<typename T::hstate_t,
00381 std::pair<typename T::hstate_t, typename U::hstate_t> >& m,
00382 const bool use_geometry)
00383 {
00384 Element<A, T> ret(rhs.structure());
00385 Infiltration<A, T, U> do_infiltration(ret.structure(), use_geometry);
00386 return do_infiltration (ret, lhs, rhs, m);
00387 }
00388
00389 template<typename A, typename T, typename U>
00390 Element<A, T>
00391 infiltration (const Element<A, T>& lhs, const Element<A, U>& rhs,
00392 const bool use_geometry)
00393 {
00394 std::map<typename T::hstate_t,
00395 std::pair<typename T::hstate_t, typename U::hstate_t> > m;
00396 return infiltration (lhs, rhs, m, use_geometry);
00397 }
00398
00399 }
00400
00401 #endif // ! VCSN_ALGORITHMS_INFILTRATION_HXX