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