Vaucanson 1.4
|
00001 // minimization_moore.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, 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_MINIMIZATION_MOORE_HXX 00018 # define VCSN_ALGORITHMS_MINIMIZATION_MOORE_HXX 00019 00020 # include <vaucanson/algorithms/minimization_moore.hh> 00021 # include <vaucanson/algorithms/complete.hh> 00022 # include <vaucanson/algorithms/transpose.hh> 00023 00024 # ifndef VCSN_NDEBUG 00025 # include <vaucanson/algorithms/is_deterministic.hh> 00026 # endif // ! VCSN_NDEBUG 00027 00028 # include <vaucanson/automata/concept/handlers.hh> 00029 # include <vaucanson/automata/concept/delta_kind.hh> 00030 # include <vaucanson/misc/usual_macros.hh> 00031 # include <vaucanson/misc/contract.hh> 00032 00033 # include <map> 00034 # include <set> 00035 # include <vector> 00036 00037 // Useful macros for Moore's minimization. 00038 00039 // Iterator on a list of groups. 00040 # define for_all_groups(I, P) \ 00041 for (typename groupid_to_group_t::iterator I = ((P).begin()); I != (P).end(); ++I) 00042 00043 // Iterator on state in a group. We don't iterate on the first not 00044 // processed state. 00045 # define for_all_state_in_groups(I, P) \ 00046 for (typename group_t::iterator I = ++((P).begin()); I != (P).end(); ++I) 00047 00048 namespace vcsn { 00049 00050 /*-------------------. 00051 | minimization_moore | 00052 `-------------------*/ 00053 // precondition : the input automaton is deterministic or 00054 // co-deterministic according to Transposed 00055 template<typename A, typename AI, bool Transposed> 00056 void 00057 do_minimization_moore(const Element<A, AI>& input, Element<A, AI>& output) 00058 { 00059 BENCH_TASK_SCOPED("minimization_moore"); 00060 typedef Element<A, AI> automaton_t; 00061 AUTOMATON_TYPES(automaton_t); 00062 AUTOMATON_FREEMONOID_TYPES(automaton_t); 00063 using std::map; 00064 using std::vector; 00065 using std::set; 00066 00067 // Consts. 00068 00069 const hstate_t NullState; 00070 const hstate_t NullGroup; 00071 const alphabet_t& alphabet (input.series().monoid().alphabet()); 00072 00073 // Typedefs. 00074 00075 typedef int letterid_t; 00076 typedef int groupid_t; 00077 00078 typedef set<hstate_t> group_t; 00079 typedef vector<group_t> groupid_to_group_t; 00080 00081 typedef vector<hstate_t> letterid_to_state_t; 00082 00083 typedef map<hstate_t, letterid_to_state_t> state_to_letterid_to_state_t; 00084 00085 typedef map<hstate_t, groupid_t> state_to_groupid_t; 00086 typedef map<letter_t, letterid_t> letter_to_letterid_t; 00087 00088 /*---------------. 00089 | Initialization | 00090 `---------------*/ 00091 00092 precondition(input.exists()); 00093 00094 groupid_to_group_t groupid_to_group(input.states().size()); 00095 00096 state_to_groupid_t state_to_groupid; 00097 state_to_groupid[NullState] = NullGroup; 00098 00099 letter_to_letterid_t letter_to_letterid; 00100 int letter_count = 0; 00101 for_all_const_letters(iletter, alphabet) 00102 letter_to_letterid[*iletter] = letter_count++; 00103 00104 state_to_letterid_to_state_t aut_view; 00105 for_all_const_states(istate, input) 00106 { 00107 aut_view[*istate] = letterid_to_state_t(letter_count, NullState); 00108 if ((not Transposed and input.is_final(*istate)) or 00109 (Transposed and input.is_initial(*istate))) 00110 { 00111 groupid_to_group[0].insert(*istate); 00112 state_to_groupid[*istate] = 0; 00113 } 00114 else 00115 { 00116 groupid_to_group[1].insert(*istate); 00117 state_to_groupid[*istate] = 1; 00118 } 00119 } 00120 00121 for_all_const_states(istate, input) 00122 { 00123 for_all_const_(letter_to_letterid_t, iletter, letter_to_letterid) 00124 { 00125 bool empty = true; 00126 hstate_t first; 00127 if (not Transposed) 00128 { 00129 for (delta_iterator t(input.value(), *istate); 00130 ! t.done() && empty; 00131 t.next()) 00132 { 00133 monoid_elt_t w(input.series_of(*t).structure().monoid(), iletter->first); 00134 if (input.series_of(*t).get(w) != input.series().semiring().wzero_) 00135 { 00136 empty = false; 00137 first = input.dst_of(*t); 00138 break; 00139 } 00140 } 00141 } 00142 else 00143 { 00144 for (rdelta_iterator t(input.value(), *istate); 00145 ! t.done() && empty; 00146 t.next()) 00147 { 00148 monoid_elt_t w(input.series_of(*t).structure().monoid(), iletter->first); 00149 if (input.series_of(*t).get(w) != input.series().semiring().wzero_) 00150 { 00151 empty = false; 00152 first = input.src_of(*t); 00153 break; 00154 } 00155 } 00156 } 00157 if (not empty) 00158 aut_view[*istate][iletter->second] = first; 00159 } 00160 } 00161 00162 00163 /*-----. 00164 | Loop | 00165 `-----*/ 00166 00167 int last_group = 1; 00168 for (bool group_modified = true; group_modified;) 00169 { 00170 group_modified = false; 00171 for_all_groups(igroup, groupid_to_group) 00172 { 00173 if (igroup->empty()) 00174 break; 00175 00176 hstate_t first_state = *(igroup->begin()); 00177 bool group_created = false; 00178 00179 for_all_state_in_groups(istate, *igroup) 00180 { 00181 int i; 00182 for (i = 0; i < letter_count; ++i) 00183 if (state_to_groupid[aut_view[first_state][i]] != 00184 state_to_groupid[aut_view[*istate][i]]) 00185 break; 00186 if (i != letter_count) 00187 { 00188 typename group_t::iterator istate_save = istate; 00189 00190 istate_save--; 00191 if (group_created == false) 00192 { 00193 last_group++; 00194 group_created = true; 00195 group_modified = true; 00196 } 00197 groupid_to_group[last_group].insert(*istate); 00198 state_to_groupid[*istate] = last_group; 00199 igroup->erase(*istate); 00200 istate = istate_save; 00201 } 00202 } 00203 } 00204 } 00205 00206 00207 /*-----------------------. 00208 | Automaton construction | 00209 `-----------------------*/ 00210 00211 std::vector<hstate_t> new_states(last_group + 1); 00212 00213 // Create all states. 00214 for (int i = 0; i <= last_group; ++i) 00215 new_states[i] = output.add_state(); 00216 00217 // Create all transitions. 00218 for (int i = 0; i <= last_group; ++i) 00219 { 00220 hstate_t repres = *(groupid_to_group[i].begin()); 00221 00222 for_all_const_(letter_to_letterid_t, iletter, letter_to_letterid) 00223 if (aut_view[repres][iletter->second] != NullState) 00224 { 00225 if (not Transposed) 00226 output.add_letter_transition(new_states[i], 00227 new_states[state_to_groupid 00228 [aut_view[repres] 00229 [iletter->second]]], 00230 iletter->first); 00231 else 00232 output.add_letter_transition(new_states[state_to_groupid 00233 [aut_view[repres] 00234 [iletter->second]]], 00235 new_states[i], 00236 iletter->first); 00237 } 00238 } 00239 00240 // Setting initial and final states. 00241 if (not Transposed) 00242 { 00243 output.set_final(new_states[0]); 00244 output.set_initial(new_states[state_to_groupid[*input.initial().begin()]]); 00245 } 00246 else 00247 { 00248 output.set_initial(new_states[0]); 00249 output.set_final(new_states[state_to_groupid[*input.final().begin()]]); 00250 } 00251 00252 } 00253 00254 00255 template<typename A, typename AI> 00256 void 00257 minimization_moore_here(Element<A, AI>& a) 00258 { 00259 precondition(is_deterministic(a)); 00260 precondition(is_complete(a)); 00261 Element<A, AI> output(a.structure()); 00262 do_minimization_moore<A, AI, false>(a, output); 00263 a = output; 00264 } 00265 00266 00267 template<typename A, typename AI> 00268 Element<A, AI> 00269 minimization_moore(const Element<A, AI>& a) 00270 { 00271 precondition(is_deterministic(a)); 00272 precondition(is_complete(a)); 00273 Element<A, AI> output(a.structure()); 00274 do_minimization_moore<A, AI, false>(a, output); 00275 return output; 00276 } 00277 00278 template<typename A, typename AI> 00279 void 00280 co_minimization_moore_here(Element<A, AI>& a) 00281 { 00282 precondition(is_deterministic(transpose(a))); 00283 precondition(is_complete(transpose(a))); 00284 Element<A, AI> output(a.structure()); 00285 do_minimization_moore<A, AI, true>(a, output); 00286 a = output; 00287 } 00288 00289 00290 template<typename A, typename AI> 00291 Element<A, AI> 00292 co_minimization_moore(const Element<A, AI>& a) 00293 { 00294 precondition(is_deterministic(transpose(a))); 00295 precondition(is_complete(transpose(a))); 00296 Element<A, AI> output(a.structure()); 00297 do_minimization_moore<A, AI, true>(a, output); 00298 return output; 00299 } 00300 00301 } // vcsn 00302 00303 // Prevent potential conflicts. 00304 # undef for_all_groups 00305 # undef for_all_state_in_groups 00306 00307 00308 #endif // ! VCSN_ALGORITHMS_MINIMIZATION_MOORE_HXX