Generated on Mon Aug 25 11:35:43 2008 for Gecode by doxygen 1.5.6

inter.icc

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Guido Tack <tack@gecode.org>
00005  *     Christian Schulte <schulte@gecode.org>
00006  *
00007  *  Contributing authors:
00008  *     Gabor Szokoli <szokoli@gecode.org>
00009  *
00010  *  Copyright:
00011  *     Guido Tack, 2004
00012  *     Christian Schulte, 2004
00013  *     Gabor Szokoli, 2004
00014  *
00015  *  Last modified:
00016  *     $Date: 2008-07-11 11:03:40 +0200 (Fri, 11 Jul 2008) $ by $Author: tack $
00017  *     $Revision: 7356 $
00018  *
00019  *  This file is part of Gecode, the generic constraint
00020  *  development environment:
00021  *     http://www.gecode.org
00022  *
00023  *  Permission is hereby granted, free of charge, to any person obtaining
00024  *  a copy of this software and associated documentation files (the
00025  *  "Software"), to deal in the Software without restriction, including
00026  *  without limitation the rights to use, copy, modify, merge, publish,
00027  *  distribute, sublicense, and/or sell copies of the Software, and to
00028  *  permit persons to whom the Software is furnished to do so, subject to
00029  *  the following conditions:
00030  *
00031  *  The above copyright notice and this permission notice shall be
00032  *  included in all copies or substantial portions of the Software.
00033  *
00034  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00035  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00036  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00037  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00038  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00039  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00040  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00041  *
00042  */
00043 
00044 namespace Gecode { namespace Set { namespace RelOp {
00045 
00046   /*
00047    * "Ternary intersection" propagator
00048    *
00049    */
00050 
00051   template <class View0, class View1, class View2> ExecStatus
00052   Intersection<View0,View1,View2>::post(Space* home,
00053                                         View0 x0,View1 x1,View2 x2) {
00054     (void) new (home) Intersection<View0,View1,View2>(home,x0,x1,x2);
00055     return ES_OK;
00056   }
00057 
00058   template <class View0, class View1, class View2>
00059   Actor*
00060   Intersection<View0,View1,View2>::copy(Space* home, bool share) {
00061     return new (home) Intersection(home,share,*this);
00062   }
00063 
00064   template <class View0, class View1, class View2>
00065   Support::Symbol
00066   Intersection<View0,View1,View2>::ati(void) {
00067     return Reflection::mangle<View0,View1,View2>("Gecode::Set::RelOp::Intersection");
00068   }
00069 
00070   template <class View0, class View1, class View2>
00071   Reflection::ActorSpec
00072   Intersection<View0,View1,View2>::spec(const Space* home,
00073                                         Reflection::VarMap& m) const {
00074     return MixTernaryPropagator<View0,PC_SET_ANY,View1,PC_SET_ANY,
00075       View2,PC_SET_ANY>::spec(home, m, ati());
00076   }
00077 
00078   template <class View0, class View1, class View2>
00079   void
00080   Intersection<View0,View1,View2>::post(Space* home,
00081                                         Reflection::VarMap& vars,
00082                                         const Reflection::ActorSpec& spec) {
00083     spec.checkArity(3);
00084     View0 x0(home, vars, spec[0]);
00085     View1 x1(home, vars, spec[1]);
00086     View2 x2(home, vars, spec[2]);
00087     (void) new (home) Intersection(home,x0,x1,x2);
00088   }
00089 
00090   template <class View0, class View1, class View2>
00091   ExecStatus
00092   Intersection<View0,View1,View2>::propagate(Space* home, ModEventDelta med) {
00093     // This propagator implements the constraint
00094     // x2 = x0 \cap x1
00095 
00096     bool x0ass = x0.assigned();
00097     bool x1ass = x1.assigned();
00098     bool x2ass = x2.assigned();
00099 
00100     ModEvent me0 = View0::me(med);
00101     ModEvent me1 = View1::me(med);
00102     ModEvent me2 = View2::me(med);
00103 
00104     bool x0lbmod = false;
00105     bool x1lbmod = false;
00106     bool modified = false;
00107 
00108     do {
00109 
00110       modified = false;
00111       do {
00112         // 4) glb(x2) <= glb(x0) \cap glb(x1)
00113         {
00114           GlbRanges<View0> x0lb(x0);
00115           GlbRanges<View1> x1lb(x1);
00116           Iter::Ranges::Inter<GlbRanges<View0>, GlbRanges<View1> > 
00117             i2(x0lb,x1lb);
00118           GECODE_ME_CHECK_MODIFIED(modified, x2.includeI(home,i2) );
00119         }
00120 
00121         if (modified || Rel::testSetEventLB(me2) )
00122           {
00123             modified = false;
00124             // 5) x2 <= x0
00125             GlbRanges<View2> x2lb1(x2);
00126             GECODE_ME_CHECK_MODIFIED(modified, x0.includeI(home,x2lb1) );
00127             x0lbmod |= modified;
00128 
00129             // 6) x2 <= x1
00130             bool modified2=false;
00131             GlbRanges<View2> x2lb2(x2);
00132             GECODE_ME_CHECK_MODIFIED(modified2, x1.includeI(home,x2lb2) );
00133             x1lbmod |= modified2;
00134             modified |= modified2;
00135           }
00136 
00137       } while (modified);
00138 
00139       modified = false;
00140       do {
00141         bool modifiedOld = modified;
00142         modified = false;
00143 
00144         if (Rel::testSetEventUB(me2) || Rel::testSetEventLB(me0)
00145              || x0lbmod || modifiedOld)
00146           {
00147             // 1) lub(x2) \ glb(x0) => lub(x1)
00148             GlbRanges<View0> x0lb(x0);
00149             LubRanges<View2> x2ub(x2);
00150             Iter::Ranges::Diff<GlbRanges<View0>,LubRanges<View2> >
00151               diff(x0lb, x2ub);
00152             GECODE_ME_CHECK_MODIFIED(modified, x1.excludeI(home,diff) );
00153           }
00154 
00155         if (Rel::testSetEventUB(me2) || Rel::testSetEventLB(me1)
00156             || x1lbmod || modifiedOld)
00157           {
00158             // 2) lub(x2) \ glb(x1) => lub(x0)
00159             GlbRanges<View1> x1lb(x1);
00160             LubRanges<View2> x2ub(x2);
00161             Iter::Ranges::Diff<GlbRanges<View1>, LubRanges<View2> >
00162               diff(x1lb, x2ub);
00163             GECODE_ME_CHECK_MODIFIED(modified, x0.excludeI(home,diff) );
00164           }
00165 
00166          if (Rel::testSetEventUB(me0,me1) || modified)
00167           {
00168             //            modified = false;
00169             // 3) lub(x0) \cap lub(x1) <= lub(x2)
00170             LubRanges<View0> x0ub(x0);
00171             LubRanges<View1> x1ub(x1);
00172             Iter::Ranges::Inter<LubRanges<View0>, LubRanges<View1> >
00173               i1(x0ub,x1ub);
00174             GECODE_ME_CHECK_MODIFIED(modified, x2.intersectI(home,i1) );
00175           }
00176 
00177       } while(modified);
00178 
00179       modified = false;
00180       {
00181         // cardinality
00182         ExecStatus ret = interCard(home,modified, x0, x1, x2);
00183         GECODE_ES_CHECK(ret);
00184       }
00185 
00186       if (x2.cardMin() == Set::Limits::card) {
00187         GECODE_ME_CHECK( x0.cardMin(home, Set::Limits::card) );
00188         GECODE_ME_CHECK( x1.cardMin(home, Set::Limits::card) );
00189         return ES_SUBSUMED(this,home);
00190       }
00191 
00192       if (x0.cardMin() == Set::Limits::card)
00193         GECODE_REWRITE(this,(Rel::Eq<View1,View2>::post(home,x1,x2)));
00194       if (x1.cardMin() == Set::Limits::card)
00195         GECODE_REWRITE(this,(Rel::Eq<View0,View2>::post(home,x0,x2)));
00196 
00197     } while(modified);
00198 
00199     if (shared(x0,x1,x2)) {
00200       return (x0ass && x1ass && x2ass) ? ES_SUBSUMED(this,home) : ES_NOFIX;
00201     } else {
00202       if (x0ass && x1ass && x2ass)
00203         return ES_SUBSUMED(this,home);
00204       if (x0ass != x0.assigned() ||
00205           x1ass != x1.assigned() ||
00206           x2ass != x2.assigned()) {
00207         return ES_NOFIX;
00208       } else {
00209          return ES_FIX;
00210       }
00211     }
00212   }
00213 
00214   template <class View0, class View1, class View2>
00215   forceinline
00216   Intersection<View0,View1,View2>::Intersection(Space* home,
00217                                              View0 y0,View1 y1,View2 y2)
00218     : MixTernaryPropagator<View0,PC_SET_ANY,View1,PC_SET_ANY,
00219                              View2,PC_SET_ANY>(home,y0,y1,y2) {}
00220 
00221   template <class View0, class View1, class View2>
00222   forceinline
00223   Intersection<View0,View1,View2>::Intersection(Space* home, bool share,
00224                                              Intersection<View0,View1,View2>& p)
00225     : MixTernaryPropagator<View0,PC_SET_ANY,View1,PC_SET_ANY,
00226                              View2,PC_SET_ANY>(home,share,p) {}
00227 
00228   /*
00229    * "Nary intersection" propagator
00230    *
00231    */
00232 
00233   template <class View0, class View1>
00234   forceinline
00235   IntersectionN<View0,View1>::IntersectionN(Space* home, ViewArray<View0>& x,
00236                                             View1 y)
00237     : MixNaryOnePropagator<View0,PC_SET_ANY,View1,PC_SET_ANY>(home,x,y),
00238       intOfDets(home) {
00239     shared = x.shared() || viewarrayshared(x,y);
00240   }
00241 
00242   template <class View0, class View1>
00243   forceinline
00244   IntersectionN<View0,View1>::IntersectionN(Space* home, ViewArray<View0>& x,
00245                                             const IntSet& z, View1 y)
00246     : MixNaryOnePropagator<View0,PC_SET_ANY,View1,PC_SET_ANY>(home,x,y),
00247       intOfDets(home) {
00248     shared = x.shared() || viewarrayshared(x,y);
00249     IntSetRanges rz(z);
00250     intOfDets.intersectI(home, rz);
00251   }
00252 
00253   template <class View0, class View1>
00254   forceinline
00255   IntersectionN<View0,View1>::IntersectionN(Space* home, bool share,
00256                                             IntersectionN& p)
00257     : MixNaryOnePropagator<View0,PC_SET_ANY,View1,PC_SET_ANY>(home,share,p),
00258       shared(p.shared),
00259       intOfDets() {
00260     intOfDets.update(home, p.intOfDets);
00261   }
00262 
00263   template <class View0, class View1>
00264   ExecStatus
00265   IntersectionN<View0,View1>::post(Space* home,
00266                                    ViewArray<View0>& x, View1 y) {
00267     switch (x.size()) {
00268     case 0:
00269       GECODE_ME_CHECK(y.cardMin(home, Limits::card));
00270       return ES_OK;
00271     case 1:
00272       return Rel::Eq<View0,View1>::post(home, x[0], y);
00273     case 2:
00274       return Intersection<View0,View0,View1>::post(home, x[0], x[1], y);
00275     default:
00276       (void) new (home) IntersectionN<View0,View1>(home,x,y);
00277       return ES_OK;
00278     }
00279   }
00280 
00281   template <class View0, class View1>
00282   ExecStatus
00283   IntersectionN<View0,View1>::post(Space* home, ViewArray<View0>& x,
00284                                    const IntSet& z, View1 y) {
00285     (void) new (home) IntersectionN<View0,View1>(home,x,z,y);
00286     return ES_OK;
00287   }
00288 
00289   template <class View0, class View1>
00290   Actor*
00291   IntersectionN<View0,View1>::copy(Space* home, bool share) {
00292     return new (home) IntersectionN<View0,View1>(home,share,*this);
00293   }
00294 
00295   template <class View0, class View1>
00296   PropCost
00297   IntersectionN<View0,View1>::cost(ModEventDelta) const {
00298     return PC_QUADRATIC_LO;
00299   }
00300 
00301   template <class View0, class View1>
00302   Support::Symbol
00303   IntersectionN<View0,View1>::ati(void) {
00304     return Reflection::mangle<View0,View1>("Gecode::Set::RelOp::IntersectionN");
00305   }
00306 
00307   template <class View0, class View1>
00308   Reflection::ActorSpec
00309   IntersectionN<View0,View1>::spec(const Space* home,
00310                                    Reflection::VarMap& m) const {
00311     Reflection::ActorSpec s =
00312       MixNaryOnePropagator<View0,PC_SET_ANY,View1,PC_SET_ANY>
00313         ::spec(home, m, ati());
00314     int count = 0;
00315     for (BndSetRanges iod(intOfDets); iod(); ++iod)
00316       count++;
00317     Reflection::IntArrayArg* a = Reflection::Arg::newIntArray(count*2);
00318     count = 0;
00319     for (BndSetRanges iod(intOfDets); iod(); ++iod) {
00320       (*a)[count++] = iod.min();
00321       (*a)[count++] = iod.max();
00322     }
00323     return s << a;
00324   }
00325 
00326   template <class View0, class View1>
00327   void
00328   IntersectionN<View0,View1>::post(Space* home,
00329                                    Reflection::VarMap& vars,
00330                                    const Reflection::ActorSpec& spec) {
00331     spec.checkArity(3);
00332     ViewArray<View0> x0(home, vars, spec[0]);
00333     View1 x1(home, vars, spec[1]);
00334     Reflection::IntArrayArgRanges zr(spec[2]->toIntArray());
00335     IntSet z(zr);
00336     (void) new (home) IntersectionN(home,x0,z,x1);
00337   }
00338 
00339   template <class View0, class View1>
00340   ExecStatus
00341   IntersectionN<View0,View1>::propagate(Space* home, ModEventDelta) {
00342 
00343     bool repeat = false;
00344     do {
00345       repeat = false;
00346       int xsize = x.size();
00347       if (xsize == 0)
00348         goto size0;
00349       for (int i = xsize; i--; ) {
00350         GECODE_ME_CHECK( y.cardMax(home,x[i].cardMax()) );
00351         GECODE_ME_CHECK( x[i].cardMin(home,y.cardMin()) );
00352         if (x[i].cardMax()==0) {
00353           GECODE_ME_CHECK( y.cardMax(home, 0));
00354           intOfDets.dispose(home);
00355           return ES_SUBSUMED(this,home);
00356         }
00357       }
00358       {
00359         GECODE_AUTOARRAY(GlbRanges<View0>,xLBs,xsize);
00360         GECODE_AUTOARRAY(LubRanges<View0>,xUBs,xsize);
00361         for (int i = xsize; i--; ) {
00362           GlbRanges<View0> lb(x[i]);
00363           LubRanges<View0> ub(x[i]);
00364           xLBs[i]=lb;
00365           xUBs[i]=ub;
00366         }
00367         Iter::Ranges::NaryInter<GlbRanges<View0> > lbi(xLBs,xsize);
00368         BndSetRanges dets1(intOfDets);
00369         Iter::Ranges::Inter< Iter::Ranges::NaryInter<GlbRanges<View0> >,
00370           BndSetRanges >
00371           lbiAll(lbi,dets1);
00372         GECODE_ME_CHECK( y.includeI(home,lbiAll) );
00373 
00374         Iter::Ranges::NaryInter<LubRanges<View0> > ubi(xUBs,xsize);
00375         BndSetRanges dets2(intOfDets);
00376         Iter::Ranges::Inter< Iter::Ranges::NaryInter<LubRanges<View0> >,
00377           BndSetRanges >
00378           ubiAll(ubi,dets2);
00379         GECODE_ME_CHECK( y.intersectI(home,ubiAll) );
00380       }
00381 
00382       for (int i = xsize; i--; ) {
00383         GlbRanges<View1> ylb(y);
00384         GECODE_ME_CHECK( x[i].includeI(home,ylb) );
00385       }
00386 
00387       // xi.exclude (Intersection(xj.lb) - y.ub)
00388       {
00389         GECODE_AUTOARRAY(GLBndSet, rightSet, xsize);
00390         new (&rightSet[xsize-1]) GLBndSet(home);
00391         rightSet[xsize-1].update(home,intOfDets);
00392         for (int i=xsize-1;i--;) {
00393           GlbRanges<View0> xilb(x[i+1]);
00394           BndSetRanges prev(rightSet[i+1]);
00395           Iter::Ranges::Inter<GlbRanges<View0>,
00396             BndSetRanges> inter(xilb,prev);
00397           new (&rightSet[i]) GLBndSet(home);
00398           rightSet[i].includeI(home,inter);
00399         }
00400 
00401         LUBndSet leftAcc(home);
00402 
00403         for (int i=0;i<xsize;i++) {
00404           BndSetRanges left(leftAcc);
00405           BndSetRanges right(rightSet[i]);
00406           Iter::Ranges::Inter<BndSetRanges,
00407             BndSetRanges> inter(left, right);
00408           LubRanges<View1> yub(y);
00409           Iter::Ranges::Diff<Iter::Ranges::Inter<BndSetRanges,
00410             BndSetRanges>, LubRanges<View1> >
00411             forbidden(inter, yub);
00412           GECODE_ME_CHECK( x[i].excludeI(home,forbidden) );
00413           GlbRanges<View0> xlb(x[i]);
00414           leftAcc.intersectI(home,xlb);
00415         }
00416         for (int i=xsize; i--;)
00417           rightSet[i].dispose(home);
00418         leftAcc.dispose(home);
00419       }
00420 
00421 
00422       for(int i=0;i<x.size();i++){
00423         //Do not reverse! Eats away the end of the array!
00424         while (i<x.size() && x[i].assigned()) {
00425           GlbRanges<View0> det(x[i]);
00426           if (intOfDets.intersectI(home,det)) {repeat = true;}
00427           x.move_lst(i);
00428           if (intOfDets.size()==0) {
00429             GECODE_ME_CHECK( y.cardMax(home,0) );
00430             intOfDets.dispose(home);
00431             return ES_SUBSUMED(this,home);
00432           }
00433         }
00434       }
00435     size0:
00436       if (x.size()==0) {
00437         BndSetRanges all1(intOfDets);
00438         GECODE_ME_CHECK( y.intersectI(home,all1) );
00439         BndSetRanges all2(intOfDets);
00440         GECODE_ME_CHECK( y.includeI(home,all2) );
00441         intOfDets.dispose(home);
00442         return ES_SUBSUMED(this,home);
00443       }
00444 
00445     } while (repeat);
00446 
00447     return shared ? ES_NOFIX : ES_FIX;
00448   }
00449 
00450 }}}
00451 
00452 // STATISTICS: set-prop