Generated on Wed Nov 1 15:04:47 2006 for Gecode by doxygen 1.4.5

integerset.cc

Go to the documentation of this file.
00001 /*
00002  *  Main authors:
00003  *     Guido Tack <tack@gecode.org>
00004  *
00005  *  Copyright:
00006  *     Guido Tack, 2004
00007  *
00008  *  Last modified:
00009  *     $Date: 2006-04-11 15:58:37 +0200 (Tue, 11 Apr 2006) $ by $Author: tack $
00010  *     $Revision: 3188 $
00011  *
00012  *  This file is part of Gecode, the generic constraint
00013  *  development environment:
00014  *     http://www.gecode.org
00015  *
00016  *  See the file "LICENSE" for information on usage and
00017  *  redistribution of this file, and for a
00018  *     DISCLAIMER OF ALL WARRANTIES.
00019  *
00020  */
00021 
00022 
00023 
00024 #include "gecode/set.hh"
00025 
00026 namespace Gecode { namespace Set {
00027 
00028   BndSet::BndSet(Space* home, const IntSet& is)  {
00029     if (is.size()==0) {
00030       fst(NULL); lst(NULL); _size = 0;
00031     } else {
00032       int n = is.size();
00033       RangeList* r = reinterpret_cast<RangeList*>
00034         (home->alloc(sizeof(RangeList)*n));
00035       fst(r); lst(r+n-1);
00036       unsigned int s = 0;
00037       for (int i = n; i--; ) {
00038         s += is.width(i);
00039         r[i].min(is.min(i)); r[i].max(is.max(i));
00040         r[i].prevnext(&r[i-1],&r[i+1]);
00041       }
00042       r[0].prev(&r[-1],NULL); 
00043       r[n-1].next(&r[n],NULL);
00044       _size = s;
00045     }
00046     assert(isConsistent());
00047   }
00048 
00049   bool
00050   GLBndSet::include_full(Space* home, int mi, int ma) {
00051     assert(ma >= mi);
00052     assert(fst() != NULL);
00053     
00054     RangeList* p = NULL;
00055     RangeList* c = fst();
00056     while (c != NULL) {
00057       if (c->max() >= mi-1){
00058         if (c->min() > ma+1) {  //in a hole before c
00059           _size+=(ma-mi+1);
00060           RangeList* q=new (home) RangeList(mi,ma,NULL,c);
00061           if (p==NULL){ //the new range is the first
00062             assert(c==fst());
00063             c->prev(NULL,q);
00064             fst(q);
00065             return true;
00066           }
00067           q->prev(NULL, p);
00068           p->next(c, q);
00069           c->prev(p, q);
00070           return true;
00071         }
00072         //if the range starts before c, update c->min and size
00073         bool result = false;
00074         if (c->min()>mi) {
00075           _size+=(c->min()-mi);
00076           c->min(mi);
00077           result = true;
00078         }
00079         assert(c->min()<=mi);
00080         assert(c->max()+1>=mi);
00081         if (c->max() >= ma) { 
00082           return result; }
00083 
00084         RangeList* qp = p;
00085         RangeList* q = c;
00086         //sum up the size of holes eaten
00087         int prevMax = c->max();
00088         int growth =0;
00089         // invariant: q->min()<=ma+1
00090         while (q->next(qp)!=NULL && q->next(qp)->min()<=ma+1){
00091           RangeList* nq = q->next(qp);
00092           qp = q; q = nq;
00093           growth+=q->min()-prevMax-1;
00094           prevMax=q->max();
00095         }
00096         assert(growth>=0);
00097         _size+=growth;
00098         if (q->max() < ma) {_size+=ma-q->max(); }
00099         c->max(std::max(ma,q->max()));
00100         if (c==q) {
00101           return true; }
00102         RangeList* oldCNext = c->next(p);
00103         assert(oldCNext!=NULL); //q would have stayed c if c was last.
00104         c->next(oldCNext, q->next(qp));
00105         if (q->next(qp)==NULL){
00106           assert(q==lst());
00107           lst(c);
00108         } else {
00109           q->next(qp)->prev(q,c);
00110         }
00111         oldCNext->dispose(home,c,q);
00112         return true;
00113       }
00114       RangeList* nc = c->next(p);
00115       p=c; c=nc;
00116     }
00117     //the new range is disjoint from the old domain and we add it as last:
00118     assert(mi>max()+1);
00119     RangeList* q = new (home) RangeList(mi, ma, lst(), NULL);
00120     lst()->next(NULL, q);
00121     lst(q);
00122     _size+= q->width();
00123     return true;
00124   }
00125 
00126   bool
00127   LUBndSet::exclude_full(Space* home, int mi, int ma) {
00128     assert(ma >= mi);
00129     assert(mi <= max() && ma >= min() &&
00130            (mi > min() || ma < max()));
00131     bool result=false;
00132 
00133     RangeList* p = NULL;
00134     RangeList* c = fst();
00135     while (c != NULL) {
00136       if (c->max() >= mi){
00137         if (c->min() > ma) { return result; } //in a hole
00138 
00139         if (c->min()<mi && c->max() > ma) {  //Range split:
00140           RangeList* q =
00141             new (home) RangeList(ma+1,c->max(),c,c->next(p));
00142           c->max(mi-1);
00143           if (c != lst()) {c->next(p)->prev(c,q); }
00144           else { lst(q); }
00145           c->next(c->next(p),q);
00146           _size -= (ma-mi+1);
00147           return true;
00148         }
00149 
00150         if (c->max() > ma) { //start of range clipped, end remains
00151           _size-=(ma-c->min()+1);
00152           c->min(ma+1);
00153           return true;
00154         }
00155 
00156         if (c->min() < mi) { //end of range clipped, start remains
00157           _size-=(c->max()-mi+1);
00158           c->max(mi-1);
00159           result=true;
00160         } else { //range *c destroyed
00161           _size-=c->width();
00162           RangeList *cendp = p;
00163           RangeList *cend = c;
00164           while ((cend->next(cendp)!=NULL) && (cend->next(cendp)->max()<=ma)){
00165             RangeList *ncend = cend->next(cendp);
00166             cendp=cend; cend=ncend;
00167             _size-=cend->width();
00168           }
00169           if (fst()==c) { fst(cend->next(cendp)); }
00170           else { p->next(c, cend->next(cendp)); }
00171           if (lst()==cend) { lst(p); }
00172           else { cend->next(cendp)->prev(cend,p); }
00173           RangeList* nc=cend->next(cendp); //performs loop step!
00174           c->dispose(home,p,cend);
00175           p=cend;
00176           c=nc;
00177           if (c!=NULL && c->min() <= ma ) { //start of range clipped, end remains
00178             _size-=(ma-c->min()+1);
00179             c->min(ma+1);
00180           }
00181           return true;
00182         }
00183       }
00184       RangeList *nc = c->next(p);
00185       p=c; c=nc;
00186     }
00187     return result;
00188   }
00189 
00190 #ifndef NDEBUG
00191   using namespace Gecode::Int;
00192 #endif
00193 
00194   bool
00195   BndSet::isConsistent(void) const {
00196 #ifndef NDEBUG
00197     if (fst()==NULL) {
00198       if (lst()!=NULL || size()!=0) {
00199         std::cout<<"Strange empty set.\n";
00200         return false;
00201       } else return true;
00202     }
00203 
00204     if (fst()!=NULL && lst()==NULL) {
00205       std::cout<<"First is not null, last is.\n";
00206       return false;
00207     }
00208 
00209     RangeList *p=NULL;
00210     RangeList *c=fst();
00211 
00212     int min = c->min();
00213     int max = c->max();
00214 
00215     if (max<min) {
00216       std::cout << "Single range list twisted: ("<<min<<","<<max<<")" ;
00217       return false;
00218     }
00219 
00220     RangeList *nc=c->next(p);
00221     p=c; c=nc;
00222     while (c) {
00223       if (max<min) {
00224         std::cout << "1";
00225         return false;
00226       }
00227       if ((max+1)>=c->min()) {
00228         std::cout << "2";
00229         return false;
00230       }
00231       if (c->next(p)==NULL && c!=lst()) {
00232         std::cout << "3";
00233         return false;
00234       }
00235 
00236       if (c->next(p)!=NULL && c->next(p)->prev(c->next(p)->next(c))!=c) {
00237         std::cout<<"Prev of next not self.\n";
00238         ((RangeList *)NULL)->min();
00239         return false;
00240       }
00241 
00242       min = c->min();
00243       max = c->max();
00244       
00245       nc=c->next(p);
00246       p=c; c=nc;
00247     }
00248 #endif
00249     return true;
00250   }
00251 
00252 
00253 }}
00254 
00255 // STATISTICS: set-var
00256