Vaucanson 1.4
|
00001 // determinize.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 The 00006 // 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_DETERMINIZE_HXX 00019 # define VCSN_ALGORITHMS_DETERMINIZE_HXX 00020 00021 # include <map> 00022 # include <set> 00023 # include <queue> 00024 # include <vaucanson/misc/usual_macros.hh> 00025 # include <vaucanson/automata/concept/automata_base.hh> 00026 00027 # ifndef VCSN_NDEBUG 00028 # include <vaucanson/algorithms/realtime.hh> 00029 # endif // ! VCSN_NDEBUG 00030 00031 namespace vcsn { 00032 00033 /*--------------------. 00034 | subset_construction | 00035 `--------------------*/ 00036 // preconditions : 00037 // - output has been initialized with good series set 00038 // (alphabet is well initialized) ; 00039 // - this algorithm is intended to work with realtime automaton 00040 // over |B<A*> => add concept checking. 00041 // 00042 00043 template <typename A, typename input_t, typename output_t> 00044 void 00045 do_subset_construction(const AutomataBase<A>& , 00046 output_t& output, 00047 const input_t& input, 00048 std::map<typename output_t::hstate_t, 00049 std::set<typename input_t::hstate_t> >& m = 00050 std::map<typename output_t::hstate_t, 00051 std::set<typename input_t::hstate_t> >()) 00052 { 00053 00054 /*--------. 00055 | Typedef | 00056 `--------*/ 00057 00058 AUTOMATON_TYPES(input_t); 00059 AUTOMATON_FREEMONOID_TYPES(input_t); 00060 typedef typename std::set<typename input_t::hstate_t> subset_t; 00061 typedef typename std::map<subset_t, typename output_t::hstate_t> 00062 subset_set_t; 00063 typedef std::pair<subset_t, typename output_t::hstate_t> subset_set_pair_t; 00064 typedef std::vector<typename input_t::hstate_t> delta_ret_t; 00065 00066 00067 /*-----------------. 00068 | Initialization. | 00069 `-----------------*/ 00070 00071 typename output_t::hstate_t qi_hstate = output.add_state(); 00072 subset_t qi; 00073 bool is_final = false; 00074 for_all_const_initial_states(i, input) 00075 { 00076 qi.insert(*i); 00077 is_final |= input.is_final(*i); 00078 } 00079 output.set_initial(qi_hstate); 00080 00081 if (is_final) 00082 output.set_final(qi_hstate); 00083 00084 subset_set_t subset_set; 00085 subset_set[qi] = qi_hstate; 00086 m[qi_hstate] = qi; 00087 00088 00089 /*------------. 00090 | Main loop. | 00091 `------------*/ 00092 00093 subset_t q; 00094 const alphabet_t& alphabet(input.structure().series().monoid().alphabet()); 00095 delta_ret_t dst; 00096 dst.reserve(input.states().size()); 00097 std::queue<subset_t> path; 00098 path.push(qi); 00099 while (!path.empty()) 00100 { 00101 subset_t s = path.front(); 00102 typename input_t::hstate_t s_hstate = subset_set[s]; 00103 path.pop(); 00104 00105 for_all_const_letters(e, alphabet) 00106 { 00107 q.clear (); 00108 bool is_final = false; 00109 for_all_const_ (subset_t, j, s) 00110 { 00111 for (delta_iterator t(input.value(), *j); ! t.done(); t.next()) 00112 { 00113 monoid_elt_t w(input.series_of(*t).structure().monoid(), *e); 00114 if (input.series_of(*t).get(w) != input.series().semiring().wzero_) 00115 { 00116 hstate_t s = input.dst_of(*t); 00117 q.insert(s); 00118 is_final |= input.is_final(s); 00119 } 00120 } 00121 } 00122 typename subset_set_t::const_iterator current = subset_set.find(q); 00123 if (current == subset_set.end()) 00124 { 00125 typename output_t::hstate_t qs = output.add_state(); 00126 current = (subset_set.insert(subset_set_pair_t(q, qs))).first; 00127 m[qs] = q; 00128 00129 if (is_final) 00130 output.set_final(current->second); 00131 path.push(q); 00132 } 00133 output.add_letter_transition(s_hstate, (*current).second, *e); 00134 } 00135 } 00136 } 00137 00138 template<typename A, typename AI> 00139 Element<A, AI> 00140 subset_construction(const Element<A, AI>& a) 00141 { 00142 Element<A, AI> res(a.structure()); 00143 do_subset_construction(res.structure(), res, a); 00144 return res; 00145 } 00146 00147 /*--------------. 00148 | determinize. | 00149 `--------------*/ 00150 template <typename A, typename AI> 00151 void 00152 do_determinize(const AutomataBase<A>& a_set, 00153 Element<A, AI>& output, 00154 const Element<A, AI>& input, 00155 std::map<typename Element<A, AI>::hstate_t, 00156 std::set<typename Element<A, AI>::hstate_t> >& m) 00157 { 00158 BENCH_TASK_SCOPED("determinize"); 00159 precondition(is_realtime(input)); 00160 do_subset_construction(a_set, output, input, m); 00161 } 00162 00163 template<typename A, typename AI> 00164 Element<A, AI> 00165 determinize(const Element<A, AI>& a, 00166 std::map<typename Element<A, AI>::hstate_t, 00167 std::set<typename Element<A, AI>::hstate_t> >& m) 00168 { 00169 Element<A, AI> ret(a.structure()); 00170 do_determinize(ret.structure(), ret, a, m); 00171 return ret; 00172 } 00173 00174 template<typename A, typename AI> 00175 Element<A, AI> 00176 determinize(const Element<A, AI>& a) 00177 { 00178 std::map<typename Element<A, AI>::hstate_t, 00179 std::set<typename Element<A, AI>::hstate_t> > m; 00180 return determinize(a, m); 00181 } 00182 00183 } // vcsn 00184 00185 #endif // ! VCSN_ALGORITHMS_DETERMINIZE_HXX