Vaucanson 1.4
|
00001 // infiltration.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, 2006, 2007, 2008, 2011 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_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 | Functor for infiltration algorithm. | 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 // returns the infiltration of @c lhs and @c rhs (and put it also in @c output) 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 //merge transitions with the same ends 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 // Some little graphic tools 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 // Diagonal alignement with a depth-first traversal 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 // ensure inaccessible states will be visited 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 // useful typedefs 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 // add a @c new_state in the queue 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 // initialize queue with all pairs of intials states from @c lhs and @c rhs 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 // If set to true, <geometry> tags of the result automaton should be filled 00359 const bool use_geometry_; 00360 00361 // keep traces of new states created 00362 visited_t visited_; 00363 // @c to_process_ stores all states of output that needs are not 00364 std::queue<pair_hstate_t> to_process_; 00365 00366 // frequently used objects in computation 00367 const series_set_t& series_; 00368 const monoid_t& monoid_; 00369 // This variable's type must not be set to a reference. 00370 const semiring_elt_t semiring_zero_; 00371 }; 00372 00373 /*-----------. 00374 | Wrappers. | 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 } // End of namespace vcsn. 00400 00401 #endif // ! VCSN_ALGORITHMS_INFILTRATION_HXX