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

common.icc

Go to the documentation of this file.
00001 /*
00002  *  Main authors:
00003  *     Guido Tack <tack@gecode.org>
00004  *     Christian Schulte <schulte@gecode.org>
00005  *
00006  *  Contributing authors:
00007  *     Gabor Szokoli <szokoli@gecode.org>
00008  *
00009  *  Copyright:
00010  *     Guido Tack, 2004
00011  *     Christian Schulte, 2004
00012  *     Gabor Szokoli, 2004
00013  *
00014  *  Last modified:
00015  *     $Date: 2006-08-25 17:31:32 +0200 (Fri, 25 Aug 2006) $ by $Author: tack $
00016  *     $Revision: 3573 $
00017  *
00018  *  This file is part of Gecode, the generic constraint
00019  *  development environment:
00020  *     http://www.gecode.org
00021  *
00022  *  See the file "LICENSE" for information on usage and
00023  *  redistribution of this file, and for a
00024  *     DISCLAIMER OF ALL WARRANTIES.
00025  *
00026  */
00027 
00028 namespace Gecode { 
00029 
00030   template <class View0, class View1>
00031   forceinline bool
00032   viewarrayshared(const ViewArray<View0>& va,
00033                        const View1& y) {
00034     return va.shared(y);
00035   }
00036 
00037   template <>
00038   forceinline bool
00039   viewarrayshared<Set::SingletonView,Set::SetView>
00040   (const ViewArray<Set::SingletonView>& va, const Set::SetView& y) {
00041     return false;
00042   }
00043 
00044   template <>
00045   forceinline bool
00046   viewarrayshared<Set::ComplementView<Set::SingletonView>,Set::SetView>
00047   (const ViewArray<Set::ComplementView<Set::SingletonView> >& va,
00048    const Set::SetView& y) {
00049     return false;
00050   }
00051 
00052   template <>
00053   forceinline bool
00054   viewarrayshared<Set::ComplementView<Set::SingletonView>,
00055                        Set::ComplementView<Set::SetView> >
00056   (const ViewArray<Set::ComplementView<Set::SingletonView> >& va,
00057    const Set::ComplementView<Set::SetView>& y) {
00058     return false;
00059   }
00060 
00061 
00062 namespace Set { namespace RelOp {
00063 
00064   /*
00065    * Detect sharing between 3 variables
00066    *
00067    */
00068   template <class View0, class View1, class View2>
00069   forceinline bool
00070   shared(View0 v0, View1 v1, View2 v2) {
00071     return shared(v0,v1) || shared(v0,v2) || shared(v1,v2);
00072   }
00073 
00074   template <class View0, class View1, class View2>
00075   ExecStatus unionCard(Space* home,
00076                        bool& retmodified, View0& x0, View1& x1, View2& x2) {
00077     bool modified = false;
00078     do {
00079       retmodified |= modified;
00080       modified = false;
00081 
00082       {
00083         LubRanges<View0> x0ub(x0);
00084         LubRanges<View1> x1ub(x1);
00085         Iter::Ranges::Inter<LubRanges<View0>, LubRanges<View1> > i1(x0ub,x1ub);
00086         unsigned int s1 = Iter::Ranges::size(i1);
00087         unsigned int res = std::max(x0.cardMin()+
00088                                     (x1.cardMin()<s1 ?
00089                                      0 : x1.cardMin()-s1),
00090                                     std::max(x0.cardMin(),
00091                                              x1.cardMin()));
00092         GECODE_ME_CHECK_MODIFIED(modified, x2.cardMin(home,res));
00093       }
00094 
00095       {
00096         LubRanges<View0> x0ub(x0);
00097         LubRanges<View1> x1ub(x1);
00098         Iter::Ranges::Union<LubRanges<View0>, LubRanges<View1> > u1(x0ub,x1ub);
00099         unsigned int s1 = Iter::Ranges::size(u1);
00100         GECODE_ME_CHECK_MODIFIED(modified, 
00101                           x2.cardMax(home,
00102                                      std::min(x0.cardMax()+x1.cardMax(),s1)));
00103       }
00104 
00105       if (x2.cardMin() > x1.cardMax())
00106         GECODE_ME_CHECK_MODIFIED(modified,
00107                           x0.cardMin(home,x2.cardMin() - x1.cardMax()));
00108 
00109       if (x2.cardMin() > x0.cardMax())
00110         GECODE_ME_CHECK_MODIFIED(modified,
00111                           x1.cardMin(home,x2.cardMin() - x0.cardMax()));
00112 
00113       GECODE_ME_CHECK_MODIFIED(modified,
00114                         x0.cardMax(home,x2.cardMax()));
00115       GECODE_ME_CHECK_MODIFIED(modified,
00116                         x1.cardMax(home,x2.cardMax()));
00117     } while(modified);
00118     return ES_FIX;
00119   }
00120 
00121   template <class View0, class View1>
00122   ExecStatus
00123   unionNCard(Space* home, bool& modified, ViewArray<View0>& x,
00124              View1& y, GLBndSet& unionOfDets) {
00125     int xsize = x.size();
00126     // Max(Xi.cardMin) <= y.card <= Sum(Xi.cardMax)
00127     // Xi.card <=y.cardMax
00128     unsigned int cardMaxSum=unionOfDets.size();
00129     bool maxValid = true;
00130     for (int i=xsize; i--; ){
00131       cardMaxSum+=x[i].cardMax();
00132       if (cardMaxSum < x[i].cardMax()) { maxValid = false; } //overflow
00133       GECODE_ME_CHECK_MODIFIED(modified, y.cardMin(home,x[i].cardMin()) );
00134       GECODE_ME_CHECK_MODIFIED(modified, x[i].cardMax(home,y.cardMax()) );
00135     }
00136     if (maxValid) {
00137       GECODE_ME_CHECK_MODIFIED(modified, y.cardMax(home,cardMaxSum));
00138     }
00139     //y.cardMin - Sum(Xj.cardMax) <= Xi.card
00140 
00141     //TODO: overflow management is a waste now.
00142     {
00143       GECODE_AUTOARRAY(unsigned int, rightSum, xsize);
00144       rightSum[xsize-1]=0;
00145 
00146       for (int i=x.size()-1;i--;) {
00147         rightSum[i] = rightSum[i+1] + x[i+1].cardMax();
00148         if (rightSum[i] < rightSum[i+1]) {
00149           //overflow, fill the rest of the array.
00150           for (int j=i; j>0;j--) {
00151             rightSum[j]=Limits::Set::card_max;
00152           }
00153           break;
00154         }
00155       }
00156 
00157       //Size of union of determied vars missing from x sneaked in here:
00158       unsigned int leftAcc=unionOfDets.size();
00159 
00160       for (int i=0; i<xsize;i++) {
00161         unsigned int jsum = leftAcc+rightSum[i];
00162         //If jsum did not overflow and is less than y.cardMin:
00163         if (jsum >= leftAcc &&  jsum < y.cardMin()) {
00164           GECODE_ME_CHECK_MODIFIED(modified, x[i].cardMin(home,y.cardMin()-jsum));
00165         }
00166         leftAcc += x[i].cardMax();
00167         if (leftAcc < x[i].cardMax()) {leftAcc = Limits::Set::card_max;}
00168       }
00169     }
00170 
00171     //y.cardMin - |U(Xj.ub)| <= Xi.card
00172 
00173     {
00174       GECODE_AUTOARRAY(GLBndSet, rightUnion, xsize);
00175       rightUnion[xsize-1].init(home);
00176       for (int i=xsize-1;i--;){
00177         BndSetRanges prev(rightUnion[i+1]);
00178         LubRanges<View0> prevX(x[i+1]);
00179         Iter::Ranges::Union< BndSetRanges,LubRanges<View0> >
00180           iter(prev,prevX);
00181         rightUnion[i].init(home);
00182         rightUnion[i].includeI(home, iter);
00183       }
00184 
00185       //union of determied vars missing from x sneaked in here:
00186       GLBndSet leftAcc;
00187       leftAcc.update(home,unionOfDets);
00188       for (int i=0; i<xsize; i++) {
00189         BndSetRanges left(leftAcc);
00190         BndSetRanges right(rightUnion[i]);
00191         Iter::Ranges::Union<BndSetRanges,
00192           BndSetRanges> iter(left, right);
00193         unsigned int unionSize = Iter::Ranges::size(iter);
00194         if (y.cardMin() > unionSize) {
00195           GECODE_ME_CHECK_MODIFIED(modified,
00196                             x[i].cardMin(home, y.cardMin() - unionSize) );
00197         }
00198         LubRanges<View0> xiub(x[i]);
00199         leftAcc.includeI(home, xiub);
00200       }
00201 
00202       for (int i=xsize; i--;)
00203         rightUnion[i].dispose(home);
00204       leftAcc.dispose(home);
00205     }
00206 
00207     //no need for this: |y.lb - U(Xj.cardMax)| <= S.card
00208 
00209     return ES_NOFIX;
00210 
00211   }
00212 
00213   /*
00214    * Xi UB is subset of YUB
00215    * Subscribes to Y UB
00216    */
00217   template <class View0, class View1>
00218   ExecStatus
00219   unionNXiUB(Space* home,
00220              bool& modified, ViewArray<View0>& x, View1& y,
00221              GLBndSet & unionOfDets) {
00222     int xsize = x.size();
00223     for (int i=xsize; i--; ) {
00224       LubRanges<View1> yub(y);
00225       GECODE_ME_CHECK_MODIFIED(modified, x[i].intersectI(home, yub));
00226     }
00227     return ES_FIX;
00228   }
00229 
00230   // cardinality rules for PartitionN constraint
00231   template <class View0, class View1>
00232   ExecStatus
00233   partitionNCard(Space* home,
00234                  bool& modified, ViewArray<View0>& x, View1& y,
00235                  GLBndSet& unionOfDets) {
00236     unsigned int cardMinSum=unionOfDets.size();
00237     unsigned int cardMaxSum=unionOfDets.size();
00238     int xsize = x.size();
00239     for (int i=xsize; i--; ) {
00240       cardMinSum+=x[i].cardMin();
00241       if (cardMinSum < x[i].cardMin()) {
00242         //sum of mins overflows: fail the space.
00243         GECODE_ME_CHECK(ME_SET_FAILED);
00244       }
00245     }
00246     GECODE_ME_CHECK_MODIFIED(modified, y.cardMin(home,cardMinSum));
00247     for (int i=xsize; i--; ) {
00248       cardMaxSum+=x[i].cardMax();
00249       if (cardMaxSum < x[i].cardMax()) {
00250         //sum of maxes overflows: no useful information to tell.
00251         goto overflow;
00252       }
00253     }
00254     GECODE_ME_CHECK_MODIFIED(modified, y.cardMax(home,cardMaxSum));
00255   overflow:
00256 
00257     //Cardinality of each x[i] limited by cardinality of y minus all x[j]s:
00258 
00259     {
00260       GECODE_AUTOARRAY(unsigned int, rightMinSum, xsize);
00261       GECODE_AUTOARRAY(unsigned int, rightMaxSum, xsize);
00262       rightMinSum[xsize-1]=0;
00263       rightMaxSum[xsize-1]=0;
00264 
00265       for (int i=x.size()-1;i--;) {
00266         rightMaxSum[i] = rightMaxSum[i+1] + x[i+1].cardMax();
00267         if (rightMaxSum[i] < rightMaxSum[i+1]) {
00268           //overflow, fill the rest of the array.
00269           for (int j=i; j>0;j--) {
00270             rightMaxSum[j]=Limits::Set::card_max;
00271           }
00272           break;
00273         }
00274 
00275         rightMinSum[i] = rightMinSum[i+1] + x[i+1].cardMin();
00276         if (rightMinSum[i] < rightMinSum[i+1]) {
00277           //overflow, fail the space
00278           GECODE_ME_CHECK(ME_SET_FAILED);
00279         }
00280 
00281 
00282       }
00283       unsigned int leftMinAcc=unionOfDets.size();
00284       unsigned int leftMaxAcc=unionOfDets.size();
00285 
00286       for (int i=0; i<xsize;i++) {
00287         unsigned int maxSum = leftMaxAcc+rightMaxSum[i];
00288         unsigned int minSum = leftMinAcc+rightMinSum[i];
00289         //If maxSum did not overflow and is less than y.cardMin:
00290         if (maxSum >= leftMaxAcc &&  maxSum < y.cardMin()) {
00291           GECODE_ME_CHECK_MODIFIED(modified, x[i].cardMin(home,y.cardMin()-maxSum));
00292         }
00293 
00294         //Overflow, fail.
00295         if (minSum < leftMinAcc || y.cardMax() < minSum) {
00296           GECODE_ME_CHECK(ME_SET_FAILED);
00297         }
00298         else {
00299           GECODE_ME_CHECK_MODIFIED(modified, x[i].cardMax(home,y.cardMax()-minSum));
00300         }
00301 
00302         leftMaxAcc += x[i].cardMax();
00303         if (leftMaxAcc < x[i].cardMax()) {leftMaxAcc = Limits::Set::card_max;}
00304         leftMinAcc += x[i].cardMin();
00305         if (leftMinAcc < x[i].cardMin()) {GECODE_ME_CHECK(ME_SET_FAILED);}
00306       }
00307     }
00308 
00309     return ES_NOFIX;
00310   }
00311 
00312   // Xi LB includes YLB minus union Xj UB
00313   // Xi UB is subset of YUB minus union of Xj LBs
00314   template <class View0, class View1>
00315   ExecStatus
00316   partitionNXi(Space* home,
00317                bool& modified, ViewArray<View0>& x, View1& y) {
00318     int xsize = x.size();
00319     GECODE_AUTOARRAY(GLBndSet, afterUB, xsize);
00320     GECODE_AUTOARRAY(GLBndSet, afterLB, xsize);
00321 
00322     {
00323       GLBndSet sofarAfterUB;
00324       GLBndSet sofarAfterLB;
00325       for (int i=xsize; i--;) {
00326         afterUB[i].init(home);
00327         afterLB[i].init(home);
00328         afterUB[i].update(home,sofarAfterUB);
00329         afterLB[i].update(home,sofarAfterLB);
00330         LubRanges<View0> xiub(x[i]);
00331         GlbRanges<View0> xilb(x[i]);
00332         sofarAfterUB.includeI(home,xiub);
00333         sofarAfterLB.includeI(home,xilb);
00334       }
00335       sofarAfterUB.dispose(home);
00336       sofarAfterLB.dispose(home);
00337     }
00338 
00339     {
00340       GLBndSet sofarBeforeUB;
00341       GLBndSet sofarBeforeLB;
00342       for (int i=0; i<xsize; i++) {
00343         LubRanges<View1> yub(y);
00344         BndSetRanges slb(sofarBeforeLB);
00345         BndSetRanges afterlb(afterLB[i]);
00346         Iter::Ranges::Union<BndSetRanges,
00347           BndSetRanges> xjlb(slb, afterlb);
00348         Iter::Ranges::Diff<LubRanges<View1>,
00349           Iter::Ranges::Union<BndSetRanges,
00350           BndSetRanges> > diff1(yub, xjlb);
00351         GECODE_ME_CHECK_MODIFIED(modified, x[i].intersectI(home,diff1));
00352 
00353         GlbRanges<View1> ylb(y);
00354         BndSetRanges sub(sofarBeforeUB);
00355         BndSetRanges afterub(afterUB[i]);
00356         Iter::Ranges::Union<BndSetRanges,
00357           BndSetRanges> xjub(sub, afterub);
00358         Iter::Ranges::Diff<GlbRanges<View1>,
00359           Iter::Ranges::Union<BndSetRanges,
00360           BndSetRanges> > diff2(ylb, xjub);
00361         GECODE_ME_CHECK_MODIFIED(modified, x[i].includeI(home,diff2));
00362 
00363         LubRanges<View0> xiub(x[i]);
00364         GlbRanges<View0> xilb(x[i]);
00365         sofarBeforeUB.includeI(home,xiub);
00366         sofarBeforeLB.includeI(home,xilb);
00367       }
00368       sofarBeforeLB.dispose(home);
00369       sofarBeforeUB.dispose(home);
00370     }
00371 
00372     for (int i=xsize;i--;) {
00373       afterUB[i].dispose(home);
00374       afterLB[i].dispose(home);
00375     }
00376 
00377     return ES_NOFIX;
00378   }
00379 
00380   // Xi UB is subset of YUB minus union of Xj LBs
00381   template <class View0, class View1>
00382   ExecStatus
00383   partitionNXiUB(Space* home,
00384                  bool& modified, ViewArray<View0>& x, View1& y,
00385                  GLBndSet& unionOfDets) {
00386     int xsize = x.size();
00387     GECODE_AUTOARRAY(GLBndSet, afterLB, xsize);
00388 
00389     {
00390       GLBndSet sofarAfterLB;
00391       for (int i=xsize; i--;) {
00392         afterLB[i].init(home);
00393         afterLB[i].update(home,sofarAfterLB);
00394         GlbRanges<View0> xilb(x[i]);
00395         sofarAfterLB.includeI(home,xilb);
00396       }
00397       sofarAfterLB.dispose(home);
00398     }
00399 
00400     {
00401       GLBndSet sofarBeforeLB;
00402       sofarBeforeLB.update(home,unionOfDets);
00403       for (int i=0; i<xsize; i++) {
00404         LubRanges<View1> yub(y);
00405         BndSetRanges slb(sofarBeforeLB);
00406         BndSetRanges afterlb(afterLB[i]);
00407         Iter::Ranges::Union<BndSetRanges,
00408           BndSetRanges> xjlb(slb, afterlb);
00409         Iter::Ranges::Diff<LubRanges<View1>,
00410           Iter::Ranges::Union<BndSetRanges,
00411           BndSetRanges> > diff1(yub, xjlb);
00412         GECODE_ME_CHECK_MODIFIED(modified, x[i].intersectI(home,diff1));
00413 
00414         GlbRanges<View0> xilb(x[i]);
00415         sofarBeforeLB.includeI(home,xilb);
00416       }
00417       sofarBeforeLB.dispose(home);
00418     }
00419     for (int i=xsize; i--;)
00420       afterLB[i].dispose(home);
00421     return ES_NOFIX;
00422   }
00423 
00424   // Xi LB includes YLB minus union Xj UB
00425   template <class View0, class View1>
00426   ExecStatus
00427   partitionNXiLB(Space* home,
00428                  bool& modified, ViewArray<View0>& x, View1& y,
00429                  GLBndSet& unionOfDets) {
00430     int xsize = x.size();
00431     GECODE_AUTOARRAY(GLBndSet, afterUB, xsize);
00432 
00433     {
00434       GLBndSet sofarAfterUB;
00435       for (int i=xsize; i--;) {
00436         afterUB[i].init(home);
00437         afterUB[i].update(home,sofarAfterUB);
00438         LubRanges<View0> xiub(x[i]);
00439         sofarAfterUB.includeI(home,xiub);
00440       }
00441       sofarAfterUB.dispose(home);
00442     }
00443 
00444     {
00445       //The union of previously determined x[j]-s is added to the mix here:
00446       GLBndSet sofarBeforeUB;
00447       sofarBeforeUB.update(home,unionOfDets);
00448       for (int i=0; i<xsize; i++) {
00449         GlbRanges<View1> ylb(y);
00450         BndSetRanges sub(sofarBeforeUB);
00451         BndSetRanges afterub(afterUB[i]);
00452         Iter::Ranges::Union<BndSetRanges,
00453           BndSetRanges> xjub(sub, afterub);
00454         Iter::Ranges::Diff<GlbRanges<View1>,
00455           Iter::Ranges::Union<BndSetRanges,
00456           BndSetRanges> > diff2(ylb, xjub);
00457         GECODE_ME_CHECK_MODIFIED(modified, x[i].includeI(home,diff2));
00458 
00459         LubRanges<View0> xiub(x[i]);
00460         sofarBeforeUB.includeI(home,xiub);
00461       }
00462       sofarBeforeUB.dispose(home);
00463     }
00464     for (int i=xsize;i--;)
00465       afterUB[i].dispose(home);
00466     return ES_NOFIX;
00467   }
00468 
00469   // Y LB contains union of X LBs
00470   template <class View0, class View1>
00471   ExecStatus
00472   partitionNYLB(Space* home,
00473                 bool& modified, ViewArray<View0>& x, View1& y,
00474                 GLBndSet& unionOfDets) {
00475     assert(unionOfDets.isConsistent());
00476     int xsize = x.size();
00477     GECODE_AUTOARRAY(GlbRanges<View0>,xLBs,xsize);
00478     int nonEmptyCounter=0;
00479     for (int i = xsize; i--; ) {
00480       GlbRanges<View0> r(x[i]);
00481       if (r()) {
00482         xLBs[nonEmptyCounter] = r;
00483         nonEmptyCounter++;
00484       }
00485     }
00486     if (nonEmptyCounter !=0) {
00487       Iter::Ranges::NaryUnion<GlbRanges<View0> >
00488         xLBUnion(xLBs,nonEmptyCounter);
00489       BndSetRanges dets(unionOfDets);
00490       Iter::Ranges::Union<Iter::Ranges::NaryUnion<GlbRanges<View0> >,
00491         BndSetRanges>
00492         allUnion(xLBUnion,dets);
00493       GECODE_ME_CHECK_MODIFIED(modified, y.includeI(home,allUnion));
00494     }
00495     return ES_FIX;
00496   }
00497 
00498   // Y UB is subset of union of X UBs
00499   template <class View0, class View1>
00500   ExecStatus
00501   partitionNYUB(Space* home,
00502                 bool& modified, ViewArray<View0>& x, View1& y,
00503                 GLBndSet& unionOfDets) {
00504     int xsize = x.size();
00505     GECODE_AUTOARRAY(LubRanges<View0>,xUBs,xsize);
00506     int nonEmptyCounter=0;
00507     for (int i = xsize; i--; ) {
00508       LubRanges<View0> r(x[i]);
00509       if (r()) {
00510         xUBs[nonEmptyCounter] = r;
00511         nonEmptyCounter++;
00512       }
00513     }
00514     if (nonEmptyCounter !=0) {
00515       Iter::Ranges::NaryUnion<LubRanges<View0> >
00516         xUBUnion(xUBs,nonEmptyCounter);
00517       BndSetRanges dets(unionOfDets);
00518       Iter::Ranges::Union<Iter::Ranges::NaryUnion<LubRanges<View0> >,
00519         BndSetRanges>
00520         fullUnion(xUBUnion, dets);
00521       GECODE_ME_CHECK_MODIFIED(modified, y.intersectI(home,fullUnion));
00522     }
00523     return ES_FIX;
00524   }
00525 
00526 }}}
00527 
00528 // STATISTICS: set-prop