Vaucanson 1.4
|
00001 // eps_removal.hxx: this file is part of the Vaucanson project. 00002 // 00003 // Vaucanson, a generic library for finite state machines. 00004 // 00005 // Copyright (C) 2004, 2005, 2006, 2008, 2010, 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_EPS_REMOVAL_HXX 00018 # define VCSN_ALGORITHMS_EPS_REMOVAL_HXX 00019 00020 # include <vaucanson/algorithms/eps_removal.hh> 00021 00022 # include <vaucanson/automata/concept/automata_base.hh> 00023 # include <vaucanson/algebra/concept/freemonoid_product.hh> 00024 # include <vaucanson/misc/usual_macros.hh> 00025 00026 # include <list> 00027 # include <map> 00028 # include <utility> 00029 00030 namespace vcsn { 00031 00032 // For automata. 00033 template <class A, typename M, typename AI> 00034 bool 00035 do_is_proper(const AutomataBase<A>&, const M&, const Element<A, AI>& a) 00036 { 00037 BENCH_TASK_SCOPED("is_proper (automaton)"); 00038 typedef Element<A, AI> automaton_t; 00039 AUTOMATON_TYPES(automaton_t); 00040 00041 for_all_const_transitions(e, a) 00042 { 00043 // A transition labelled by "1+a" is not considered to be 00044 // spontaneous by is_spontaneous(), yet it cannot belong to a 00045 // proper automaton. 00046 series_set_elt_t label = a.series_of(*e); 00047 for_all_const_(series_set_elt_t::support_t, it, label.supp()) 00048 if ((*it).empty()) 00049 return false; 00050 } 00051 return true; 00052 } 00053 00054 // For FMP. 00055 template <class A, typename F, typename S, typename AI> 00056 bool 00057 do_is_proper(const AutomataBase<A>&, 00058 const algebra::FreeMonoidProduct<F, S>&, 00059 const Element<A, AI>& a) 00060 { 00061 BENCH_TASK_SCOPED("is_proper (FMP)"); 00062 typedef Element<A, AI> automaton_t; 00063 AUTOMATON_TYPES(automaton_t); 00064 00065 for_all_const_transitions(e, a) 00066 { 00067 series_set_elt_t label = a.series_of(*e); 00068 for_all_const_(series_set_elt_t::support_t, it, label.supp()) 00069 if ((*it).first.empty() && (*it).second.empty()) 00070 return false; 00071 } 00072 return true; 00073 } 00074 00075 template <typename A, typename AI> 00076 bool 00077 is_proper(const Element<A, AI>& a) 00078 { 00079 return do_is_proper(a.structure(), a.series().monoid(), a); 00080 } 00081 00082 00083 // Forward declaration. 00084 template <class A_, typename Auto, typename Weight> 00085 class EpsilonRemover; 00086 00087 template <class A_, typename Auto, typename Weight, int> 00088 struct test_for_non_positive_semiring 00089 { 00090 bool run(const Auto&) const 00091 { 00092 return true; 00093 } 00094 }; 00095 00096 template <class A_, typename Auto, typename Weight> 00097 struct test_for_non_positive_semiring<A_, Auto, Weight, 0> 00098 { 00099 bool run(const Auto& a) const; // See After the EpsilonRemover declaration. 00100 }; 00101 00102 /*--------------------------------------. 00103 | EpsilonRemover for weighted automaton | 00104 `--------------------------------------*/ 00105 00106 template <class A_, typename Auto, typename Weight> 00107 class EpsilonRemover 00108 { 00109 AUTOMATON_TYPES(Auto); 00110 typedef typename series_set_elt_t::support_t support_t; 00111 00112 friend struct test_for_non_positive_semiring 00113 <A_, Auto, Weight, semiring_traits<semiring_t, 00114 semiring_elt_value_t>::is_positive>; 00115 00116 00117 automaton_t& a; 00118 // zero and identity of used algebraic structure. 00119 series_set_elt_t null_series; 00120 semiring_elt_t semiring_elt_zero, 00121 semiring_elt_unit; 00122 monoid_elt_t monoid_identity; 00123 00124 00125 public: 00126 EpsilonRemover(const AutomataBase<A_>&, 00127 Auto& aut) 00128 : a(aut), 00129 null_series(aut.series().zero_), 00130 semiring_elt_zero(aut.series().semiring().wzero_), 00131 semiring_elt_unit(aut.series().semiring().wone_), 00132 monoid_identity(aut.series().monoid().VCSN_EMPTY_) 00133 {} 00134 00135 void operator()(misc::direction_type dir) 00136 { 00137 test_for_non_positive_semiring 00138 <A_, Auto, Weight, semiring_traits<semiring_t, 00139 semiring_elt_value_t>::is_positive> 00140 nps; 00141 result_not_computable_if(!nps.run(a)); 00142 std::list<hstate_t> eps_states; 00143 if (dir == misc::backward) 00144 this->epsilon_covering(eps_states); 00145 else 00146 this->epsilon_co_covering(eps_states); 00147 result_not_computable_if(!spontaneous_suppression(eps_states)); 00148 merge_transitions(); 00149 } 00150 00151 private: 00152 00153 /* This method computes a covering of the automaton such 00154 that, in this covering, there are two kinds of states: 00155 -- states whose incoming transitions are not spontaneous; 00156 -- non initial states whose incoming transitions are spontaneous. 00157 The argument is filled with the states which belong to the second kind. 00158 */ 00159 void epsilon_covering(std::list<hstate_t>& spontaneous_states) 00160 { 00161 //list of states to split 00162 std::list<hstate_t> split_states; 00163 for_all_states(s, a) 00164 { 00165 bool eps_in = false; 00166 bool other_in = a.is_initial(*s); 00167 00168 // Test whether there are different types of incoming transitions. 00169 00170 std::list<htransition_t> transitions; 00171 for (rdelta_iterator e(a.value(), *s); ! e.done(); e.next()) 00172 transitions.push_back(*e); 00173 for_all_(std::list<htransition_t>, e, transitions) 00174 { 00175 series_set_elt_t t = a.series_of(*e); 00176 semiring_elt_t eps_weight= t.get(monoid_identity); 00177 if (eps_weight == semiring_elt_zero) 00178 other_in = true ; 00179 else 00180 { 00181 eps_in=true; 00182 if (t.supp().size() > 1) 00183 other_in = true; 00184 } 00185 } 00186 if (eps_in) 00187 { 00188 if (other_in) 00189 split_states.push_back(*s); 00190 else 00191 spontaneous_states.push_back(*s); 00192 } 00193 } 00194 //Split the states which have to 00195 for_all_(std::list<hstate_t>, s, split_states) 00196 { 00197 hstate_t eps_state = a.add_state(); 00198 spontaneous_states.push_back(eps_state); 00199 //incoming transitions (the original state remains initial if it is) 00200 std::list<htransition_t> transitions; 00201 for (rdelta_iterator e(a.value(), *s); ! e.done(); e.next()) 00202 transitions.push_back(*e); 00203 for_all_(std::list<htransition_t>, e, transitions) 00204 { 00205 series_set_elt_t t = a.series_of(*e); 00206 semiring_elt_t eps_weight= t.get(monoid_identity); 00207 if (eps_weight == semiring_elt_zero) 00208 continue; 00209 series_set_elt_t eps_label(a.structure().series()); 00210 eps_label.assoc(monoid_identity.value(), eps_weight.value()); 00211 //which remains on the transition without epsilon: 00212 t.assoc(monoid_identity.value(), semiring_elt_zero.value()); 00213 hstate_t source=a.src_of(*e); 00214 a.add_series_transition(source, eps_state, eps_label); 00215 if (t != null_series) 00216 a.add_series_transition(source, *s, t); 00217 a.del_transition(*e); 00218 } 00219 //outgoing transitions and final states 00220 if (a.is_final(*s)) 00221 a.set_final(eps_state,a.get_final(*s)); 00222 for (delta_iterator e(a.value(), *s); ! e.done(); e.next()) 00223 a.add_series_transition(eps_state, a.dst_of(*e), a.series_of(*e)); 00224 /* Notice that if there is a loop on *s, with label a+1, the 00225 step "incoming transitions" turns it into a loop with 00226 label 'a' and a transition from *s to eps_state with 00227 label 1, and the step "outgoing transitions" build a 00228 transition from eps_state to *s with label '1' and a loop 00229 on eps_state with label 1, which is what it is 00230 expected */ 00231 } 00232 } 00233 00234 /* Initial and final cleaner. This method adds if necessary an 00235 initial and/or a final state such that series labelling initial 00236 and final arrows are constant. This method is presently unused. 00237 */ 00238 void initial_final_cleaner() 00239 { 00240 { 00241 //Initial 00242 std::list<hstate_t> initial_states; 00243 for_all_initial_states(s, a) 00244 initial_states.push_back(*s); 00245 hstate_t new_initial=a.add_state(); 00246 for_all_(std::list<hstate_t>, s, initial_states) 00247 { 00248 series_set_elt_t t = a.get_initial(*s); 00249 semiring_elt_t eps_weight= t.get(monoid_identity); 00250 t.assoc(monoid_identity, semiring_elt_zero.value()); 00251 if (t != null_series) 00252 { 00253 a.unset_initial(*s); 00254 a.add_series_transition(new_initial, *s, t); 00255 if (eps_weight != semiring_elt_zero) 00256 { 00257 series_set_elt_t cst(a.structure().series()); 00258 cst.assoc(monoid_identity, eps_weight.value()); 00259 a.set_initial(*s, cst); 00260 } 00261 } 00262 } 00263 delta_iterator test(a.value(), new_initial); 00264 if (test.done()) 00265 a.del_state(new_initial); 00266 else 00267 a.set_initial(new_initial); 00268 } 00269 { 00270 //Final 00271 std::list<hstate_t> final_states; 00272 for_all_final_states(s, a) 00273 final_states.push_back(*s); 00274 hstate_t new_final=a.add_state(); 00275 for_all_(std::list<hstate_t>, s, final_states) 00276 { 00277 series_set_elt_t t = a.get_final(*s); 00278 semiring_elt_t eps_weight= t.get(monoid_identity); 00279 t.assoc(monoid_identity, semiring_elt_zero.value()); 00280 if (t != null_series) 00281 { 00282 a.unset_final(*s); 00283 a.add_series_transition(*s, new_final, t); 00284 if(eps_weight != semiring_elt_zero) 00285 { 00286 series_set_elt_t cst(a.structure().series()); 00287 cst.assoc(monoid_identity, eps_weight.value()); 00288 a.set_final(*s, cst); 00289 } 00290 } 00291 } 00292 rdelta_iterator test(a.value(), new_final); 00293 if (test.done()) 00294 a.del_state(new_final); 00295 else 00296 a.set_final(new_final); 00297 } 00298 } 00299 00300 /* This method computes a co-covering of the automaton such 00301 that, in this co-covering, there are two kinds of states: 00302 -- states whose outgoing transitions are not spontaneous; 00303 -- non final states whose outgoing transitions are spontaneous. 00304 The argument is filled with the states which belong to the second kind. 00305 */ 00306 void epsilon_co_covering(std::list<hstate_t>& spontaneous_states) 00307 { 00308 //list of states to split 00309 std::list<hstate_t> split_states; 00310 for_all_states(s, a) 00311 { 00312 bool eps_out = false; 00313 bool other_out = a.is_final(*s); 00314 00315 // Test whether there are different types of outgoing transitions. 00316 00317 std::list<htransition_t> transitions; 00318 for (delta_iterator e(a.value(), *s); !e.done(); e.next()) 00319 transitions.push_back(*e); 00320 for_all_(std::list<htransition_t>, e, transitions) 00321 { 00322 series_set_elt_t t = a.series_of(*e); 00323 semiring_elt_t eps_weight= t.get(monoid_identity); 00324 if(eps_weight == semiring_elt_zero) 00325 other_out=true ; 00326 else 00327 { 00328 eps_out=true; 00329 if (t.supp().size() > 1) 00330 other_out=true; 00331 } 00332 } 00333 if (eps_out) 00334 { 00335 if (other_out) 00336 split_states.push_back(*s); 00337 else 00338 spontaneous_states.push_back(*s); 00339 } 00340 } 00341 //Split the states which have to 00342 for_all_(std::list<hstate_t>, s, split_states) 00343 { 00344 hstate_t eps_state = a.add_state(); 00345 spontaneous_states.push_back(eps_state); 00346 //outgoing transitions (the original state remains final if it is) 00347 std::list<htransition_t> transitions; 00348 for (delta_iterator e(a.value(), *s); !e.done(); e.next()) 00349 transitions.push_back(*e); 00350 for_all_(std::list<htransition_t>, e, transitions) 00351 { 00352 series_set_elt_t t = a.series_of(*e); 00353 semiring_elt_t eps_weight= t.get(monoid_identity); 00354 if (eps_weight == semiring_elt_zero) 00355 continue; 00356 series_set_elt_t eps_label(a.structure().series()); 00357 eps_label.assoc(monoid_identity.value(), eps_weight.value()); 00358 //which remains on the transition without epsilon: 00359 t.assoc(monoid_identity.value(), semiring_elt_zero.value()); 00360 hstate_t target=a.dst_of(*e); 00361 a.add_series_transition(eps_state, target, eps_label); 00362 if (t != null_series) 00363 a.add_series_transition(*s, target, t); 00364 a.del_transition(*e); 00365 } 00366 //incoming transitions and initial states 00367 if (a.is_initial(*s)) 00368 a.set_initial(eps_state,a.get_initial(*s)); 00369 for (rdelta_iterator e(a.value(), *s); ! e.done(); e.next()) 00370 a.add_series_transition(a.src_of(*e), eps_state, a.series_of(*e)); 00371 /* Notice that if there is a loop on *s, with label a+1, the 00372 step "outgoing transitions" turns it into a loop with 00373 label 'a' and a transition from eps_state to *s with 00374 label 1, and the step "incoming transitions" build a 00375 transition from *s to eps_state with label '1' and a loop 00376 on eps_state with label 1, which is what it is 00377 expected */ 00378 } 00379 } 00380 00381 /* This method computes an equivalent K-automaton with only 00382 positive transitions (excepted final arrows). A second copy of 00383 the automaton is built, a negative weight makes switch from a 00384 copy to another. Two final states are added, one where 00385 positive paths end, the other one where negative paths end. In 00386 the result, all the edges have positive weight; the two final 00387 states have resp. weights equal to 1 and -1. 00388 */ 00389 void positive_path_covering() 00390 { 00391 std::map<hstate_t,hstate_t> clones; 00392 std::list<hstate_t> states; 00393 for_all_states(s, a) 00394 states.push_back(*s); 00395 for_all_(std::list<hstate_t>, s, states) 00396 clones[*s]=a.add_state(); 00397 hstate_t pos_final_state=a.add_state(); 00398 hstate_t neg_final_state=a.add_state(); 00399 std::list<htransition_t> transitions; 00400 for_all_transitions(e, a) 00401 transitions.push_back(*e); 00402 for_all_(std::list<htransition_t>, e, transitions) 00403 { 00404 series_set_elt_t posit = a.series_of(*e); 00405 series_set_elt_t negat(a.structure().series()); 00406 support_t su = posit.supp(); 00407 for_all_(support_t, x, su) 00408 { 00409 semiring_elt_t weight=posit.get(*x); 00410 if (weight < semiring_elt_zero) 00411 { 00412 negat.assoc(*x,-weight.value()); 00413 posit.assoc(*x,semiring_elt_zero.value()); 00414 } 00415 } 00416 hstate_t src=a.src_of(*e), dst=a.dst_of(*e); 00417 if (posit != null_series) 00418 a.add_series_transition(clones[src], clones[dst], posit); 00419 if (negat != null_series) 00420 { 00421 a.add_series_transition(src, clones[dst], negat); 00422 a.add_series_transition(clones[src], dst, negat); 00423 if (posit != null_series) 00424 a.add_series_transition(src, dst, posit); 00425 a.del_transition(*e); 00426 } 00427 } 00428 states.clear(); 00429 for_all_initial_states(s, a) 00430 states.push_back(*s); 00431 for_all_(std::list<hstate_t>, s, states) 00432 { 00433 series_set_elt_t posit = a.get_initial(*s); 00434 series_set_elt_t negat(a.structure().series()); 00435 support_t su = posit.supp(); 00436 for_all_(support_t, x, su) 00437 { 00438 semiring_elt_t weight = posit.get(*x); 00439 if (weight < semiring_elt_zero) 00440 { 00441 negat.assoc(*x,-weight.value()); 00442 posit.assoc(*x,semiring_elt_zero.value()); 00443 } 00444 } 00445 if (negat != null_series) 00446 { 00447 a.set_initial(clones[*s], negat); 00448 a.unset_initial(*s); 00449 if (posit != null_series) 00450 a.set_initial(*s,posit); 00451 } 00452 } 00453 states.clear(); 00454 for_all_final_states(s, a) 00455 states.push_back(*s); 00456 for_all_(std::list<hstate_t>, s, states) 00457 { 00458 series_set_elt_t posit = a.get_final(*s); 00459 series_set_elt_t negat(a.structure().series()); 00460 support_t su = posit.supp(); 00461 for_all_(support_t, x, su) 00462 { 00463 semiring_elt_t weight=posit.get(*x); 00464 if (weight < semiring_elt_zero) 00465 { 00466 negat.assoc(*x,-weight.value()); 00467 posit.assoc(*x,semiring_elt_zero.value()); 00468 } 00469 } 00470 if (negat != null_series) 00471 { 00472 a.add_series_transition(*s, neg_final_state, negat); 00473 a.add_series_transition(clones[*s], pos_final_state, negat); 00474 } 00475 a.unset_final(*s); 00476 if (posit != null_series) 00477 { 00478 a.add_series_transition(*s, pos_final_state, posit); 00479 a.add_series_transition(clones[*s], neg_final_state, posit); 00480 } 00481 } 00482 a.set_final(pos_final_state); 00483 series_set_elt_t mss = a.get_final(pos_final_state); 00484 mss.assoc(monoid_identity,-semiring_elt_unit.value()); 00485 a.set_final(neg_final_state,mss); 00486 accessible_here(a); 00487 } 00488 00489 /* This method makes every weight in the K-automaton positive 00490 */ 00491 void absolute_weight() 00492 { 00493 std::list<htransition_t> transitions; 00494 for_all_transitions(e, a) 00495 transitions.push_back(*e); 00496 for_all_(std::list<htransition_t>, e, transitions) 00497 { 00498 series_set_elt_t label = a.series_of(*e); 00499 support_t support = label.supp(); 00500 for_all_(support_t, x, support) 00501 { 00502 semiring_elt_t weight=label.get(*x); 00503 if (weight < semiring_elt_zero) 00504 label.assoc(*x,-weight.value()); 00505 } 00506 hstate_t src=a.src_of(*e), dst=a.dst_of(*e); 00507 a.del_transition(*e); 00508 a.add_series_transition(src, dst, label); 00509 } 00510 std::list<hstate_t> states; 00511 for_all_initial_states(s, a) 00512 states.push_back(*s); 00513 for_all_(std::list<hstate_t>, s, states) 00514 { 00515 series_set_elt_t label = a.get_initial(*s); 00516 support_t support = label.supp(); 00517 for_all_(support_t, x, support) 00518 { 00519 semiring_elt_t weight = label.get(*x); 00520 if (weight < semiring_elt_zero) 00521 label.assoc(*x,-weight.value()); 00522 } 00523 a.set_initial(*s,label); 00524 } 00525 states.clear(); 00526 for_all_final_states(s, a) 00527 states.push_back(*s); 00528 for_all_(std::list<hstate_t>, s, states) 00529 { 00530 series_set_elt_t label = a.get_final(*s); 00531 support_t support = label.supp(); 00532 for_all_(support_t, x, support) 00533 { 00534 semiring_elt_t weight = label.get(*x); 00535 if (weight < semiring_elt_zero) 00536 label.assoc(*x,-weight.value()); 00537 } 00538 a.set_final(*s,label); 00539 } 00540 } 00541 00542 /*supression of "epsilon-states" 00543 epsilon_covering should have been called before 00544 This part of the algorithm is symmetrical and is exactly 00545 the "elimination state method" applicated to a list of states. 00546 We consider the case where the state is initial or final, even if 00547 in the backward case the 'epsilon state' cannot be initial for instance 00548 */ 00549 bool spontaneous_suppression(std::list<hstate_t>& sp_states) 00550 { 00551 for_all_(std::list<hstate_t>, s, sp_states) 00552 { 00553 std::list<htransition_t> incoming_transitions; 00554 //list of incoming transitions, beginning with loops 00555 for (rdelta_iterator e(a.value(), *s); ! e.done(); e.next()) 00556 { 00557 if (a.src_of(*e) == a.dst_of(*e)) 00558 incoming_transitions.push_front(*e); 00559 else 00560 incoming_transitions.push_back(*e); 00561 } 00562 bool hasloop=false; 00563 series_set_elt_t loop_series(a.structure().series()); 00564 //loops are removed from incoming transitions; 00565 while (!incoming_transitions.empty()) 00566 { 00567 htransition_t& loop=incoming_transitions.front(); 00568 if(a.src_of(loop)==a.dst_of(loop)) 00569 { 00570 hasloop=true; 00571 loop_series += a.series_of(loop); 00572 incoming_transitions.pop_front(); 00573 } 00574 else 00575 break; 00576 } 00577 if (hasloop) 00578 { 00579 if (!loop_series.get(monoid_identity).starable()) 00580 return false; 00581 loop_series = loop_series.star(); 00582 } 00583 std::list<htransition_t> outgoing_transitions; 00584 for (delta_iterator e(a.value(), *s); ! e.done(); e.next()) 00585 if (a.src_of(*e)!=a.dst_of(*e)) 00586 outgoing_transitions.push_back(*e); 00587 for_all_(std::list<htransition_t>, e, incoming_transitions) 00588 for_all_(std::list<htransition_t>, f, outgoing_transitions) 00589 if (hasloop) 00590 a.add_series_transition(a.src_of(*e), a.dst_of(*f), 00591 a.series_of(*e)*loop_series*a.series_of(*f)); 00592 else 00593 a.add_series_transition(a.src_of(*e), a.dst_of(*f), 00594 a.series_of(*e)*a.series_of(*f)); 00595 if (a.is_final(*s)) 00596 { 00597 series_set_elt_t final_s = a.get_final(*s); 00598 for_all_(std::list<htransition_t>, e, incoming_transitions) 00599 { 00600 hstate_t p = a.src_of(*e); 00601 series_set_elt_t t = a.get_final(p); 00602 if (hasloop) 00603 t += a.series_of(*e)*loop_series*final_s; 00604 else 00605 t += a.series_of(*e)*final_s; 00606 a.unset_final(p); 00607 if (t != null_series) 00608 a.set_final(p,t); 00609 } 00610 } 00611 if (a.is_initial(*s)) 00612 { 00613 series_set_elt_t initial_s=a.get_initial(*s); 00614 for_all_(std::list<htransition_t>, f, outgoing_transitions) 00615 { 00616 hstate_t p = a.dst_of(*f); 00617 series_set_elt_t t = a.get_initial(p); 00618 if (hasloop) 00619 t += initial_s*loop_series*a.series_of(*f); 00620 else 00621 t += initial_s*a.series_of(*f); 00622 a.unset_initial(p); 00623 if (t != null_series) 00624 a.set_initial(p,t); 00625 } 00626 } 00627 a.del_state(*s); 00628 } 00629 return true; 00630 } 00631 00632 //merge transitions with the same ends 00633 void merge_transitions() 00634 { 00635 typedef std::map<hstate_t, series_set_elt_t> map_t; 00636 for_all_states(s, a) 00637 { 00638 map_t map; 00639 std::list<htransition_t> transitions; 00640 for (delta_iterator e(a.value(), *s); ! e.done(); e.next()) 00641 { 00642 hstate_t target = a.dst_of(*e); 00643 transitions.push_back(*e); 00644 typename map_t::iterator it = map.find(target); 00645 if (it == map.end()) 00646 map.insert(std::pair<hstate_t, series_set_elt_t>(target, 00647 a.series_of(*e))); 00648 else 00649 it->second += a.series_of(*e); 00650 } 00651 for_all_(std::list<htransition_t>, e, transitions) 00652 a.del_transition(*e); 00653 for_all_(map_t, it, map) 00654 if(it->second != null_series) 00655 a.add_series_transition(*s, it->first, it->second); 00656 } 00657 } 00658 00659 }; 00660 00661 00662 template <class A_, typename Auto, typename Weight> 00663 bool test_for_non_positive_semiring<A_, Auto, Weight, 0>::run(const Auto& a) const 00664 { 00665 AUTOMATON_TYPES(Auto); 00666 00667 std::list<hstate_t> eps_states; 00668 automaton_t test(a); 00669 EpsilonRemover<A_, Auto, Weight> epsTest(test.structure(), test); 00670 epsTest.absolute_weight(); 00671 epsTest.epsilon_covering(eps_states); 00672 return epsTest.spontaneous_suppression(eps_states); 00673 } 00674 00675 00676 00677 00678 /*--------------. 00679 | eps_removal. | 00680 `--------------*/ 00681 00682 template<class A_, typename Auto, typename Weight> 00683 void 00684 do_eps_removal_here(const AutomataBase<A_>& a_set, 00685 const Weight&, 00686 Auto& a, 00687 misc::direction_type dir) 00688 { 00689 BENCH_TASK_SCOPED("eps_removal"); 00690 AUTOMATON_TYPES(Auto); 00691 EpsilonRemover<A_, Auto, Weight> algo(a_set, a); 00692 algo(dir); 00693 } 00694 00695 template<typename A, typename AI> 00696 void 00697 eps_removal_here(Element<A, AI>& a, misc::direction_type dir) 00698 { 00699 typedef Element<A, AI> automaton_t; 00700 AUTOMATON_TYPES(automaton_t); 00701 00702 do_eps_removal_here(a.structure(), 00703 SELECT(semiring_elt_value_t), 00704 a, dir); 00705 } 00706 00707 template<typename A, typename AI> 00708 Element<A, AI> 00709 eps_removal(const Element<A, AI>& a, misc::direction_type dir) 00710 { 00711 typedef Element<A, AI> automaton_t; 00712 AUTOMATON_TYPES(automaton_t); 00713 00714 automaton_t ret(a); 00715 do_eps_removal_here(ret.structure(), 00716 SELECT(semiring_elt_value_t), 00717 ret, dir); 00718 return ret; 00719 } 00720 00721 template<typename A, typename AI> 00722 void 00723 backward_eps_removal_here(Element<A, AI>& a) 00724 { 00725 typedef Element<A, AI> automaton_t; 00726 AUTOMATON_TYPES(automaton_t); 00727 00728 do_eps_removal_here(a.structure(), 00729 SELECT(semiring_elt_value_t), 00730 a, misc::backward); 00731 } 00732 00733 template<typename A, typename AI> 00734 Element<A, AI> 00735 backward_eps_removal(const Element<A, AI>& a) 00736 { 00737 typedef Element<A, AI> automaton_t; 00738 AUTOMATON_TYPES(automaton_t); 00739 00740 automaton_t ret(a); 00741 do_eps_removal_here(ret.structure(), 00742 SELECT(semiring_elt_value_t), 00743 ret, misc::backward); 00744 return ret; 00745 } 00746 00747 template<typename A, typename AI> 00748 void 00749 forward_eps_removal_here(Element<A, AI>& a) 00750 { 00751 typedef Element<A, AI> automaton_t; 00752 AUTOMATON_TYPES(automaton_t); 00753 00754 do_eps_removal_here(a.structure(), 00755 SELECT(semiring_elt_value_t), 00756 a, misc::forward); 00757 } 00758 00759 template<typename A, typename AI> 00760 Element<A, AI> 00761 forward_eps_removal(const Element<A, AI>& a) 00762 { 00763 typedef Element<A, AI> automaton_t; 00764 AUTOMATON_TYPES(automaton_t); 00765 00766 automaton_t ret(a); 00767 do_eps_removal_here(ret.structure(), 00768 SELECT(semiring_elt_value_t), 00769 ret, misc::forward); 00770 return ret; 00771 } 00772 00773 } // vcsn 00774 00775 #endif // ! VCSN_ALGORITHMS_EPS_REMOVAL_HXX