00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef ASTL_MINIMIZE_H
00023 #define ASTL_MINIMIZE_H
00024
00025 #include <astl.h>
00026 #include <determinize.h>
00027
00028 #include <iostream>
00029 #ifndef __DFA_GLIMPSE_H_
00030 #include <vector>
00031 #endif
00032 #include <iterator>
00033 #include <algorithm>
00034 #include <map>
00035 #include <set>
00036
00037 using namespace std;
00038
00039 namespace astl {
00040
00041 struct minimization_tag
00042 {
00043 unsigned long _degree_in, _equivalent_to;
00044 unsigned char _height;
00045
00046 minimization_tag() : _degree_in(0), _equivalent_to(0), _height(0) { }
00047 unsigned char height() const { return (_height); }
00048 void height(unsigned char x) { _height = x; }
00049 unsigned long degree_in() const { return (_degree_in); }
00050 void degree_in(unsigned long x) { _degree_in = x; }
00051 unsigned long equivalent_to() const { return (_equivalent_to); }
00052 void equivalent_to(unsigned long x) { _equivalent_to = x; }
00053 friend bool operator == (const minimization_tag &x, const minimization_tag &y) {
00054 return (x.degree_in() == y.degree_in() && x.equivalent_to() == y.equivalent_to());
00055 }
00056 minimization_tag& operator=(const empty&) { return *this; }
00057 };
00058
00059 ostream& operator << (ostream &out, const struct minimization_tag &t)
00060 {
00061 out << t.degree_in() << " " << t.equivalent_to();
00062 return (out);
00063 }
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 template <class DFA, class Dstate>
00074 unsigned char
00075 height(DFA& A, Dstate q, vector<vector < Dstate> *> &partition)
00076 {
00077 const typename DFA::Edges edg = A.delta2(q);
00078 unsigned char max_height = 0;
00079 typename DFA::Edges::const_iterator q_trans, edg_end = edg.end();
00080 Dstate aim;
00081
00082 for (q_trans = edg.begin(); q_trans != edg_end; ++q_trans)
00083 {
00084 aim = (*q_trans).second;
00085 A.tag(aim).degree_in(A.tag(aim).degree_in() + 1);
00086 if (A.tag(aim).degree_in()>1)
00087 max_height = max__(max_height,(unsigned char)(A.tag(aim).height()+1));
00088 else
00089 max_height = max__(max_height,(unsigned char)(height(A,aim,partition)+1));
00090 }
00091 if (partition.size() <= max_height)
00092 partition.push_back(new vector<Dstate>(1, q));
00093 else
00094 partition[max_height]->push_back(q);
00095 A.tag(q).height(max_height);
00096 return (max_height);
00097 }
00098
00099
00100
00101
00102 template <class DFA, class iterator>
00103 void
00104 fusion(DFA &A, iterator start, iterator finish)
00105 {
00106 typedef typename DFA::state_type Dstate;
00107 typename vector<Dstate>::iterator where;
00108 Dstate reference = *start;
00109
00110 for (where = start + 1; where != finish; ++where)
00111 A.tag(*where).equivalent_to((unsigned long) reference);
00112 }
00113
00114
00115
00116
00117 template <class DFA, class State>
00118 void
00119 redirect_edges(DFA &A, vector<State> &v)
00120 {
00121 typename vector<State>::iterator where;
00122 for (where = v.begin(); where != v.end(); ++where)
00123 {
00124 const typename DFA::Edges edg = A.delta2(*where);
00125 typename DFA::Edges::const_iterator trans, edg_end = edg.end();
00126 typename DFA::state_type new_aim, aim;
00127 for (trans = edg.begin(); trans != edg_end; ++trans)
00128 {
00129 aim = (*trans).second;
00130 new_aim = (typename DFA::state_type) A.tag(aim).equivalent_to();
00131 if (new_aim != A.null_state)
00132 {
00133 A.change_trans(*where, (*trans).first, new_aim);
00134 A.tag(aim).degree_in(A.tag(aim).degree_in() - 1);
00135 if (A.tag(aim).degree_in() == 0)
00136 A.del_state(aim);
00137 }
00138 }
00139 }
00140 }
00141
00142
00143 template <class DFA, class State>
00144 int
00145 compare_states(DFA &A, State q, State p)
00146 {
00147 bool fq = A.final(q);
00148 bool fp = A.final(p);
00149 if (fq != fp)
00150 return ((int) fq - (int) fp);
00151
00152 typename DFA::Edges::size_type q_trans_count = A.delta2(q).size();
00153 typename DFA::Edges::size_type p_trans_count = A.delta2(p).size();
00154 if (q_trans_count - p_trans_count != 0)
00155 return (q_trans_count - p_trans_count);
00156 if (q_trans_count == 0) return (0);
00157
00158
00159
00160 typename DFA::Edges::const_iterator left_edg_end = A.delta2(q).end();
00161 typename DFA::Edges::const_iterator left = A.delta2(q).begin();
00162 typename DFA::Edges::const_iterator right = A.delta2(p).begin();
00163
00164 for (; left != left_edg_end; ++left, ++right)
00165 {
00166 typedef typename DFA::char_type Dalph;
00167 typedef typename DFA::state_type Dstate;
00168 const pair<const Dalph, Dstate>& q_trans = *left;
00169 const pair<const Dalph, Dstate>& p_trans = *right;
00170
00171 if (q_trans.first == p_trans.first)
00172 {
00173 if (q_trans.second < p_trans.second)
00174 return (-1);
00175 else
00176 if (p_trans.second < q_trans.second)
00177 return (1);
00178 }
00179 else
00180 if (q_trans.first < p_trans.first)
00181 return (-1);
00182 else
00183 return (1);
00184 }
00185 return (0);
00186 }
00187
00188
00189
00190 template <class DFA, class Size_type, class State>
00191 void
00192 group_equivalent_states(DFA &A, vector<State> &v, Size_type start,
00193 Size_type finish, pair<Size_type, Size_type> &rang)
00194 {
00195
00196 Size_type g, d, pg;
00197 pg = g = start + 1;
00198 d = finish;
00199 State e = v[start];
00200 int res;
00201
00202 while (g <= d) {
00203 res = compare_states(A, v[g], e);
00204 if (res == 0) {
00205 swap(v[pg],v[g]);
00206 pg++;
00207 g++;
00208 }
00209 else
00210 if (res < 0) g++;
00211 else {
00212 res = compare_states(A, v[d], e);
00213 if (res == 0)
00214 if(g == pg) {
00215 swap(v[pg],v[d]);
00216 pg++;
00217 g++;
00218 }
00219 else {
00220 swap(v[pg],v[g]);
00221 swap(v[pg],v[d]);
00222 pg++;
00223 }
00224 else
00225 if(res > 0) d--;
00226 else {
00227 swap(v[g],v[d]);
00228 g++;
00229 }
00230 }
00231 }
00232
00233 rang.second = d;
00234 rang.first = pg;
00235 }
00236
00237
00238
00239 template <class DFA, class Size_type, class State>
00240 void
00241 refine_partition(DFA &A, vector<State> &v,
00242 Size_type start, Size_type finish)
00243 {
00244 if (start < finish)
00245 {
00246 pair<typename vector<State>::size_type, typename vector<State>::size_type> range;
00247
00248 group_equivalent_states(A, v, start, finish, range);
00249 if (start < range.first - 1) fusion(A, v.begin() + start, v.begin() + range.first);
00250 if (range.first < range.second) refine_partition(A, v, range.first, range.second);
00251 if (range.second + 1 < finish) refine_partition(A, v, range.second + 1, finish);
00252 }
00253 }
00254
00255
00256
00257 template <class DFA>
00258 void
00259 acyclic_minimization(DFA &dfa)
00260 {
00261 if (dfa.state_count() > 0) {
00262 typedef typename DFA::state_type Dstate;
00263 typedef vector<vector < Dstate> *> matrix;
00264 matrix partition(1, new vector< Dstate>);
00265 height(dfa,dfa.initial(),partition);
00266
00267 if (partition[0]->empty() == false) {
00268 typename matrix::iterator where;
00269 for (where = partition.begin(); where != partition.end(); ++where) {
00270 redirect_edges(dfa, **where);
00271 refine_partition(dfa, **where, (typename matrix::size_type) 0,
00272 (**where).size() - 1);
00273 delete (*where);
00274 }
00275 }
00276 }
00277 }
00278
00279 template <typename DFA, typename NFA>
00280 void
00281 reverse(const DFA &a1, NFA &a2)
00282 {
00283 map<typename DFA::state_type,
00284 safe<typename NFA::state_type, NFA::null_state> > m;
00285
00286
00287 for(typename DFA::const_iterator src = a1.begin();
00288 src != a1.end(); ++src) {
00289
00290 safe<typename NFA::state_type, NFA::null_state> &new_aim = m[*src];
00291 if (new_aim == NFA::null_state) {
00292 new_aim = a2.new_state();
00293 a2.final(new_aim) = (a1.initial() == *src);
00294 if (a1.final(*src))
00295 a2.initial().insert(new_aim);
00296 }
00297
00298
00299 typename DFA::edges_type t = a1.delta2(*src);
00300 for(typename DFA::edges_type::const_iterator i = t.begin();
00301 i != t.end(); ++i) {
00302
00303 safe<typename NFA::state_type, NFA::null_state> &new_src = m[(*i).second];
00304 if (new_src == NFA::null_state) {
00305 new_src = a2.new_state();
00306 a2.final(new_src) = a1.initial() == new_src;
00307 if (a1.final((*i).second))
00308 a2.initial().insert(new_src);
00309 }
00310 a2.set_trans(new_src, (*i).first, new_aim);
00311 }
00312 }
00313 }
00314
00315
00316 template <typename DFA1, typename DFA2>
00317 void
00318 brzozowski(const DFA1 &a1, DFA2 &a2)
00319 {
00320 typedef NFA_mmap<typename DFA1::char_traits> nfa_type;
00321
00322 if (a1.state_count() > 0) {
00323 nfa_type tmp2;
00324 {
00325 DFA1 tmp3;
00326 {
00327 nfa_type tmp1;
00328 reverse(a1, tmp1);
00329 tmp3.initial(clone(tmp3, dfirst_markc(forwarddc(tmp1))));
00330 }
00331 reverse(tmp3, tmp2);
00332 }
00333 a2.initial(clone(a2, dfirst_markc(forwarddc(tmp2))));
00334 }
00335 }
00336
00337 }
00338
00339 #endif // ASTL_MINIMIZE_H