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 # include <vaucanson/automata/concept/automata_base.hh>
00028 # include <vaucanson/tools/usual_macros.hh>
00029 # include <vaucanson/automata/implementation/geometry.hh>
00030 # include <vaucanson/misc/static.hh>
00031
00032 # define if_(cond, then_clause, else_clause) \
00033 utility::static_if_simple<cond, then_clause, else_clause>::t
00034
00035 # define eq_(type1, type2) \
00036 utility::static_eq<type1, type2>::value
00037
00038
00039 namespace vcsn {
00040
00041 namespace geom {
00042
00043
00044 struct grphx {
00045
00046
00047 template<typename I>
00048 static
00049 void align(const I& a)
00050 {
00051 AUTOMATON_TYPES(I);
00052 int x = 0;
00053 std::map<hstate_t,bool> visited;
00054 std::stack<hstate_t> stack;
00055
00056 for_each_state(i, a) {
00057 visited[*i] = false;
00058
00059 stack.push(*i);
00060 }
00061
00062 for_each_initial_state(i, a)
00063 stack.push(*i);
00064
00065 while (!stack.empty()) {
00066 hstate_t i = stack.top();
00067 stack.pop();
00068
00069 if (!visited[i]) {
00070 visited[i] = true;
00071
00072 a.geometry()[i] = std::make_pair(x, x);
00073 x++;
00074
00075 std::list<htransition_t> aim;
00076 a.deltac(aim, i, delta_kind::transitions());
00077 for_all_const_(std::list<htransition_t>, j, aim)
00078 stack.push(a.dst_of(*j));
00079 }
00080 }
00081 }
00082
00083
00084 template <typename Output, typename Lhs, typename Rhs>
00085 static
00086 void setcoordfrom(Output& a,
00087 const Lhs& lhs,
00088 const Rhs& rhs,
00089 const hstate_t state,
00090 const hstate_t x_state,
00091 const hstate_t y_state)
00092 {
00093 std::map<hstate_t, std::pair<double, double> >::const_iterator iter;
00094 double x = 0, y = 0;
00095
00096 iter = lhs.geometry().states().find(x_state);
00097 if (iter != lhs.geometry().states().end())
00098 x = iter->second.first;
00099
00100 iter = rhs.geometry().states().find(y_state);
00101 if (iter != rhs.geometry().states().end())
00102 y = iter->second.second;
00103
00104 a.geometry().states()[state] = std::make_pair(x, y);
00105 }
00106
00107 };
00108
00109 struct no_grphx
00110 {
00111 template <typename Output, typename Lhs, typename Rhs>
00112 static
00113 void setcoordfrom(Output& a,
00114 const Lhs& lhs,
00115 const Rhs& rhs,
00116 const hstate_t state,
00117 const hstate_t x_state,
00118 const hstate_t y_state)
00119 {}
00120
00121 };
00122
00123 }
00124
00125
00126
00127
00128
00129
00130 template <typename A, typename lhs_t, typename rhs_t, typename output_t>
00131 void
00132 product(const AutomataBase<A>&,
00133 output_t& output,
00134 const lhs_t& lhs,
00135 const rhs_t& rhs,
00136 std::map< hstate_t, std::pair<hstate_t, hstate_t> >& m,
00137 const bool use_geometry = false)
00138 {
00139 AUTOMATON_TYPES(output_t);
00140
00141 typedef std::pair<hstate_t, hstate_t> pair_hstate_t;
00142 typedef std::set<htransition_t> delta_ret_t;
00143 typedef std::map<pair_hstate_t, hstate_t> visited_t;
00144 typedef typename series_set_elt_t::support_t support_t;
00145
00146 const series_set_t& series = output.structure().series();
00147 const monoid_t& monoid = series.monoid();
00148 const semiring_t& semiring = series.semiring();
00149
00150 const semiring_elt_t semiring_zero =
00151 semiring.zero(SELECT(semiring_elt_value_t));
00152
00153 visited_t visited;
00154 std::queue<pair_hstate_t> to_process;
00155
00156
00157
00158
00159
00160 for_each_initial_state(lhs_s, lhs)
00161 for_each_initial_state(rhs_s, rhs)
00162 {
00163 const hstate_t new_state = output.add_state();
00164 const pair_hstate_t new_pair (*lhs_s, *rhs_s);
00165
00166 m[new_state] = new_pair;
00167 visited[new_pair] = new_state;
00168 to_process.push(new_pair);
00169
00170 if (use_geometry)
00171 if_(eq_(typename output_t::geometry_t, geometry) and \
00172 eq_(typename rhs_t::geometry_t, geometry) and \
00173 eq_(typename lhs_t::geometry_t, geometry), \
00174 geom::grphx, geom::no_grphx)
00175 ::setcoordfrom(output, lhs, rhs, new_state, *lhs_s, *rhs_s);
00176 }
00177
00178
00179
00180
00181 while (not to_process.empty())
00182 {
00183 const pair_hstate_t current_pair = to_process.front();
00184 to_process.pop();
00185
00186 const hstate_t lhs_s = current_pair.first;
00187 const hstate_t rhs_s = current_pair.second;
00188 const hstate_t current_state = visited[current_pair];
00189
00190 output.set_initial(current_state,
00191 lhs.get_initial(lhs_s) * rhs.get_initial(rhs_s));
00192 output.set_final(current_state,
00193 lhs.get_final(lhs_s) * rhs.get_final(rhs_s));
00194
00195 delta_ret_t transition_lhs;
00196 delta_ret_t transition_rhs;
00197 lhs.deltac(transition_lhs, lhs_s, delta_kind::transitions());
00198 rhs.deltac(transition_rhs, rhs_s, delta_kind::transitions());
00199
00200 for_all_const_(delta_ret_t, l, transition_lhs)
00201 for_all_const_(delta_ret_t, r, transition_rhs)
00202 {
00203 const series_set_elt_t left_series = lhs.series_of(*l);
00204 const series_set_elt_t right_series = rhs.series_of(*r);
00205 series_set_elt_t prod_series (series);
00206
00207 bool prod_is_null (true);
00208 for_all_(support_t, supp, left_series.supp())
00209 {
00210 const monoid_elt_t supp_elt (monoid, *supp);
00211 const semiring_elt_t l = left_series.get(supp_elt);
00212 const semiring_elt_t r = right_series.get(supp_elt);
00213 const semiring_elt_t p = l * r;
00214 if (p != semiring_zero)
00215 {
00216 prod_series.assoc(*supp, p.value());
00217 prod_is_null = false;
00218 }
00219 }
00220
00221 if (not prod_is_null)
00222 {
00223 const pair_hstate_t new_pair (lhs.dst_of(*l), rhs.dst_of(*r));
00224
00225 typename visited_t::const_iterator found =
00226 visited.find(new_pair);
00227
00228 hstate_t aim;
00229 if (found == visited.end())
00230 {
00231 aim = output.add_state();
00232 visited[new_pair] = aim;
00233 m[aim] = new_pair;
00234 to_process.push(new_pair);
00235
00236 if (use_geometry)
00237 if_(eq_(typename output_t::geometry_t, geometry) and \
00238 eq_(typename rhs_t::geometry_t, geometry) and \
00239 eq_(typename lhs_t::geometry_t, geometry), \
00240 geom::grphx, geom::no_grphx)
00241 ::setcoordfrom(output, lhs, rhs, aim,
00242 new_pair.first, new_pair.second);
00243 }
00244 else
00245 aim = found->second;
00246 output.add_series_transition(current_state, aim, prod_series);
00247 }
00248 }
00249 }
00250 }
00251
00252
00253 template<typename A, typename T, typename U>
00254 Element<A, T>
00255 product(const Element<A, T>& lhs, const Element<A, U>& rhs,
00256 const bool use_geometry)
00257 {
00258 std::map<hstate_t, std::pair<hstate_t, hstate_t> > m;
00259
00260 Element<A, T> ret(rhs.structure());
00261 product(ret.structure(), ret, lhs, rhs, m, use_geometry);
00262 return ret;
00263 }
00264
00265 template<typename A, typename T, typename U>
00266 Element<A, T>
00267 product(const Element<A, T>& lhs, const Element<A, U>& rhs,
00268 std::map<hstate_t, std::pair<hstate_t, hstate_t> >& m,
00269 const bool use_geometry)
00270 {
00271 Element<A, T> ret(rhs.structure());
00272 product(ret.structure(), ret, lhs, rhs, m, use_geometry);
00273 return ret;
00274 }
00275
00276 }
00277
00278
00279 #undef if_
00280 #undef eq_
00281
00282
00283 #endif // ! VCSN_ALGORITHMS_PRODUCT_HXX