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>
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 public:
00038 reducer(const Element<A, AI>& input, Element<A, AI>& output) :
00039 null_series_(input.series().zero_),
00040 semiring_elt_zero_(input.series().semiring().wzero_),
00041 semiring_elt_one_(input.series().semiring().wone_),
00042 monoid_identity_(input.series().monoid().VCSN_EMPTY_),
00043 output_(output)
00044 {
00045 std::map<hstate_t, int> state_to_index;
00046 int i = 0;
00047
00048 for_all_const_states(s, input)
00049 state_to_index[*s] = i++;
00050 nb_states_ = i;
00051
00052 init_.resize(i);
00053 final_.resize(i);
00054
00055
00056
00057 for_all_const_initial_states(s, input)
00058 init_[state_to_index[*s]] = input.get_initial(*s).get(monoid_identity_);
00059
00060 for_all_const_final_states(s, input)
00061 final_[state_to_index[*s]] = input.get_final(*s).get(monoid_identity_);
00062
00063 for_all_const_transitions(t, input)
00064 {
00065 series_set_elt_t s = input.series_of(*t);
00066 assert(is_support_in_alphabet(s));
00067 for_all_(series_set_elt_t::support_t, l, s.supp())
00068 {
00069 const monoid_elt_t m(input.structure().series().monoid(), *l);
00070 typename semiring_matrix_set_t::iterator it = letter_matrix_set_.find(m);
00071 if (it == letter_matrix_set_.end())
00072 it = letter_matrix_set_.insert(make_pair(m, semiring_matrix_t(nb_states_))).first;
00073 it->second[state_to_index[input.src_of(*t)]][state_to_index[input.dst_of(*t)]] = s.get(m);
00074 }
00075 }
00076 }
00077
00078 void
00079 left_reduce()
00080 {
00081 std::queue<semiring_vector_t> q;
00082 q.push(init_);
00083 semiring_matrix_t m;
00084
00085 while (!q.empty())
00086 {
00087 semiring_vector_t curr = q.front();
00088 q.pop();
00089
00090
00091 std::size_t curr_fnn = 0;
00092
00093
00094 typename semiring_matrix_t::iterator m_row = m.begin();
00095 while (m_row != m.end())
00096 {
00097 while (curr_fnn < nb_states_ && curr[curr_fnn] == semiring_elt_zero_)
00098 curr_fnn++;
00099
00100
00101 std::size_t m_row_fnn = 0;
00102 while (m_row_fnn < nb_states_ && m_row->find(m_row_fnn) == m_row->end())
00103 m_row_fnn++;
00104
00105
00106
00107 if (curr_fnn < m_row_fnn)
00108 break;
00109
00110 if (curr_fnn == m_row_fnn)
00111 {
00112 semiring_elt_t coef = curr[curr_fnn] / (*m_row)[m_row_fnn];
00113 for (typename std::map<std::size_t, semiring_elt_t>::const_iterator it = (*m_row).begin();
00114 it != (*m_row).end(); it++)
00115 {
00116 semiring_elt_t tmp = curr[it->first] - coef * it->second;
00117
00118
00119 if (tmp == semiring_elt_zero_)
00120 curr[it->first] = semiring_elt_zero_;
00121 else
00122 curr[it->first] = tmp;
00123 }
00124 }
00125 m_row++;
00126 }
00127 while (curr_fnn < nb_states_ && curr[curr_fnn] == semiring_elt_zero_)
00128 curr_fnn++;
00129 if (curr_fnn != nb_states_)
00130 {
00131 m_row = m.insert(m_row, std::map<std::size_t, semiring_elt_t>());
00132 for (size_t i = curr_fnn; i < nb_states_; i++)
00133 if (curr[i] != semiring_elt_zero_)
00134 (*m_row)[i] = curr[i];
00135
00136
00137
00138 for (typename semiring_matrix_set_t::const_iterator it = letter_matrix_set_.begin();
00139 it != letter_matrix_set_.end(); it++)
00140 {
00141 semiring_vector_t to_push(nb_states_, semiring_elt_zero_);
00142 typename std::map<std::size_t, semiring_elt_t>::const_iterator tmp;
00143 for (size_t i = 0; i < nb_states_; i++)
00144 for (size_t j = 0; j < nb_states_; j++)
00145 if ((tmp = it->second[j].find(i)) != it->second[j].end())
00146 to_push[i] += curr[j] * tmp->second;
00147 q.push(to_push);
00148 }
00149 }
00150 }
00151
00152
00153 semiring_vector_t newinit(m.size(), semiring_elt_zero_);
00154
00155 for (std::size_t i = 0; i < m.size(); i++)
00156 {
00157 std::size_t init_fnn = 0;
00158 for (std::size_t j = 0; j < m.size(); j++)
00159 {
00160 while (init_fnn < nb_states_ && init_[init_fnn] == semiring_elt_zero_)
00161 init_fnn++;
00162
00163 std::size_t mj_fnn = 0;
00164 while (mj_fnn < m.size() && m[j].find(mj_fnn) == m[j].end())
00165 mj_fnn++;
00166
00167 if (init_fnn == mj_fnn)
00168 {
00169 semiring_elt_t coef = init_[init_fnn] / m[j][mj_fnn];
00170 for (typename std::map<std::size_t, semiring_elt_t>::const_iterator it = m[j].begin();
00171 it != m[j].end(); it++)
00172 {
00173 semiring_elt_t tmp = init_[it->first] - coef * it->second;
00174
00175
00176 if (tmp == semiring_elt_zero_)
00177 init_[it->first] = semiring_elt_zero_;
00178 else
00179 init_[it->first] = tmp;
00180 }
00181 newinit[j] = coef;
00182 }
00183 }
00184 }
00185 std::swap(init_, newinit);
00186
00187
00188 semiring_vector_t newfinal(m.size(), semiring_elt_zero_);
00189 for (std::size_t i = 0; i < m.size(); i++)
00190 {
00191 for (typename std::map<std::size_t, semiring_elt_t>::iterator it = m[i].begin();
00192 it != m[i].end(); it++)
00193 newfinal[i] += it->second * final_[it->first];
00194 }
00195 std::swap(final_, newfinal);
00196
00197
00198 for (typename semiring_matrix_set_t::iterator lit = letter_matrix_set_.begin();
00199 lit != letter_matrix_set_.end(); lit++)
00200 {
00201 std::vector<semiring_vector_t> lm(m.size(),
00202 semiring_vector_t(nb_states_,
00203 semiring_elt_zero_));
00204
00205 typename std::map<std::size_t, semiring_elt_t>::iterator tmp;
00206 for (std::size_t i = 0; i < m.size(); i++)
00207 {
00208 for (std::size_t k = 0; k < nb_states_; k++)
00209 for (typename std::map<std::size_t, semiring_elt_t>::iterator mit = m[i].begin();
00210 mit != m[i].end(); mit++)
00211 if ((tmp = lit->second[mit->first].find(k)) != lit->second[mit->first].end())
00212 lm[i][k] += mit->second * tmp->second;
00213 lit->second.resize(m.size());
00214 }
00215
00216 for (std::size_t i = 0; i < m.size(); i++)
00217 {
00218 lit->second[i].clear();
00219 std::size_t lmi_fnn = 0;
00220 for (std::size_t j = 0; j < m.size(); j++)
00221 {
00222 while (lmi_fnn < nb_states_ && lm[i][lmi_fnn] == semiring_elt_zero_)
00223 lmi_fnn++;
00224
00225 std::size_t mj_fnn = 0;
00226 while (mj_fnn < m.size() && m[j].find(mj_fnn) == m[j].end())
00227 mj_fnn++;
00228
00229 if (lmi_fnn == mj_fnn)
00230 {
00231 semiring_elt_t coef = lm[i][lmi_fnn] / m[j][mj_fnn];
00232 for (typename std::map<std::size_t, semiring_elt_t>::const_iterator it = m[j].begin();
00233 it != m[j].end(); it++)
00234 {
00235 semiring_elt_t tmp = lm[i][it->first] - coef * it->second;
00236
00237
00238 if (tmp == semiring_elt_zero_)
00239 lm[i][it->first] = semiring_elt_zero_;
00240 else
00241 lm[i][it->first] = tmp;
00242 }
00243 lit->second[i][j] = coef;
00244 }
00245 }
00246 }
00247 }
00248 nb_states_ = m.size();
00249 }
00250
00251 void
00252 transpose()
00253 {
00254 std::swap(init_, final_);
00255 for (typename semiring_matrix_set_t::iterator lit = letter_matrix_set_.begin();
00256 lit != letter_matrix_set_.end(); lit++)
00257 {
00258 for (std::size_t i = 0; i < nb_states_; i++)
00259 for (std::size_t j = i; j < nb_states_; j++)
00260 {
00261 typename std::map<std::size_t, semiring_elt_t>::iterator ij = lit->second[i].find(j);
00262 typename std::map<std::size_t, semiring_elt_t>::iterator ji = lit->second[j].find(i);
00263 if (ij != lit->second[i].end())
00264 if (ji != lit->second[j].end())
00265 std::swap(ij->second, ji->second);
00266 else
00267 {
00268 lit->second[j][i] = ij->second;
00269 lit->second[i].erase(ij);
00270 }
00271 else
00272 if (ji != lit->second[j].end())
00273 {
00274 lit->second[i][j] = ji->second;
00275 lit->second[j].erase(ji);
00276 }
00277 }
00278 }
00279 }
00280
00281 void
00282 release()
00283 {
00284
00285 automaton_t empty(output_.structure());
00286 output_ = empty;
00287
00288 std::vector<hstate_t> new_states(nb_states_);
00289
00290
00291 for (std::size_t i = 0; i < nb_states_; i++)
00292 {
00293 new_states[i] = output_.add_state();
00294 if (init_[i] != semiring_elt_zero_)
00295 {
00296 series_set_elt_t s(output_.structure().series());
00297 s.assoc(monoid_identity_, init_[i]);
00298 output_.set_initial(new_states[i], s);
00299 }
00300 if (final_[i] != semiring_elt_zero_)
00301 {
00302 series_set_elt_t s(output_.structure().series());
00303 s.assoc(monoid_identity_, final_[i]);
00304 output_.set_final(new_states[i], s);
00305 }
00306 }
00307
00308
00309 for (typename semiring_matrix_set_t::iterator lit = letter_matrix_set_.begin();
00310 lit != letter_matrix_set_.end(); lit++)
00311 for (std::size_t i = 0; i < nb_states_; i++)
00312 for (std::size_t j = 0; j < nb_states_; j++)
00313 {
00314 typename std::map<std::size_t, semiring_elt_t>::iterator tmp;
00315 if ((tmp = lit->second[i].find(j)) != lit->second[i].end())
00316 {
00317 output_.add_weighted_transition(new_states[i], new_states[j],
00318 tmp->second, lit->first.value());
00319 }
00320 }
00321 }
00322
00323 private:
00324
00325 series_set_elt_t null_series_;
00326 semiring_elt_t semiring_elt_zero_;
00327 semiring_elt_t semiring_elt_one_;
00328 monoid_elt_t monoid_identity_;
00329
00330
00331 semiring_vector_t init_;
00332 semiring_vector_t final_;
00333 semiring_matrix_set_t letter_matrix_set_;
00334 size_t nb_states_;
00335
00336 automaton_t& output_;
00337 };
00338
00339
00340 template<typename A, typename AI>
00341 Element<A, AI>
00342 reduce(const Element<A, AI>& a, misc::direction_type dir)
00343 {
00344 precondition(is_realtime(a));
00345 Element<A, AI> output(a.structure());
00346 reducer<A, AI> r(a, output);
00347 if (dir == misc::right_left)
00348 r.transpose();
00349 r.left_reduce();
00350 r.transpose();
00351 r.left_reduce();
00352 if (dir == misc::left_right)
00353 r.transpose();
00354 r.release();
00355 return output;
00356 }
00357
00358 template<typename A, typename AI>
00359 void
00360 reduce_here(Element<A, AI>& a, misc::direction_type dir)
00361 {
00362 precondition(is_realtime(a));
00363 reducer<A, AI> r(a, a);
00364 if (dir == misc::right_left)
00365 r.transpose();
00366 r.left_reduce();
00367 r.transpose();
00368 r.left_reduce();
00369 if (dir == misc::left_right)
00370 r.transpose();
00371 r.release();
00372 }
00373
00374 }
00375
00376 #endif // !VCSN_ALGORITHMS_REDUCE_HXX //