Vaucanson 1.4
|
00001 // aut_to_exp.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 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_AUT_TO_EXP_HXX 00018 # define VCSN_ALGORITHMS_AUT_TO_EXP_HXX 00019 00020 # include <vaucanson/algorithms/aut_to_exp.hh> 00021 00022 # include <vaucanson/automata/concept/handlers.hh> 00023 # include <vaucanson/algorithms/normalized.hh> 00024 # include <vaucanson/misc/usual_macros.hh> 00025 # include <vaucanson/misc/contract.hh> 00026 # include <vaucanson/misc/limits.hh> 00027 # include <vaucanson/misc/random.hh> 00028 # include <vaucanson/automata/concept/automata_base.hh> 00029 00030 # include <list> 00031 # include <set> 00032 # include <vector> 00033 00034 # include <stdlib.h> 00035 # include <time.h> 00036 00037 namespace vcsn { 00038 00039 /*---------------. 00040 | DefaultChooser | 00041 `---------------*/ 00042 00043 template <class Auto_> 00044 typename Auto_::hstate_t 00045 DefaultChooser::operator()(const Auto_& a) const 00046 { 00047 assertion(a.states().size() > 0); 00048 typename Auto_::state_iterator s = a.states().begin(); 00049 typename Auto_::state_iterator k = s; 00050 while ((k != a.states().end()) && 00051 ((a.is_initial(*k)) || (a.is_final(*k)))) 00052 ++k; 00053 s = k; 00054 return *s; 00055 } 00056 00057 /*--------------. 00058 | RandomChooser | 00059 `--------------*/ 00060 00061 template <class Auto_> 00062 typename Auto_::hstate_t 00063 RandomChooser::operator()(const Auto_& a) const 00064 { 00065 assertion(a.states().size() > 0); 00066 00067 int n_init = 0; 00068 int n_final = 0; 00069 for (typename Auto_::state_iterator i = a.states().begin(); 00070 i != a.states().end(); 00071 ++i) 00072 { 00073 if (a.is_initial(*i)) 00074 ++n_init; 00075 if (a.is_final(*i)) 00076 ++n_final; 00077 } 00078 00079 unsigned n = misc::random::generate((unsigned) 0, 00080 a.states().size() - 00081 (n_init + n_final)); 00082 00083 typename Auto_::state_iterator k = a.states().begin(); 00084 unsigned kk = 0; 00085 while (kk <= n || k == a.states().end() || 00086 ((a.is_initial(*k)) || (a.is_final(*k)))) 00087 { 00088 if (k == a.states().end()) 00089 { 00090 k = a.states().begin(); 00091 continue; 00092 } 00093 ++k; 00094 ++kk; 00095 } 00096 return *k; 00097 } 00098 00099 /*----------------------------. 00100 | Heuristic chooser: | 00101 | Transition Number Heuristic | 00102 `----------------------------*/ 00103 00104 template <class Auto_> 00105 typename Auto_::hstate_t 00106 HChooser::operator()(const Auto_& a) const 00107 { 00108 assertion(a.states().size() > 0); 00109 00110 std::list<typename Auto_::htransition_t> delta_in; 00111 std::list<typename Auto_::htransition_t> delta_out; 00112 00113 typename Auto_::state_iterator s = a.states().begin(); 00114 unsigned int d_in = 0; 00115 unsigned int d_out = 0; 00116 unsigned int max = misc::limits<unsigned int>::max(); 00117 bool has_loop = false; 00118 bool has_loop_old = false; 00119 00120 for (typename Auto_::state_iterator i = a.states().begin(); 00121 i != a.states().end(); 00122 ++i) 00123 { 00124 if (a.is_final(*i) || a.is_initial(*i)) 00125 continue; 00126 has_loop = false; 00127 00128 for (typename Auto_::delta_iterator j(a.value(), *i); 00129 ! j.done(); 00130 j.next()) 00131 delta_out.push_back(*j); 00132 for (typename Auto_::rdelta_iterator j(a.value(), *i); 00133 ! j.done(); 00134 j.next()) 00135 delta_in.push_back(*j); 00136 for (typename std::list<typename Auto_::htransition_t>::iterator j = delta_out.begin(); 00137 j != delta_out.end(); 00138 ++j) 00139 if (*i == a.dst_of(*j)) 00140 has_loop = true; 00141 00142 //FIXME : If the state has several loops 00143 if (has_loop) 00144 d_in = delta_in.size() - 1; 00145 else 00146 d_in = delta_in.size(); 00147 d_out = delta_out.size(); 00148 00149 //We prefer to delete a state that has no loop transition 00150 if (d_in * d_out < max || 00151 (d_in * d_out == max && 00152 has_loop_old && not has_loop)) 00153 { 00154 s = i; 00155 max = d_in * d_out; 00156 has_loop_old = has_loop; 00157 } 00158 delta_out.clear(); 00159 delta_in.clear(); 00160 } 00161 return *s; 00162 } 00163 00164 /*-------------------------. 00165 | Heuristic chooser: | 00166 | from Delgado & Morais | 00167 | (Proposed in CIAA 2004) | 00168 `-------------------------*/ 00169 00170 template <class Auto_> 00171 typename Auto_::hstate_t 00172 DMChooser::operator()(const Auto_& a) const 00173 { 00174 assertion(a.states().size() > 0); 00175 00176 std::list<typename Auto_::htransition_t> delta_in; 00177 std::list<typename Auto_::htransition_t> delta_out; 00178 typename Auto_::state_iterator s = a.states().begin(); 00179 00180 int weight_min = misc::limits<int>::max(); 00181 for (typename Auto_::state_iterator i = a.states().begin(); 00182 i != a.states().end(); 00183 ++i) 00184 { 00185 if (a.is_final(*i) || a.is_initial(*i)) 00186 continue; 00187 unsigned int n_loops = 0; 00188 unsigned int in = 0; 00189 unsigned int out = 0; 00190 00191 int weight = 0; 00192 00193 delta_in.clear(); 00194 delta_out.clear(); 00195 for (typename Auto_::delta_iterator j(a.value(), *i); 00196 ! j.done(); 00197 j.next()) 00198 delta_out.push_back(*j); 00199 for (typename Auto_::rdelta_iterator j(a.value(), *i); 00200 ! j.done(); 00201 j.next()) 00202 delta_in.push_back(*j); 00203 00204 for (typename std::list<typename Auto_::htransition_t>::iterator j = delta_out.begin(); 00205 j != delta_out.end(); 00206 ++j) 00207 if (*i == a.dst_of(*j)) 00208 ++n_loops; 00209 00210 in = delta_in.size() - n_loops; 00211 out = delta_out.size() - n_loops; 00212 00213 // Compute SUM(Win(k) * (Out - 1)) 00214 for (typename std::list<typename Auto_::htransition_t>::iterator j = delta_in.begin(); 00215 j != delta_in.end(); 00216 ++j) 00217 if (*i != a.dst_of(*j)) 00218 { 00219 weight += a.series_value_of(*j).length() * (out - 1); 00220 } 00221 00222 // Compute SUM(Wout(k) * (In - 1)) 00223 for (typename std::list<typename Auto_::htransition_t>::iterator j = delta_out.begin(); 00224 j != delta_out.end(); 00225 ++j) 00226 if (*i != a.dst_of(*j)) 00227 { 00228 weight += a.series_value_of(*j).length() * (in - 1); 00229 } 00230 00231 // Compute Wloop * (In * Out - 1) 00232 for (typename std::list<typename Auto_::htransition_t>::iterator j = delta_out.begin(); 00233 j != delta_out.end(); 00234 ++j) 00235 if (*i == a.dst_of(*j)) 00236 { 00237 weight += a.series_value_of(*j).length() * (in * out - 1); 00238 } 00239 00240 if (weight < weight_min) 00241 { 00242 s = i; 00243 weight_min = weight; 00244 } 00245 } 00246 return *s; 00247 } 00248 00249 /*------------. 00250 | ListChooser | 00251 `------------*/ 00252 00253 inline ListChooser::ListChooser(const std::list<unsigned int>& l) : 00254 list_(l), 00255 pos_(l.begin()) 00256 { 00257 } 00258 00259 template <class Auto_> 00260 typename Auto_::hstate_t 00261 ListChooser::operator() (const Auto_& a) 00262 { 00263 assertion(pos_ != list_.end()); 00264 return a.get_state(*pos_++); 00265 } 00266 00267 /*-----------. 00268 | aut_to_exp | 00269 `-----------*/ 00270 00271 template <class A, typename AI, typename Chooser> 00272 typename Element<A, AI>::series_set_elt_t 00273 do_in_aut_to_exp(const AutomataBase<A>& a_set, 00274 Element<A, AI>& a, 00275 Chooser chooser) 00276 { 00277 typedef Element<A, AI> automaton_t; 00278 AUTOMATON_TYPES(automaton_t); 00279 typedef typename automaton_t::series_set_t series_set_t; 00280 typedef typename automaton_t::series_set_elt_t series_set_elt_t; 00281 00282 typedef typename std::list<htransition_t> htransition_set_t; 00283 typedef std::map<hstate_t, series_set_elt_t> sums_t; 00284 00285 typename htransition_set_t::const_iterator i, j; 00286 hstate_t q; 00287 htransition_set_t transitions; 00288 std::list<htransition_t> transitions_to_remove; 00289 normalize_here(a); 00290 // assertion(is_normalized(a)); // FIXME To remove 00291 00292 while (a.states().size() != 2) 00293 { 00294 series_set_elt_t loop_sum(a_set.series()); 00295 sums_t in_sums, out_sums; 00296 00297 q = chooser(a); 00298 if (a.is_initial(q) || a.is_final(q)) 00299 continue; 00300 00301 transitions.clear(); 00302 for (delta_iterator e(a.value(), q); ! e.done(); e.next()) 00303 transitions.push_back(*e); 00304 for (i = transitions.begin(); i != transitions.end(); i = j) 00305 { 00306 j = i; ++j; 00307 00308 if (a.dst_of(*i) == q) 00309 loop_sum += a.series_of(*i); 00310 else 00311 { 00312 typename sums_t::iterator f = out_sums.find(a.dst_of(*i)); 00313 if (f == out_sums.end()) 00314 f = out_sums.insert 00315 (std::make_pair(a.dst_of(*i), 00316 series_set_elt_t(a_set.series()))).first; 00317 f->second += a.series_of(*i); 00318 } 00319 a.del_transition(*i); 00320 } 00321 transitions.clear(); 00322 for (rdelta_iterator e(a.value(), q); ! e.done(); e.next()) 00323 transitions.push_back(*e); 00324 for (i = transitions.begin(); i != transitions.end(); i = j) 00325 { 00326 j = i; ++j; 00327 // Here all loops have already been removed. 00328 typename sums_t::iterator f = in_sums.find(a.src_of(*i)); 00329 if (f == in_sums.end()) 00330 f = in_sums.insert 00331 (std::make_pair(a.src_of(*i), 00332 series_set_elt_t(a_set.series()))).first; 00333 00334 f->second += a.series_of(*i); 00335 a.del_transition(*i); 00336 } 00337 loop_sum.star(); 00338 //Slow 00339 for_all_const_(sums_t, in, in_sums) 00340 for_all_const_(sums_t, out, out_sums) 00341 { 00342 series_set_elt_t res = in->second * loop_sum * out->second; 00343 a.add_series_transition(in->first, out->first, res); 00344 } 00345 a.del_state(q); 00346 } 00347 series_set_elt_t final(a_set.series()); 00348 for_all_const_transitions(i, a) 00349 final += a.label_of(*i); 00350 return final; 00351 } 00352 00353 /*-----------. 00354 | aut_to_exp | 00355 `-----------*/ 00356 00357 template<typename A, typename AI, typename Chooser> 00358 typename Element<A, AI>::series_set_elt_t 00359 aut_to_exp(const Element<A, AI>& a, const Chooser& c) 00360 { 00361 BENCH_TASK_SCOPED("aut_to_exp"); 00362 Element<A, AI> ret(a); 00363 return do_in_aut_to_exp(ret.structure(), ret, c); 00364 } 00365 00366 template<typename A, typename AI> 00367 typename Element<A, AI>::series_set_elt_t 00368 aut_to_exp(const Element<A, AI>& a) 00369 { 00370 return aut_to_exp(a, DefaultChooser()); 00371 } 00372 00373 } // vcsn 00374 00375 #endif // ! VCSN_ALGORITHMS_AUT_TO_EXP_HXX