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