00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "gecode/int.hh"
00023
00024 #include "gecode/support/sort.hh"
00025 #include "gecode/support/block-allocator.hh"
00026 #include "gecode/support/dynamic-stack.hh"
00027 #include "gecode/support/dynamic-array.hh"
00028
00029 namespace Gecode {
00030
00031 namespace Int { namespace Regular {
00032
00033 class PosSet;
00037 typedef Support::BlockAllocator<PosSet> PosSetAllocator;
00038
00039 class NodeInfo;
00040 class PosInfo;
00041
00042 }}
00043
00045 class REG::Exp {
00046 public:
00047 unsigned int use_cnt;
00048 unsigned int _n_pos;
00052 enum ExpType {
00053 ET_SYMBOL,
00054 ET_CONC,
00055 ET_OR,
00056 ET_STAR
00057 };
00058 ExpType type;
00059 union {
00060 int symbol;
00061 Exp* kids[2];
00062 } data;
00063
00064 void followpos(Int::Regular::PosSetAllocator&,
00065 Int::Regular::NodeInfo&,
00066 Int::Regular::PosInfo*,
00067 int&);
00068 void inc(void);
00069 void dec(void);
00070 unsigned int n_pos(void) const;
00071 std::ostream& print(std::ostream&) const;
00072
00073 static void* operator new(size_t);
00074 static void operator delete(void*);
00075 private:
00076 void dispose(void);
00077 };
00078
00079
00080
00081
00082
00083
00084
00085
00086 forceinline void*
00087 REG::Exp::operator new(size_t s) {
00088 return Memory::malloc(s);
00089 }
00090 forceinline void
00091 REG::Exp::operator delete(void*) {
00092
00093 }
00094
00095 void
00096 REG::Exp::dispose(void) {
00097 Support::DynamicStack<Exp*> todo;
00098 todo.push(this);
00099 while (!todo.empty()) {
00100 Exp* e = todo.pop();
00101 switch (e->type) {
00102 case ET_OR:
00103 case ET_CONC:
00104 if ((e->data.kids[1] != NULL) && (--e->data.kids[1]->use_cnt == 0))
00105 todo.push(e->data.kids[1]);
00106 case ET_STAR:
00107 if ((e->data.kids[0] != NULL) && (--e->data.kids[0]->use_cnt == 0))
00108 todo.push(e->data.kids[0]);
00109 default: ;
00110 }
00111 Memory::free(e);
00112 }
00113 }
00114
00115 forceinline void
00116 REG::Exp::inc(void) {
00117 if (this != NULL)
00118 use_cnt++;
00119 }
00120 forceinline void
00121 REG::Exp::dec(void) {
00122 if ((this != NULL) && (--use_cnt == 0))
00123 dispose();
00124 }
00125
00126
00127 forceinline unsigned int
00128 REG::Exp::n_pos(void) const {
00129 return (this != NULL) ? _n_pos : 0;
00130 }
00131
00132 std::ostream&
00133 REG::Exp::print(std::ostream& os) const {
00134 if (this == NULL)
00135 return os << "[]";
00136 switch (type) {
00137 case ET_SYMBOL:
00138 return os << "[" << data.symbol << "]";
00139 case ET_STAR:
00140 {
00141 bool par = ((data.kids[0] != NULL) &&
00142 ((data.kids[0]->type == ET_CONC) ||
00143 (data.kids[0]->type == ET_OR)));
00144 return data.kids[0]->print(os << (par ? "*(" : "*"))
00145 << (par ? ")" : "");
00146 }
00147 case ET_CONC:
00148 {
00149 bool par0 = ((data.kids[0] != NULL) &&
00150 (data.kids[0]->type == ET_OR));
00151 std::ostream& os1 = data.kids[0]->print(os << (par0 ? "(" : ""))
00152 << (par0 ? ")+" : "+");
00153 bool par1 = ((data.kids[1] != NULL) &&
00154 (data.kids[1]->type == ET_OR));
00155 return data.kids[1]->print(os1 << (par1 ? "(" : "") )
00156 << (par1 ? ")" : "");
00157 }
00158 case ET_OR:
00159 return data.kids[1]->print(data.kids[0]->print(os) << "|");
00160 default: GECODE_NEVER;
00161 }
00162 GECODE_NEVER;
00163 return os;
00164 }
00165
00166
00167
00168
00169
00170
00171
00172 forceinline
00173 REG::REG(Exp* f) : e(f) {}
00174
00175 REG::REG(void) : e(NULL) {}
00176
00177 REG::REG(const REG& r) : e(r.e) {
00178 e->inc();
00179 }
00180
00181 std::ostream&
00182 REG::print(std::ostream& os) const {
00183 return e->print(os);
00184 }
00185
00186 const REG&
00187 REG::operator=(const REG& r) {
00188 if (&r != this) {
00189 r.e->inc();
00190 e->dec();
00191 e = r.e;
00192 }
00193 return *this;
00194 }
00195
00196 REG::~REG(void) {
00197 e->dec();
00198 }
00199
00200 REG::REG(int s) : e(new Exp) {
00201 e->use_cnt = 1;
00202 e->_n_pos = 1;
00203 e->type = REG::Exp::ET_SYMBOL;
00204 e->data.symbol = s;
00205 }
00206
00207 REG
00208 REG::operator|(const REG& r2) {
00209 if (e == r2.e)
00210 return *this;
00211 Exp* f = new Exp();
00212 f->use_cnt = 1;
00213 f->_n_pos = e->n_pos() + r2.e->n_pos();
00214 f->type = REG::Exp::ET_OR;
00215 f->data.kids[0] = e; e->inc();
00216 f->data.kids[1] = r2.e; r2.e->inc();
00217 REG r(f);
00218 return r;
00219 }
00220
00221 REG
00222 REG::operator+(const REG& r2) {
00223 if (e == NULL) return r2;
00224 if (r2.e == NULL) return *this;
00225 Exp* f = new Exp();
00226 f->use_cnt = 1;
00227 f->_n_pos = e->n_pos() + r2.e->n_pos();
00228 f->type = REG::Exp::ET_CONC;
00229 f->data.kids[0] = e; e->inc();
00230 f->data.kids[1] = r2.e; r2.e->inc();
00231 REG r(f);
00232 return r;
00233 }
00234
00235 REG
00236 REG::operator*(void) {
00237 if ((e == NULL) || (e->type == REG::Exp::ET_STAR))
00238 return *this;
00239 Exp* f = new Exp();
00240 f->use_cnt = 1;
00241 f->_n_pos = e->n_pos();
00242 f->type = REG::Exp::ET_STAR;
00243 f->data.kids[0] = e; e->inc();
00244 REG r(f);
00245 return r;
00246 }
00247
00248 REG
00249 REG::operator()(unsigned int n, unsigned int m) {
00250 REG r;
00251 if ((n>m) || (m == 0))
00252 return r;
00253 if (n>0) {
00254 int i = n;
00255 REG r0 = *this;
00256 while (i>0)
00257 if (i & 1) {
00258 r = r0+r; i--;
00259 } else {
00260 r0 = r0+r0; i >>= 1;
00261 }
00262 }
00263 if (m > n) {
00264 int i = m-n;
00265 REG s0;
00266 s0 = s0 | *this;
00267 REG s;
00268 while (i>0)
00269 if (i & 1) {
00270 s = s0+s; i--;
00271 } else {
00272 s0 = s0+s0; i >>= 1;
00273 }
00274 r = r + s;
00275 }
00276 return r;
00277 }
00278
00279 REG
00280 REG::operator()(unsigned int n) {
00281 REG r;
00282 if (n > 0) {
00283 REG r0 = *this;
00284 int i = n;
00285 while (i>0)
00286 if (i & 1) {
00287 r = r0+r; i--;
00288 } else {
00289 r0 = r0+r0; i >>= 1;
00290 }
00291 }
00292 return r+**this;
00293 }
00294
00295 REG
00296 REG::operator+(void) {
00297 return this->operator()(1);
00298 }
00299
00300
00301 namespace Int { namespace Regular {
00302
00303
00304
00305
00306
00307
00311 enum PosSetCmp {
00312 PSC_LE,
00313 PSC_EQ,
00314 PSC_GR
00315 };
00316
00320 class PosSet : public Support::BlockClient<PosSet> {
00321
00322
00323
00324 public:
00325 int pos; PosSet* next;
00326
00327 PosSet(void);
00328 PosSet(int);
00329
00330 bool in(int) const;
00331 static PosSetCmp cmp(PosSet*,PosSet*);
00332 static PosSet* cup(PosSetAllocator&,PosSet*,PosSet*);
00333 };
00334
00335
00336 forceinline
00337 PosSet::PosSet(void) {}
00338 forceinline
00339 PosSet::PosSet(int p) : pos(p), next(NULL) {}
00340
00341
00342 forceinline bool
00343 PosSet::in(int p) const {
00344 for (const PosSet* ps = this; ps != NULL; ps = ps->next)
00345 if (ps->pos == p) {
00346 return true;
00347 } else if (ps->pos < p) {
00348 return false;
00349 }
00350 return false;
00351 }
00352
00353 forceinline PosSetCmp
00354 PosSet::cmp(PosSet* ps1, PosSet* ps2) {
00355 while ((ps1 != NULL) && (ps2 != NULL)) {
00356 if (ps1 == ps2)
00357 return PSC_EQ;
00358 if (ps1->pos < ps2->pos)
00359 return PSC_LE;
00360 if (ps1->pos > ps2->pos)
00361 return PSC_GR;
00362 ps1 = ps1->next; ps2 = ps2->next;
00363 }
00364 if (ps1 == ps2)
00365 return PSC_EQ;
00366 return ps1 == NULL ? PSC_LE : PSC_GR;
00367 }
00368
00369 PosSet*
00370 PosSet::cup(PosSetAllocator& psm, PosSet* ps1, PosSet* ps2) {
00371 PosSet* ps;
00372 PosSet** p = &ps;
00373 while ((ps1 != NULL) && (ps2 != NULL)) {
00374 if (ps1 == ps2) {
00375 *p = ps1; return ps;
00376 }
00377 PosSet* n = new (psm) PosSet;
00378 *p = n; p = &n->next;
00379 if (ps1->pos == ps2->pos) {
00380 n->pos = ps1->pos;
00381 ps1 = ps1->next; ps2 = ps2->next;
00382 } else if (ps1->pos > ps2->pos) {
00383 n->pos = ps1->pos; ps1 = ps1->next;
00384 } else {
00385 n->pos = ps2->pos; ps2 = ps2->next;
00386 }
00387 }
00388 *p = (ps1 != NULL) ? ps1 : ps2;
00389 return ps;
00390 }
00391
00392
00397 class NodeInfo {
00398 public:
00399 bool nullable;
00400 PosSet* firstpos;
00401 PosSet* lastpos;
00402 };
00403
00404
00409 class PosInfo {
00410 public:
00411 int symbol;
00412 PosSet* followpos;
00413 };
00414
00415 }}
00416
00417 void
00418 REG::Exp::followpos(Int::Regular::PosSetAllocator& psm,
00419 Int::Regular::NodeInfo& ni,
00420 Int::Regular::PosInfo* pi, int& p) {
00421 using Int::Regular::PosSet;
00422 using Int::Regular::NodeInfo;
00423 if (this == NULL) {
00424 ni.nullable = true;
00425 ni.firstpos = NULL;
00426 ni.lastpos = NULL;
00427 return;
00428 }
00429 switch (type) {
00430 case ET_SYMBOL:
00431 {
00432 pi[p].symbol = data.symbol;
00433 PosSet* ps = new (psm) PosSet(p);
00434 p++;
00435 ni.nullable = false;
00436 ni.firstpos = ps;
00437 ni.lastpos = ps;
00438 }
00439 break;
00440 case ET_STAR:
00441 {
00442 data.kids[0]->followpos(psm, ni, pi, p);
00443 ni.nullable = true;
00444 for (PosSet* ps = ni.lastpos; ps != NULL; ps = ps->next)
00445 pi[ps->pos].followpos =
00446 PosSet::cup(psm,pi[ps->pos].followpos, ni.firstpos);
00447 }
00448 break;
00449 case ET_CONC:
00450 {
00451 NodeInfo ni0; data.kids[0]->followpos(psm, ni0, pi, p);
00452 data.kids[1]->followpos(psm, ni, pi, p);
00453 for (PosSet* ps = ni0.lastpos; ps != NULL; ps = ps->next)
00454 pi[ps->pos].followpos =
00455 PosSet::cup(psm,pi[ps->pos].followpos,ni.firstpos);
00456 ni.firstpos =
00457 ni0.nullable ? PosSet::cup(psm,ni0.firstpos,ni.firstpos)
00458 : ni0.firstpos;
00459 ni.lastpos =
00460 ni.nullable ? PosSet::cup(psm,ni0.lastpos,ni.lastpos)
00461 : ni.lastpos;
00462 ni.nullable &= ni0.nullable;
00463 }
00464 break;
00465 case ET_OR:
00466 {
00467 NodeInfo ni0; data.kids[0]->followpos(psm, ni0, pi, p);
00468 data.kids[1]->followpos(psm, ni, pi, p);
00469 ni.nullable |= ni0.nullable;
00470 ni.firstpos = PosSet::cup(psm,ni0.firstpos,ni.firstpos);
00471 ni.lastpos = PosSet::cup(psm,ni0.lastpos,ni.lastpos);
00472 }
00473 break;
00474 default: GECODE_NEVER;
00475 }
00476 }
00477
00478
00479 namespace Int { namespace Regular {
00480
00481 class StateNode;
00482
00486 typedef Support::BlockAllocator<StateNode> StatePoolAllocator;
00487
00491 class StateNode : public Support::BlockClient<StateNode> {
00492 public:
00493 PosSet* pos;
00494 int state;
00495 StateNode* next;
00496 StateNode* left;
00497 StateNode* right;
00498 };
00499
00503 class StatePool {
00504 public:
00505 int n_states;
00506 StateNode root;
00507 StateNode* next;
00508 StateNode* all;
00509
00510 StatePool(PosSet*);
00511
00512 StateNode* pop(void);
00513 bool empty(void) const;
00514
00515 int state(StatePoolAllocator&, PosSet*);
00516 };
00517
00518 forceinline
00519 StatePool::StatePool(PosSet* ps) {
00520 next = &root;
00521 all = NULL;
00522 n_states = 1;
00523 root.pos = ps;
00524 root.state = 0;
00525 root.next = NULL;
00526 root.left = NULL;
00527 root.right = NULL;
00528 }
00529
00530 forceinline StateNode*
00531 StatePool::pop(void) {
00532 StateNode* n = next;
00533 next = n->next;
00534 n->next = all;
00535 all = n;
00536 return n;
00537 }
00538
00539 forceinline bool
00540 StatePool::empty(void) const {
00541 return next == NULL;
00542 }
00543
00544 forceinline int
00545 StatePool::state(StatePoolAllocator& spm, PosSet* ps) {
00546 int d = 0;
00547 StateNode** p = NULL;
00548 StateNode* n = &root;
00549 do {
00550 switch (PosSet::cmp(ps,n->pos)) {
00551 case PSC_EQ: return n->state;
00552 case PSC_LE: p = &n->left; n = *p; break;
00553 case PSC_GR: p = &n->right; n = *p; break;
00554 default: GECODE_NEVER;
00555 }
00556 d++;
00557 } while (n != NULL);
00558 n = new (spm) StateNode; *p = n;
00559 n->pos = ps;
00560 n->state = n_states++;
00561 n->next = next;
00562 n->left = NULL;
00563 n->right = NULL;
00564 next = n;
00565 return n->state;
00566 }
00567
00571 class SymbolsInc {
00572 public:
00573 forceinline bool
00574 operator()(int x, int y) {
00575 return x < y;
00576 }
00577 forceinline static void
00578 sort(int s[], int n) {
00579 SymbolsInc o;
00580 Support::quicksort<int,SymbolsInc>(s,n,o);
00581 }
00582 };
00583
00584
00589 class TransitionBag {
00590 private:
00591 Support::DynamicArray<DFA::Transition> t;
00592 int n;
00593 public:
00594 TransitionBag(void);
00595 void add(int,int,int);
00596 void finish(void);
00597 DFA::Transition* transitions(void);
00598 };
00599
00600 forceinline
00601 TransitionBag::TransitionBag(void) : n(0) {}
00602
00603 forceinline void
00604 TransitionBag::add(int i_state, int symbol, int o_state) {
00605 t[n].i_state = i_state;
00606 t[n].symbol = symbol;
00607 t[n].o_state = o_state;
00608 n++;
00609 }
00610
00611 forceinline void
00612 TransitionBag::finish(void) {
00613 t[n].i_state = -1;
00614 }
00615
00616 forceinline DFA::Transition*
00617 TransitionBag::transitions(void) {
00618 return &t[0];
00619 }
00620
00621
00626 class FinalBag {
00627 private:
00628 Support::DynamicArray<int> f;
00629 int n;
00630 public:
00631 FinalBag(void);
00632 void add(int);
00633 void finish(void);
00634 int* finals(void);
00635 };
00636
00637 forceinline
00638 FinalBag::FinalBag(void) : n(0) {}
00639
00640 forceinline void
00641 FinalBag::add(int state) {
00642 f[n++] = state;
00643 }
00644
00645 forceinline void
00646 FinalBag::finish(void) {
00647 f[n] = -1;
00648 }
00649
00650 forceinline int*
00651 FinalBag::finals(void) {
00652 return &f[0];
00653 }
00654
00655 }}
00656
00657 DFA::DFA(REG& r0) {
00658 using Int::Regular::PosSetAllocator;
00659 using Int::Regular::StatePoolAllocator;
00660 using Int::Regular::PosInfo;
00661 using Int::Regular::PosSet;
00662 using Int::Regular::NodeInfo;
00663
00664 using Int::Regular::StatePool;
00665 using Int::Regular::StateNode;
00666
00667 using Int::Regular::TransitionBag;
00668 using Int::Regular::FinalBag;
00669
00670 using Int::Regular::SymbolsInc;
00671
00672 PosSetAllocator psm;
00673 StatePoolAllocator spm;
00674 REG r = r0 + REG(Limits::Int::int_max+1);
00675 int n_pos = r.e->n_pos();
00676
00677 GECODE_AUTOARRAY(PosInfo, pi, n_pos);
00678 for (int i=n_pos; i--; )
00679 pi[i].followpos = NULL;
00680
00681 NodeInfo ni_root;
00682 int n_p = 0;
00683 r.e->followpos(psm,ni_root,&pi[0],n_p);
00684 assert(n_p == n_pos);
00685
00686
00687 GECODE_AUTOARRAY(int, symbols, n_pos);
00688 for (int i=n_pos; i--; )
00689 symbols[i] = pi[i].symbol;
00690
00691 SymbolsInc::sort(&symbols[0],n_pos-1);
00692 int n_symbols = 1;
00693 for (int i = 1; i<n_pos-1; i++)
00694 if (symbols[i-1] != symbols[i])
00695 symbols[n_symbols++] = symbols[i];
00696
00697
00698 TransitionBag tb;
00699 StatePool sp(ni_root.firstpos);
00700 while (!sp.empty()) {
00701 StateNode* sn = sp.pop();
00702 for (int i = n_symbols; i--; ) {
00703 PosSet* u = NULL;
00704 for (PosSet* ps = sn->pos; ps != NULL; ps = ps->next)
00705 if (pi[ps->pos].symbol == symbols[i])
00706 u = PosSet::cup(psm,u,pi[ps->pos].followpos);
00707 if (u != NULL)
00708 tb.add(sn->state,symbols[i],sp.state(spm,u));
00709 }
00710 }
00711 tb.finish();
00712
00713
00714 FinalBag fb;
00715 for (StateNode* n = sp.all; n != NULL; n = n->next)
00716 if (n->pos->in(n_pos-1))
00717 fb.add(n->state);
00718 fb.finish();
00719
00720 init(0,tb.transitions(),fb.finals(),true);
00721 }
00722
00723 }
00724
00725
00726
00727
00728
00729
00730
00731 std::ostream&
00732 operator<<(std::ostream& os, const Gecode::REG& r) {
00733 return r.print(os);
00734 }
00735
00736
00737
00738