Vaucanson 1.4
|
00001 // standard.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, 2009, 00006 // 2010, 2011 The Vaucanson Group. 00007 // 00008 // This program is free software; you can redistribute it and/or 00009 // modify it under the terms of the GNU General Public License 00010 // as published by the Free Software Foundation; either version 2 00011 // of the License, or (at your option) any later version. 00012 // 00013 // The complete GNU General Public Licence Notice can be found as the 00014 // `COPYING' file in the root directory. 00015 // 00016 // The Vaucanson Group consists of people listed in the `AUTHORS' file. 00017 // 00018 #ifndef VCSN_ALGORITHMS_STANDARD_HXX 00019 # define VCSN_ALGORITHMS_STANDARD_HXX 00020 00021 # include <vaucanson/algorithms/standard.hh> 00022 # include <vaucanson/algorithms/one_eps_closure.hh> 00023 # include <vaucanson/algorithms/internal/has_neighbour.hh> 00024 # include <vaucanson/algorithms/internal/build_pattern.hh> 00025 00026 # include <vaucanson/algorithms/accessible.hh> 00027 # include <vaucanson/automata/concept/automata_base.hh> 00028 # include <vaucanson/automata/concept/automata.hh> 00029 # include <vaucanson/misc/usual_macros.hh> 00030 00031 # include <set> 00032 00033 namespace vcsn { 00034 00035 /*------------. 00036 | basic_sptr | 00037 `------------*/ 00038 00039 template<typename HSTATE, typename WEIGHT> 00040 struct basic_sptr 00041 { 00042 private: 00043 const HSTATE& src_; 00044 const HSTATE& dst_; 00045 const WEIGHT& weight_; 00046 00047 public: 00048 basic_sptr(const HSTATE& src, const HSTATE& dst, const WEIGHT& weight) : 00049 src_(src), dst_(dst), weight_(weight) {} 00050 00051 HSTATE src() const { 00052 return src_; 00053 } 00054 00055 HSTATE dst() const { 00056 return dst_; 00057 } 00058 00059 WEIGHT weight() const { 00060 return weight_; 00061 } 00062 }; 00063 00064 00065 /*--------. 00066 | union | 00067 `--------*/ 00068 00069 template <typename A, typename AI1, typename AI2> 00070 void 00071 do_union_here(const AutomataBase<A>&, 00072 Element<A, AI1>& lhs, 00073 const Element<A, AI2>& rhs) 00074 { 00075 typedef Element<A, AI1> lhs_t; 00076 AUTOMATON_TYPES(lhs_t); 00077 typedef Element<A, AI2> rhs_t; 00078 typedef typename rhs_t::hstate_t r_hstate_t; 00079 00080 std::map<r_hstate_t, hstate_t> states_map; 00081 00082 // union of states 00083 for_all_states(it, rhs) 00084 { 00085 hstate_t new_state = lhs.add_state(); 00086 states_map[*it] = new_state; 00087 00088 lhs.set_initial(new_state, rhs.get_initial(*it)); 00089 lhs.set_final(new_state, rhs.get_final(*it)); 00090 } 00091 00092 // union of transitions. 00093 for_all_transitions(it, rhs) 00094 { 00095 lhs.add_transition(states_map[rhs.src_of(*it)], 00096 states_map[rhs.dst_of(*it)], 00097 rhs.label_of(*it)); 00098 } 00099 } 00100 00101 // wrappers for union 00102 template<typename A, typename AI1, typename AI2> 00103 void 00104 union_here(Element<A, AI1>& lhs, const Element<A, AI2>& rhs) 00105 { 00106 do_union_here(lhs.structure(), lhs, rhs); 00107 } 00108 00109 00110 template<typename A, typename AI1, typename AI2> 00111 Element<A, AI1> 00112 union_(const Element<A, AI1>& lhs, const Element<A, AI2>& rhs) 00113 { 00114 Element<A, AI1> ret(lhs); 00115 do_union_here(ret.structure(), ret, rhs); 00116 return ret; 00117 } 00118 00119 // same as union, but keeps track of two states in the union 00120 // (will be used for initial states) 00121 template <typename A, typename AI1, typename AI2> 00122 void 00123 marked_union_here(const AutomataBase<A>&, 00124 Element<A, AI1>& lhs, 00125 const Element<A, AI2>& rhs, 00126 const typename Element<A, AI1>::hstate_t& lhs_stt, 00127 typename Element<A, AI1>::hstate_t& mrk_stt, 00128 const typename Element<A, AI2>::hstate_t& rhs_stt) 00129 { 00130 typedef Element<A, AI1> lhs_t; 00131 AUTOMATON_TYPES(lhs_t); 00132 typedef Element<A, AI2> rhs_t; 00133 typedef typename rhs_t::hstate_t r_hstate_t; 00134 std::map<r_hstate_t, hstate_t> states_map; 00135 00136 // copy of rhs states into lhs 00137 for_all_states(it, rhs) 00138 { 00139 hstate_t new_state = lhs.add_state(); 00140 states_map[*it] = new_state; 00141 00142 lhs.set_initial(new_state, rhs.get_initial(*it)); 00143 lhs.set_final(new_state, rhs.get_final(*it)); 00144 } 00145 mrk_stt = states_map[rhs_stt]; // mark copy of rhs_stt 00146 00147 // copy of rhs transitions into lhs 00148 for_all_transitions(it, rhs) 00149 { 00150 lhs.add_transition(states_map[rhs.src_of(*it)], 00151 states_map[rhs.dst_of(*it)], 00152 rhs.label_of(*it)); 00153 } 00154 } 00155 00156 /*--------------. 00157 | is_standard. | 00158 `--------------*/ 00159 template<typename A, typename AI> 00160 bool 00161 do_is_standard(const AutomataBase<A>&, const Element<A, AI>& a) 00162 { 00163 BENCH_TASK_SCOPED("is_standard"); 00164 typedef Element<A, AI> automaton_t; 00165 typedef typename automaton_t::series_set_elt_value_t series_set_elt_value_t; 00166 00167 // Check there is only one initial state. 00168 if (a.initial().size() != 1) 00169 return false; 00170 00171 // Check the multiplicity of the initial state. 00172 typename automaton_t::hstate_t s = *a.initial().begin(); 00173 if (a.get_initial(s) 00174 != a.series().identity(SELECT(series_set_elt_value_t))) 00175 return false; 00176 00177 // Check that there is no input transition on the initial state. 00178 return !has_predecessors(a, s); 00179 } 00180 00181 template<typename A, typename AI> 00182 bool 00183 is_standard(const Element<A, AI>& a) 00184 { 00185 return do_is_standard(a.structure(), a); 00186 } 00187 00188 /*------------. 00189 | standardize | 00190 `------------*/ 00191 00192 template<typename S, typename AI> 00193 void 00194 do_standardize(const AutomataBase<S>&, Element<S, AI>& a) 00195 { 00196 BENCH_TASK_SCOPED("standardize"); 00197 typedef Element<S, AI> automaton_t; 00198 AUTOMATON_TYPES(automaton_t); 00199 typedef basic_sptr<hstate_t, series_set_elt_t> sptr_t; 00200 typedef typename std::list<hstate_t> stt_lst_t; 00201 00202 stt_lst_t stt_list; 00203 series_set_elt_t fin_wgt = 00204 algebra::zero_as<series_set_elt_value_t>::of(a.series()); 00205 00206 if (is_standard(a)) return; 00207 00208 hstate_t i = a.add_state(); // add a new state that will be the 00209 // initial state 00210 // put all initial states of a in a list 00211 for_all_initial_states(it, a) stt_list.push_back(*it); 00212 00213 for_all(typename stt_lst_t, it, stt_list) 00214 { 00215 hstate_t ini_stt = *it; 00216 series_set_elt_t ini_wgt = a.get_initial(ini_stt); 00217 00218 // emulates closure with respect of a spt transition between i and ini_stt 00219 sptr_t t(i, ini_stt, ini_wgt); 00220 one_eps_closure(a, t, misc::backward); 00221 // computes the final weight of the new initial state 00222 a.unset_initial(ini_stt); 00223 // delete state if there is zero incoming transitions 00224 if (!has_predecessors(a, ini_stt)) 00225 a.del_state(ini_stt); 00226 } 00227 00228 a.set_initial(i); 00229 00230 return; 00231 } 00232 00233 // standardize is always 'here' 00234 template<typename A, typename AI> 00235 void 00236 standardize(Element<A, AI>& a) 00237 { 00238 do_standardize(a.structure(), a); 00239 } 00240 00241 /*-----------------. 00242 | sum_of_standard | 00243 `-----------------*/ 00244 00245 template <typename A, typename AI> 00246 void 00247 sum_of_standard_inside(const AutomataBase<A>&, Element<A, AI>& aut, 00248 const typename Element<A, AI>::hstate_t& aut_stt, 00249 typename Element<A, AI>::hstate_t& mrk_stt) 00250 { 00251 typedef Element<A, AI> automaton_t; AUTOMATON_TYPES(automaton_t); 00252 typedef series_set_elt_t weight_t; 00253 typedef basic_sptr<hstate_t, weight_t> sptr_t; 00254 00255 weight_t unit = aut.series().identity(SELECT(series_set_elt_value_t)); 00256 00257 sptr_t t(aut_stt, mrk_stt, unit); 00258 one_eps_closure(aut, t, misc::backward); 00259 aut.del_state(mrk_stt); 00260 } 00261 00262 00263 template <typename A, typename AI1, typename AI2> 00264 void 00265 do_sum_of_standard_here(const AutomataBase<A>&, 00266 Element<A, AI1>& lhs, 00267 const Element<A, AI2>& rhs) 00268 { 00269 BENCH_TASK_SCOPED("sum_of_standard"); 00270 00271 typedef Element<A, AI1> lhs_t; 00272 AUTOMATON_TYPES(lhs_t); 00273 typedef Element<A, AI2> rhs_t; 00274 typedef typename rhs_t::hstate_t r_hstate_t; 00275 00276 hstate_t mrk_stt; 00277 00278 // Mark the initial states 00279 hstate_t lhs_stt = *lhs.initial().begin(); 00280 r_hstate_t rhs_stt = *rhs.initial().begin(); 00281 00282 marked_union_here(lhs.structure(), lhs, rhs, lhs_stt, mrk_stt, rhs_stt); 00283 00284 sum_of_standard_inside(lhs.structure(), lhs, lhs_stt, mrk_stt); 00285 } 00286 00287 00288 template<typename A, typename AI1, typename AI2> 00289 void 00290 sum_of_standard_here(Element<A, AI1>& lhs, const Element<A, AI2>& rhs) 00291 { 00292 precondition(is_standard(lhs)); 00293 precondition(is_standard(rhs)); 00294 do_sum_of_standard_here(lhs.structure(), lhs, rhs); 00295 } 00296 00297 template<typename A, typename AI1, typename AI2> 00298 Element<A, AI1> 00299 sum_of_standard(const Element<A, AI1>& lhs, const Element<A, AI2>& rhs) 00300 { 00301 precondition(is_standard(lhs)); 00302 precondition(is_standard(rhs)); 00303 Element<A, AI1> ret(lhs); 00304 sum_of_standard_here(ret, rhs); 00305 return ret; 00306 } 00307 00308 /*---------------------. 00309 | concat_of_standard. | 00310 `---------------------*/ 00311 00312 00313 template <typename A, typename AI> 00314 void 00315 concat_of_standard_inside(const AutomataBase<A>&, Element<A, AI>& aut, 00316 typename std::list<typename Element<A, AI>::hstate_t>& stt_list, 00317 typename Element<A, AI>::hstate_t& mrk_stt) 00318 { 00319 typedef Element<A, AI> aut_t; 00320 AUTOMATON_TYPES(aut_t); 00321 typedef series_set_elt_t weight_t; 00322 typedef typename std::list<hstate_t> stt_lst_t; 00323 typedef basic_sptr<hstate_t, weight_t> sptr_t; 00324 00325 weight_t mrk_wgt = aut.get_final(mrk_stt); 00326 00327 for_all(typename stt_lst_t, it, stt_list) 00328 { 00329 hstate_t fin_stt = *it; 00330 weight_t fin_wgt = aut.get_final(fin_stt); 00331 aut.unset_final(fin_stt); 00332 sptr_t t(fin_stt, mrk_stt, fin_wgt); 00333 one_eps_closure(aut, t, misc::backward); 00334 } 00335 aut.del_state(mrk_stt); 00336 } 00337 00338 00339 template <typename A, typename AI1, typename AI2> 00340 void 00341 do_concat_of_standard_here(const AutomataBase<A>&, 00342 Element<A, AI1>& lhs, 00343 const Element<A, AI2>& rhs) 00344 { 00345 BENCH_TASK_SCOPED("concat_of_standard"); 00346 00347 typedef Element<A, AI1> lhs_t; 00348 AUTOMATON_TYPES(lhs_t); 00349 typedef std::list<hstate_t> stt_lst_t; 00350 typedef Element<A, AI2> rhs_t; 00351 typedef typename rhs_t::hstate_t r_hstate_t; 00352 00353 // Remember list of final states in lhs 00354 stt_lst_t stt_list; 00355 for_all_final_states(it, lhs) stt_list.push_back(*it); 00356 00357 // Mark the initial states and perform marked union of states 00358 hstate_t mrk_stt; 00359 hstate_t lhs_stt = *lhs.initial().begin(); 00360 r_hstate_t rhs_stt = *rhs.initial().begin(); 00361 marked_union_here(lhs.structure(), lhs, rhs, lhs_stt, mrk_stt, rhs_stt); 00362 00363 concat_of_standard_inside(lhs.structure(), lhs, stt_list, mrk_stt); 00364 } 00365 00366 00367 template<typename A, typename AI1, typename AI2> 00368 void 00369 concat_of_standard_here(Element<A, AI1>& lhs, const Element<A, AI2>& rhs) 00370 { 00371 precondition(is_standard(lhs)); 00372 precondition(is_standard(rhs)); 00373 do_concat_of_standard_here(lhs.structure(), lhs, rhs); 00374 } 00375 00376 template<typename A, typename AI1, typename AI2> 00377 Element<A, AI1> 00378 concat_of_standard(const Element<A, AI1>& lhs, 00379 const Element<A, AI2>& rhs) 00380 { 00381 precondition(is_standard(lhs)); 00382 precondition(is_standard(rhs)); 00383 Element<A, AI1> ret(lhs); 00384 do_concat_of_standard_here(ret.structure(), ret, rhs); 00385 return ret; 00386 } 00387 00388 00389 /*----------------------------------. 00390 | left_ext_mult_of_standard_inside | 00391 `----------------------------------*/ 00392 00393 template <typename A, typename AI> 00394 void 00395 left_ext_mult_of_standard_inside(const AutomataBase<A>&, 00396 Element<A, AI>& aut, 00397 const typename Element<A, AI>::hstate_t& ini_stt, 00398 const typename Element<A, AI>::series_set_elt_t& k) 00399 { 00400 typedef Element<A, AI> automaton_t; AUTOMATON_TYPES(automaton_t); 00401 typedef series_set_elt_t weight_t; 00402 typedef typename std::list<htransition_t> trn_lst_t; 00403 00404 weight_t zero(aut.series().zero_); 00405 trn_lst_t ini_out_list; 00406 00407 // Build the list of outgoing transitions from ini_stt 00408 for (delta_iterator it(aut.value(), ini_stt); !it.done(); it.next()) 00409 ini_out_list.push_back(*it); 00410 00411 // In case of multiplication by zero (this cannot happen if we are 00412 // working from a rational expression, but we check it nonetheless 00413 // in case one day this function is used with a used-supplied 00414 // weight). 00415 if (k == zero) 00416 { 00417 // erase all outgoing transitions from ini_stt 00418 for_all(typename trn_lst_t, it, ini_out_list) 00419 aut.del_transition(*it); 00420 // make ini_stt non final 00421 aut.unset_final(ini_stt); 00422 } 00423 // In all other cases 00424 else 00425 { 00426 for_all(typename trn_lst_t, it, ini_out_list) 00427 { // multiply by k the series of all outgoing transitions from ini_stt 00428 hstate_t dest = aut.dst_of(*it); 00429 weight_t wgt = k * aut.series_of(*it); 00430 aut.del_transition(*it); 00431 aut.add_series_transition(ini_stt, dest, wgt); 00432 } 00433 // multiply by k the final weight of ini_stt 00434 aut.set_final(ini_stt, k * aut.get_final(ini_stt)); 00435 } 00436 } 00437 00438 template <typename A, typename AI> 00439 void 00440 left_mult_of_standard_here(Element<A, AI>& aut, 00441 const typename Element<A, AI>::series_set_elt_t& k) 00442 { 00443 precondition(is_standard(aut)); 00444 left_ext_mult_of_standard_inside(aut.structure(), aut, 00445 *aut.initial().begin(), k); 00446 } 00447 00448 /*----------------------------------. 00449 | right_ext_mult_of_standard_inside | 00450 `----------------------------------*/ 00451 00452 template <typename A, typename AI> 00453 void 00454 right_ext_mult_of_standard_inside 00455 (const AutomataBase<A>&, Element<A, AI>& aut, 00456 typename std::list<typename Element<A, AI>::hstate_t>& stt_list, 00457 const typename Element<A, AI>::series_set_elt_t& k) 00458 { 00459 typedef Element<A, AI> automaton_t; AUTOMATON_TYPES(automaton_t); 00460 typedef typename std::list<hstate_t> stt_lst_t; 00461 00462 // multiply by k (on the right) the final weight of of every state 00463 // in stt_list 00464 for_all(typename stt_lst_t, it, stt_list) 00465 aut.set_final(*it, aut.get_final(*it) * k); 00466 } 00467 00468 template <typename A, typename AI> 00469 void 00470 right_mult_of_standard_here(Element<A, AI>& aut, 00471 const typename Element<A, AI>::series_set_elt_t& k) 00472 { 00473 typedef Element<A, AI> automaton_t; 00474 AUTOMATON_TYPES(automaton_t); 00475 00476 precondition(is_standard(aut)); 00477 std::list<hstate_t> finals; 00478 for_all_final_states(it, aut) finals.push_back(*it); 00479 00480 right_ext_mult_of_standard_inside(aut.structure(), aut, 00481 finals, k); 00482 } 00483 00484 /*------------------. 00485 | star_of_standard | 00486 `------------------*/ 00487 00488 template <typename A, typename AI> 00489 void 00490 star_of_standard_inside(const AutomataBase<A>&, Element<A, AI>& aut, 00491 const typename Element<A, AI>::hstate_t& ini_stt, 00492 typename std::list<typename Element<A, AI>::hstate_t>& stt_list) 00493 { 00494 typedef Element<A, AI> automaton_t; AUTOMATON_TYPES(automaton_t); 00495 typedef series_set_elt_t weight_t; 00496 typedef typename std::list<hstate_t> stt_lst_t; 00497 typedef basic_sptr<hstate_t, weight_t> sptr_t; 00498 weight_t unit = aut.series().identity(SELECT(series_set_elt_value_t)); 00499 00500 // compute the star of the final weight of ini_stt (starable has 00501 // already been called) 00502 weight_t fin_wgt = aut.get_final(ini_stt); fin_wgt.star(); 00503 00504 // multiply on the left by that coefficient 00505 aut.set_final(ini_stt, unit); 00506 left_ext_mult_of_standard_inside(aut.structure(), aut, ini_stt, fin_wgt); 00507 00508 // emulates closure of spt transition from every 00509 // state in stt_list to ini_stt 00510 for_all(typename stt_lst_t, it, stt_list) 00511 { 00512 hstate_t crn_stt = *it; 00513 weight_t crn_fin_wgt = aut.get_final(crn_stt); 00514 aut.unset_final(crn_stt); 00515 00516 sptr_t t(crn_stt, ini_stt, crn_fin_wgt); 00517 one_eps_closure(aut, t, misc::backward); 00518 } 00519 } 00520 00521 00522 template <typename A, typename AI> 00523 void 00524 do_star_of_standard_here(const AutomataBase<A>&, Element<A, AI>& a) 00525 { 00526 BENCH_TASK_SCOPED("star_of_standard"); 00527 typedef Element<A, AI> automaton_t; AUTOMATON_TYPES(automaton_t); 00528 typedef series_set_elt_t weight_t; 00529 typedef std::list<hstate_t> stt_lst_t; 00530 00531 hstate_t ini_stt = *a.initial().begin(); 00532 weight_t fin_wgt = a.get_final(ini_stt); 00533 00534 precondition(fin_wgt.starable()); 00535 00536 stt_lst_t stt_list; 00537 for_all_final_states(it, a) 00538 if (*it != ini_stt) 00539 stt_list.push_back(*it); 00540 00541 star_of_standard_inside(a.structure(), a, ini_stt, stt_list); 00542 } 00543 00544 template<typename A, typename AI> 00545 void 00546 star_of_standard_here(Element<A, AI>& a) 00547 { 00548 precondition(is_standard(a)); 00549 do_star_of_standard_here(a.structure(), a); 00550 } 00551 00552 template<typename A, typename AI> 00553 Element<A, AI> 00554 star_of_standard(const Element<A, AI>& a) 00555 { 00556 precondition(is_standard(a)); 00557 Element<A, AI> ret(a); 00558 do_star_of_standard_here(ret.structure(), ret); 00559 return ret; 00560 } 00561 00562 } // vcsn 00563 00564 #endif // ! VCSN_ALGORITHMS_STANDARD_HXX