Generated on Thu Mar 22 10:39:34 2012 for Gecode by doxygen 1.6.3

lq.hpp

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  *
00006  *  Copyright:
00007  *     Guido Tack, 2011
00008  *
00009  *  Last modified:
00010  *     $Date: 2011-08-24 16:34:16 +0200 (Wed, 24 Aug 2011) $ by $Author: tack $
00011  *     $Revision: 12346 $
00012  *
00013  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  *  Permission is hereby granted, free of charge, to any person obtaining
00018  *  a copy of this software and associated documentation files (the
00019  *  "Software"), to deal in the Software without restriction, including
00020  *  without limitation the rights to use, copy, modify, merge, publish,
00021  *  distribute, sublicense, and/or sell copies of the Software, and to
00022  *  permit persons to whom the Software is furnished to do so, subject to
00023  *  the following conditions:
00024  *
00025  *  The above copyright notice and this permission notice shall be
00026  *  included in all copies or substantial portions of the Software.
00027  *
00028  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00029  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00031  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00032  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00033  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00034  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00035  *
00036  */
00037 
00038 namespace Gecode { namespace Set { namespace Rel {
00039 
00043   class CharacteristicSets {
00044   protected:
00046     unsigned int xsize;
00048     Support::BitSetBase b;
00050     int* ub;
00052     bool xlm;
00054     bool xum;
00056     bool ylm;
00058     bool yum;
00060     void set(int i, bool j) {
00061       if (j)
00062         b.set(i);
00063       else
00064         b.clear(i);
00065     }
00066     
00068     class CSIter {
00069     public:
00071       CharacteristicSets* cs;
00073       unsigned int i;
00075       int xoff;
00077       int yoff;
00079       void operator++ (void) {
00080         i++;
00081         while (i<cs->xsize && !cs->b.get(xoff+2*i+yoff))
00082           i++;
00083       }
00085       CSIter(void) {}
00087       CSIter(CharacteristicSets& cs0, int xoff0, int yoff0)
00088         : cs(&cs0), i(-1), xoff(xoff0), yoff(yoff0) {
00089         ++(*this);
00090       }
00092       bool operator() (void) const { return i<cs->xsize; }
00094       int val(void) const { return cs->ub[i]; }
00095     };
00096     
00097   public:
00099     template<class View0, class View1>
00100     CharacteristicSets(Region& re, View0 x, View1 y);
00101     
00103     bool xmin(int i) const { return b.get(2*i); }
00105     bool xmax(int i) const { return b.get(2*i+1); }
00107     bool ymin(int i) const { return b.get(2*xsize+2*i); }
00109     bool ymax(int i) const { return b.get(2*xsize+2*i+1); }
00110 
00112     void xmin(int i, bool j) { set(2*i,j); }
00114     void xmax(int i, bool j) { set(2*i+1,j); }
00116     void ymin(int i, bool j) { set(2*xsize+2*i,j); }
00118     void ymax(int i, bool j) { set(2*xsize+2*i+1,j); }
00119 
00121     ModEvent xlq(int i, bool j) {
00122       if (!j) {
00123         if (xmin(i)) return ME_SET_FAILED;
00124         if (xmax(i)) {
00125           xmax(i,false);
00126           xum=true;
00127         }
00128       }
00129       return ME_SET_NONE;
00130     }
00132     ModEvent xgq(int i, bool j) {
00133       if (j) {
00134         if (!xmax(i)) return ME_SET_FAILED;
00135         if (!xmin(i)) {
00136           xmin(i,true);
00137           xlm=true;
00138         }
00139       }
00140       return ME_SET_NONE;
00141     }
00143     ModEvent ylq(int i, bool j) {
00144       if (!j) {
00145         if (ymin(i)) return ME_SET_FAILED;
00146         if (ymax(i)) {
00147           ymax(i,false);
00148           yum=true;
00149         }
00150       }
00151       return ME_SET_NONE;
00152     }
00154     ModEvent ygq(int i, bool j) {
00155       if (j) {
00156         if (!ymax(i)) return ME_SET_FAILED;
00157         if (!ymin(i)) {
00158           ymin(i,true);
00159           ylm=true;
00160         }
00161       }
00162       return ME_SET_NONE;
00163     }
00164 
00166     int size(void) const { return xsize; }
00167     
00169     template<class View0, class View1>
00170     ExecStatus prune(Space& home, View0 x, View1 y) {
00171       if (xlm) {
00172         CSIter i(*this,0,0);
00173         Iter::Values::ToRanges<CSIter> ir(i);
00174         GECODE_ME_CHECK(x.includeI(home,ir));
00175       }
00176       if (xum) {
00177         CSIter i(*this,0,1);
00178         Iter::Values::ToRanges<CSIter> ir(i);
00179         GECODE_ME_CHECK(x.intersectI(home,ir));
00180       }
00181       if (ylm) {
00182         CSIter i(*this,2*xsize,0);
00183         Iter::Values::ToRanges<CSIter> ir(i);
00184         GECODE_ME_CHECK(y.includeI(home,ir));
00185       }
00186       if (yum) {
00187         CSIter i(*this,2*xsize,1);
00188         Iter::Values::ToRanges<CSIter> ir(i);
00189         GECODE_ME_CHECK(y.intersectI(home,ir));
00190       }
00191       return ES_OK;
00192     }
00193     
00194   };
00195 
00196   template<class View0, class View1>
00197   CharacteristicSets::CharacteristicSets(Region& re,View0 x, View1 y)
00198     : xlm(false), xum(false), ylm(false), yum(false) {
00199     LubRanges<View0> xlub(x);
00200     LubRanges<View1> ylub(y);
00201     Iter::Ranges::Union<LubRanges<View0>,LubRanges<View1> > xylub(xlub,ylub);
00202     Iter::Ranges::Cache xylubc(re,xylub);
00203     xsize = Iter::Ranges::size(xylubc);
00204     b.init(re,4*xsize);
00205     ub = re.alloc<int>(xsize);
00206     xylubc.reset();
00207     Iter::Ranges::ToValues<Iter::Ranges::Cache> xylubv(xylubc);
00208     LubRanges<View0> xur(x);
00209     GlbRanges<View0> xlr(x);
00210     LubRanges<View1> yur(y);
00211     GlbRanges<View1> ylr(y);
00212     Iter::Ranges::ToValues<LubRanges<View0> > xuv(xur);
00213     Iter::Ranges::ToValues<GlbRanges<View0> > xlv(xlr);
00214     Iter::Ranges::ToValues<LubRanges<View1> > yuv(yur);
00215     Iter::Ranges::ToValues<GlbRanges<View1> > ylv(ylr);
00216     for (int i=0; xylubv(); ++xylubv, ++i) {
00217       ub[i] = xylubv.val();
00218       if (xlv() && xylubv.val()==xlv.val()) {
00219         b.set(2*i);
00220         ++xlv;
00221       }
00222       if (xuv() && xylubv.val()==xuv.val()) {
00223         b.set(2*i+1);
00224         ++xuv;
00225       }
00226       if (ylv() && xylubv.val()==ylv.val()) {
00227         b.set(2*xsize+2*i);
00228         ++ylv;
00229       }
00230       if (yuv() && xylubv.val()==yuv.val()) {
00231         b.set(2*xsize+2*i+1);
00232         ++yuv;
00233       }
00234     }
00235   }
00236 
00237   template<class View0, class View1, bool strict>
00238   forceinline
00239   Lq<View0,View1,strict>::Lq(Home home, View0 x, View1 y)
00240     : MixBinaryPropagator<View0,PC_SET_ANY,View1,PC_SET_ANY>(home,x,y) {}
00241 
00242   template<class View0, class View1, bool strict>
00243   forceinline
00244   Lq<View0,View1,strict>::Lq(Space& home, bool share, Lq& p)
00245     : MixBinaryPropagator<View0,PC_SET_ANY,View1,PC_SET_ANY>(home,share,p) {}
00246 
00247   template<class View0, class View1, bool strict>
00248   ExecStatus
00249   Lq<View0,View1,strict>::post(Home home, View0 x, View1 y) {
00250     if (strict)
00251       GECODE_ME_CHECK(y.cardMin(home,1));
00252     (void) new (home) Lq(home,x,y);
00253     return ES_OK;
00254   }
00255 
00256   template<class View0, class View1, bool strict>
00257   Actor*
00258   Lq<View0,View1,strict>::copy(Space& home, bool share) {
00259     return new (home) Lq(home,share,*this);
00260   }
00261 
00262   template<class View0, class View1, bool strict>
00263   ExecStatus
00264   Lq<View0,View1,strict>::propagate(Space& home, const ModEventDelta&) {
00265     if ( (!strict) && x1.cardMax()==0) {
00266       GECODE_ME_CHECK(x0.cardMax(home,0));
00267     }
00268 
00269     if (x0.cardMax()==0) {
00270       return home.ES_SUBSUMED(*this);
00271     }
00272 
00273     if (x0.glbMin() < x1.lubMin())
00274       return ES_FAILED;
00275     if (x1.glbMin() < x0.lubMin())
00276       return home.ES_SUBSUMED(*this);
00277     
00278     bool assigned = x0.assigned() && x1.assigned();
00279     
00280     Region re(home);
00281     CharacteristicSets cs(re,x0,x1);
00282 
00283     /*
00284      * State 1
00285      *
00286      */
00287     int i=0;
00288     int firsti=0;
00289     int n=cs.size();
00290     while ((i<n) && cs.xmin(i) == cs.ymax(i)) {
00291       // case: =, >=
00292       GECODE_ME_CHECK(cs.xlq(i,cs.ymax(i)));
00293       GECODE_ME_CHECK(cs.ygq(i,cs.xmin(i)));
00294       i++;
00295     }
00296     
00297     if (i == n) {// case: $
00298       if (strict) {
00299         return ES_FAILED;
00300       } else {
00301         GECODE_ES_CHECK(cs.prune(home,x0,x1));
00302         return home.ES_SUBSUMED(*this);
00303       }
00304     }
00305     
00306     // Possible cases left: <, <=, > (yields failure), ?
00307     GECODE_ME_CHECK(cs.xlq(i,cs.ymax(i)));
00308     GECODE_ME_CHECK(cs.ygq(i,cs.xmin(i)));
00309 
00310     if (cs.xmax(i) < cs.ymin(i)) { // case: < (after tell)
00311       GECODE_ES_CHECK(cs.prune(home,x0,x1));
00312       return home.ES_SUBSUMED(*this);
00313     }
00314 
00315     firsti=i;
00316 
00317     /*
00318      * State 2
00319      *   prefix: (?|<=)
00320      *
00321      */
00322     i++;
00323 
00324     while ((i < n) &&
00325            (cs.xmin(i) == cs.ymax(i)) &&
00326            (cs.xmax(i) == cs.ymin(i))) { // case: =
00327       i++;
00328     }
00329 
00330     if (i == n) { // case: $
00331       if (strict)
00332         goto rewrite_le;
00333       else
00334         goto rewrite_lq;
00335     }
00336 
00337     if (cs.xmax(i) < cs.ymin(i)) // case: <
00338       goto rewrite_lq;
00339 
00340     if (cs.xmin(i) > cs.ymax(i)) // case: >
00341       goto rewrite_le;
00342     
00343     if (cs.xmax(i) <= cs.ymin(i)) {
00344       // case: <= (invariant: not =, <)
00345       /*
00346        * State 3
00347        *   prefix: (?|<=),<=
00348        *
00349        */
00350       i++;
00351 
00352       while ((i < n) && (cs.xmax(i) == cs.ymin(i))) {// case: <=, =
00353         i++;
00354       }
00355 
00356       if (i == n) { // case: $
00357         if (strict) {
00358           GECODE_ES_CHECK(cs.prune(home,x0,x1));
00359           return assigned ? home.ES_SUBSUMED(*this) : ES_NOFIX;
00360         } else {
00361           goto rewrite_lq;
00362         }
00363       }
00364 
00365       if (cs.xmax(i) < cs.ymin(i)) // case: <
00366         goto rewrite_lq;
00367 
00368       GECODE_ES_CHECK(cs.prune(home,x0,x1));
00369       return assigned ? home.ES_SUBSUMED(*this) : ES_NOFIX;
00370     }
00371 
00372     if (cs.xmin(i) >= cs.ymax(i)) {
00373       // case: >= (invariant: not =, >)
00374       /*
00375        * State 4
00376        *   prefix: (?|<=) >=
00377        *
00378        */
00379       i++;
00380 
00381       while ((i < n) && (cs.xmin(i) == cs.ymax(i))) {
00382         // case: >=, =
00383         i++;
00384       }
00385 
00386       if (i == n) { // case: $
00387         if (strict) {
00388           goto rewrite_le;
00389         } else {
00390           GECODE_ES_CHECK(cs.prune(home,x0,x1));
00391           return assigned ? home.ES_SUBSUMED(*this) : ES_NOFIX;
00392         }
00393       }
00394 
00395       if (cs.xmin(i) > cs.ymax(i)) // case: >
00396         goto rewrite_le;
00397 
00398       GECODE_ES_CHECK(cs.prune(home,x0,x1));
00399       return assigned ? home.ES_SUBSUMED(*this) : ES_NOFIX;
00400     }    
00401 
00402     GECODE_ES_CHECK(cs.prune(home,x0,x1));
00403     return assigned ? home.ES_SUBSUMED(*this) : ES_NOFIX;
00404 
00405   rewrite_le:
00406     GECODE_ME_CHECK(cs.xlq(firsti,false));
00407     GECODE_ME_CHECK(cs.ygq(firsti,true));
00408     GECODE_ES_CHECK(cs.prune(home,x0,x1));
00409     return home.ES_SUBSUMED(*this);
00410   rewrite_lq:
00411     GECODE_ES_CHECK(cs.prune(home,x0,x1));
00412     return assigned ? home.ES_SUBSUMED(*this) : ES_NOFIX;
00413   }
00414 
00415 }}}
00416 
00417 // STATISTICS: set-prop