Generated on Wed Nov 1 15:04:34 2006 for Gecode by doxygen 1.4.5

ubc.icc

Go to the documentation of this file.
00001 /*
00002  *  Main authors:
00003  *     Patrick Pekczynski <pekczynski@ps.uni-sb.de>
00004  *
00005  *  Copyright:
00006  *     Patrick Pekczynski, 2004
00007  *
00008  *  Last modified:
00009  *     $Date: 2006-08-04 16:03:26 +0200 (Fri, 04 Aug 2006) $ by $Author: schulte $
00010  *     $Revision: 3512 $
00011  *
00012  *  This file is part of Gecode, the generic constraint
00013  *  development environment:
00014  *     http://www.gecode.org
00015  *
00016  *  See the file "LICENSE" for information on usage and
00017  *  redistribution of this file, and for a
00018  *     DISCLAIMER OF ALL WARRANTIES.
00019  *
00020  */
00021 namespace Gecode { namespace Int { namespace GCC {
00022 
00044   template <class View, class Card, bool shared>
00045   inline ExecStatus
00046   ubc(Space* home, ViewArray<View>& x, int& nb,
00047       HallInfo hall[], Rank rank[],
00048       PartialSum<Card>* ups,
00049       int mu[], int nu[]){
00050     ExecStatus es = ES_FIX;
00051 
00052     int rightmost = nb + 1; // rightmost accesible value in bounds
00053     int bsize     = nb + 2; // number of unique bounds including sentinels
00054 
00055     //Narrow lower bounds (UBC)
00056 
00057     /*
00058      * Initializing tree structure with the values from bounds
00059      * and the interval capacities of neighboured values
00060      * from left to right
00061      */
00062 
00063 
00064     hall[0].h = 0;
00065     hall[0].t = 0;
00066     hall[0].d = 0;
00067 
00068     for (int i = 1; i < bsize; i++) {
00069       int pred  = i - 1;
00070       hall[i].h = pred;
00071       hall[i].t = pred;
00072       hall[i].d = ups->sumup(hall[pred].bounds, hall[i].bounds - 1);
00073     }
00074 
00075     int n          = x.size();
00076 
00077     for (int i = 0; i < n; i++) {
00078 
00079       // visit intervals in increasing max order
00080       int x0   = rank[mu[i]].min;
00081       int succ = x0 + 1;
00082       int y    = rank[mu[i]].max;
00083       int z    = pathmax_t(hall, succ);
00084       int j    = hall[z].t;
00085 
00086       /* DOMINATION:
00087        *     v^i_j denotes
00088        *     unused values in the current interval. If the difference d
00089        *     between to critical capacities v^i_j and v^i_z
00090        *     is equal to zero, j dominates z
00091        *
00092        *     i.e. [hall[l].bounds, hall[nb+1].bounds] is not left-maximal and
00093        *     [hall[j].bounds, hall[l].bounds] is a Hall set iff
00094        *     [hall[j].bounds, hall[l].bounds] processing a variable x_i uses up a value in the interval
00095        *     [hall[z].bounds,hall[z+1].bounds] according to the intervals
00096        *     capacity. Therefore, if d = 0
00097        *     the considered value has already been used by processed variables
00098        *     m-times, where m = u[i] for value v_i. Since this value must not
00099        *     be reconsidered the path can be compressed
00100        */
00101       if (--hall[z].d == 0){
00102         hall[z].t = z + 1;
00103         z         = pathmax_t(hall, hall[z].t);
00104         if (z >= bsize) {
00105           z--;
00106         }
00107         hall[z].t = j;
00108       }
00109       pathset_t(hall, succ, z, z); // path compression
00110       /* NEGATIVE CAPACITY:
00111        *     A negative capacity results in a failure.Since a
00112        *     negative capacity signals that the number of variables
00113        *     whose domain is contained in the set S is larger than
00114        *     the maximum capacity of S => UBC is not satisfiable,
00115        *     i.e. there are more variables than values to instantiate them
00116        */
00117 
00118       if (hall[z].d < ups->sumup(hall[y].bounds, hall[z].bounds - 1)){
00119         return ES_FAILED;
00120       }
00121 
00122       /* UPDATING LOWER BOUND:
00123        *   If the lower bound min_i lies inside a Hall interval [a,b]
00124        *   i.e. a <= min_i <=b <= max_i
00125        *   min_i is set to  min_i := b+1
00126        */
00127       if (hall[x0].h > x0) {
00128         int w       = pathmax_h(hall, hall[x0].h);
00129         int m       = hall[w].bounds;
00130 
00131         ModEvent me = x[mu[i]].gq(home, m);
00132         if (me_failed(me)) {
00133           return ES_FAILED;
00134         }
00135         if (me_modified(me) && (m != x[mu[i]].min())) {
00136           es = ES_NOFIX;
00137         }
00138         if (shared && me_modified(me)) {
00139           es = ES_NOFIX;
00140         }
00141         pathset_h(hall, x0, w, w); // path compression
00142       }
00143 
00144       /* ZEROTEST:
00145        *     (using the difference between capacity pointers)
00146        *     zero capacity => the difference between critical capacity
00147        *     pointers is equal to the maximum capacity of the interval,i.e.
00148        *     the number of variables whose domain is contained in the
00149        *     interval is equal to the sum over all u[i] for a value v_i that
00150        *     lies in the Hall-Intervall which can also be thought of as a
00151        *     Hall-Set
00152        *
00153        *    ZeroTestLemma: Let k and l be succesive critical indices.
00154        *          v^i_k=0  =>  v^i_k = max_i+1-l+d
00155        *                   <=> v^i_k = y + 1 - z + d
00156        *                   <=> d = z-1-y
00157        *    if this equation holds the interval [j,z-1] is a hall intervall
00158        */
00159 
00160       if (hall[z].d == ups->sumup(hall[y].bounds, hall[z].bounds - 1)) {
00161         /*
00162          *mark hall interval [j,z-1]
00163          * hall pointers form a path to the upper bound of the interval
00164          */
00165         int predj = j - 1;
00166         pathset_h(hall, hall[y].h, predj, y);
00167         hall[y].h = predj;
00168       }
00169     }
00170 
00171     /* Narrow upper bounds (UBC)
00172      * symmetric to the narrowing of the lower bounds
00173      */
00174     for (int i = 0; i < rightmost; i++) {
00175       int succ  = i + 1;
00176       hall[i].h = succ;
00177       hall[i].t = succ;
00178       hall[i].d = ups->sumup(hall[i].bounds, hall[succ].bounds - 1);
00179     }
00180 
00181     for (int i = n; i--; ) {
00182       // visit intervals in decreasing min order
00183       int x0   = rank[nu[i]].max;
00184       int pred = x0 - 1;
00185       int y    = rank[nu[i]].min;
00186       int z    = pathmin_t(hall, pred);
00187       int j    = hall[z].t;
00188 
00189       // DOMINATION:
00190       if (--hall[z].d == 0){
00191         hall[z].t = z - 1;
00192         z         = pathmin_t(hall, hall[z].t);
00193         hall[z].t = j;
00194       }
00195       pathset_t(hall, pred, z, z);
00196 
00197       // NEGATIVE CAPACITY:
00198       if (hall[z].d < ups->sumup(hall[z].bounds,hall[y].bounds-1)){
00199         return ES_FAILED;
00200       }
00201 
00202       /* UPDATING UPPER BOUND:
00203        *   If the upper bound max_i lies inside a Hall interval [a,b]
00204        *   i.e. min_i <= a <= max_i < b
00205        *   max_i is set to  max_i := a-1
00206        */
00207       if (hall[x0].h < x0) {
00208         int w       = pathmin_h(hall, hall[x0].h);
00209         int m       = hall[w].bounds - 1;
00210         ModEvent me = x[nu[i]].lq(home, m);
00211         if (me_failed(me)) {
00212           return ES_FAILED;
00213         }
00214         if (me_modified(me) && (m != x[nu[i]].max())) {
00215           es = ES_NOFIX;
00216         }
00217         if (me_modified(me) && shared) {
00218           es = ES_NOFIX;
00219         }
00220         pathset_h(hall, x0, w, w);
00221       }
00222       // ZEROTEST
00223       if (hall[z].d == ups->sumup(hall[z].bounds, hall[y].bounds - 1)) {
00224         //mark hall interval [y,j]
00225         int succj = j + 1;
00226         pathset_h(hall, hall[y].h, succj, y);
00227         hall[y].h = succj;
00228       }
00229     }
00230     return es;
00231   }
00232 
00233 }}}
00234 
00235 // STATISTICS: int-prop
00236