Generated on Mon Jul 6 18:09:08 2009 for Gecode by doxygen 1.5.9

bnd.hpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Patrick Pekczynski <pekczynski@ps.uni-sb.de>
00005  *
00006  *  Copyright:
00007  *     Patrick Pekczynski, 2004/2005
00008  *
00009  *  Last modified:
00010  *     $Date: 2009-02-03 11:13:22 +0100 (Tue, 03 Feb 2009) $ by $Author: schulte $
00011  *     $Revision: 8129 $
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 GCC {
00039 
00040   // for posting
00041   template <class View, class Card, bool isView, bool shared>
00042   inline
00043   BndImp<View, Card, isView, shared>::
00044   BndImp(Space& home, ViewArray<View>& x0, ViewArray<Card>& k0,
00045          bool cf,  bool nolbc) :
00046     Propagator(home), x(x0), k(k0), lps(NULL), ups(NULL),
00047     card_fixed(cf), skip_lbc(nolbc) {
00048     home.notice(*this,AP_DISPOSE);
00049     x.subscribe(home, *this, PC_INT_BND);
00050     k.subscribe(home, *this, PC_INT_BND);
00051   }
00052 
00053   // for cloning
00054   template <class View, class Card, bool isView, bool shared>
00055   forceinline
00056   BndImp<View, Card, isView, shared>::
00057   BndImp(Space& home, bool share, BndImp<View, Card, isView, shared>& p)
00058     : Propagator(home, share, p), lps(NULL), ups(NULL),
00059       card_fixed(p.card_fixed), skip_lbc(p.skip_lbc) {
00060     x.update(home, share, p.x);
00061     k.update(home, share, p.k);
00062   }
00063 
00064   template <class View, class Card, bool isView, bool shared>
00065   size_t
00066   BndImp<View, Card, isView, shared>::dispose(Space& home){
00067     home.ignore(*this,AP_DISPOSE);
00068     if (!home.failed()) {
00069       x.cancel(home,*this, PC_INT_BND);
00070       k.cancel(home,*this, PC_INT_BND);
00071     }
00072     if (lps != NULL) {
00073       delete lps;
00074     }
00075     if (ups != NULL) {
00076       delete ups;
00077     }
00078     (void) Propagator::dispose(home);
00079     return sizeof(*this);
00080   }
00081 
00082   template <class View, class Card, bool isView, bool shared>
00083   size_t
00084   BndImp<View, Card, isView, shared>::allocated(void) const {
00085     size_t s = 0;
00086     if (lps != NULL)
00087       s += lps->allocated();
00088     if (ups != NULL)
00089       s += ups->allocated();
00090     return s;
00091   }
00092 
00093   template <class View, class Card, bool isView, bool shared>
00094   Actor*
00095   BndImp<View, Card, isView, shared>::copy(Space& home, bool share){
00096     return new (home) BndImp<View, Card, isView, shared>
00097       (home, share, *this);
00098   }
00099 
00100   template <class View, class Card, bool isView, bool shared>
00101   PropCost
00102   BndImp<View, Card, isView, shared>::cost(const Space&, const ModEventDelta&) const {
00103     /*
00104      * The bounds consistent version of the Global Cardinality constraint
00105      * has a theoretical complexity of
00106      *   O(t + n\cdot log(n)) with
00107      *   n = number of variables
00108      *   t = time needed to sort the domain bounds of the variables
00109      */
00110     return PropCost::linear(PropCost::HI,x.size());
00111   }
00112 
00113   template <class View, class Card, bool isView, bool shared>
00114   ExecStatus
00115   BndImp<View, Card, isView, shared>::propagate(Space& home, const ModEventDelta&) {
00116     bool all_assigned = true;
00117     bool mod          = false;
00118     int  smin         = 0;
00119     int  smax         = 0;
00120 
00121     if (isView) {
00122       // if a cardinality of first or last value is
00123       // out of the variable bounds (cardvar == 0)
00124       // reduce cardinality variables
00125 
00126       int m = k.size();
00127       bool locut = k[0].max() == 0;
00128       bool hicut = k[m - 1].max() == 0;
00129 
00130       if (locut) {
00131         int low = k[0].card();
00132         for (int i = 0; i < x.size(); i++) {
00133           ModEvent me = x[i].gr(home, low);
00134           GECODE_ME_CHECK(me);
00135           mod |= me_modified(me) && (x[i].min() != low + 1);
00136           mod |= shared && me_modified(me);
00137         }
00138       }
00139       if (hicut) {
00140         int hi = k[m - 1].card();
00141         for (int i = 0; i < x.size(); i++) {
00142           ModEvent me = x[i].le(home, hi);
00143           GECODE_ME_CHECK(me);
00144           mod |= me_modified(me) && (x[i].max() != hi - 1);
00145           mod |= shared && me_modified(me);
00146         }
00147       }
00148 
00149       if (locut || hicut) {
00150         int cmin = k[0].card();
00151         int cmax = k[m - 1].card();
00152         if (k[0].max() == 0) {
00153           cmin = k[1].card();
00154         }
00155         if (k[m - 1].max() == 0) {
00156           cmax = k[m - 2].card();
00157         }
00158         reduce_card<Card>(home,cmin, cmax, k);
00159 
00160         if (lps != NULL) {
00161           delete lps; lps = NULL;
00162           assert(ups != NULL);
00163           delete ups; ups = NULL;
00164         }
00165       }
00166     }
00167 
00168     Region r(home);
00169     int* count = r.alloc<int>(k.size());
00170     for (int i = k.size(); i--; )
00171       count[i] = 0;
00172 
00173     int noa = 0;
00174     int single = 0;
00175     int xlb = 0;
00176     int xub = 0;
00177     for (int i = x.size(); i--; ) {
00178       bool b = x[i].assigned();
00179       xlb += x[i].min();
00180       xub += x[i].max();
00181       all_assigned &= b;
00182       if (b) {
00183         noa++;
00184         int idx = lookupValue(k,x[i].val());
00185         // reduction is essential for order on value nodes in dom
00186         // hence introduce test for failed lookup
00187         if (idx == -1)
00188           return ES_FAILED;
00189         count[idx]++;
00190       } else {
00191         single = i;
00192       }
00193     }
00194 
00195     if (isView) {
00196       // before propagation performs inferences on cardinality variables:
00197       if (noa > 0) {
00198         int n  = x.size();
00199         int ks = k.size();
00200 
00201         for (int i = ks; i--; ) {
00202           if (!k[i].assigned()) {
00203             int ub = n - (noa - count[i]);
00204             int lb = count[i];
00205             ModEvent melq = k[i].lq(home, ub);
00206             GECODE_ME_CHECK(melq);
00207             mod |= me_modified(melq) && (k[i].max() != ub);
00208             mod |= shared && me_modified(melq);
00209 
00210             ModEvent megq = k[i].gq(home, lb);
00211             GECODE_ME_CHECK(megq);
00212             mod |= me_modified(megq) && (k[i].min() != lb);
00213             mod |= shared && me_modified(megq);
00214           }
00215         }
00216       }
00217 
00218       if (!card_consistent<View, Card>(smin, smax, x, k))
00219         return ES_FAILED;
00220 
00221       // can only modified cardinality variables
00222       GECODE_ES_CHECK((prop_card<View, Card, shared>(home, x, k, mod)));
00223 
00224       // mimicking linear constraint
00225       int smax = 0;
00226       int smin = 0;
00227       int total_min = 0;
00228       int total_max = 0;
00229       for (int i = k.size(); i--; ) {
00230         smax += k[i].max();
00231         total_min += k[i].card() * k[i].min();
00232         total_max += k[i].card() * k[i].max();
00233       }
00234       int xsmax = x.size() - smax;
00235       int xsmin = x.size() - smin;
00236       smax = 0;
00237       smin = 0;
00238       bool card_ass = true;
00239       for (int i = k.size(); i--; ) {
00240         int lb = xsmax + k[i].max();
00241         int ub = xsmin + k[i].min();
00242         ModEvent me = k[i].gq(home, lb);
00243         GECODE_ME_CHECK(me);
00244         mod |= me_modified(me) && (k[i].min() != lb);
00245         mod |= shared && me_modified(me);
00246         smax += k[i].max();
00247 
00248         me = k[i].lq(home, ub);
00249         GECODE_ME_CHECK(me);
00250         mod |= me_modified(me) && (k[i].max() != ub);
00251         mod |= shared && me_modified(me);
00252         card_ass &= k[i].assigned();
00253       }
00254       if (card_ass) {
00255         if (smax < x.size() || smax > x.size())
00256           return ES_FAILED;
00257 
00258         // redundant linear constraint
00259         for (int i = x.size(); i--; ) {
00260           if (!x[i].assigned()) {
00261             int xmin = xub - x[i].max();
00262             int xgq  = total_max - xmin;
00263 
00264             int xmax = xlb - x[i].min();
00265             int xlq  = total_max - xmax;
00266 
00267             ModEvent me = x[i].gq(home, xgq);
00268             GECODE_ME_CHECK(me);
00269             mod |= me_modified(me) && (x[i].min() != xgq);
00270             mod |= shared && me_modified(me);
00271 
00272             me = x[i].lq(home, xlq);
00273             GECODE_ME_CHECK(me);
00274             mod |= me_modified(me) && (x[i].max() != xlq);
00275             mod |= shared && me_modified(me);
00276           }
00277         }
00278       }
00279     }
00280 
00281     for (int i = k.size(); i--; )
00282       count[i] = 0;
00283 
00284     all_assigned = true;
00285     noa = 0;
00286     single = 0;
00287 
00288     for (int i = x.size(); i--; ) {
00289       bool b = x[i].assigned();
00290       xlb += x[i].min();
00291       xub += x[i].max();
00292       all_assigned &= b;
00293       if (b) {
00294         noa++;
00295         int idx = lookupValue(k,x[i].val());
00296         // reduction is essential for order on value nodes in dom
00297         // hence introduce test for failed lookup
00298         if (idx == -1)
00299           return ES_FAILED;
00300         count[idx]++;
00301       } else {
00302         single = i;
00303       }
00304     }
00305 
00306     if (all_assigned) {
00307       for (int i = k.size(); i--; ) {
00308         int ci = count[i];
00309         if (! (k[i].min() <= ci && ci <= k[i].max())) {
00310           return ES_FAILED;
00311         } else {
00312           if (isView) {
00313             if (!k[i].assigned()) {
00314               ModEvent me = k[i].eq(home, ci);
00315               GECODE_ME_CHECK(me);
00316               mod |= k[i].assigned();
00317             }
00318             all_assigned &= k[i].assigned();
00319           }
00320         }
00321       }
00322       if (all_assigned)
00323         return ES_SUBSUMED(*this,home);
00324     }
00325 
00326     if (isView) {
00327       // check again for zero entries at first or last position
00328       int m = k.size();
00329       bool locut = k[0].max() == 0;
00330       bool hicut = k[m - 1].max() == 0;
00331 
00332       if (locut) {
00333         int low = k[0].card();
00334         for (int i = 0; i < x.size(); i++) {
00335           ModEvent me = x[i].gr(home, low);
00336           GECODE_ME_CHECK(me);
00337           mod |= me_modified(me) && (x[i].min() != low + 1);
00338           mod |= shared && me_modified(me);
00339         }
00340       }
00341       if (hicut) {
00342         int hi = k[m - 1].card();
00343         for (int i = 0; i < x.size(); i++) {
00344           ModEvent me = x[i].le(home, hi);
00345           GECODE_ME_CHECK(me);
00346           mod |= me_modified(me) && (x[i].max() != hi - 1);
00347           mod |= shared && me_modified(me);
00348         }
00349       }
00350 
00351       if (locut || hicut) {
00352         int cmin = k[0].card();
00353         int cmax = k[m - 1].card();
00354         if (k[0].max() == 0) {
00355           cmin = k[1].card();
00356         }
00357         if (k[m - 1].max() == 0) {
00358           cmax = k[m - 2].card();
00359         }
00360         reduce_card<Card>(home,cmin, cmax, k);
00361 
00362         if (lps != NULL) {
00363           delete lps;
00364           lps = NULL;
00365           assert(ups != NULL);
00366           delete ups;
00367           ups = NULL;
00368         }
00369       }
00370     }
00371 
00372     ExecStatus es_ubc = ES_FIX;
00373     ExecStatus es_lbc = ES_FIX;
00374     int n = x.size();
00375 
00376     int* mu = r.alloc<int>(n);
00377     int* nu = r.alloc<int>(n);
00378 
00379     for (int i = n; i--; )
00380       nu[i] = mu[i] = i;
00381 
00382     // Create sorting permutation mu according to the variables upper bounds
00383     MaxInc<View> max_inc(x);
00384     Support::quicksort<int, MaxInc<View> >(mu, n, max_inc);
00385 
00386     // Create sorting permutation nu according to the variables lower bounds
00387     MinInc<View> min_inc(x);
00388     Support::quicksort<int, MinInc<View> >(nu, n, min_inc);
00389 
00390     if (isView) {
00391       // assert guaranteed bounds in the set of all values for variable case
00392       assert(k[0].card() == x[nu[0]].min());
00393     }
00394 
00395     // ensure that only values are considered lying in the variable domain
00396     int cur_minx = x[nu[0]].min();
00397     if (lps == NULL) {
00398       assert (ups == NULL);
00399       lps = new PartialSum<Card>(cur_minx,  k.size(), k, false);
00400       ups = new PartialSum<Card>(cur_minx,  k.size(), k, true);
00401     }
00402 
00403     if (isView) {
00404       // if there has been a change to the cardinality variables
00405       // reconstruction of the partial sum structure is necessary
00406       if (lps->check_update_min(k)) {
00407         delete lps;
00408         lps = new PartialSum<Card>(cur_minx,  k.size(), k, false);
00409       }
00410 
00411       if (ups->check_update_max(k)) {
00412         delete ups;
00413         ups = new PartialSum<Card>(cur_minx,  k.size(), k, true);
00414       }
00415     }
00416 
00417     // already holds by construction
00418     assert(lps->minValue() == ups->minValue());
00419     assert(lps->maxValue() == ups->maxValue());
00420 
00421     bool minima_equal = lps->minValue() == ups->minValue();
00422     bool maxima_equal = lps->maxValue() == ups->maxValue();
00423 
00424     if (!minima_equal || !maxima_equal ) {
00425       delete lps;
00426       lps = new PartialSum<Card>(cur_minx, k.size(), k, false);
00427       delete ups;
00428       ups = new PartialSum<Card>(cur_minx, k.size(), k, true);
00429     }
00430 
00431     // assert that the minimal value of the partial sum structure for
00432     // LBC is consistent with the smallest value a variable can take
00433     assert(lps->minValue() <= x[nu[0]].min());
00434     // assert that the maximal value of the partial sum structure for
00435     // UBC is consistent with the largest value a variable can take
00436     //std::cerr << x[mu[x.size() - 1]].max() <<"<="<< ups->maxValue() << "\n";
00437     //assert(x[mu[x.size() - 1]].max() <= ups->maxValue());
00438 
00439     /*
00440      *  Setup rank and bounds info
00441      *  Since this implementation is based on the theory of Hall Intervals
00442      *  additional datastructures are needed in order to represent these
00443      *  intervals and the "partial-sum" data structure (cf."gcc/gccbndsup.hpp")
00444      *
00445      */
00446 
00447     HallInfo* hall = r.alloc<HallInfo>(2 * n + 2);
00448     Rank* rank = r.alloc<Rank>(n);
00449 
00450     int nb = 0;
00451     // setup bounds and rank
00452     int min        = x[nu[0]].min();
00453     int max        = x[mu[0]].max() + 1;
00454     int last       = lps->firstValue + 1; //equivalent to last = min -2
00455     hall[0].bounds = last;
00456 
00457     /*
00458      * First the algorithm merges the arrays minsorted and maxsorted
00459      * into bounds i.e. hall[].bounds contains the ordered union
00460      * of the lower and upper domain bounds including two sentinels
00461      * at the beginning and at the end of the set
00462      * ( the upper variable bounds in this union are increased by 1 )
00463      */
00464 
00465     {
00466       int i = 0;
00467       int j = 0;
00468       while (true) {
00469         if (i < n && min < max) {
00470           if (min != last) {
00471             last = min;
00472             hall[++nb].bounds = last;
00473           }
00474           rank[nu[i]].min = nb;
00475           if (++i < n) {
00476             min = x[nu[i]].min();
00477           }
00478         } else {
00479           if (max != last) {
00480             last = max;
00481             hall[++nb].bounds = last;
00482           }
00483           rank[mu[j]].max = nb;
00484           if (++j == n) {
00485             break;
00486           }
00487           max = x[mu[j]].max() + 1;
00488         }
00489       }
00490     }
00491 
00492     int rightmost = nb + 1; // rightmost accesible value in bounds
00493     hall[rightmost].bounds = ups->lastValue + 1 ;
00494 
00495     skip_lbc = true;
00496     for (int i = k.size(); i--; ) {
00497       skip_lbc &= (k[i].min() == 0);
00498     }
00499 
00500     if (!card_fixed && !skip_lbc) {
00501       es_lbc = lbc<View, Card, shared>(home, x, nb, hall, rank,lps, mu, nu);
00502       GECODE_ES_CHECK(es_lbc);
00503       mod |= (es_lbc == ES_NOFIX);
00504     }
00505 
00506     es_ubc = ubc<View, Card, shared>(home, x, nb, hall, rank, ups, mu, nu);
00507     GECODE_ES_CHECK(es_ubc);
00508     mod |= (es_ubc == ES_NOFIX);
00509 
00510     if (isView) {
00511       GECODE_ES_CHECK((prop_card<View, Card, shared>(home, x, k, mod)));
00512     }
00513 
00514     all_assigned = true;
00515     noa = 0;
00516     single = 0;
00517     for (int i = k.size(); i--; ) {
00518       count[i] = 0;
00519     }
00520 
00521     for (int i = x.size(); i--; ) {
00522       bool b = x[i].assigned();
00523       all_assigned &= b;
00524       if (b) {
00525         noa++;
00526         int idx = lookupValue(k,x[i].val());
00527         count[idx]++;
00528       } else {
00529         single = i;
00530       }
00531     }
00532 
00533     if (all_assigned) {
00534       for (int i = k.size(); i--; ) {
00535         int ci = count[i];
00536         if (! (k[i].min() <= ci && ci <= k[i].max())) {
00537           return ES_FAILED;
00538         } else {
00539           if (isView) {
00540             if (!k[i].assigned()) {
00541               ModEvent me = k[i].eq(home, ci);
00542               GECODE_ME_CHECK(me);
00543               mod |= k[i].assigned();
00544             }
00545             all_assigned &= k[i].assigned();
00546           }
00547         }
00548       }
00549       if (all_assigned)
00550         return ES_SUBSUMED(*this,home);
00551     }
00552 
00553     return mod ? ES_NOFIX : ES_FIX;
00554   }
00555 
00564   template <class View1, class View2>
00565   class SharingTest {
00566   public:
00571     static bool shared(Space& home, ViewArray<View1>& x0,
00572                        ViewArray<View2>& k0) {
00573       ViewArray<View1> xc(home, x0.size()+k0.size());
00574       for (int i = 0; i < x0.size(); i++) {
00575         xc[i] = x0[i];
00576       }
00577       for (int i = x0.size(); i < x0.size()+k0.size(); i++) {
00578         xc[i] = k0[i - x0.size()].intview();
00579       }
00580       return xc.shared(home);
00581     }
00582   };
00583 
00588   template <>
00589   class SharingTest<IntView,OccurBndsView> {
00590   public:
00592     static bool shared(Space& home,
00593                        ViewArray<IntView>& xs, ViewArray<OccurBndsView>&) {
00594       return xs.shared(home);
00595     }
00596   };
00597 
00598   template <class View, class Card, bool isView>
00599   ExecStatus
00600   Bnd<View, Card, isView>::post(Space& home,
00601                                 ViewArray<View>& x0,
00602                                 ViewArray<Card>& k0) {
00603     bool cardfix = true;
00604     bool nolbc = true;
00605     for (int i = k0.size(); i--; ) {
00606       cardfix &= k0[i].assigned();
00607       nolbc &= (k0[i].min() == 0);
00608     }
00609     if (SharingTest<View,Card>::shared(home,x0,k0)) {
00610       new (home) BndImp<View, Card, isView, true>
00611         (home, x0, k0, cardfix, nolbc);
00612     } else {
00613       new (home) BndImp<View, Card, isView, false>
00614         (home, x0, k0, cardfix, nolbc);
00615     }
00616     return ES_OK;
00617   }
00618 
00619 }}}
00620 
00621 // STATISTICS: int-prop
00622