Generated on Tue Apr 18 10:21:59 2017 for Gecode by doxygen 1.6.3

lex.hpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christian Schulte <schulte@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Christian Schulte, 2003
00008  *
00009  *  Last modified:
00010  *     $Date: 2016-11-08 17:23:24 +0100 (Tue, 08 Nov 2016) $ by $Author: schulte $
00011  *     $Revision: 15253 $
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 Int { namespace Rel {
00039 
00040   /*
00041    * Lexical order propagator
00042    */
00043   template<class VX, class VY>
00044   inline
00045   LexLqLe<VX,VY>::LexLqLe(Home home,
00046                           ViewArray<VX>& x0, ViewArray<VY>& y0, bool s)
00047     : Propagator(home), x(x0), y(y0), strict(s) {
00048     x.subscribe(home, *this, PC_INT_BND);
00049     y.subscribe(home, *this, PC_INT_BND);
00050   }
00051 
00052   template<class VX, class VY>
00053   forceinline
00054   LexLqLe<VX,VY>::LexLqLe(Space& home, bool share, LexLqLe<VX,VY>& p)
00055     : Propagator(home,share,p), strict(p.strict) {
00056     x.update(home,share,p.x);
00057     y.update(home,share,p.y);
00058   }
00059 
00060   template<class VX, class VY>
00061   Actor*
00062   LexLqLe<VX,VY>::copy(Space& home, bool share) {
00063     return new (home) LexLqLe<VX,VY>(home,share,*this);
00064   }
00065 
00066   template<class VX, class VY>
00067   PropCost
00068   LexLqLe<VX,VY>::cost(const Space&, const ModEventDelta&) const {
00069     return PropCost::linear(PropCost::LO, x.size());
00070   }
00071 
00072   template<class VX, class VY>
00073   void
00074   LexLqLe<VX,VY>::reschedule(Space& home) {
00075     x.reschedule(home,*this,PC_INT_BND);
00076     y.reschedule(home,*this,PC_INT_BND);
00077   }
00078 
00079   template<class VX, class VY>
00080   forceinline size_t
00081   LexLqLe<VX,VY>::dispose(Space& home) {
00082     assert(!home.failed());
00083     x.cancel(home,*this,PC_INT_BND);
00084     y.cancel(home,*this,PC_INT_BND);
00085     (void) Propagator::dispose(home);
00086     return sizeof(*this);
00087   }
00088 
00089   template<class VX, class VY>
00090   ExecStatus
00091   LexLqLe<VX,VY>::propagate(Space& home, const ModEventDelta&) {
00092     /*
00093      * State 1
00094      *
00095      */
00096     {
00097       int i = 0;
00098       int n = x.size();
00099 
00100       while ((i < n) && (x[i].min() == y[i].max())) {
00101         // case: =, >=
00102         GECODE_ME_CHECK(x[i].lq(home,y[i].max()));
00103         GECODE_ME_CHECK(y[i].gq(home,x[i].min()));
00104         i++;
00105       }
00106 
00107       if (i == n) // case: $
00108         return strict ? ES_FAILED : home.ES_SUBSUMED(*this);
00109 
00110       // Possible cases left: <, <=, > (yields failure), ?
00111       GECODE_ME_CHECK(x[i].lq(home,y[i].max()));
00112       GECODE_ME_CHECK(y[i].gq(home,x[i].min()));
00113 
00114       if (x[i].max() < y[i].min()) // case: < (after tell)
00115         return home.ES_SUBSUMED(*this);
00116 
00117       // x[i] can never be equal to y[i] (otherwise: >=)
00118       assert(!(x[i].assigned() && y[i].assigned() &&
00119                x[i].val() == y[i].val()));
00120       // Remove all elements between 0...i-1 as they are assigned and equal
00121       x.drop_fst(i); y.drop_fst(i);
00122       // After this, execution continues at [1]
00123     }
00124 
00125     /*
00126      * State 2
00127      *   prefix: (?|<=)
00128      *
00129      */
00130     {
00131       int i = 1;
00132       int n = x.size();
00133 
00134       while ((i < n) &&
00135              (x[i].min() == y[i].max()) &&
00136              (x[i].max() == y[i].min())) { // case: =
00137         assert(x[i].assigned() && y[i].assigned() &&
00138                (x[i].val() == y[i].val()));
00139         i++;
00140       }
00141 
00142       if (i == n) { // case: $
00143         if (strict)
00144           goto rewrite_le;
00145         else
00146           goto rewrite_lq;
00147       }
00148 
00149       if (x[i].max() < y[i].min()) // case: <
00150         goto rewrite_lq;
00151 
00152       if (x[i].min() > y[i].max()) // case: >
00153         goto rewrite_le;
00154 
00155       if (i > 1) {
00156         // Remove equal elements [1...i-1], keep element [0]
00157         x[i-1]=x[0]; x.drop_fst(i-1);
00158         y[i-1]=y[0]; y.drop_fst(i-1);
00159       }
00160     }
00161 
00162     if (x[1].max() <= y[1].min()) {
00163       // case: <= (invariant: not =, <)
00164       /*
00165        * State 3
00166        *   prefix: (?|<=),<=
00167        *
00168        */
00169       int i = 2;
00170       int n = x.size();
00171 
00172       while ((i < n) && (x[i].max() == y[i].min())) // case: <=, =
00173         i++;
00174 
00175       if (i == n) { // case: $
00176         if (strict)
00177           return ES_FIX;
00178         else
00179           goto rewrite_lq;
00180       }
00181 
00182       if (x[i].max() < y[i].min()) // case: <
00183         goto rewrite_lq;
00184 
00185       if (x[i].min() > y[i].max()) { // case: >
00186         // Eliminate [i]...[n-1]
00187         for (int j=i; j<n; j++) {
00188           x[j].cancel(home,*this,PC_INT_BND);
00189           y[j].cancel(home,*this,PC_INT_BND);
00190         }
00191         x.size(i); y.size(i);
00192         strict = true;
00193       }
00194 
00195       return ES_FIX;
00196     }
00197 
00198     if (x[1].min() >= y[1].max()) {
00199       // case: >= (invariant: not =, >)
00200       /*
00201        * State 4
00202        *   prefix: (?|<=) >=
00203        *
00204        */
00205       int i = 2;
00206       int n = x.size();
00207 
00208       while ((i < n) && (x[i].min() == y[i].max()))
00209         // case: >=, =
00210         i++;
00211 
00212       if (i == n) { // case: $
00213         if (strict)
00214           goto rewrite_le;
00215         else
00216           return ES_FIX;
00217       }
00218 
00219       if (x[i].min() > y[i].max()) // case: >
00220         goto rewrite_le;
00221 
00222       if (x[i].max() < y[i].min()) { // case: <
00223         // Eliminate [i]...[n-1]
00224         for (int j=i; j<n; j++) {
00225           x[j].cancel(home,*this,PC_INT_BND);
00226           y[j].cancel(home,*this,PC_INT_BND);
00227         }
00228         x.size(i); y.size(i);
00229         strict = false;
00230       }
00231 
00232       return ES_FIX;
00233     }
00234 
00235     return ES_FIX;
00236 
00237   rewrite_le:
00238     GECODE_REWRITE(*this,(Le<VX,VY>::post(home(*this),x[0],y[0])));
00239   rewrite_lq:
00240     GECODE_REWRITE(*this,(Lq<VX,VY>::post(home(*this),x[0],y[0])));
00241   }
00242 
00243   template<class VX, class VY>
00244   ExecStatus
00245   LexLqLe<VX,VY>::post(Home home,
00246                       ViewArray<VX>& x, ViewArray<VY>& y, bool strict) {
00247     if (x.size() < y.size()) {
00248       y.size(x.size()); strict=false;
00249     } else if (x.size() > y.size()) {
00250       x.size(y.size()); strict=true;
00251     }
00252     if (x.size() == 0)
00253       return strict ? ES_FAILED : ES_OK;
00254     if (x.size() == 1) {
00255       if (strict)
00256         return Le<VX,VY>::post(home,x[0],y[0]);
00257       else
00258         return Lq<VX,VY>::post(home,x[0],y[0]);
00259     }
00260     (void) new (home) LexLqLe<VX,VY>(home,x,y,strict);
00261     return ES_OK;
00262   }
00263 
00264 
00265   /*
00266    * Lexical disequality propagator
00267    */
00268   template<class VX, class VY>
00269   forceinline
00270   LexNq<VX,VY>::LexNq(Home home, ViewArray<VX>& xv, ViewArray<VY>& yv)
00271     : Propagator(home),
00272       x0(xv[xv.size()-2]), y0(yv[xv.size()-2]),
00273       x1(xv[xv.size()-1]), y1(yv[xv.size()-1]),
00274       x(xv), y(yv) {
00275     int n = x.size();
00276     assert(n > 1);
00277     assert(n == y.size());
00278     x.size(n-2); y.size(n-2);
00279     x0.subscribe(home,*this,PC_INT_VAL); y0.subscribe(home,*this,PC_INT_VAL);
00280     x1.subscribe(home,*this,PC_INT_VAL); y1.subscribe(home,*this,PC_INT_VAL);
00281   }
00282 
00283   template<class VX, class VY>
00284   PropCost
00285   LexNq<VX,VY>::cost(const Space&, const ModEventDelta&) const {
00286     return PropCost::binary(PropCost::HI);
00287   }
00288 
00289   template<class VX, class VY>
00290   void
00291   LexNq<VX,VY>::reschedule(Space& home) {
00292     x0.reschedule(home,*this,PC_INT_VAL);
00293     y0.reschedule(home,*this,PC_INT_VAL);
00294     x1.reschedule(home,*this,PC_INT_VAL);
00295     y1.reschedule(home,*this,PC_INT_VAL);
00296   }
00297 
00298   template<class VX, class VY>
00299   forceinline
00300   LexNq<VX,VY>::LexNq(Space& home, bool share, LexNq<VX,VY>& p)
00301     : Propagator(home,share,p) {
00302     x0.update(home,share,p.x0); y0.update(home,share,p.y0);
00303     x1.update(home,share,p.x1); y1.update(home,share,p.y1);
00304     x.update(home,share,p.x); y.update(home,share,p.y);
00305   }
00306 
00307   template<class VX, class VY>
00308   Actor*
00309   LexNq<VX,VY>::copy(Space& home, bool share) {
00310     int n = x.size();
00311     if (n > 0) {
00312       // Eliminate all equal views and keep one disequal pair
00313       for (int i=n; i--; )
00314         switch (rtest_eq_bnd(x[i],y[i])) {
00315         case RT_TRUE:
00316           // Eliminate equal pair
00317           n--; x[i]=x[n]; y[i]=y[n];
00318           break;
00319         case RT_FALSE:
00320           // Just keep a single disequal pair
00321           n=1; x[0]=x[i]; y[0]=y[i];
00322           goto done;
00323         case RT_MAYBE:
00324           break;
00325         default:
00326           GECODE_NEVER;
00327         }
00328     done:
00329       x.size(n); y.size(n);
00330     }
00331     return new (home) LexNq<VX,VY>(home,share,*this);
00332   }
00333 
00334   template<class VX, class VY>
00335   inline ExecStatus
00336   LexNq<VX,VY>::post(Home home, ViewArray<VX>& x, ViewArray<VY>& y) {
00337     if (x.size() != y.size())
00338       return ES_OK;
00339     int n = x.size();
00340     if (n > 0) {
00341       // Eliminate all equal views
00342       for (int i=n; i--; )
00343         switch (rtest_eq_dom(x[i],y[i])) {
00344         case RT_TRUE:
00345           // Eliminate equal pair
00346           n--; x[i]=x[n]; y[i]=y[n];
00347           break;
00348         case RT_FALSE:
00349           return ES_OK;
00350         case RT_MAYBE:
00351           if (same(x[i],y[i])) {
00352             // Eliminate equal pair
00353             n--; x[i]=x[n]; y[i]=y[n];
00354           }
00355           break;
00356         default:
00357           GECODE_NEVER;
00358         }
00359       x.size(n); y.size(n);
00360     }
00361     if (n == 0)
00362       return ES_FAILED;
00363     if (n == 1)
00364       return Nq<VX,VY>::post(home,x[0],y[0]);
00365     (void) new (home) LexNq<VX,VY>(home,x,y);
00366     return ES_OK;
00367   }
00368 
00369   template<class VX, class VY>
00370   forceinline size_t
00371   LexNq<VX,VY>::dispose(Space& home) {
00372     x0.cancel(home,*this,PC_INT_VAL); y0.cancel(home,*this,PC_INT_VAL);
00373     x1.cancel(home,*this,PC_INT_VAL); y1.cancel(home,*this,PC_INT_VAL);
00374     (void) Propagator::dispose(home);
00375     return sizeof(*this);
00376   }
00377 
00378   template<class VX, class VY>
00379   forceinline ExecStatus
00380   LexNq<VX,VY>::resubscribe(Space& home,
00381                             RelTest rt, VX& x0, VY& y0, VX x1, VY y1) {
00382     if (rt == RT_TRUE) {
00383       assert(x0.assigned() && y0.assigned());
00384       assert(x0.val() == y0.val());
00385       int n = x.size();
00386       for (int i=n; i--; )
00387         switch (rtest_eq_dom(x[i],y[i])) {
00388         case RT_TRUE:
00389           // Eliminate equal pair
00390           n--; x[i]=x[n]; y[i]=y[n];
00391           break;
00392         case RT_FALSE:
00393           return home.ES_SUBSUMED(*this);
00394         case RT_MAYBE:
00395           // Move to x0, y0 and subscribe
00396           x0=x[i]; y0=y[i];
00397           n--; x[i]=x[n]; y[i]=y[n];
00398           x.size(n); y.size(n);
00399           x0.subscribe(home,*this,PC_INT_VAL,false);
00400           y0.subscribe(home,*this,PC_INT_VAL,false);
00401           return ES_FIX;
00402         default:
00403           GECODE_NEVER;
00404         }
00405       // No more views to subscribe to left
00406       GECODE_REWRITE(*this,(Nq<VX,VY>::post(home(*this),x1,y1)));
00407     }
00408     return ES_FIX;
00409   }
00410 
00411   template<class VX, class VY>
00412   ExecStatus
00413   LexNq<VX,VY>::propagate(Space& home, const ModEventDelta&) {
00414     RelTest rt0 = rtest_eq_dom(x0,y0);
00415     if (rt0 == RT_FALSE)
00416       return home.ES_SUBSUMED(*this);
00417     RelTest rt1 = rtest_eq_dom(x1,y1);
00418     if (rt1 == RT_FALSE)
00419       return home.ES_SUBSUMED(*this);
00420     GECODE_ES_CHECK(resubscribe(home,rt0,x0,y0,x1,y1));
00421     GECODE_ES_CHECK(resubscribe(home,rt1,x1,y1,x0,y0));
00422     return ES_FIX;
00423   }
00424 
00425 
00426 }}}
00427 
00428 // STATISTICS: int-prop