Generated on Fri Mar 20 15:56:20 2015 for Gecode by doxygen 1.6.3

minmax.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  *     Christian Schulte <schulte@gecode.org>
00006  *     Gabor Szokoli <szokoli@gecode.org>
00007  *     Denys Duchier <denys.duchier@univ-orleans.fr>
00008  *
00009  *  Copyright:
00010  *     Guido Tack, 2004
00011  *     Christian Schulte, 2004
00012  *     Gabor Szokoli, 2004
00013  *
00014  *  Last modified:
00015  *     $Date: 2012-10-19 05:58:26 +0200 (Fri, 19 Oct 2012) $ by $Author: tack $
00016  *     $Revision: 13156 $
00017  *
00018  *  This file is part of Gecode, the generic constraint
00019  *  development environment:
00020  *     http://www.gecode.org
00021  *
00022  *  Permission is hereby granted, free of charge, to any person obtaining
00023  *  a copy of this software and associated documentation files (the
00024  *  "Software"), to deal in the Software without restriction, including
00025  *  without limitation the rights to use, copy, modify, merge, publish,
00026  *  distribute, sublicense, and/or sell copies of the Software, and to
00027  *  permit persons to whom the Software is furnished to do so, subject to
00028  *  the following conditions:
00029  *
00030  *  The above copyright notice and this permission notice shall be
00031  *  included in all copies or substantial portions of the Software.
00032  *
00033  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00034  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00035  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00036  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00037  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00038  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00039  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00040  *
00041  */
00042 
00043 
00044 
00045 #include <gecode/set.hh>
00046 #include <gecode/int.hh>
00047 
00048 namespace Gecode { namespace Set { namespace Int {
00049 
00050   template<class View>
00051   forceinline
00052   MinElement<View>::MinElement(Home home, View y0, Gecode::Int::IntView y1)
00053     : MixBinaryPropagator<View,PC_SET_ANY,Gecode::Int::IntView,Gecode::Int::PC_INT_BND> (home, y0, y1) {}
00054 
00055   template<class View>
00056   forceinline ExecStatus
00057   MinElement<View>::post(Home home, View x0, Gecode::Int::IntView x1) {
00058     GECODE_ME_CHECK(x0.cardMin(home,1));
00059     (void) new (home) MinElement(home,x0,x1);
00060     return ES_OK;
00061   }
00062 
00063   template<class View>
00064   forceinline
00065   MinElement<View>::MinElement(Space& home, bool share, MinElement& p)
00066     : MixBinaryPropagator<View,PC_SET_ANY,Gecode::Int::IntView,Gecode::Int::PC_INT_BND> (home, share, p) {}
00067 
00068   template<class View>
00069   Actor*
00070   MinElement<View>::copy(Space& home, bool share) {
00071    return new (home) MinElement(home,share,*this);
00072   }
00073 
00074   template<class View>
00075   ExecStatus
00076   MinElement<View>::propagate(Space& home, const ModEventDelta&) {
00077     //x1 is an element of x0.ub
00078     //x1 =< smallest element of x0.lb
00079     //x1 =< x0.cardinialityMin-est largest element of x0.ub
00080     //(these 2 take care of determined x0)
00081     //No element in x0 is smaller than x1
00082     //if x1 is determined, it is part of the ub.
00083 
00084     //Consequently:
00085     //The domain of x1 is a subset of x0.ub up to the first element in x0.lb.
00086     //x0 lacks everything smaller than smallest possible x1.
00087 
00088     {
00089       LubRanges<View> ub(x0);
00090       GECODE_ME_CHECK(x1.inter_r(home,ub,false));
00091     }
00092     GECODE_ME_CHECK(x1.lq(home,x0.glbMin()));
00093     //if cardMin>lbSize?
00094     assert(x0.cardMin()>=1);
00095 
00096     {
00098       unsigned int size = 0;
00099       int maxN = BndSet::MAX_OF_EMPTY;
00100       for (LubRanges<View> ubr(x0); ubr(); ++ubr, ++size) {}
00101       Region r(home);
00102       int* ub = r.alloc<int>(size*2);
00103       int i=0;
00104       for (LubRanges<View> ubr(x0); ubr(); ++ubr, ++i) {
00105         ub[2*i]   = ubr.min();
00106         ub[2*i+1] = ubr.max();
00107       }
00108       unsigned int x0cm = x0.cardMin()-1;
00109       for (unsigned int i=size; i--;) {
00110         unsigned int width = static_cast<unsigned int>(ub[2*i+1]-ub[2*i]+1);
00111         if (width > x0cm) {
00112           maxN = static_cast<int>(ub[2*i+1]-x0cm);
00113           break;
00114         }
00115         x0cm -= width;
00116       }
00117       GECODE_ME_CHECK(x1.lq(home,maxN));
00118     }
00119 
00120     GECODE_ME_CHECK( x0.exclude(home,
00121                                 Limits::min, x1.min()-1) );
00122 
00123     if (x1.assigned()) {
00124       GECODE_ME_CHECK(x0.include(home,x1.val()));
00125       GECODE_ME_CHECK(x0.exclude(home,
00126                                  Limits::min, x1.val()-1));
00127       return home.ES_SUBSUMED(*this);
00128     }
00129 
00130     return ES_FIX;
00131   }
00132 
00133 
00134   template<class View>
00135   forceinline
00136   NotMinElement<View>::NotMinElement(Home home, View y0,
00137                                      Gecode::Int::IntView y1)
00138     : MixBinaryPropagator<View,PC_SET_ANY,
00139       Gecode::Int::IntView,Gecode::Int::PC_INT_DOM> (home, y0, y1) {}
00140 
00141   template<class View>
00142   forceinline ExecStatus
00143   NotMinElement<View>::post(Home home, View x0, Gecode::Int::IntView x1) {
00144     (void) new (home) NotMinElement(home,x0,x1);
00145     return ES_OK;
00146   }
00147 
00148   template<class View>
00149   forceinline
00150   NotMinElement<View>::NotMinElement(Space& home, bool share,
00151                                      NotMinElement& p)
00152     : MixBinaryPropagator<View,PC_SET_ANY,
00153       Gecode::Int::IntView,Gecode::Int::PC_INT_DOM> (home, share, p) {}
00154 
00155   template<class View>
00156   Actor*
00157   NotMinElement<View>::copy(Space& home, bool share) {
00158     return new (home) NotMinElement(home,share,*this);
00159   }
00160 
00161   template<class View>
00162   ExecStatus
00163   NotMinElement<View>::propagate(Space& home, const ModEventDelta&) {
00164     // cheap tests for entailment:
00165     // if x0 is empty, then entailed
00166     // if max(x1) < min(x0.lub) or min(x1) > max(x0.lub), then entailed
00167     // if min(x0.glb) < min(x1), then entailed
00168     if ((x0.cardMax() == 0) ||
00169         ((x1.max() < x0.lubMin()) || (x1.min() > x0.lubMax())) ||
00170         ((x0.glbSize() > 0) && (x0.glbMin() < x1.min())))
00171       return home.ES_SUBSUMED(*this);
00172     // if x1 is determined and = x0.lub.min: remove it from x0,
00173     // then entailed
00174     if (x1.assigned() && x1.val()==x0.lubMin()) {
00175       GECODE_ME_CHECK(x0.exclude(home,x1.val()));
00176       return home.ES_SUBSUMED(*this);
00177     }
00178     // if min(x0) is decided: remove min(x0) from the domain of x1
00179     // then entailed
00180     if (x0.glbMin() == x0.lubMin()) {
00181       GECODE_ME_CHECK(x1.nq(home,x0.glbMin()));
00182       return home.ES_SUBSUMED(*this);
00183     }
00184     // if x1 is determined and = x0.glb.min, then we need at least
00185     // one more element; if there is only one below, then we must
00186     // take it.
00187     if (x1.assigned() && x0.glbSize() > 0 && x1.val()==x0.glbMin()) {
00188       unsigned int oldGlbSize = x0.glbSize();
00189       // if there is only 1 unknown below x1, then we must take it
00190       UnknownRanges<View> ur(x0);
00191       assert(ur());
00192       // the iterator is not empty: otherwise x0 would be determined
00193       // and min(x0) would have been decided and the preceding if
00194       // would have caught it.  Also, the first range is not above
00195       // x1 otherwise the very first if would have caught it.
00196       // so let's check if the very first range of unknowns is of
00197       // size 1 and there is no second one or it starts above x1.
00198       if (ur.width()==1) {
00199         int i=ur.min();
00200         ++ur;
00201         if (!ur() || ur.min()>x1.val()) {
00202           GECODE_ME_CHECK(x0.include(home,i));
00203           return home.ES_SUBSUMED(*this);
00204         }
00205       }
00206       GECODE_ME_CHECK(x0.cardMin(home, oldGlbSize+1));
00207     }
00208     // if dom(x1) and lub(x0) are disjoint, then entailed;
00209     {
00210       LubRanges<View> ub(x0);
00211       Gecode::Int::ViewRanges<Gecode::Int::IntView> d(x1);
00212       Gecode::Iter::Ranges::Inter<LubRanges<View>,
00213         Gecode::Int::ViewRanges<Gecode::Int::IntView> > ir(ub,d);
00214       if (!ir()) return home.ES_SUBSUMED(*this);
00215     }
00216     // x0 is fated to eventually contain at least x0.cardMin elements.
00217     // therefore min(x0) <= x0.cardMin-th largest element of x0.lub
00218     // if x1 > than that, then entailed.
00219     {
00220       // to find the x0.cardMin-th largest element of x0.lub, we need
00221       // some sort of reverse range iterator. we will need to fake one
00222       // by storing the ranges of the forward iterator in an array.
00223       // first we need to know how large the array needs to be. so, let's
00224       // count the ranges:
00225       int num_ranges = 0;
00226       for (LubRanges<View> ur(x0); ur(); ++ur, ++num_ranges) {}
00227       // create an array for storing min and max of each range
00228       Region r(home);
00229       int* _ur = r.alloc<int>(num_ranges*2);
00230       // now, we fill the array:
00231       int i = 0;
00232       for (LubRanges<View> ur(x0); ur(); ++ur, ++i) {
00233         _ur[2*i  ] = ur.min();
00234         _ur[2*i+1] = ur.max();
00235       }
00236       // now we search from the top the range that contains the
00237       // nth largest value.
00238       unsigned int n = x0.cardMin();
00239       int nth_largest = BndSet::MAX_OF_EMPTY;
00240       for (int i=num_ranges; i--; ) {
00241         // number of values in range
00242         unsigned int num_values = static_cast<unsigned int>(_ur[2*i+1]-_ur[2*i]+1);
00243         // does the range contain the value?
00244         if (num_values >= n) {
00245           // record it and exit the loop
00246           nth_largest = static_cast<int>(_ur[2*i+1]-n+1);
00247           break;
00248         }
00249         // otherwise, we skipped num_values
00250         n -= num_values;
00251       }
00252       // if x1.min > nth_largest, then entailed
00253       if (x1.min() > nth_largest)
00254         return home.ES_SUBSUMED(*this);
00255     }
00256     return ES_FIX;
00257   }
00258 
00259   template<class View, ReifyMode rm>
00260   forceinline
00261   ReMinElement<View,rm>::ReMinElement(Home home, View y0,
00262                                       Gecode::Int::IntView y1,
00263                                       Gecode::Int::BoolView b2)
00264     : Gecode::Int::ReMixBinaryPropagator<View,PC_SET_ANY,
00265       Gecode::Int::IntView,Gecode::Int::PC_INT_DOM,
00266       Gecode::Int::BoolView> (home, y0, y1, b2) {}
00267 
00268   template<class View, ReifyMode rm>
00269   forceinline ExecStatus
00270   ReMinElement<View,rm>::post(Home home, View x0, Gecode::Int::IntView x1,
00271                               Gecode::Int::BoolView b2) {
00272     (void) new (home) ReMinElement(home,x0,x1,b2);
00273     return ES_OK;
00274   }
00275 
00276   template<class View, ReifyMode rm>
00277   forceinline
00278   ReMinElement<View,rm>::ReMinElement(Space& home, bool share,
00279                                       ReMinElement& p)
00280     : Gecode::Int::ReMixBinaryPropagator<View,PC_SET_ANY,
00281       Gecode::Int::IntView,Gecode::Int::PC_INT_DOM,
00282       Gecode::Int::BoolView> (home, share, p) {}
00283 
00284   template<class View, ReifyMode rm>
00285   Actor*
00286   ReMinElement<View,rm>::copy(Space& home, bool share) {
00287    return new (home) ReMinElement(home,share,*this);
00288   }
00289 
00290   template<class View, ReifyMode rm>
00291   ExecStatus
00292   ReMinElement<View,rm>::propagate(Space& home, const ModEventDelta&) {
00293     // check if b is determined
00294     if (b.one()) {
00295       if (rm == RM_PMI)
00296         return home.ES_SUBSUMED(*this);
00297       GECODE_REWRITE(*this, (MinElement<View>::post(home(*this),x0,x1)));
00298     }
00299     if (b.zero()) {
00300       if (rm == RM_IMP)
00301         return home.ES_SUBSUMED(*this);        
00302       GECODE_REWRITE(*this, (NotMinElement<View>::post(home(*this),x0,x1)));
00303     }
00304     // cheap tests for => b=0
00305     // if x0 is empty, then b=0 and entailed
00306     // if max(x1) < min(x0.lub) or min(x1) > max(x0.lub), then b=0 and entailed
00307     // if min(x0.glb) < min(x1), then b=0 and entailed
00308     if ((x0.cardMax() == 0) ||
00309         ((x1.max() < x0.lubMin()) || (x1.min() > x0.lubMax())) ||
00310         ((x0.glbSize() > 0) && (x0.glbMin() < x1.min())))
00311       {
00312         if (rm != RM_PMI)
00313           GECODE_ME_CHECK(b.zero(home));
00314         return home.ES_SUBSUMED(*this);
00315       }
00316     // if min(x0) is decided
00317     if (x0.glbMin() == x0.lubMin()) {
00318       // if x1 is det: check if = min(x0), assign b, entailed
00319       if (x1.assigned()) {
00320         if (x1.val() == x0.glbMin()) {
00321           if (rm != RM_IMP)
00322             GECODE_ME_CHECK(b.one(home));
00323         } else {
00324           if (rm != RM_PMI)
00325             GECODE_ME_CHECK(b.zero(home));
00326         }
00327         return home.ES_SUBSUMED(*this);
00328       }
00329       // if min(x0) not in dom(x1): b=0, entailed
00330       else if ((x0.glbMin() < x1.min()) ||
00331                (x0.glbMin() > x1.max()) ||
00332                !x1.in(x0.glbMin()))
00333         {
00334           if (rm != RM_PMI)
00335             GECODE_ME_CHECK(b.zero(home));
00336           return home.ES_SUBSUMED(*this);
00337         }
00338     }
00339     // // if dom(x1) and lub(x0) are disjoint, then b=0, entailed;
00340     // {
00341     //   LubRanges<View> ub(x0);
00342     //   Gecode::Int::ViewRanges<Gecode::Int::IntView> d(x1);
00343     //   Gecode::Iter::Ranges::Inter<LubRanges<View>,
00344     //     Gecode::Int::ViewRanges<Gecode::Int::IntView> > ir(ub,d);
00345     //   if (!ir()) {
00346     //     GECODE_ME_CHECK(b.zero(home));
00347     //     return home.ES_SUBSUMED(*this);
00348     //   }
00349     // }
00350     // // x0 is fated to eventually contain at least x0.cardMin elements.
00351     // // therefore min(x0) <= x0.cardMin-th largest element of x0.lub
00352     // // if x1 > than that, then b=0 and entailed.
00353     // {
00354     //   // to find the x0.cardMin-th largest element of x0.lub, we need
00355     //   // some sort of reverse range iterator. we will need to fake one
00356     //   // by storing the ranges of the forward iterator in an array.
00357     //   // first we need to know how large the array needs to be. so, let's
00358     //   // count the ranges:
00359     //   int num_ranges = 0;
00360     //   for (LubRanges<View> ur(x0); ur(); ++ur, ++num_ranges) {}
00361     //   // create an array for storing min and max of each range
00362     //   Region re(home);
00363     //   int* _ur = re.alloc<int>(num_ranges*2);
00364     //   // now, we fill the array:
00365     //   int i = 0;
00366     //   for (LubRanges<View> ur(x0); ur(); ++ur, ++i) {
00367     //     _ur[2*i  ] = ur.min();
00368     //     _ur[2*i+1] = ur.max();
00369     //   }
00370     //   // now we search from the top the range that contains the
00371     //   // nth largest value.
00372     //   int n = x0.cardMin();
00373     //   int nth_largest = BndSet::MAX_OF_EMPTY;
00374     //   for (int i=num_ranges; i--; ) {
00375     //     // number of values in range
00376     //     int num_values = _ur[2*i+1]-_ur[2*i]+1;
00377     //     // does the range contain the value?
00378     //     if (num_values >= n)
00379     //       {
00380     //         // record it and exit the loop
00381     //         nth_largest = _ur[2*i+1]-n+1;
00382     //         break;
00383     //       }
00384     //     // otherwise, we skipped num_values
00385     //     n -= num_values;
00386     //   }
00387     //   // if x1.min > nth_largest, then entailed
00388     //   if (x1.min() > nth_largest) {
00389     //     GECODE_ME_CHECK(b.zero(home));
00390     //     return home.ES_SUBSUMED(*this);
00391     //   }
00392     // }
00393     return ES_FIX;
00394   }
00395 
00396   template<class View>
00397   forceinline
00398   MaxElement<View>::MaxElement(Home home, View y0, Gecode::Int::IntView y1)
00399     : MixBinaryPropagator<View,PC_SET_ANY,
00400       Gecode::Int::IntView,Gecode::Int::PC_INT_BND> (home, y0, y1) {}
00401 
00402   template<class View>
00403   forceinline
00404   MaxElement<View>::MaxElement(Space& home, bool share, MaxElement& p)
00405     : MixBinaryPropagator<View,PC_SET_ANY,
00406       Gecode::Int::IntView,Gecode::Int::PC_INT_BND> (home, share, p) {}
00407 
00408   template<class View>
00409   ExecStatus
00410   MaxElement<View>::post(Home home, View x0,
00411                               Gecode::Int::IntView x1) {
00412     GECODE_ME_CHECK(x0.cardMin(home,1));
00413     (void) new (home) MaxElement(home,x0,x1);
00414     return ES_OK;
00415   }
00416 
00417   template<class View>
00418   Actor*
00419   MaxElement<View>::copy(Space& home, bool share) {
00420     return new (home) MaxElement(home,share,*this);
00421   }
00422 
00423   template<class View>
00424   ExecStatus
00425   MaxElement<View>::propagate(Space& home, const ModEventDelta&) {
00426     LubRanges<View> ub(x0);
00427     GECODE_ME_CHECK(x1.inter_r(home,ub,false));
00428     GECODE_ME_CHECK(x1.gq(home,x0.glbMax()));
00429     assert(x0.cardMin()>=1);
00430     GECODE_ME_CHECK(x1.gq(home,x0.lubMinN(x0.cardMin()-1)));
00431     GECODE_ME_CHECK(x0.exclude(home,
00432                                x1.max()+1,Limits::max) );
00433 
00434     if (x1.assigned()) {
00435       GECODE_ME_CHECK(x0.include(home,x1.val()));
00436       GECODE_ME_CHECK( x0.exclude(home,
00437                                   x1.val()+1,Limits::max) );
00438       return home.ES_SUBSUMED(*this);
00439     }
00440 
00441     return ES_FIX;
00442   }
00443 
00444   template<class View>
00445   forceinline
00446   NotMaxElement<View>::NotMaxElement(Home home, View y0,
00447                                      Gecode::Int::IntView y1)
00448     : MixBinaryPropagator<View,PC_SET_ANY,
00449       Gecode::Int::IntView,Gecode::Int::PC_INT_DOM> (home, y0, y1) {}
00450 
00451   template<class View>
00452   forceinline
00453   NotMaxElement<View>::NotMaxElement(Space& home, bool share,
00454                                      NotMaxElement& p)
00455     : MixBinaryPropagator<View,PC_SET_ANY,
00456       Gecode::Int::IntView,Gecode::Int::PC_INT_DOM> (home, share, p) {}
00457 
00458   template<class View>
00459   ExecStatus
00460   NotMaxElement<View>::post(Home home, View x0, Gecode::Int::IntView x1) {
00461     (void) new (home) NotMaxElement(home,x0,x1);
00462     return ES_OK;
00463   }
00464 
00465   template<class View>
00466   Actor*
00467   NotMaxElement<View>::copy(Space& home, bool share) {
00468     return new (home) NotMaxElement(home,share,*this);
00469   }
00470 
00471   template<class View>
00472   ExecStatus
00473   NotMaxElement<View>::propagate(Space& home, const ModEventDelta&) {
00474     // cheap tests for entailment:
00475     // if x0 is empty, then entailed
00476     // if max(x1) < min(x0.lub) or min(x1) > max(x0.lub), then entailed
00477     // if max(x0.glb) > max(x1), then entailed
00478     if ((x0.cardMax() == 0) ||
00479         ((x1.max() < x0.lubMin()) || (x1.min() > x0.lubMax())) ||
00480         ((x0.glbSize() > 0) && (x0.glbMax() > x1.max())))
00481       return home.ES_SUBSUMED(*this);
00482     // if x1 is determined and = max(x0.lub): remove it from x0,
00483     // then entailed
00484     if (x1.assigned() && x1.val()==x0.lubMax()) {
00485       GECODE_ME_CHECK(x0.exclude(home,x1.val()));
00486       return home.ES_SUBSUMED(*this);
00487     }
00488     // if max(x0) is decided: remove max(x0) from the domain of x1
00489     // then entailed
00490     if (x0.glbMax() == x0.lubMax()) {
00491       GECODE_ME_CHECK(x1.nq(home,x0.glbMax()));
00492       return home.ES_SUBSUMED(*this);
00493     }
00494     // if x1 is determined and = max(x0.glb), then we need at least
00495     // one more element; if there is only one above, then we must
00496     // take it.
00497     if (x1.assigned() && x0.glbSize() > 0 && x1.val()==x0.glbMax()) {
00498       unsigned int oldGlbSize = x0.glbSize();
00499       // if there is only 1 unknown above x1, then we must take it
00500       UnknownRanges<View> ur(x0);
00501       // there is at least one unknown above x1 otherwise it would
00502       // have been caught by the if for x1=max(x0.lub)
00503       while (ur.max() < x1.val()) {
00504         assert(ur());
00505         ++ur;
00506       };
00507       // if the first range above x1 contains just 1 element,
00508       // and is the last range, then take that element
00509       if (ur.width() == 1) {
00510         int i = ur.min();
00511         ++ur;
00512         if (!ur()) {
00513           // last range
00514           GECODE_ME_CHECK(x0.include(home,i));
00515           return home.ES_SUBSUMED(*this);
00516         }
00517       }
00518       GECODE_ME_CHECK(x0.cardMin(home, oldGlbSize+1));
00519     }
00520     // if dom(x1) and lub(x0) are disjoint, then entailed
00521     {
00522       LubRanges<View> ub(x0);
00523       Gecode::Int::ViewRanges<Gecode::Int::IntView> d(x1);
00524       Gecode::Iter::Ranges::Inter<LubRanges<View>,
00525         Gecode::Int::ViewRanges<Gecode::Int::IntView> > ir(ub,d);
00526       if (!ir()) return home.ES_SUBSUMED(*this);
00527     }
00528     // x0 is fated to eventually contain at least x0.cardMin elements.
00529     // therefore max(x0) >= x0.cardMin-th smallest element of x0.lub.
00530     // if x1 < than that, then entailed.
00531     {
00532       unsigned int n = x0.cardMin();
00533       int nth_smallest = BndSet::MIN_OF_EMPTY;
00534       for (LubRanges<View> ur(x0); ur(); ++ur) {
00535         if (ur.width() >= n) {
00536           // record it and exit the loop
00537           nth_smallest = static_cast<int>(ur.min() + n - 1);
00538           break;
00539         }
00540         // otherwise, we skipped ur.width() values
00541         n -= ur.width();
00542       }
00543       // if x1.max < nth_smallest, then entailed
00544       if (x1.max() < nth_smallest)
00545         return home.ES_SUBSUMED(*this);
00546     }
00547     return ES_FIX;
00548   }
00549 
00550   template<class View, ReifyMode rm>
00551   forceinline
00552   ReMaxElement<View,rm>::ReMaxElement(Home home, View y0,
00553                                       Gecode::Int::IntView y1,
00554                                       Gecode::Int::BoolView b2)
00555     : Gecode::Int::ReMixBinaryPropagator<View,PC_SET_ANY,
00556       Gecode::Int::IntView,Gecode::Int::PC_INT_DOM,
00557       Gecode::Int::BoolView> (home, y0, y1, b2) {}
00558 
00559   template<class View, ReifyMode rm>
00560   forceinline
00561   ReMaxElement<View,rm>::ReMaxElement(Space& home, bool share,
00562                                       ReMaxElement& p)
00563     : Gecode::Int::ReMixBinaryPropagator<View,PC_SET_ANY,
00564       Gecode::Int::IntView,Gecode::Int::PC_INT_DOM,
00565       Gecode::Int::BoolView> (home, share, p) {}
00566 
00567   template<class View, ReifyMode rm>
00568   ExecStatus
00569   ReMaxElement<View,rm>::post(Home home, View x0,
00570                               Gecode::Int::IntView x1,
00571                               Gecode::Int::BoolView b2) {
00572     (void) new (home) ReMaxElement(home,x0,x1,b2);
00573     return ES_OK;
00574   }
00575 
00576   template<class View, ReifyMode rm>
00577   Actor*
00578   ReMaxElement<View,rm>::copy(Space& home, bool share) {
00579     return new (home) ReMaxElement(home,share,*this);
00580   }
00581 
00582   template<class View, ReifyMode rm>
00583   ExecStatus
00584   ReMaxElement<View,rm>::propagate(Space& home, const ModEventDelta&) {
00585     // check if b is determined
00586     if (b.one()) {
00587       if (rm == RM_PMI)
00588         return home.ES_SUBSUMED(*this);
00589       GECODE_REWRITE(*this, (MaxElement<View>::post(home(*this),x0,x1)));
00590     }
00591     if (b.zero()) {
00592       if (rm == RM_IMP)
00593         return home.ES_SUBSUMED(*this);
00594       GECODE_REWRITE(*this, (NotMaxElement<View>::post(home(*this),x0,x1)));
00595     }
00596     // cheap tests for => b=0
00597     // if x0 is empty, then b=0 and entailed
00598     // if max(x1) < min(x0.lub) or min(x1) > max(x0.lub), then b=0 and entailed
00599     // if max(x0.glb) > max(x1), then b=0 and entailed
00600     if ((x0.cardMax() == 0) ||
00601         ((x1.max() < x0.lubMin()) || (x1.min() > x0.lubMax())) ||
00602         ((x0.glbSize() > 0) && (x0.glbMax() > x1.max())))
00603       {
00604         if (rm != RM_PMI)
00605           GECODE_ME_CHECK(b.zero(home));
00606         return home.ES_SUBSUMED(*this);
00607       }
00608     // if max(x0) is decided
00609     if (x0.glbMax() == x0.lubMax()) {
00610       // if x1 is det: check if = max(x0), assign b, entailed
00611       if (x1.assigned()) {
00612         if (x1.val() == x0.glbMax()) {
00613           if (rm != RM_IMP)
00614             GECODE_ME_CHECK(b.one(home));
00615         } else {
00616           if (rm != RM_PMI)
00617             GECODE_ME_CHECK(b.zero(home));
00618         }
00619         return home.ES_SUBSUMED(*this);
00620       }
00621       // if max(x0) not in dom(x1): b=0, entailed
00622       else if ((x0.glbMax() < x1.min()) ||
00623                (x0.glbMax() > x1.max()) ||
00624                !x1.in(x0.glbMax()))
00625         {
00626           if (rm != RM_PMI)
00627             GECODE_ME_CHECK(b.zero(home));
00628           return home.ES_SUBSUMED(*this);
00629         }
00630     }
00631     // if dom(x1) and lub(x0) are disjoint, then b=0, entailed
00632     {
00633       LubRanges<View> ub(x0);
00634       Gecode::Int::ViewRanges<Gecode::Int::IntView> d(x1);
00635       Gecode::Iter::Ranges::Inter<LubRanges<View>,
00636         Gecode::Int::ViewRanges<Gecode::Int::IntView> > ir(ub,d);
00637       if (!ir()) {
00638         if (rm != RM_PMI)
00639           GECODE_ME_CHECK(b.zero(home));
00640         return home.ES_SUBSUMED(*this);
00641       }
00642     }
00643     // x0 is fated to eventually contain at least x0.cardMin elements.
00644     // therefore max(x0) >= x0.cardMin-th smallest element of x0.lub.
00645     // if x1 < than that, then b=0, entailed.
00646     {
00647       unsigned int n = x0.cardMin();
00648       int nth_smallest = BndSet::MIN_OF_EMPTY;
00649       for (LubRanges<View> ur(x0); ur(); ++ur) {
00650         if (ur.width() >= n)
00651           {
00652             // record it and exit the loop
00653             nth_smallest = static_cast<int>(ur.min() + n - 1);
00654             break;
00655           }
00656         // otherwise, we skipped ur.width() values
00657         n -= ur.width();
00658       }
00659       // if x1.max < nth_smallest, then entailed
00660       if (x1.max() < nth_smallest) {
00661         if (rm != RM_PMI)
00662           GECODE_ME_CHECK(b.zero(home));
00663         return home.ES_SUBSUMED(*this);
00664       }
00665     }
00666     return ES_FIX;
00667   }
00668 
00669 }}}
00670 
00671 // STATISTICS: set-prop