Generated on Mon Aug 25 11:35:36 2008 for Gecode by doxygen 1.5.6

bnd.icc

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: 2008-07-11 09:28:48 +0200 (Fri, 11 Jul 2008) $ by $Author: tack $
00011  *     $Revision: 7285 $
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     force(home);
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     unforce(home);
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(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 cost_hi(x.size(),PC_LINEAR_HI);
00111   }
00112 
00113   template <class View, class Card, bool isView, bool shared>
00114   Support::Symbol
00115   BndImp<View, Card, isView, shared>::ati(void) {
00116     Support::Symbol mangled("Gecode::Int::GCC::Bnd");
00117     mangled += "<";
00118     mangled += View::type();
00119     mangled += ",";
00120     mangled += Card::type();
00121     mangled += ",";
00122     mangled += (isView ? "true" : "false");
00123     mangled += ",";
00124     mangled += (shared ? "true" : "false");
00125     mangled += ">";
00126     return mangled;
00127   }
00128 
00129   template <class View, class Card, bool isView, bool shared>
00130   Reflection::ActorSpec
00131   BndImp<View,Card,isView,shared>::spec(const Space* home,
00132                                         Reflection::VarMap& m) const {
00133     Reflection::ActorSpec s(ati());
00134     return s << x.spec(home, m) << k.spec(home, m) << card_fixed << skip_lbc;
00135   }
00136 
00137   template <class View, class Card, bool isView, bool shared>
00138   void
00139   BndImp<View,Card,isView,shared>::post(Space* home, Reflection::VarMap& vars,
00140                                         const Reflection::ActorSpec& spec) {
00141     spec.checkArity(4);
00142     ViewArray<View> x(home, vars, spec[0]);
00143     ViewArray<Card> k(home, vars, spec[1]);
00144     bool card_fixed = spec[2]->toInt();
00145     bool skip_lbc   = spec[3]->toInt();
00146     (void) new (home) BndImp(home, x, k, card_fixed, skip_lbc);
00147   }
00148 
00149   template <class View, class Card, bool isView, bool shared>
00150   ExecStatus
00151   BndImp<View, Card, isView, shared>::propagate(Space* home, ModEventDelta) {
00152     bool all_assigned = true;
00153     bool mod          = false;
00154     int  smin         = 0;
00155     int  smax         = 0;
00156 
00157     if (isView) {
00158       // if a cardinality of first or last value is
00159       // out of the variable bounds (cardvar == 0)
00160       // reduce cardinality variables
00161 
00162       int m = k.size();
00163       bool locut = k[0].max() == 0;
00164       bool hicut = k[m - 1].max() == 0;
00165       
00166       if (locut) {
00167         int low = k[0].card();
00168         for (int i = 0; i < x.size(); i++) {
00169           ModEvent me = x[i].gr(home, low);
00170           GECODE_ME_CHECK(me);
00171           mod |= me_modified(me) && (x[i].min() != low + 1);
00172           mod |= shared && me_modified(me);
00173         }
00174       }
00175       if (hicut) {
00176         int hi = k[m - 1].card();
00177         for (int i = 0; i < x.size(); i++) {
00178           ModEvent me = x[i].le(home, hi);
00179           GECODE_ME_CHECK(me);
00180           mod |= me_modified(me) && (x[i].max() != hi - 1);
00181           mod |= shared && me_modified(me);
00182         }
00183       }
00184 
00185       if (locut || hicut) {
00186         int cmin = k[0].card();
00187         int cmax = k[m - 1].card();
00188         if (k[0].max() == 0) {
00189           cmin = k[1].card();
00190         }
00191         if (k[m - 1].max() == 0) {
00192           cmax = k[m - 2].card();
00193         }
00194         reduce_card<Card>(cmin, cmax, k);
00195 
00196         if (lps != NULL) {
00197           delete lps; lps = NULL;
00198           assert(ups != NULL);
00199           delete ups; ups = NULL;
00200         }
00201       }
00202     }
00203 
00204     GECODE_AUTOARRAY(int, count, k.size());
00205     for (int i = k.size(); i--; ) {
00206       count[i] = 0;
00207     }
00208 
00209     int noa = 0;
00210     int single = 0;
00211     int xlb = 0;
00212     int xub = 0;
00213     for (int i = x.size(); i--; ) {
00214       bool b = x[i].assigned();
00215       xlb += x[i].min();
00216       xub += x[i].max();
00217       all_assigned &= b;
00218       if (b) {
00219         noa++;
00220         int idx = lookupValue(k,x[i].val());
00221         // reduction is essential for order on value nodes in dom
00222         // hence introduce test for failed lookup
00223         if (idx == -1)
00224           return ES_FAILED;
00225         count[idx]++;
00226       } else {
00227         single = i;
00228       }
00229     }
00230 
00231     if (isView) {
00232       // before propagation performs inferences on cardinality variables:
00233       if (noa > 0) {
00234         int n  = x.size();
00235         int ks = k.size();
00236 
00237         for (int i = ks; i--; ) {
00238           if (!k[i].assigned()) {
00239             int ub = n - (noa - count[i]);
00240             int lb = count[i];
00241             ModEvent melq = k[i].lq(home, ub);
00242             GECODE_ME_CHECK(melq);
00243             mod |= me_modified(melq) && (k[i].max() != ub);
00244             mod |= shared && me_modified(melq);
00245 
00246             ModEvent megq = k[i].gq(home, lb);
00247             GECODE_ME_CHECK(megq);
00248             mod |= me_modified(megq) && (k[i].min() != lb);
00249             mod |= shared && me_modified(megq);
00250           }
00251         }
00252       }
00253 
00254       if (!card_consistent<View, Card>(smin, smax, x, k))
00255         return ES_FAILED;
00256 
00257       // can only modified cardinality variables
00258       GECODE_ES_CHECK((prop_card<View, Card, shared>(home, x, k, mod)));
00259 
00260       // mimicking linear constraint
00261       int smax = 0;
00262       int smin = 0;
00263       int total_min = 0;
00264       int total_max = 0;
00265       for (int i = k.size(); i--; ) {
00266         smax += k[i].max();
00267         total_min += k[i].card() * k[i].min();
00268         total_max += k[i].card() * k[i].max();
00269       }
00270       int xsmax = x.size() - smax;
00271       int xsmin = x.size() - smin;
00272       smax = 0;
00273       smin = 0;
00274       bool card_ass = true;
00275       for (int i = k.size(); i--; ) {
00276         int lb = xsmax + k[i].max();
00277         int ub = xsmin + k[i].min();
00278         ModEvent me = k[i].gq(home, lb);
00279         GECODE_ME_CHECK(me);
00280         mod |= me_modified(me) && (k[i].min() != lb);
00281         mod |= shared && me_modified(me);
00282         smax += k[i].max();
00283 
00284         me = k[i].lq(home, ub);
00285         GECODE_ME_CHECK(me);
00286         mod |= me_modified(me) && (k[i].max() != ub);
00287         mod |= shared && me_modified(me);
00288         card_ass &= k[i].assigned();
00289       }
00290       if (card_ass) {
00291         if (smax < x.size() || smax > x.size())
00292           return ES_FAILED;
00293 
00294         // redundant linear constraint
00295         for (int i = x.size(); i--; ) {
00296           if (!x[i].assigned()) {
00297             int xmin = xub - x[i].max();
00298             int xgq  = total_max - xmin;
00299 
00300             int xmax = xlb - x[i].min();
00301             int xlq  = total_max - xmax;
00302 
00303             ModEvent me = x[i].gq(home, xgq);
00304             GECODE_ME_CHECK(me);
00305             mod |= me_modified(me) && (x[i].min() != xgq);
00306             mod |= shared && me_modified(me);
00307 
00308             me = x[i].lq(home, xlq);
00309             GECODE_ME_CHECK(me);
00310             mod |= me_modified(me) && (x[i].max() != xlq);
00311             mod |= shared && me_modified(me);
00312           }
00313         }
00314       }
00315     }
00316 
00317     for (int i = k.size(); i--; ) {
00318       count[i] = 0;
00319     }
00320 
00321     all_assigned = true;
00322     noa = 0;
00323     single = 0;
00324 
00325     for (int i = x.size(); i--; ) {
00326       bool b = x[i].assigned();
00327       xlb += x[i].min();
00328       xub += x[i].max();
00329       all_assigned &= b;
00330       if (b) {
00331         noa++;
00332         int idx = lookupValue(k,x[i].val());
00333         // reduction is essential for order on value nodes in dom
00334         // hence introduce test for failed lookup
00335         if (idx == -1)
00336           return ES_FAILED;
00337         count[idx]++;
00338       } else {
00339         single = i;
00340       }
00341     }
00342 
00343     if (all_assigned) {
00344       for (int i = k.size(); i--; ) {
00345         int ci = count[i];
00346         if (! (k[i].min() <= ci && ci <= k[i].max())) {
00347           return ES_FAILED;
00348         } else {
00349           if (isView) {
00350             if (!k[i].assigned()) {
00351               ModEvent me = k[i].eq(home, ci);
00352               GECODE_ME_CHECK(me);
00353               mod |= k[i].assigned();
00354             }        
00355             all_assigned &= k[i].assigned();
00356           }
00357         }
00358       }
00359       if (all_assigned)
00360         return ES_SUBSUMED(this,home);
00361     }
00362 
00363     if (isView) {
00364       // check again for zero entries at first or last position
00365       int m = k.size();
00366       bool locut = k[0].max() == 0;
00367       bool hicut = k[m - 1].max() == 0;
00368 
00369       if (locut) {
00370         int low = k[0].card();
00371         for (int i = 0; i < x.size(); i++) {
00372           ModEvent me = x[i].gr(home, low);
00373           GECODE_ME_CHECK(me);
00374           mod |= me_modified(me) && (x[i].min() != low + 1);
00375           mod |= shared && me_modified(me);
00376         }
00377       }
00378       if (hicut) {
00379         int hi = k[m - 1].card();
00380         for (int i = 0; i < x.size(); i++) {
00381           ModEvent me = x[i].le(home, hi);
00382           GECODE_ME_CHECK(me);
00383           mod |= me_modified(me) && (x[i].max() != hi - 1);
00384           mod |= shared && me_modified(me);
00385         }
00386       }
00387 
00388       if (locut || hicut) {
00389         int cmin = k[0].card();
00390         int cmax = k[m - 1].card();
00391         if (k[0].max() == 0) {
00392           cmin = k[1].card();
00393         }
00394         if (k[m - 1].max() == 0) {
00395           cmax = k[m - 2].card();
00396         }
00397         reduce_card<Card>(cmin, cmax, k);
00398 
00399         if (lps != NULL) {
00400           delete lps;
00401           lps = NULL;
00402           assert(ups != NULL);
00403           delete ups;
00404           ups = NULL;
00405         }
00406       }
00407     }
00408 
00409     ExecStatus es_ubc = ES_FIX;
00410     ExecStatus es_lbc = ES_FIX;
00411     int n = x.size();
00412 
00413     GECODE_AUTOARRAY(int, mu, n);
00414     GECODE_AUTOARRAY(int, nu, n);
00415 
00416     for (int i = n; i--; ) {
00417       nu[i] = i;
00418       mu[i] = i;
00419     }
00420     // Create sorting permutation mu according to the variables upper bounds
00421     MaxInc<View> max_inc(x);
00422     Support::quicksort<int, MaxInc<View> >(mu, n, max_inc);
00423 
00424     // Create sorting permutation nu according to the variables lower bounds
00425     MinInc<View> min_inc(x);
00426     Support::quicksort<int, MinInc<View> >(nu, n, min_inc);
00427 
00428     if (isView) {
00429       // assert guaranteed bounds in the set of all values for variable case
00430       assert(k[0].card() == x[nu[0]].min());
00431     }
00432 
00433     // ensure that only values are considered lying in the variable domain
00434     int cur_minx = x[nu[0]].min();
00435     if (lps == NULL) {
00436       assert (ups == NULL);
00437       lps = new PartialSum<Card>(cur_minx,  k.size(), k, false);
00438       ups = new PartialSum<Card>(cur_minx,  k.size(), k, true);
00439     }
00440 
00441     if (isView) {
00442       // if there has been a change to the cardinality variables
00443       // reconstruction of the partial sum structure is necessary
00444       if (lps->check_update_min(k)) {
00445         delete lps;
00446         lps = new PartialSum<Card>(cur_minx,  k.size(), k, false);
00447       }
00448 
00449       if (ups->check_update_max(k)) {
00450         delete ups;
00451         ups = new PartialSum<Card>(cur_minx,  k.size(), k, true);
00452       }
00453     }
00454 
00455     // already holds by construction
00456     assert(lps->minValue() == ups->minValue());
00457     assert(lps->maxValue() == ups->maxValue());
00458 
00459     bool minima_equal = lps->minValue() == ups->minValue();
00460     bool maxima_equal = lps->maxValue() == ups->maxValue();
00461 
00462     if (!minima_equal || !maxima_equal ) {
00463       delete lps;
00464       lps = new PartialSum<Card>(cur_minx, k.size(), k, false);
00465       delete ups;
00466       ups = new PartialSum<Card>(cur_minx, k.size(), k, true);
00467     }
00468 
00469     // assert that the minimal value of the partial sum structure for
00470     // LBC is consistent with the smallest value a variable can take
00471     assert(lps->minValue() <= x[nu[0]].min());
00472     // assert that the maximal value of the partial sum structure for
00473     // UBC is consistent with the largest value a variable can take
00474     //std::cerr << x[mu[x.size() - 1]].max() <<"<="<< ups->maxValue() << "\n";
00475     //assert(x[mu[x.size() - 1]].max() <= ups->maxValue());
00476 
00477     /*
00478      *  Setup rank and bounds info
00479      *  Since this implementation is based on the theory of Hall Intervals
00480      *  additional datastructures are needed in order to represent these
00481      *  intervals and the "partial-sum" data structure (cf."gcc/gccbndsup.icc")
00482      *
00483      */
00484 
00485     GECODE_AUTOARRAY(HallInfo, hall, (2 * n + 2));
00486     GECODE_AUTOARRAY(Rank,     rank, n);
00487 
00488     int nb = 0;
00489     // setup bounds and rank
00490     int min        = x[nu[0]].min();
00491     int max        = x[mu[0]].max() + 1;
00492     int last       = lps->firstValue + 1; //equivalent to last = min -2
00493     hall[0].bounds = last;
00494 
00495     /*
00496      * First the algorithm merges the arrays minsorted and maxsorted
00497      * into bounds i.e. hall[].bounds contains the ordered union
00498      * of the lower and upper domain bounds including two sentinels
00499      * at the beginning and at the end of the set
00500      * ( the upper variable bounds in this union are increased by 1 )
00501      */
00502 
00503     {
00504       int i = 0;
00505       int j = 0;
00506       while (true) {
00507         if (i < n && min < max) {
00508           if (min != last) {
00509             last = min;
00510             hall[++nb].bounds = last;
00511           }
00512           rank[nu[i]].min = nb;
00513           if (++i < n) {
00514             min = x[nu[i]].min();
00515           }
00516         } else {
00517           if (max != last) {
00518             last = max;
00519             hall[++nb].bounds = last;
00520           }
00521           rank[mu[j]].max = nb;
00522           if (++j == n) {
00523             break;
00524           }
00525           max = x[mu[j]].max() + 1;
00526         }
00527       }
00528     }
00529 
00530     int rightmost = nb + 1; // rightmost accesible value in bounds
00531     hall[rightmost].bounds = ups->lastValue + 1 ;
00532 
00533     skip_lbc = true;
00534     for (int i = k.size(); i--; ) {
00535       skip_lbc &= (k[i].min() == 0);
00536     }
00537 
00538     if (!card_fixed && !skip_lbc) {
00539       es_lbc = lbc<View, Card, shared>(home, x, nb, hall, rank,lps, mu, nu);
00540       GECODE_ES_CHECK(es_lbc);
00541       mod |= (es_lbc == ES_NOFIX);
00542     }
00543 
00544     es_ubc = ubc<View, Card, shared>(home, x, nb, hall, rank, ups, mu, nu);
00545     GECODE_ES_CHECK(es_ubc);
00546     mod |= (es_ubc == ES_NOFIX);
00547 
00548     if (isView) {
00549       GECODE_ES_CHECK((prop_card<View, Card, shared>(home, x, k, mod)));
00550     }
00551 
00552     all_assigned = true;
00553     noa = 0;
00554     single = 0;
00555     for (int i = k.size(); i--; ) {
00556       count[i] = 0;
00557     }
00558 
00559     for (int i = x.size(); i--; ) {
00560       bool b = x[i].assigned();
00561       all_assigned &= b;
00562       if (b) {
00563         noa++;
00564         int idx = lookupValue(k,x[i].val());
00565         count[idx]++;
00566       } else {
00567         single = i;
00568       }
00569     }
00570 
00571     if (all_assigned) {
00572       for (int i = k.size(); i--; ) {
00573         int ci = count[i];
00574         if (! (k[i].min() <= ci && ci <= k[i].max())) {
00575           return ES_FAILED;
00576         } else {
00577           if (isView) {
00578             if (!k[i].assigned()) {
00579               ModEvent me = k[i].eq(home, ci);
00580               GECODE_ME_CHECK(me);
00581               mod |= k[i].assigned();
00582             }
00583             all_assigned &= k[i].assigned();
00584           }
00585         }
00586       }
00587       if (all_assigned)
00588         return ES_SUBSUMED(this,home);
00589     }
00590 
00591     return mod ? ES_NOFIX : ES_FIX;
00592   }
00593 
00602   template <class View1, class View2>
00603   class SharingTest {
00604   public:
00609     static bool shared(Space* home, ViewArray<View1>& x0,
00610                        ViewArray<View2>& k0) {
00611       ViewArray<View1> xc(home, x0.size()+k0.size());
00612       for (int i = 0; i < x0.size(); i++) {
00613         xc[i] = x0[i];
00614       }
00615       for (int i = x0.size(); i < x0.size()+k0.size(); i++) {
00616         xc[i] = k0[i - x0.size()].intview();
00617       }
00618       return xc.shared();
00619     }
00620   };
00621 
00626   template <>
00627   class SharingTest<IntView,OccurBndsView> {
00628   public:
00630     static bool shared(Space*,
00631                        ViewArray<IntView>& xs, ViewArray<OccurBndsView>&) {
00632       return xs.shared();
00633     }
00634   };
00635 
00636   template <class View, class Card, bool isView>
00637   ExecStatus
00638   Bnd<View, Card, isView>::post(Space* home,
00639                                 ViewArray<View>& x0,
00640                                 ViewArray<Card>& k0) {
00641     bool cardfix = true;
00642     bool nolbc = true;
00643     for (int i = k0.size(); i--; ) {
00644       cardfix &= k0[i].assigned();
00645       nolbc &= (k0[i].min() == 0);
00646     }
00647     if (SharingTest<View,Card>::shared(home,x0,k0)) {
00648       new (home) BndImp<View, Card, isView, true>
00649         (home, x0, k0, cardfix, nolbc);
00650     } else {
00651       new (home) BndImp<View, Card, isView, false>
00652         (home, x0, k0, cardfix, nolbc);
00653     }
00654     return ES_OK;
00655   }
00656 
00657 }}}
00658 
00659 // STATISTICS: int-prop
00660