00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <gecode/int.hh>
00035
00036 namespace Gecode { namespace Int { namespace Extensional {
00037
00041 class TransByI_State {
00042 public:
00043 forceinline bool
00044 operator ()(const DFA::Transition& x, const DFA::Transition& y) {
00045 return x.i_state < y.i_state;
00046 }
00047 forceinline static void
00048 sort(DFA::Transition t[], int n) {
00049 TransByI_State tbis;
00050 Support::quicksort<DFA::Transition,TransByI_State>(t,n,tbis);
00051 }
00052 };
00053
00057 class TransBySymbol {
00058 public:
00059 forceinline bool
00060 operator ()(const DFA::Transition& x, const DFA::Transition& y) {
00061 return x.symbol < y.symbol;
00062 }
00063 forceinline static void
00064 sort(DFA::Transition t[], int n) {
00065 TransBySymbol tbs;
00066 Support::quicksort<DFA::Transition,TransBySymbol>(t,n,tbs);
00067 }
00068 };
00069
00073 class TransBySymbolI_State {
00074 public:
00075 forceinline bool
00076 operator ()(const DFA::Transition& x, const DFA::Transition& y) {
00077 return ((x.symbol < y.symbol) ||
00078 ((x.symbol == y.symbol) && (x.i_state < y.i_state)));
00079 }
00080 forceinline static void
00081 sort(DFA::Transition t[], int n) {
00082 TransBySymbolI_State tbsi;
00083 Support::quicksort<DFA::Transition,TransBySymbolI_State>(t,n,tbsi);
00084 }
00085 };
00086
00090 class TransByO_State {
00091 public:
00092 forceinline bool
00093 operator ()(const DFA::Transition& x, const DFA::Transition& y) {
00094 return x.o_state < y.o_state;
00095 }
00096 forceinline static void
00097 sort(DFA::Transition t[], int n) {
00098 TransByO_State tbos;
00099 Support::quicksort<DFA::Transition,TransByO_State>(t,n,tbos);
00100 }
00101 };
00102
00103
00107 class StateGroup {
00108 public:
00109 int state;
00110 int group;
00111 };
00112
00116 class StateGroupByGroup {
00117 public:
00118 forceinline bool
00119 operator ()(const StateGroup& x, const StateGroup& y) {
00120 return ((x.group < y.group) ||
00121 ((x.group == y.group) && (x.state < y.state)));
00122 }
00123 static void
00124 sort(StateGroup sg[], int n) {
00125 StateGroupByGroup o;
00126 Support::quicksort<StateGroup,StateGroupByGroup>(sg,n,o);
00127 }
00128 };
00129
00133 class GroupStates {
00134 public:
00135 StateGroup* fst;
00136 StateGroup* lst;
00137 };
00138
00140 enum StateInfo {
00141 SI_NONE = 0,
00142 SI_FROM_START = 1,
00143 SI_TO_FINAL = 2,
00144 SI_FINAL = 4
00145 };
00146
00147 }}}
00148
00149 namespace Gecode {
00150
00151 void
00152 DFA::init(int start, Transition t_spec[], int f_spec[], bool minimize) {
00153 using namespace Int;
00154 using namespace Extensional;
00155 Region region;
00156
00157
00158 int n_states = start;
00159 int n_trans = 0;
00160 for (Transition* t = &t_spec[0]; t->i_state >= 0; t++) {
00161 n_states = std::max(n_states,t->i_state);
00162 n_states = std::max(n_states,t->o_state);
00163 n_trans++;
00164 }
00165 for (int* f = &f_spec[0]; *f >= 0; f++)
00166 n_states = std::max(n_states,*f);
00167 n_states++;
00168
00169
00170 Transition* trans = region.alloc<Transition>(n_trans);
00171 for (int i=0; i<n_trans; i++)
00172 trans[i] = t_spec[i];
00173
00174 int* final = region.alloc<int>(n_states+1);
00175 bool* is_final = region.alloc<bool>(n_states+1);
00176 int n_finals = 0;
00177 for (int i=0; i<n_states+1; i++)
00178 is_final[i] = false;
00179 for (int* f = &f_spec[0]; *f != -1; f++) {
00180 is_final[*f] = true;
00181 final[n_finals++] = *f;
00182 }
00183
00184 if (minimize) {
00185
00186 TransBySymbolI_State::sort(trans, n_trans);
00187 Transition** idx = region.alloc<Transition*>(n_trans+1);
00188
00189 int n_symbols = 0;
00190 {
00191 int j = 0;
00192 while (j < n_trans) {
00193 idx[n_symbols++] = &trans[j];
00194 int s = trans[j].symbol;
00195 while ((j < n_trans) && (s == trans[j].symbol))
00196 j++;
00197 }
00198 idx[n_symbols] = &trans[j];
00199 assert(j == n_trans);
00200 }
00201
00202 int* s2g = region.alloc<int>(n_states+1);
00203 StateGroup* part = region.alloc<StateGroup>(n_states+1);
00204 GroupStates* g2s = region.alloc<GroupStates>(n_states+1);
00205
00206 for (int i=0; i<n_states+1; i++) {
00207 part[i].state = i;
00208 part[i].group = is_final[i] ? 1 : 0;
00209 s2g[i] = part[i].group;
00210 }
00211
00212
00213
00214
00215
00216 StateGroupByGroup::sort(part,n_states+1);
00217 int n_groups;
00218 if (part[0].group == part[n_states].group) {
00219
00220 g2s[0].fst = &part[0]; g2s[0].lst = &part[n_states+1];
00221 n_groups = 1;
00222 } else {
00223 int i = 0;
00224 assert(part[0].group == 0);
00225 do i++; while (part[i].group == 0);
00226 g2s[0].fst = &part[0]; g2s[0].lst = &part[i];
00227 g2s[1].fst = &part[i]; g2s[1].lst = &part[n_states+1];
00228 n_groups = 2;
00229 }
00230
00231
00232 {
00233 int m_groups;
00234 do {
00235 m_groups = n_groups;
00236
00237 for (int sidx = n_symbols; sidx--; ) {
00238
00239 for (int g = n_groups; g--; ) {
00240
00241 if (g2s[g].lst-g2s[g].fst > 1) {
00242
00243
00244
00245 Transition* t = idx[sidx];
00246 Transition* t_lst = idx[sidx+1];
00247 for (StateGroup* sg = g2s[g].fst; sg<g2s[g].lst; sg++) {
00248 while ((t < t_lst) && (t->i_state < sg->state))
00249 t++;
00250
00251 if ((t < t_lst) && (t->i_state == sg->state))
00252 sg->group = s2g[t->o_state];
00253 else
00254 sg->group = s2g[n_states];
00255 }
00256
00257 StateGroupByGroup::sort(g2s[g].fst,
00258 static_cast<int>(g2s[g].lst-g2s[g].fst));
00259
00260 if (g2s[g].fst->group != (g2s[g].lst-1)->group) {
00261
00262 StateGroup* sg = g2s[g].fst+1;
00263 while ((sg-1)->group == sg->group)
00264 sg++;
00265
00266 StateGroup* lst = g2s[g].lst;
00267 g2s[g].lst = sg;
00268 while (sg < lst) {
00269 s2g[sg->state] = n_groups;
00270 g2s[n_groups].fst = sg++;
00271 while ((sg < lst) && ((sg-1)->group == sg->group)) {
00272 s2g[sg->state] = n_groups; sg++;
00273 }
00274 g2s[n_groups++].lst = sg;
00275 }
00276 }
00277 }
00278 }
00279 }
00280 } while (n_groups != m_groups);
00281
00282 start = s2g[start];
00283
00284 n_finals = 0;
00285 for (int g = n_groups; g--; )
00286 for (StateGroup* sg = g2s[g].fst; sg < g2s[g].lst; sg++)
00287 if (is_final[sg->state]) {
00288 final[n_finals++] = g;
00289 break;
00290 }
00291
00292 int* s2r = region.alloc<int>(n_states+1);
00293 for (int i=0; i<n_states+1; i++)
00294 s2r[i] = -1;
00295 for (int g=0; g<n_groups; g++)
00296 s2r[g2s[g].fst->state] = g;
00297
00298 int j = 0;
00299 for (int i = 0; i<n_trans; i++)
00300 if (s2r[trans[i].i_state] != -1) {
00301 trans[j].i_state = s2g[trans[i].i_state];
00302 trans[j].symbol = trans[i].symbol;
00303 trans[j].o_state = s2g[trans[i].o_state];
00304 j++;
00305 }
00306 n_trans = j;
00307 n_states = n_groups;
00308 }
00309 }
00310
00311
00312 Gecode::Support::StaticStack<int,Region> visit(region,n_states);
00313 int* state = region.alloc<int>(n_states);
00314 for (int i=0; i<n_states; i++)
00315 state[i] = SI_NONE;
00316
00317 Transition** idx = region.alloc<Transition*>(n_states+1);
00318 {
00319
00320
00321 TransByI_State::sort(trans, n_trans);
00322 {
00323 int j = 0;
00324 for (int i=0; i<n_states; i++) {
00325 idx[i] = &trans[j];
00326 while ((j < n_trans) && (i == trans[j].i_state))
00327 j++;
00328 }
00329 idx[n_states] = &trans[j];
00330 assert(j == n_trans);
00331 }
00332
00333 state[start] = SI_FROM_START;
00334 visit.push(start);
00335 while (!visit.empty()) {
00336 int s = visit.pop();
00337 for (Transition* t = idx[s]; t < idx[s+1]; t++)
00338 if (!(state[t->o_state] & SI_FROM_START)) {
00339 state[t->o_state] |= SI_FROM_START;
00340 visit.push(t->o_state);
00341 }
00342 }
00343 }
00344
00345
00346 {
00347
00348
00349 TransByO_State::sort(trans, n_trans);
00350 {
00351 int j = 0;
00352 for (int i=0; i<n_states; i++) {
00353 idx[i] = &trans[j];
00354 while ((j < n_trans) && (i == trans[j].o_state))
00355 j++;
00356 }
00357 idx[n_states] = &trans[j];
00358 assert(j == n_trans);
00359 }
00360
00361 for (int i=0; i<n_finals; i++) {
00362 state[final[i]] |= (SI_TO_FINAL | SI_FINAL);
00363 visit.push(final[i]);
00364 }
00365 while (!visit.empty()) {
00366 int s = visit.pop();
00367 for (Transition* t = idx[s]; t < idx[s+1]; t++)
00368 if (!(state[t->i_state] & SI_TO_FINAL)) {
00369 state[t->i_state] |= SI_TO_FINAL;
00370 visit.push(t->i_state);
00371 }
00372 }
00373 }
00374
00375
00376 int* re = region.alloc<int>(n_states);
00377 for (int i=0; i<n_states; i++)
00378 re[i] = -1;
00379
00380
00381 int m_states = 0;
00382
00383 re[start] = m_states++;
00384
00385
00386 for (int i=n_states; i--; )
00387 if ((state[i] == (SI_FINAL | SI_FROM_START | SI_TO_FINAL)) && (re[i] < 0))
00388 re[i] = m_states++;
00389
00390 int final_fst = (state[start] & SI_FINAL) ? 0 : 1;
00391 int final_lst = m_states;
00392
00393
00394
00395 for (int i=n_states; i--; )
00396 if ((state[i] == (SI_FROM_START | SI_TO_FINAL)) && (re[i] < 0))
00397 re[i] = m_states++;
00398
00399
00400 int m_trans = 0;
00401 for (int i=n_trans; i--; )
00402 if ((re[trans[i].i_state] >= 0) && (re[trans[i].o_state] >= 0))
00403 m_trans++;
00404
00405
00406 DFAI* d = new DFAI(m_trans);
00407 d->n_states = m_states;
00408 d->n_trans = m_trans;
00409 d->final_fst = final_fst;
00410 d->final_lst = final_lst;
00411 {
00412 int j = 0;
00413 Transition* r = &d->trans[0];
00414 for (int i = 0; i<n_trans; i++)
00415 if ((re[trans[i].i_state] >= 0) && (re[trans[i].o_state] >= 0)) {
00416 r[j].symbol = trans[i].symbol;
00417 r[j].i_state = re[trans[i].i_state];
00418 r[j].o_state = re[trans[i].o_state];
00419 j++;
00420 }
00421 TransBySymbol::sort(r,m_trans);
00422 }
00423 {
00424
00425 unsigned int n_symbols = 0;
00426 for (int i = 0; i<m_trans; ) {
00427 int s = d->trans[i++].symbol;
00428 n_symbols++;
00429 while ((i<m_trans) && (d->trans[i].symbol == s))
00430 i++;
00431 }
00432 d->n_symbols = n_symbols;
00433 }
00434 {
00435
00436 unsigned int max_degree = 0;
00437 unsigned int* deg = region.alloc<unsigned int>(m_states);
00438
00439
00440 for (int i=0; i<m_states; i++)
00441 deg[i] = 0;
00442 for (int i=0; i<m_trans; i++)
00443 deg[d->trans[i].o_state]++;
00444 for (int i=0; i<m_states; i++)
00445 max_degree = std::max(max_degree,deg[i]);
00446
00447
00448 for (int i=0; i<m_states; i++)
00449 deg[i] = 0;
00450 for (int i=0; i<m_trans; i++)
00451 deg[d->trans[i].i_state]++;
00452 for (int i=0; i<m_states; i++)
00453 max_degree = std::max(max_degree,deg[i]);
00454
00455
00456 {
00457 int i=0;
00458 while (i < m_trans) {
00459 int j=i++;
00460 while ((i < m_trans) &&
00461 (d->trans[j].symbol == d->trans[i].symbol))
00462 i++;
00463 max_degree = std::max(max_degree,static_cast<unsigned int>(i-j));
00464 }
00465 }
00466
00467 d->max_degree = max_degree;
00468 }
00469
00470 d->fill();
00471 object(d);
00472 }
00473
00474 DFA::DFA(int start, Transition t_spec[], int f_spec[], bool minimize) {
00475 init(start,t_spec,f_spec,minimize);
00476 }
00477
00478 DFA::DFA(int start, std::initializer_list<Transition> tl,
00479 std::initializer_list<int> fl, bool minimize) {
00480 Region reg;
00481 int nt = static_cast<int>(tl.size());
00482 int nf = static_cast<int>(fl.size());
00483 Transition* ts = reg.alloc<Transition>(nt + 1);
00484 {
00485 int i=0;
00486 for (const Transition& t : tl)
00487 ts[i++] = t;
00488 ts[nt].i_state = -1;
00489 }
00490 int* fs = reg.alloc<int>(nf + 1);
00491 {
00492 int i=0;
00493 for (const int& f : fl)
00494 fs[i++] = f;
00495 fs[nf] = -1;
00496 }
00497 init(start,ts,fs,minimize);
00498 }
00499
00500 bool
00501 DFA::equal(const DFA& d) const {
00502 assert(n_states() == d.n_states());
00503 assert(n_transitions() == d.n_transitions());
00504 assert(n_symbols() == d.n_symbols());
00505 assert(final_fst() == d.final_fst());
00506 assert(final_lst() == d.final_lst());
00507 DFA::Transitions me(*this);
00508 DFA::Transitions they(d);
00509 while (me()) {
00510 if (me.i_state() != they.i_state())
00511 return false;
00512 if (me.symbol() != they.symbol())
00513 return false;
00514 if (me.o_state() != they.o_state())
00515 return false;
00516 ++me;
00517 ++they;
00518 }
00519 return true;
00520 }
00521
00522 }
00523
00524
00525