00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef VCSN_ALGORITHMS_REDUCE_HXX
00019 # define VCSN_ALGORITHMS_REDUCE_HXX
00020 # include <queue>
00021 # include <vector>
00022 # include <map>
00023 # include <vaucanson/misc/usual_macros.hh>
00024
00025 namespace vcsn {
00026
00027 template<typename A, typename AI, typename AO>
00028 class reducer
00029 {
00030 typedef Element<A, AI> Auto;
00031 AUTOMATON_TYPES(Auto);
00032 AUTOMATON_FREEMONOID_TYPES(Auto);
00033 typedef std::vector<semiring_elt_t> semiring_vector_t;
00034 typedef std::vector<std::map<std::size_t, semiring_elt_t> > semiring_matrix_t;
00035 typedef std::map<monoid_elt_t, semiring_matrix_t> semiring_matrix_set_t;
00036
00037
00038
00039
00040
00041
00042 public:
00043 reducer(const Element<A, AI>& input, Element<A, AO>& output) :
00044 zero(input.series().semiring().wzero_),
00045 one(input.series().semiring().wone_),
00046 empty_word(input.series().monoid().VCSN_EMPTY_),
00047 output(output)
00048 {
00049 std::map<hstate_t, int> state_to_index;
00050 int i = 0;
00051
00052 for_all_const_states(s, input)
00053 state_to_index[*s] = i++;
00054 nb_states = i;
00055
00056 init.resize(i);
00057 final.resize(i);
00058
00059
00060
00061
00062
00063 for_all_const_initial_states(s, input)
00064 init[state_to_index[*s]] = input.get_initial(*s).get(empty_word);
00065
00066 for_all_const_final_states(s, input)
00067 final[state_to_index[*s]] = input.get_final(*s).get(empty_word);
00068
00069 for_all_const_transitions(t, input)
00070 {
00071 series_set_elt_t s = input.series_of(*t);
00072 assert(is_support_in_alphabet(s));
00073 for_all_(series_set_elt_t::support_t, l, s.supp())
00074 {
00075 const monoid_elt_t m(input.structure().series().monoid(), *l);
00076 typename semiring_matrix_set_t::iterator it = letter_matrix_set.find(m);
00077 if (it == letter_matrix_set.end())
00078 it = letter_matrix_set.insert(make_pair(m, semiring_matrix_t(nb_states))).first;
00079 it->second[state_to_index[input.src_of(*t)]][state_to_index[input.dst_of(*t)]] = s.get(m);
00080 }
00081 }
00082 }
00083
00084
00085 struct triple_t
00086 {
00087 hstate_t state;
00088 semiring_vector_t vector;
00089 monoid_elt_t letter;
00090
00091 triple_t(const hstate_t& state, const semiring_vector_t& vector,
00092 const monoid_elt_t& letter) :
00093 state(state), vector(vector), letter(letter) {}
00094
00095 };
00096
00097
00098 void product_vector_matrix(const semiring_vector_t& v,
00099 const semiring_matrix_t& m,
00100 semiring_vector_t& res)
00101 {
00102 for(int i=0; i<nb_states; i++)
00103 for(typename std::map<std::size_t, semiring_elt_t>::const_iterator it
00104 = m[i].begin(); it != m[i].end(); ++it)
00105 {
00106 int j = it->first;
00107 res[j] += v[i] * it->second;
00108 }
00109 }
00110
00111 semiring_elt_t scalar_product(const semiring_vector_t& v,
00112 const semiring_vector_t& w)
00113 {
00114 semiring_elt_t res(zero);
00115 for(int i = 0; i < nb_states; ++i)
00116 res += v[i] * w[i];
00117 return res;
00118 }
00119
00120
00121 void
00122 left_reduce()
00123 {
00124
00125 {
00126 int i;
00127 for (i = 0; i < nb_states; ++i)
00128 if (init[i] != zero)
00129 break;
00130 if (i == nb_states)
00131 return;
00132 }
00133
00134 std::queue<triple_t> queue;
00135
00136
00137 std::list<std::pair<hstate_t,semiring_vector_t> > base;
00138
00139
00140 hstate_t n_init = output.add_state();
00141 base.push_back(std::pair<hstate_t,semiring_vector_t>(n_init, init));
00142 output.set_initial(n_init);
00143
00144 semiring_elt_t t = scalar_product(init, final);
00145 if(t != zero)
00146 {
00147 series_set_elt_t s(output.structure().series());
00148 s.assoc(empty_word, t);
00149 output.set_final(n_init, s);
00150 }
00151
00152
00153
00154
00155 for (typename semiring_matrix_set_t::const_iterator it
00156 = letter_matrix_set.begin(); it != letter_matrix_set.end(); ++it)
00157 {
00158 semiring_vector_t nv(nb_states);
00159 product_vector_matrix(init, it->second, nv);
00160 queue.push(triple_t(n_init, nv, it->first));
00161 }
00162 while (!queue.empty())
00163 {
00164 triple_t& tr = queue.front();
00165
00166 semiring_vector_t& current = tr.vector;
00167
00168 std::size_t curr_fnn = 0;
00169 std::size_t base_fnn = 0;
00170 for(typename std::list<std::pair<hstate_t,semiring_vector_t> >::iterator it
00171 = base.begin(); it!=base.end(); ++it)
00172 {
00173 while (curr_fnn < nb_states && current[curr_fnn] == zero)
00174 ++curr_fnn;
00175
00176
00177 semiring_vector_t& vbase = it->second;
00178 while (base_fnn < nb_states && vbase[base_fnn] == zero)
00179 ++base_fnn;
00180
00181 if (base_fnn < curr_fnn)
00182
00183 continue;
00184
00185 if (base_fnn > curr_fnn)
00186
00187 {
00188 hstate_t n_state= output.add_state();
00189 base.insert(it,std::pair<hstate_t,semiring_vector_t>(n_state,
00190 current));
00191 series_set_elt_t s(output.structure().series());
00192 s.assoc(tr.letter, one);
00193 output.add_series_transition(tr.state, n_state, s);
00194 semiring_elt_t t=scalar_product(current, final);
00195 if(t != zero)
00196 {
00197 series_set_elt_t s(output.structure().series());
00198 s.assoc(empty_word, t);
00199 output.set_final(n_state, s);
00200 }
00201
00202 for (typename semiring_matrix_set_t::const_iterator itm
00203 = letter_matrix_set.begin();
00204 itm != letter_matrix_set.end(); ++itm)
00205 {
00206 semiring_vector_t nv(nb_states);
00207 product_vector_matrix(current, itm->second, nv);
00208 queue.push(triple_t(n_state, nv, itm->first));
00209 }
00210
00211 curr_fnn = nb_states;
00212 break;
00213 }
00214
00215
00216 semiring_elt_t ratio = current[curr_fnn] / vbase[curr_fnn];
00217
00218 current[curr_fnn] = zero;
00219 for(int i = curr_fnn+1; i < nb_states; ++i)
00220 current[i ] =current[i] - ratio*vbase[i];
00221 series_set_elt_t s(output.structure().series());
00222 s.assoc(tr.letter, ratio);
00223 output.add_series_transition(tr.state, it->first, s);
00224 }
00225
00226
00227 while (curr_fnn < nb_states && current[curr_fnn] == zero)
00228 ++curr_fnn;
00229 if (nb_states> curr_fnn)
00230
00231 {
00232 hstate_t n_state= output.add_state();
00233 base.push_back(std::pair<hstate_t,semiring_vector_t>(n_state,
00234 current));
00235 series_set_elt_t s(output.structure().series());
00236 s.assoc(tr.letter, one);
00237 output.add_series_transition(tr.state, n_state, s);
00238 semiring_elt_t t=scalar_product(current, final);
00239 if(t != zero)
00240 {
00241 series_set_elt_t s(output.structure().series());
00242 s.assoc(empty_word, t);
00243 output.set_final(n_state, s);
00244 }
00245 for (typename semiring_matrix_set_t::const_iterator itm
00246 = letter_matrix_set.begin();
00247 itm != letter_matrix_set.end(); ++itm)
00248 {
00249 semiring_vector_t nv(nb_states);
00250 product_vector_matrix(current, itm->second, nv);
00251 queue.push(triple_t(n_state, nv, itm->first));
00252 }
00253 }
00254 queue.pop();
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 }
00266
00267 private:
00268
00269 semiring_elt_t zero;
00270 semiring_elt_t one;
00271 monoid_elt_t empty_word;
00272
00273
00274 semiring_vector_t init;
00275 semiring_vector_t final;
00276 semiring_matrix_set_t letter_matrix_set;
00277 size_t nb_states;
00278
00279 Element<A, AO>& output;
00280 };
00281
00282 template<typename A, typename AI, typename AO>
00283 void
00284 do_semi_reduce(const Element<A, AI>& a, Element<A, AO>& output)
00285 {
00286 reducer<A, AI, AO> r(a, output);
00287 r.left_reduce();
00288 }
00289
00290 template<typename A, typename AI>
00291 Element<A, AI>
00292 semi_reduce(const Element<A, AI>& a)
00293 {
00294 precondition(is_realtime(a));
00295 Element<A, AI> output(a.structure());
00296 do_semi_reduce(a, output);
00297 return output;
00298 }
00299
00300 template<typename A, typename AI>
00301 Element<A, AI>
00302 reduce(const Element<A, AI>& a, misc::direction_type dir)
00303 {
00304 precondition(is_realtime(a));
00305 Element<A, AI> tmp(a.structure());
00306 Element<A, AI> output(a.structure());
00307 if (dir == misc::right_left)
00308 {
00309 do_semi_reduce(transpose_view(a), tmp);
00310 do_semi_reduce(transpose_view(tmp), output);
00311 return output;
00312 }
00313 else
00314 {
00315 do_semi_reduce(a, tmp);
00316 do_semi_reduce(transpose_view(tmp), output);
00317 return transpose(output);
00318 }
00319 }
00320
00321
00322 }
00323
00324 #endif // !VCSN_ALGORITHMS_REDUCE_HXX //