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

lq-le.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  *     Gabor Szokoli <szokoli@gecode.org>
00006  *
00007  *  Copyright:
00008  *     Christian Schulte, 2003
00009  *     Gabor Szokoli, 2003
00010  *
00011  *  Last modified:
00012  *     $Date: 2017-02-22 03:37:18 +0100 (Wed, 22 Feb 2017) $ by $Author: schulte $
00013  *     $Revision: 15468 $
00014  *
00015  *  This file is part of Gecode, the generic constraint
00016  *  development environment:
00017  *     http://www.gecode.org
00018  *
00019  *  Permission is hereby granted, free of charge, to any person obtaining
00020  *  a copy of this software and associated documentation files (the
00021  *  "Software"), to deal in the Software without restriction, including
00022  *  without limitation the rights to use, copy, modify, merge, publish,
00023  *  distribute, sublicense, and/or sell copies of the Software, and to
00024  *  permit persons to whom the Software is furnished to do so, subject to
00025  *  the following conditions:
00026  *
00027  *  The above copyright notice and this permission notice shall be
00028  *  included in all copies or substantial portions of the Software.
00029  *
00030  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00031  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00032  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00033  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00034  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00035  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00036  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00037  *
00038  */
00039 
00040 namespace Gecode { namespace Int { namespace Rel {
00041 
00042   /*
00043    * Less or equal propagator
00044    *
00045    */
00046 
00047   template<class V0, class V1>
00048   forceinline
00049   Lq<V0,V1>::Lq(Home home, V0 x0, V1 x1)
00050     : MixBinaryPropagator<V0,PC_INT_BND,V1,PC_INT_BND>(home,x0,x1) {}
00051 
00052   template<class V0, class V1>
00053   forceinline bool
00054   Lq<V0,V1>::same(V0 x0, V1 x1) {
00055     (void) x0; (void) x1;
00056     return false;
00057   }
00058 
00059   template<>
00060   forceinline bool
00061   Lq<IntView,IntView>::same(IntView x0, IntView x1) {
00062     return Gecode::same(x0,x1);
00063   }
00064 
00065   template<>
00066   forceinline bool
00067   Lq<BoolView,BoolView>::same(BoolView x0, BoolView x1) {
00068     return Gecode::same(x0,x1);
00069   }
00070 
00071   template<class V0, class V1>
00072   ExecStatus
00073   Lq<V0,V1>::post(Home home, V0 x0, V1 x1) {
00074     GECODE_ME_CHECK(x0.lq(home,x1.max()));
00075     GECODE_ME_CHECK(x1.gq(home,x0.min()));
00076     if (!same(x0,x1) && (x0.max() > x1.min()))
00077       (void) new (home) Lq<V0,V1>(home,x0,x1);
00078     return ES_OK;
00079   }
00080 
00081   template<class V0, class V1>
00082   forceinline
00083   Lq<V0,V1>::Lq(Space& home, bool share, Lq<V0,V1>& p)
00084     : MixBinaryPropagator<V0,PC_INT_BND,V1,PC_INT_BND>(home,share,p) {}
00085 
00086   template<class V0, class V1>
00087   Actor*
00088   Lq<V0,V1>::copy(Space& home, bool share) {
00089     return new (home) Lq<V0,V1>(home,share,*this);
00090   }
00091 
00092   template<class V0, class V1>
00093   ExecStatus
00094   Lq<V0,V1>::propagate(Space& home, const ModEventDelta&) {
00095     GECODE_ME_CHECK(x0.lq(home,x1.max()));
00096     GECODE_ME_CHECK(x1.gq(home,x0.min()));
00097     return (x0.max() <= x1.min()) ? home.ES_SUBSUMED(*this) : ES_FIX;
00098   }
00099 
00100 
00101 
00102 
00103   /*
00104    * Less propagator
00105    *
00106    */
00107   template<class V0, class V1>
00108   forceinline
00109   Le<V0,V1>::Le(Home home, V0 x0, V1 x1)
00110     : MixBinaryPropagator<V0,PC_INT_BND,V1,PC_INT_BND>(home,x0,x1) {}
00111 
00112   template<class V0, class V1>
00113   forceinline bool
00114   Le<V0,V1>::same(V0 x0, V1 x1) {
00115     (void) x0; (void) x1;
00116     return false;
00117   }
00118 
00119   template<>
00120   forceinline bool
00121   Le<IntView,IntView>::same(IntView x0, IntView x1) {
00122     return Gecode::same(x0,x1);
00123   }
00124 
00125   template<>
00126   forceinline bool
00127   Le<MinusView,MinusView>::same(MinusView x0, MinusView x1) {
00128     return Gecode::same(x0,x1);
00129   }
00130 
00131   template<>
00132   forceinline bool
00133   Le<BoolView,BoolView>::same(BoolView x0, BoolView x1) {
00134     return Gecode::same(x0,x1);
00135   }
00136 
00137   template<class V0, class V1>
00138   ExecStatus
00139   Le<V0,V1>::post(Home home, V0 x0, V1 x1) {
00140     if (same(x0,x1))
00141       return ES_FAILED;
00142     GECODE_ME_CHECK(x0.le(home,x1.max()));
00143     GECODE_ME_CHECK(x1.gr(home,x0.min()));
00144     if (x0.max() >= x1.min())
00145       (void) new (home) Le<V0,V1>(home,x0,x1);
00146     return ES_OK;
00147   }
00148 
00149   template<class V0, class V1>
00150   forceinline
00151   Le<V0,V1>::Le(Space& home, bool share, Le<V0,V1>& p)
00152     : MixBinaryPropagator<V0,PC_INT_BND,V1,PC_INT_BND>(home,share,p) {}
00153 
00154   template<class V0, class V1>
00155   Actor*
00156   Le<V0,V1>::copy(Space& home, bool share) {
00157     return new (home) Le<V0,V1>(home,share,*this);
00158   }
00159 
00160   template<class V0, class V1>
00161   ExecStatus
00162   Le<V0,V1>::propagate(Space& home, const ModEventDelta&) {
00163     GECODE_ME_CHECK(x0.le(home,x1.max()));
00164     GECODE_ME_CHECK(x1.gr(home,x0.min()));
00165     return (x0.max() < x1.min()) ? home.ES_SUBSUMED(*this) : ES_FIX;
00166   }
00167 
00168 
00169 
00170   /*
00171    * Nary less and less or equal propagator
00172    *
00173    */
00174 
00175   template<class View, int o>
00176   forceinline
00177   NaryLqLe<View,o>::Index::Index(Space& home, Propagator& p,
00178                                  Council<Index>& c, int i0)
00179     : Advisor(home,p,c), i(i0) {}
00180 
00181   template<class View, int o>
00182   forceinline
00183   NaryLqLe<View,o>::Index::Index(Space& home, bool share, Index& a)
00184     : Advisor(home,share,a), i(a.i) {}
00185 
00186 
00187 
00188   template<class View, int o>
00189   forceinline
00190   NaryLqLe<View,o>::Pos::Pos(int p0, Pos* n)
00191     : FreeList(n), p(p0) {}
00192 
00193   template<class View, int o>
00194   forceinline typename NaryLqLe<View,o>::Pos*
00195   NaryLqLe<View,o>::Pos::next(void) const {
00196     return static_cast<Pos*>(FreeList::next());
00197   }
00198 
00199   template<class View, int o>
00200   forceinline void
00201   NaryLqLe<View,o>::Pos::operator delete(void*) {}
00202 
00203   template<class View, int o>
00204   forceinline void
00205   NaryLqLe<View,o>::Pos::operator delete(void*, Space&) {
00206     GECODE_NEVER;
00207   }
00208 
00209   template<class View, int o>
00210   forceinline void*
00211   NaryLqLe<View,o>::Pos::operator new(size_t, Space& home) {
00212     return home.fl_alloc<sizeof(Pos)>();
00213   }
00214 
00215   template<class View, int o>
00216   forceinline void
00217   NaryLqLe<View,o>::Pos::dispose(Space& home) {
00218     home.fl_dispose<sizeof(Pos)>(this,this);
00219   }
00220 
00221 
00222   template<class View, int o>
00223   forceinline bool
00224   NaryLqLe<View,o>::empty(void) const {
00225     return pos == NULL;
00226   }
00227   template<class View, int o>
00228   forceinline void
00229   NaryLqLe<View,o>::push(Space& home, int p) {
00230     // Try to avoid entering same position twice
00231     if ((pos != NULL) && (pos->p == p))
00232       return;
00233     pos = new (home) Pos(p,pos);
00234   }
00235   template<class View, int o>
00236   forceinline int
00237   NaryLqLe<View,o>::pop(Space& home) {
00238     Pos* t = pos;
00239     int p = t->p;
00240     pos = pos->next();
00241     t->dispose(home);
00242     return p;
00243   }
00244 
00245   template<class View, int o>
00246   forceinline
00247   NaryLqLe<View,o>::NaryLqLe(Home home, ViewArray<View>& x)
00248     : NaryPropagator<View,PC_INT_NONE>(home,x),
00249       c(home), pos(NULL), run(false), n_subsumed(0) {
00250     for (int i=x.size(); i--; )
00251       x[i].subscribe(home, *new (home) Index(home,*this,c,i));
00252   }
00253 
00254   template<class View, int o>
00255   ExecStatus
00256   NaryLqLe<View,o>::post(Home home, ViewArray<View>& x) {
00257     assert((o == 0) || (o == 1));
00258     // Check for sharing
00259     if (x.same(home)) {
00260       if (o == 1)
00261         return ES_FAILED;
00262       /*
00263        * Eliminate sharing: if a view occurs twice, all views in between
00264        * must be equal.
00265        */
00266       int n = x.size();
00267       for (int i=0; i<n; i++)
00268         for (int j=n-1; j>i; j--)
00269           if (same(x[i],x[j])) {
00270             if (i+1 != j) {
00271               // Create equality propagator for elements i+1 ... j
00272               ViewArray<View> y(home,j-i);
00273               for (int k=j-i; k--; )
00274                 y[k] = x[i+1+k];
00275               GECODE_ES_CHECK(NaryEqBnd<View>::post(home,y));
00276             }
00277             for (int k=0; k<n-1-j-1+1; k++)
00278               x[i+1+k]=x[j+1+k];
00279             n -= j-i;
00280             break;
00281           }
00282       x.size(n);
00283     }
00284 
00285     // Propagate one round
00286     for (int i=1; i<x.size(); i++)
00287       GECODE_ME_CHECK(x[i].gq(home,x[i-1].min()+o));
00288     for (int i=x.size()-1; i--;)
00289       GECODE_ME_CHECK(x[i].lq(home,x[i+1].max()-o));
00290     // Eliminate redundant variables
00291     {
00292       // Eliminate at beginning
00293       {
00294         int i=0;
00295         while ((i+1 < x.size()) && (x[i].max()+o <= x[i+1].min()))
00296           i++;
00297         x.drop_fst(i);
00298       }
00299       // Eliminate at end
00300       {
00301         int i=x.size()-1;
00302         while ((i > 0) && (x[i-1].max()+o <= x[i].min()))
00303           i--;
00304         x.drop_lst(i);
00305       }
00306       // Eliminate in the middle
00307       if (x.size() > 1) {
00308         int j=1;
00309         for (int i=1; i+1<x.size(); i++)
00310           if ((x[j-1].max()+o > x[i].min()) ||
00311               (x[i].max()+o > x[i+1].min()))
00312             x[j++]=x[i];
00313         x[j++]=x[x.size()-1];
00314         x.size(j);
00315       }
00316     }
00317     if (x.size() == 2) {
00318       if (o == 0)
00319         return Lq<View,View>::post(home,x[0],x[1]);
00320       else
00321         return Le<View,View>::post(home,x[0],x[1]);
00322     } else if (x.size() >= 2) {
00323       (void) new (home) NaryLqLe<View,o>(home,x);
00324     }
00325     return ES_OK;
00326   }
00327 
00328   template<class View, int o>
00329   forceinline
00330   NaryLqLe<View,o>::NaryLqLe(Space& home, bool share, NaryLqLe<View,o>& p)
00331     : NaryPropagator<View,PC_INT_NONE>(home,share,p),
00332       pos(NULL), run(false), n_subsumed(p.n_subsumed) {
00333     assert(p.pos == NULL);
00334     c.update(home, share, p.c);
00335   }
00336 
00337   template<class View, int o>
00338   Actor*
00339   NaryLqLe<View,o>::copy(Space& home, bool share) {
00340     if (n_subsumed > n_threshold) {
00341       Region r(home);
00342       // Record for which views there is an advisor
00343       Support::BitSet<Region> a(r,static_cast<unsigned int>(x.size()));
00344       for (Advisors<Index> as(c); as(); ++as)
00345         a.set(static_cast<unsigned int>(as.advisor().i));
00346       // Compact view array and compute map for advisors
00347       int* m = r.alloc<int>(x.size());
00348       int j=0;
00349       for (int i=0; i<x.size(); i++)
00350         if (a.get(static_cast<unsigned int>(i))) {
00351           m[i] = j; x[j++] = x[i];
00352         }
00353       x.size(j);
00354       // Remap advisors
00355       for (Advisors<Index> as(c); as(); ++as)
00356         as.advisor().i = m[as.advisor().i];
00357 
00358       n_subsumed = 0;
00359     }
00360     return new (home) NaryLqLe<View,o>(home,share,*this);
00361   }
00362 
00363   template<class View, int o>
00364   PropCost
00365   NaryLqLe<View,o>::cost(const Space&, const ModEventDelta&) const {
00366     return PropCost::binary(PropCost::HI);
00367   }
00368 
00369   template<class View, int o>
00370   forceinline size_t
00371   NaryLqLe<View,o>::dispose(Space& home) {
00372     for (Advisors<Index> as(c); as(); ++as)
00373       x[as.advisor().i].cancel(home,as.advisor());
00374     c.dispose(home);
00375     while (!empty())
00376       (void) pop(home);
00377     (void) NaryPropagator<View,PC_INT_NONE>::dispose(home);
00378     return sizeof(*this);
00379   }
00380 
00381 
00382   template<class View, int o>
00383   ExecStatus
00384   NaryLqLe<View,o>::advise(Space& home, Advisor& _a, const Delta& d) {
00385     Index& a = static_cast<Index&>(_a);
00386     const int i = a.i;
00387     switch (View::modevent(d)) {
00388     case ME_INT_VAL:
00389       a.dispose(home,c);
00390       n_subsumed++;
00391       break;
00392     case ME_INT_BND:
00393       if (((i == 0) || (x[i-1].max()+o <= x[i].min())) &&
00394           ((i == x.size()-1) || (x[i].max()+o <= x[i+1].min()))) {
00395         x[i].cancel(home,a);
00396         a.dispose(home,c);
00397         n_subsumed++;
00398         return (run || (n_subsumed + 1 < x.size())) ? ES_FIX : ES_NOFIX;
00399       }
00400       break;
00401     default:
00402       return ES_FIX;
00403     }
00404     if (run)
00405       return ES_FIX;
00406     if (((i < x.size()-1) && (x[i+1].min() < x[i].min()+o)) ||
00407         ((i > 0) && (x[i-1].max() > x[i].max()-o))) {
00408       push(home,i);
00409       return ES_NOFIX;
00410     }
00411     return (n_subsumed+1 >= x.size()) ? ES_NOFIX : ES_FIX;
00412   }
00413 
00414   template<class View, int o>
00415   void
00416   NaryLqLe<View,o>::reschedule(Space& home) {
00417     View::schedule(home, *this, ME_INT_BND);
00418   }
00419 
00420   template<class View, int o>
00421   ExecStatus
00422   NaryLqLe<View,o>::propagate(Space& home, const ModEventDelta&) {
00423     run = true;
00424     int n = x.size();
00425     while (!empty()) {
00426       int p = pop(home);
00427       for (int i=p; i<n-1; i++) {
00428         ModEvent me = x[i+1].gq(home,x[i].min()+o);
00429         if (me_failed(me))
00430           return ES_FAILED;
00431         if (!me_modified(me))
00432           break;
00433       }
00434       for (int i=p; i>0; i--) {
00435         ModEvent me = x[i-1].lq(home,x[i].max()-o);
00436         if (me_failed(me))
00437           return ES_FAILED;
00438         if (!me_modified(me))
00439           break;
00440       }
00441     }
00442 #ifdef GECODE_AUDIT
00443     for (int i=0; i<n-1; i++)
00444       assert(!me_modified(x[i+1].gq(home,x[i].min()+o)));
00445     for (int i=n-1; i>0; i--)
00446       assert(!me_modified(x[i-1].lq(home,x[i].max()-o)));
00447 #endif
00448     if (n_subsumed+1 >= n)
00449       return home.ES_SUBSUMED(*this);
00450     run = false;
00451     return ES_FIX;
00452   }
00453 
00454 
00455 
00456   /*
00457    * Reified less or equal propagator
00458    *
00459    */
00460 
00461   template<class View, class CtrlView, ReifyMode rm>
00462   forceinline
00463   ReLq<View,CtrlView,rm>::ReLq(Home home, View x0, View x1, CtrlView b)
00464     : ReBinaryPropagator<View,PC_INT_BND,CtrlView>(home,x0,x1,b) {}
00465 
00466   template<class View, class CtrlView, ReifyMode rm>
00467   ExecStatus
00468   ReLq<View,CtrlView,rm>::post(Home home, View x0, View x1, CtrlView b) {
00469     if (b.one()) {
00470       if (rm == RM_PMI)
00471         return ES_OK;
00472       return Lq<View,View>::post(home,x0,x1);
00473     }
00474     if (b.zero()) {
00475       if (rm == RM_IMP)
00476         return ES_OK;
00477       return Le<View,View>::post(home,x1,x0);
00478     }
00479     if (!same(x0,x1)) {
00480       switch (rtest_lq(x0,x1)) {
00481       case RT_TRUE:
00482         if (rm != RM_IMP)
00483           GECODE_ME_CHECK(b.one_none(home));
00484         break;
00485       case RT_FALSE:
00486         if (rm != RM_PMI)
00487           GECODE_ME_CHECK(b.zero_none(home));
00488         break;
00489       case RT_MAYBE:
00490         (void) new (home) ReLq<View,CtrlView,rm>(home,x0,x1,b);
00491         break;
00492       default: GECODE_NEVER;
00493       }
00494     } else if (rm != RM_IMP) {
00495       GECODE_ME_CHECK(b.one_none(home));
00496     }
00497     return ES_OK;
00498   }
00499 
00500   template<class View, class CtrlView, ReifyMode rm>
00501   forceinline
00502   ReLq<View,CtrlView,rm>::ReLq(Space& home, bool share, ReLq& p)
00503     : ReBinaryPropagator<View,PC_INT_BND,CtrlView>(home,share,p) {}
00504 
00505   template<class View, class CtrlView, ReifyMode rm>
00506   Actor*
00507   ReLq<View,CtrlView,rm>::copy(Space& home, bool share) {
00508     return new (home) ReLq<View,CtrlView,rm>(home,share,*this);
00509   }
00510 
00511   template<class View, class CtrlView, ReifyMode rm>
00512   ExecStatus
00513   ReLq<View,CtrlView,rm>::propagate(Space& home, const ModEventDelta&) {
00514     if (b.one()) {
00515       if (rm != RM_PMI)
00516         GECODE_REWRITE(*this,(Lq<View,View>::post(home(*this),x0,x1)));
00517     } else if (b.zero()) {
00518       if (rm != RM_IMP)
00519         GECODE_REWRITE(*this,(Le<View,View>::post(home(*this),x1,x0)));
00520     } else {
00521       switch (rtest_lq(x0,x1)) {
00522       case RT_TRUE:
00523         if (rm != RM_IMP)
00524           GECODE_ME_CHECK(b.one_none(home));
00525         break;
00526       case RT_FALSE:
00527         if (rm != RM_PMI)
00528           GECODE_ME_CHECK(b.zero_none(home));
00529         break;
00530       case RT_MAYBE:
00531         return ES_FIX;
00532       default: GECODE_NEVER;
00533       }
00534     }
00535     return home.ES_SUBSUMED(*this);
00536   }
00537 
00538   /*
00539    * Reified less or equal propagator involving one variable
00540    *
00541    */
00542 
00543   template<class View, class CtrlView, ReifyMode rm>
00544   forceinline
00545   ReLqInt<View,CtrlView,rm>::ReLqInt(Home home, View x, int c0, CtrlView b)
00546     : ReUnaryPropagator<View,PC_INT_BND,CtrlView>(home,x,b), c(c0) {}
00547 
00548   template<class View, class CtrlView, ReifyMode rm>
00549   ExecStatus
00550   ReLqInt<View,CtrlView,rm>::post(Home home, View x, int c, CtrlView b) {
00551     if (b.one()) {
00552       if (rm != RM_PMI)
00553         GECODE_ME_CHECK(x.lq(home,c));
00554     } else if (b.zero()) {
00555       if (rm != RM_IMP)
00556         GECODE_ME_CHECK(x.gr(home,c));
00557     } else {
00558       switch (rtest_lq(x,c)) {
00559       case RT_TRUE:
00560         if (rm != RM_IMP)
00561           GECODE_ME_CHECK(b.one_none(home));
00562         break;
00563       case RT_FALSE:
00564         if (rm != RM_PMI)
00565           GECODE_ME_CHECK(b.zero_none(home));
00566         break;
00567       case RT_MAYBE:
00568         (void) new (home) ReLqInt<View,CtrlView,rm>(home,x,c,b);
00569         break;
00570       default: GECODE_NEVER;
00571       }
00572     }
00573     return ES_OK;
00574   }
00575 
00576 
00577   template<class View, class CtrlView, ReifyMode rm>
00578   forceinline
00579   ReLqInt<View,CtrlView,rm>::ReLqInt(Space& home, bool share, ReLqInt& p)
00580     : ReUnaryPropagator<View,PC_INT_BND,CtrlView>(home,share,p), c(p.c) {}
00581 
00582   template<class View, class CtrlView, ReifyMode rm>
00583   Actor*
00584   ReLqInt<View,CtrlView,rm>::copy(Space& home, bool share) {
00585     return new (home) ReLqInt<View,CtrlView,rm>(home,share,*this);
00586   }
00587 
00588   template<class View, class CtrlView, ReifyMode rm>
00589   ExecStatus
00590   ReLqInt<View,CtrlView,rm>::propagate(Space& home, const ModEventDelta&) {
00591     if (b.one()) {
00592       if (rm != RM_PMI)
00593         GECODE_ME_CHECK(x0.lq(home,c));
00594     } else if (b.zero()) {
00595       if (rm != RM_IMP)
00596         GECODE_ME_CHECK(x0.gr(home,c));
00597     } else {
00598       switch (rtest_lq(x0,c)) {
00599       case RT_TRUE:
00600         if (rm != RM_IMP)
00601           GECODE_ME_CHECK(b.one_none(home));
00602         break;
00603       case RT_FALSE:
00604         if (rm != RM_PMI)
00605           GECODE_ME_CHECK(b.zero_none(home));
00606         break;
00607       case RT_MAYBE:
00608         return ES_FIX;
00609       default: GECODE_NEVER;
00610       }
00611     }
00612     return home.ES_SUBSUMED(*this);
00613   }
00614 
00615 }}}
00616 
00617 // STATISTICS: int-prop
00618