Generated on Sat Feb 7 2015 02:01:22 for Gecode by doxygen 1.8.9.1
bnd.hpp
Go to the documentation of this file.
1 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2 /*
3  * Main authors:
4  * Patrick Pekczynski <pekczynski@ps.uni-sb.de>
5  *
6  * Contributing authors:
7  * Christian Schulte <schulte@gecode.org>
8  * Guido Tack <tack@gecode.org>
9  *
10  * Copyright:
11  * Patrick Pekczynski, 2004/2005
12  * Christian Schulte, 2009
13  * Guido Tack, 2009
14  *
15  * Last modified:
16  * $Date: 2012-09-07 17:31:22 +0200 (Fri, 07 Sep 2012) $ by $Author: schulte $
17  * $Revision: 13068 $
18  *
19  * This file is part of Gecode, the generic constraint
20  * development environment:
21  * http://www.gecode.org
22  *
23  * Permission is hereby granted, free of charge, to any person obtaining
24  * a copy of this software and associated documentation files (the
25  * "Software"), to deal in the Software without restriction, including
26  * without limitation the rights to use, copy, modify, merge, publish,
27  * distribute, sublicense, and/or sell copies of the Software, and to
28  * permit persons to whom the Software is furnished to do so, subject to
29  * the following conditions:
30  *
31  * The above copyright notice and this permission notice shall be
32  * included in all copies or substantial portions of the Software.
33  *
34  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
35  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
36  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
37  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
38  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
39  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
40  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41  *
42  */
43 
44 namespace Gecode { namespace Int { namespace GCC {
45 
46  template<class Card>
50  bool cf, bool nolbc) :
51  Propagator(home), x(x0), y(home, x0), k(k0),
52  card_fixed(cf), skip_lbc(nolbc) {
53  y.subscribe(home, *this, PC_INT_BND);
54  k.subscribe(home, *this, PC_INT_BND);
55  }
56 
57  template<class Card>
60  Bnd(Space& home, bool share, Bnd<Card>& p)
61  : Propagator(home, share, p),
62  card_fixed(p.card_fixed), skip_lbc(p.skip_lbc) {
63  x.update(home, share, p.x);
64  y.update(home, share, p.y);
65  k.update(home, share, p.k);
66  }
67 
68  template<class Card>
69  forceinline size_t
71  y.cancel(home,*this, PC_INT_BND);
72  k.cancel(home,*this, PC_INT_BND);
73  (void) Propagator::dispose(home);
74  return sizeof(*this);
75  }
76 
77  template<class Card>
78  Actor*
79  Bnd<Card>::copy(Space& home, bool share) {
80  return new (home) Bnd<Card>(home,share,*this);
81  }
82 
83  template<class Card>
84  PropCost
86  const ModEventDelta& med) const {
87  int n_k = Card::propagate ? k.size() : 0;
88  if (IntView::me(med) == ME_INT_VAL)
89  return PropCost::linear(PropCost::LO, y.size() + n_k);
90  else
91  return PropCost::quadratic(PropCost::LO, x.size() + n_k);
92  }
93 
94 
95  template<class Card>
97  Bnd<Card>::lbc(Space& home, int& nb,
98  HallInfo hall[], Rank rank[], int mu[], int nu[]) {
99  int n = x.size();
100 
101  /*
102  * Let I(S) denote the number of variables whose domain intersects
103  * the set S and C(S) the number of variables whose domain is containded
104  * in S. Let further min_cap(S) be the minimal number of variables
105  * that must be assigned to values, that is
106  * min_cap(S) is the sum over all l[i] for a value v_i that is an
107  * element of S.
108  *
109  * A failure set is a set F if
110  * I(F) < min_cap(F)
111  * An unstable set is a set U if
112  * I(U) = min_cap(U)
113  * A stable set is a set S if
114  * C(S) > min_cap(S) and S intersetcs nor
115  * any failure set nor any unstable set
116  * forall unstable and failure sets
117  *
118  * failure sets determine the satisfiability of the LBC
119  * unstable sets have to be pruned
120  * stable set do not have to be pruned
121  *
122  * hall[].ps ~ stores the unstable
123  * sets that have to be pruned
124  * hall[].s ~ stores sets that must not be pruned
125  * hall[].h ~ contains stable and unstable sets
126  * hall[].d ~ contains the difference between interval bounds, i.e.
127  * the minimal capacity of the interval
128  * hall[].t ~ contains the critical capacity pointer, pointing to the
129  * values
130  */
131 
132  // LBC lower bounds
133 
134  int i = 0;
135  int j = 0;
136  int w = 0;
137  int z = 0;
138  int v = 0;
139 
140  //initialization of the tree structure
141  int rightmost = nb + 1; // rightmost accesible value in bounds
142  int bsize = nb + 2;
143  w = rightmost;
144 
145  // test
146  // unused but uninitialized
147  hall[0].d = 0;
148  hall[0].s = 0;
149  hall[0].ps = 0;
150 
151  for (i = bsize; --i; ) { // i must not be zero
152  int pred = i - 1;
153  hall[i].s = pred;
154  hall[i].ps = pred;
155  hall[i].d = lps.sumup(hall[pred].bounds, hall[i].bounds - 1);
156 
157  /* Let [hall[i].bounds,hall[i-1].bounds]=:I
158  * If the capacity is zero => min_cap(I) = 0
159  * => I cannot be a failure set
160  * => I is an unstable set
161  */
162  if (hall[i].d == 0) {
163  hall[pred].h = w;
164  } else {
165  hall[w].h = pred;
166  w = pred;
167  }
168  }
169 
170  w = rightmost;
171  for (i = bsize; i--; ) { // i can be zero
172  hall[i].t = i - 1;
173  if (hall[i].d == 0) {
174  hall[i].t = w;
175  } else {
176  hall[w].t = i;
177  w = i;
178  }
179  }
180 
181  /*
182  * The algorithm assigns to each value v in bounds
183  * empty buckets corresponding to the minimal capacity l[i] to be
184  * filled for v. (the buckets correspond to hall[].d containing the
185  * difference between the interval bounds) Processing it
186  * searches for the smallest value v in dom(x_i) that has an
187  * empty bucket, i.e. if all buckets are filled it is guaranteed
188  * that there are at least l[i] variables that will be
189  * instantiated to v. Since the buckets are initially empty,
190  * they are considered as FAILURE SETS
191  */
192 
193  for (i = 0; i < n; i++) {
194  // visit intervals in increasing max order
195  int x0 = rank[mu[i]].min;
196  int y = rank[mu[i]].max;
197  int succ = x0 + 1;
198  z = pathmax_t(hall, succ);
199  j = hall[z].t;
200 
201  /*
202  * POTENTIALLY STABLE SET:
203  * z \neq succ \Leftrigharrow z>succ, i.e.
204  * min(D_{\mu(i)}) is guaranteed to occur min(K_i) times
205  * \Rightarrow [x0, min(y,z)] is potentially stable
206  */
207 
208  if (z != succ) {
209  w = pathmax_ps(hall, succ);
210  v = hall[w].ps;
211  pathset_ps(hall, succ, w, w);
212  w = std::min(y, z);
213  pathset_ps(hall, hall[w].ps, v, w);
214  hall[w].ps = v;
215  }
216 
217  /*
218  * STABLE SET:
219  * being stable implies being potentially stable, i.e.
220  * [hall[y].ps, hall[y].bounds-1] is the largest stable subset of
221  * [hall[j].bounds, hall[y].bounds-1].
222  */
223 
224  if (hall[z].d <= lps.sumup(hall[y].bounds, hall[z].bounds - 1)) {
225  w = pathmax_s(hall, hall[y].ps);
226  pathset_s(hall, hall[y].ps, w, w);
227  // Path compression
228  v = hall[w].s;
229  pathset_s(hall, hall[y].s, v, y);
230  hall[y].s = v;
231  } else {
232  /*
233  * FAILURE SET:
234  * If the considered interval [x0,y] is neither POTENTIALLY STABLE
235  * nor STABLE there are still buckets that can be filled,
236  * therefore d can be decreased. If d equals zero the intervals
237  * minimum capacity is met and thepath can be compressed to the
238  * next value having an empty bucket.
239  * see DOMINATION in "ubc"
240  */
241  if (--hall[z].d == 0) {
242  hall[z].t = z + 1;
243  z = pathmax_t(hall, hall[z].t);
244  hall[z].t = j;
245  }
246 
247  /*
248  * FINDING NEW LOWER BOUND:
249  * If the lower bound belongs to an unstable or a stable set,
250  * remind the new value we might assigned to the lower bound
251  * in case the variable doesn't belong to a stable set.
252  */
253  if (hall[x0].h > x0) {
254  hall[i].newBound = pathmax_h(hall, x0);
255  w = hall[i].newBound;
256  pathset_h(hall, x0, w, w); // path compression
257  } else {
258  // Do not shrink the variable: take old min as new min
259  hall[i].newBound = x0;
260  }
261 
262  /* UNSTABLE SET
263  * If an unstable set is discovered
264  * the difference between the interval bounds is equal to the
265  * number of variables whose domain intersect the interval
266  * (see ZEROTEST in "gcc")
267  */
268  // CLEARLY THIS WAS NOT STABLE == UNSTABLE
269  if (hall[z].d == lps.sumup(hall[y].bounds, hall[z].bounds - 1)) {
270  if (hall[y].h > y)
271  /*
272  * y is not the end of the potentially stable set
273  * thus ensure that the potentially stable superset is marked
274  */
275  y = hall[y].h;
276  // Equivalent to pathmax since the path is fully compressed
277  pathset_h(hall, hall[y].h, j-1, y);
278  // mark the new unstable set [j,y]
279  hall[y].h = j-1;
280  }
281  }
282  pathset_t(hall, succ, z, z); // path compression
283  }
284 
285  /* If there is a FAILURE SET left the minimum occurences of the values
286  * are not guaranteed. In order to satisfy the LBC the last value
287  * in the stable and unstable datastructure hall[].h must point to
288  * the sentinel at the beginning of bounds.
289  */
290  if (hall[nb].h != 0)
291  return ES_FAILED;
292 
293  // Perform path compression over all elements in
294  // the stable interval data structure. This data
295  // structure will no longer be modified and will be
296  // accessed n or 2n times. Therefore, we can afford
297  // a linear time compression.
298  for (i = bsize; --i;)
299  if (hall[i].s > i)
300  hall[i].s = w;
301  else
302  w = i;
303 
304  /*
305  * UPDATING LOWER BOUND:
306  * For all variables that are not a subset of a stable set,
307  * shrink the lower bound, i.e. forall stable sets S we have:
308  * x0 < S_min <= y <=S_max or S_min <= x0 <= S_max < y
309  * that is [x0,y] is NOT a proper subset of any stable set S
310  */
311  for (i = n; i--; ) {
312  int x0 = rank[mu[i]].min;
313  int y = rank[mu[i]].max;
314  // update only those variables that are not contained in a stable set
315  if ((hall[x0].s <= x0) || (y > hall[x0].s)) {
316  // still have to check this out, how skipping works (consider dominated indices)
317  int m = lps.skipNonNullElementsRight(hall[hall[i].newBound].bounds);
318  GECODE_ME_CHECK(x[mu[i]].gq(home, m));
319  }
320  }
321 
322  // LBC narrow upper bounds
323  w = 0;
324  for (i = 0; i <= nb; i++) {
325  hall[i].d = lps.sumup(hall[i].bounds, hall[i + 1].bounds - 1);
326  if (hall[i].d == 0) {
327  hall[i].t = w;
328  } else {
329  hall[w].t = i;
330  w = i;
331  }
332  }
333  hall[w].t = i;
334 
335  w = 0;
336  for (i = 1; i <= nb; i++)
337  if (hall[i - 1].d == 0) {
338  hall[i].h = w;
339  } else {
340  hall[w].h = i;
341  w = i;
342  }
343  hall[w].h = i;
344 
345  for (i = n; i--; ) {
346  // visit intervals in decreasing min order
347  // i.e. minsorted from right to left
348  int x0 = rank[nu[i]].max;
349  int y = rank[nu[i]].min;
350  int pred = x0 - 1; // predecessor of x0 in the indices
351  z = pathmin_t(hall, pred);
352  j = hall[z].t;
353 
354  /* If the variable is not in a discovered stable set
355  * (see above condition for STABLE SET)
356  */
357  if (hall[z].d > lps.sumup(hall[z].bounds, hall[y].bounds - 1)) {
358  // FAILURE SET
359  if (--hall[z].d == 0) {
360  hall[z].t = z - 1;
361  z = pathmin_t(hall, hall[z].t);
362  hall[z].t = j;
363  }
364  // FINDING NEW UPPER BOUND
365  if (hall[x0].h < x0) {
366  w = pathmin_h(hall, hall[x0].h);
367  hall[i].newBound = w;
368  pathset_h(hall, x0, w, w); // path compression
369  } else {
370  hall[i].newBound = x0;
371  }
372  // UNSTABLE SET
373  if (hall[z].d == lps.sumup(hall[z].bounds, hall[y].bounds - 1)) {
374  if (hall[y].h < y) {
375  y = hall[y].h;
376  }
377  int succj = j + 1;
378  // mark new unstable set [y,j]
379  pathset_h(hall, hall[y].h, succj, y);
380  hall[y].h = succj;
381  }
382  }
383  pathset_t(hall, pred, z, z);
384  }
385 
386  // UPDATING UPPER BOUND
387  for (i = n; i--; ) {
388  int x0 = rank[nu[i]].min;
389  int y = rank[nu[i]].max;
390  if ((hall[x0].s <= x0) || (y > hall[x0].s)) {
391  int m = lps.skipNonNullElementsLeft(hall[hall[i].newBound].bounds - 1);
392  GECODE_ME_CHECK(x[nu[i]].lq(home, m));
393  }
394  }
395  return ES_OK;
396  }
397 
398 
399  template<class Card>
401  Bnd<Card>::ubc(Space& home, int& nb,
402  HallInfo hall[], Rank rank[], int mu[], int nu[]) {
403  int rightmost = nb + 1; // rightmost accesible value in bounds
404  int bsize = nb + 2; // number of unique bounds including sentinels
405 
406  //Narrow lower bounds (UBC)
407 
408  /*
409  * Initializing tree structure with the values from bounds
410  * and the interval capacities of neighboured values
411  * from left to right
412  */
413 
414 
415  hall[0].h = 0;
416  hall[0].t = 0;
417  hall[0].d = 0;
418 
419  for (int i = bsize; --i; ) {
420  hall[i].h = hall[i].t = i-1;
421  hall[i].d = ups.sumup(hall[i-1].bounds, hall[i].bounds - 1);
422  }
423 
424  int n = x.size();
425 
426  for (int i = 0; i < n; i++) {
427  // visit intervals in increasing max order
428  int x0 = rank[mu[i]].min;
429  int succ = x0 + 1;
430  int y = rank[mu[i]].max;
431  int z = pathmax_t(hall, succ);
432  int j = hall[z].t;
433 
434  /* DOMINATION:
435  * v^i_j denotes
436  * unused values in the current interval. If the difference d
437  * between to critical capacities v^i_j and v^i_z
438  * is equal to zero, j dominates z
439  *
440  * i.e. [hall[l].bounds, hall[nb+1].bounds] is not left-maximal and
441  * [hall[j].bounds, hall[l].bounds] is a Hall set iff
442  * [hall[j].bounds, hall[l].bounds] processing a variable x_i uses up a value in the interval
443  * [hall[z].bounds,hall[z+1].bounds] according to the intervals
444  * capacity. Therefore, if d = 0
445  * the considered value has already been used by processed variables
446  * m-times, where m = u[i] for value v_i. Since this value must not
447  * be reconsidered the path can be compressed
448  */
449  if (--hall[z].d == 0) {
450  hall[z].t = z + 1;
451  z = pathmax_t(hall, hall[z].t);
452  if (z >= bsize)
453  z--;
454  hall[z].t = j;
455  }
456  pathset_t(hall, succ, z, z); // path compression
457 
458  /* NEGATIVE CAPACITY:
459  * A negative capacity results in a failure.Since a
460  * negative capacity signals that the number of variables
461  * whose domain is contained in the set S is larger than
462  * the maximum capacity of S => UBC is not satisfiable,
463  * i.e. there are more variables than values to instantiate them
464  */
465  if (hall[z].d < ups.sumup(hall[y].bounds, hall[z].bounds - 1))
466  return ES_FAILED;
467 
468  /* UPDATING LOWER BOUND:
469  * If the lower bound min_i lies inside a Hall interval [a,b]
470  * i.e. a <= min_i <=b <= max_i
471  * min_i is set to min_i := b+1
472  */
473  if (hall[x0].h > x0) {
474  int w = pathmax_h(hall, hall[x0].h);
475  int m = hall[w].bounds;
476  GECODE_ME_CHECK(x[mu[i]].gq(home, m));
477  pathset_h(hall, x0, w, w); // path compression
478  }
479 
480  /* ZEROTEST:
481  * (using the difference between capacity pointers)
482  * zero capacity => the difference between critical capacity
483  * pointers is equal to the maximum capacity of the interval,i.e.
484  * the number of variables whose domain is contained in the
485  * interval is equal to the sum over all u[i] for a value v_i that
486  * lies in the Hall-Intervall which can also be thought of as a
487  * Hall-Set
488  *
489  * ZeroTestLemma: Let k and l be succesive critical indices.
490  * v^i_k=0 => v^i_k = max_i+1-l+d
491  * <=> v^i_k = y + 1 - z + d
492  * <=> d = z-1-y
493  * if this equation holds the interval [j,z-1] is a hall intervall
494  */
495 
496  if (hall[z].d == ups.sumup(hall[y].bounds, hall[z].bounds - 1)) {
497  /*
498  *mark hall interval [j,z-1]
499  * hall pointers form a path to the upper bound of the interval
500  */
501  int predj = j - 1;
502  pathset_h(hall, hall[y].h, predj, y);
503  hall[y].h = predj;
504  }
505  }
506 
507  /* Narrow upper bounds (UBC)
508  * symmetric to the narrowing of the lower bounds
509  */
510  for (int i = 0; i < rightmost; i++) {
511  hall[i].h = hall[i].t = i+1;
512  hall[i].d = ups.sumup(hall[i].bounds, hall[i+1].bounds - 1);
513  }
514 
515  for (int i = n; i--; ) {
516  // visit intervals in decreasing min order
517  int x0 = rank[nu[i]].max;
518  int pred = x0 - 1;
519  int y = rank[nu[i]].min;
520  int z = pathmin_t(hall, pred);
521  int j = hall[z].t;
522 
523  // DOMINATION:
524  if (--hall[z].d == 0) {
525  hall[z].t = z - 1;
526  z = pathmin_t(hall, hall[z].t);
527  hall[z].t = j;
528  }
529  pathset_t(hall, pred, z, z);
530 
531  // NEGATIVE CAPACITY:
532  if (hall[z].d < ups.sumup(hall[z].bounds,hall[y].bounds-1))
533  return ES_FAILED;
534 
535  /* UPDATING UPPER BOUND:
536  * If the upper bound max_i lies inside a Hall interval [a,b]
537  * i.e. min_i <= a <= max_i < b
538  * max_i is set to max_i := a-1
539  */
540  if (hall[x0].h < x0) {
541  int w = pathmin_h(hall, hall[x0].h);
542  int m = hall[w].bounds - 1;
543  GECODE_ME_CHECK(x[nu[i]].lq(home, m));
544  pathset_h(hall, x0, w, w);
545  }
546 
547  // ZEROTEST
548  if (hall[z].d == ups.sumup(hall[z].bounds, hall[y].bounds - 1)) {
549  //mark hall interval [y,j]
550  pathset_h(hall, hall[y].h, j+1, y);
551  hall[y].h = j+1;
552  }
553  }
554  return ES_OK;
555  }
556 
557  template<class Card>
558  ExecStatus
560  // Remove all values with 0 max occurrence
561  // and remove corresponding occurrence variables from k
562 
563  // The number of zeroes
564  int n_z = 0;
565  for (int i=k.size(); i--;)
566  if (k[i].max() == 0)
567  n_z++;
568 
569  if (n_z > 0) {
570  Region r(home);
571  int* z = r.alloc<int>(n_z);
572  n_z = 0;
573  int n_k = 0;
574  for (int i=0; i<k.size(); i++)
575  if (k[i].max() == 0) {
576  z[n_z++] = k[i].card();
577  } else {
578  k[n_k++] = k[i];
579  }
580  k.size(n_k);
581  Support::quicksort(z,n_z);
582  for (int i=x.size(); i--;) {
583  Iter::Values::Array zi(z,n_z);
584  GECODE_ME_CHECK(x[i].minus_v(home,zi,false));
585  }
586  lps.reinit(); ups.reinit();
587  }
588  return ES_OK;
589  }
590 
591  template<class Card>
592  ExecStatus
594  if (IntView::me(med) == ME_INT_VAL) {
595  GECODE_ES_CHECK(prop_val<Card>(home,*this,y,k));
596  return home.ES_NOFIX_PARTIAL(*this,IntView::med(ME_INT_BND));
597  }
598 
599  if (Card::propagate)
600  GECODE_ES_CHECK(pruneCards(home));
601 
602  Region r(home);
603  int* count = r.alloc<int>(k.size());
604 
605  for (int i = k.size(); i--; )
606  count[i] = 0;
607  bool all_assigned = true;
608  int noa = 0;
609  for (int i = x.size(); i--; ) {
610  if (x[i].assigned()) {
611  noa++;
612  int idx;
613  // reduction is essential for order on value nodes in dom
614  // hence introduce test for failed lookup
615  if (!lookupValue(k,x[i].val(),idx))
616  return ES_FAILED;
617  count[idx]++;
618  } else {
619  all_assigned = false;
620  // We only need the counts in the view case or when all
621  // x are assigned
622  if (!Card::propagate)
623  break;
624  }
625  }
626 
627  if (Card::propagate) {
628  // before propagation performs inferences on cardinality variables:
629  if (noa > 0)
630  for (int i = k.size(); i--; )
631  if (!k[i].assigned()) {
632  GECODE_ME_CHECK(k[i].lq(home, x.size() - (noa - count[i])));
633  GECODE_ME_CHECK(k[i].gq(home, count[i]));
634  }
635 
636  if (!card_consistent<Card>(x, k))
637  return ES_FAILED;
638 
639  GECODE_ES_CHECK(prop_card<Card>(home, x, k));
640 
641  // Cardinalities may have been modified, so recompute
642  // count and all_assigned
643  for (int i = k.size(); i--; )
644  count[i] = 0;
645  all_assigned = true;
646  for (int i = x.size(); i--; ) {
647  if (x[i].assigned()) {
648  int idx;
649  // reduction is essential for order on value nodes in dom
650  // hence introduce test for failed lookup
651  if (!lookupValue(k,x[i].val(),idx))
652  return ES_FAILED;
653  count[idx]++;
654  } else {
655  // We won't need the remaining counts, they're only used when
656  // all x are assigned
657  all_assigned = false;
658  break;
659  }
660  }
661  }
662 
663  if (all_assigned) {
664  for (int i = k.size(); i--; )
665  GECODE_ME_CHECK(k[i].eq(home, count[i]));
666  return home.ES_SUBSUMED(*this);
667  }
668 
669  if (Card::propagate)
670  GECODE_ES_CHECK(pruneCards(home));
671 
672  int n = x.size();
673 
674  int* mu = r.alloc<int>(n);
675  int* nu = r.alloc<int>(n);
676 
677  for (int i = n; i--; )
678  nu[i] = mu[i] = i;
679 
680  // Create sorting permutation mu according to the variables upper bounds
681  MaxInc<IntView> max_inc(x);
682  Support::quicksort<int, MaxInc<IntView> >(mu, n, max_inc);
683 
684  // Create sorting permutation nu according to the variables lower bounds
685  MinInc<IntView> min_inc(x);
686  Support::quicksort<int, MinInc<IntView> >(nu, n, min_inc);
687 
688  // Sort the cardinality bounds by index
689  MinIdx<Card> min_idx;
690  Support::quicksort<Card, MinIdx<Card> >(&k[0], k.size(), min_idx);
691 
692  if (!lps.initialized()) {
693  assert (!ups.initialized());
694  lps.init(home, k, false);
695  ups.init(home, k, true);
696  } else if (Card::propagate) {
697  // if there has been a change to the cardinality variables
698  // reconstruction of the partial sum structure is necessary
699  if (lps.check_update_min(k))
700  lps.init(home, k, false);
701  if (ups.check_update_max(k))
702  ups.init(home, k, true);
703  }
704 
705  // assert that the minimal value of the partial sum structure for
706  // LBC is consistent with the smallest value a variable can take
707  assert(lps.minValue() <= x[nu[0]].min());
708  // assert that the maximal value of the partial sum structure for
709  // UBC is consistent with the largest value a variable can take
710 
711  /*
712  * Setup rank and bounds info
713  * Since this implementation is based on the theory of Hall Intervals
714  * additional datastructures are needed in order to represent these
715  * intervals and the "partial-sum" data structure (cf."gcc/bnd-sup.hpp")
716  *
717  */
718 
719  HallInfo* hall = r.alloc<HallInfo>(2 * n + 2);
720  Rank* rank = r.alloc<Rank>(n);
721 
722  int nb = 0;
723  // setup bounds and rank
724  int min = x[nu[0]].min();
725  int max = x[mu[0]].max() + 1;
726  int last = lps.firstValue + 1; //equivalent to last = min -2
727  hall[0].bounds = last;
728 
729  /*
730  * First the algorithm merges the arrays minsorted and maxsorted
731  * into bounds i.e. hall[].bounds contains the ordered union
732  * of the lower and upper domain bounds including two sentinels
733  * at the beginning and at the end of the set
734  * ( the upper variable bounds in this union are increased by 1 )
735  */
736 
737  {
738  int i = 0;
739  int j = 0;
740  while (true) {
741  if (i < n && min < max) {
742  if (min != last) {
743  last = min;
744  hall[++nb].bounds = last;
745  }
746  rank[nu[i]].min = nb;
747  if (++i < n)
748  min = x[nu[i]].min();
749  } else {
750  if (max != last) {
751  last = max;
752  hall[++nb].bounds = last;
753  }
754  rank[mu[j]].max = nb;
755  if (++j == n)
756  break;
757  max = x[mu[j]].max() + 1;
758  }
759  }
760  }
761 
762  int rightmost = nb + 1; // rightmost accesible value in bounds
763  hall[rightmost].bounds = ups.lastValue + 1 ;
764 
765  if (Card::propagate) {
766  skip_lbc = true;
767  for (int i = k.size(); i--; )
768  if (k[i].min() != 0) {
769  skip_lbc = false;
770  break;
771  }
772  }
773 
774  if (!card_fixed && !skip_lbc)
775  GECODE_ES_CHECK((lbc(home, nb, hall, rank, mu, nu)));
776 
777  GECODE_ES_CHECK((ubc(home, nb, hall, rank, mu, nu)));
778 
779  if (Card::propagate)
780  GECODE_ES_CHECK(prop_card<Card>(home, x, k));
781 
782  for (int i = k.size(); i--; )
783  count[i] = 0;
784  for (int i = x.size(); i--; )
785  if (x[i].assigned()) {
786  int idx;
787  if (!lookupValue(k,x[i].val(),idx))
788  return ES_FAILED;
789  count[idx]++;
790  } else {
791  // We won't need the remaining counts, they're only used when
792  // all x are assigned
793  return ES_NOFIX;
794  }
795 
796  for (int i = k.size(); i--; )
797  GECODE_ME_CHECK(k[i].eq(home, count[i]));
798 
799  return home.ES_SUBSUMED(*this);
800  }
801 
802 
803  template<class Card>
804  ExecStatus
807  bool cardfix = true;
808  for (int i=k.size(); i--; )
809  if (!k[i].assigned()) {
810  cardfix = false; break;
811  }
812  bool nolbc = true;
813  for (int i=k.size(); i--; )
814  if (k[i].min() != 0) {
815  nolbc = false; break;
816  }
817 
818  GECODE_ES_CHECK(postSideConstraints<Card>(home, x, k));
819 
820  if (isDistinct<Card>(home,x,k))
821  return Distinct::Bnd<IntView>::post(home,x);
822 
823  (void) new (home) Bnd<Card>(home,x,k,cardfix,nolbc);
824  return ES_OK;
825  }
826 
827 }}}
828 
829 // STATISTICS: int-prop
Bnd(Space &home, bool share, Bnd< Card > &p)
Constructor for cloning p.
Definition: bnd.hpp:60
int d
Difference between critical capacities.
Definition: bnd-sup.hpp:477
void update(Space &, bool share, ViewArray< View > &a)
Update array to be a clone of array a.
Definition: array.hpp:1387
NodeType t
Type of node.
Definition: bool-expr.cpp:234
virtual Actor * copy(Space &home, bool share)
Copy propagator during cloning.
Definition: bnd.hpp:79
static PropCost quadratic(PropCost::Mod m, unsigned int n)
Quadratic complexity for modifier m and size measure n.
Definition: core.hpp:4032
Container class provding information about the Hall structure of the problem variables.
Definition: bnd-sup.hpp:460
static PropCost linear(PropCost::Mod m, unsigned int n)
Linear complexity for modifier pcm and size measure n.
Definition: core.hpp:4041
ExecStatus ES_SUBSUMED(Propagator &p)
Definition: core.hpp:2973
int size(void) const
Return size of array (number of elements)
Definition: array.hpp:1662
T * alloc(long unsigned int n)
Allocate block of n objects of type T from region.
Definition: region.hpp:326
Value iterator for array of integers
ExecStatus ES_NOFIX_PARTIAL(Propagator &p, const ModEventDelta &med)
Propagator p has not computed partial fixpoint
Definition: core.hpp:2986
bool lookupValue(T &a, int v, int &i)
Return index of v in array a.
Definition: view.hpp:48
void pathset_s(HallInfo hall[], int start, int end, int to)
Path compression for stable set structure.
Definition: bnd-sup.hpp:519
virtual PropCost cost(const Space &home, const ModEventDelta &med) const
Cost funtion.
Definition: bnd.hpp:85
void max(Home home, FloatVar x0, FloatVar x1, FloatVar x2)
Post propagator for .
Definition: arithmetic.cpp:57
void pathset_h(HallInfo hall[], int start, int end, int to)
Path compression for hall pointer structure.
Definition: bnd-sup.hpp:535
ViewArray< Card > k
Array containing either fixed cardinalities or CardViews.
Definition: gcc.hh:122
Base-class for propagators.
Definition: core.hpp:755
int h
Hall set pointer.
Definition: bnd-sup.hpp:486
Handle to region.
Definition: region.hpp:61
int pathmax_t(const HallInfo hall[], int i)
Path maximum for capacity pointer structure.
Definition: bnd-sup.hpp:583
int pathmin_h(const HallInfo hall[], int i)
Path minimum for hall pointer structure.
Definition: bnd-sup.hpp:553
int pathmin_t(const HallInfo hall[], int i)
Path minimum for capacity pointer structure.
Definition: bnd-sup.hpp:560
Computation spaces.
Definition: core.hpp:1362
Base-class for both propagators and branchers.
Definition: core.hpp:666
Compares two indices i, j of two views according to the ascending order of the views lower bounds...
Definition: bnd-sup.hpp:203
Gecode::IntSet d(v, 7)
int pathmax_h(const HallInfo hall[], int i)
Path maximum for hall pointer structure.
Definition: bnd-sup.hpp:576
#define GECODE_ES_CHECK(es)
Check whether execution status es is failed or subsumed, and forward failure or subsumption.
Definition: macros.hpp:84
int p
Number of positive literals for node type.
Definition: bool-expr.cpp:236
const FloatNum min
Smallest allowed float value.
Definition: float.hh:833
Gecode::IntArgs i(4, 1, 2, 3, 4)
static ExecStatus post(Home home, ViewArray< View > &x)
Post propagator for view array x.
Definition: bnd.hpp:459
void quicksort(Type *l, Type *r, Less &less)
Standard quick sort.
Definition: sort.hpp:134
int n
Number of negative literals for node type.
Definition: bool-expr.cpp:238
int t
Critical capacity pointer t represents a predecessor function where denotes the predecessor of i in ...
Definition: bnd-sup.hpp:469
Compares two indices i, j of two views according to the ascending order of the views upper bounds...
Definition: bnd-sup.hpp:180
Execution has resulted in failure.
Definition: core.hpp:525
virtual size_t dispose(Space &home)
Destructor.
Definition: bnd.hpp:70
NNF * r
Right subtree.
Definition: bool-expr.cpp:246
void subscribe(Space &home, Propagator &p, PropCond pc, bool process=true)
Subscribe propagator p with propagation condition pc to variable.
Definition: array.hpp:1400
const Gecode::PropCond PC_INT_BND
Propagate when minimum or maximum of a view changes.
Definition: var-type.hpp:91
const Gecode::ModEvent ME_INT_VAL
Domain operation has resulted in a value (assigned variable)
Definition: var-type.hpp:56
int pathmax_ps(const HallInfo hall[], int i)
Path maximum for potentially stable set pointer structure.
Definition: bnd-sup.hpp:598
ExecStatus ubc(Space &home, int &nb, HallInfo hall[], Rank rank[], int mu[], int nu[])
Upper Bounds constraint (UBC) stating Hence the ubc constraints the variables such that no value occ...
Definition: bnd.hpp:401
const Gecode::ModEvent ME_INT_BND
Domain operation has changed the minimum or maximum of the domain.
Definition: var-type.hpp:65
static ExecStatus post(Home home, ViewArray< IntView > &x, ViewArray< Card > &k)
Post propagator for views x and cardinalities k.
Definition: bnd.hpp:805
ExecStatus pruneCards(Space &home)
Prune cardinality variables with 0 maximum occurrence.
Definition: bnd.hpp:559
#define GECODE_ME_CHECK(me)
Check whether modification event me is failed, and forward failure.
Definition: macros.hpp:45
int bounds
Represents the union of all lower and upper domain bounds.
Definition: bnd-sup.hpp:463
void pathset_t(HallInfo hall[], int start, int end, int to)
Path compression for capacity pointer structure.
Definition: bnd-sup.hpp:527
const int v[7]
Definition: distinct.cpp:207
void min(Home home, FloatVar x0, FloatVar x1, FloatVar x2)
Post propagator for .
Definition: arithmetic.cpp:75
int newBound
Bound update.
Definition: bnd-sup.hpp:497
Maps domain bounds to their position in hall[].bounds.
Definition: bnd-sup.hpp:158
Node * x
Pointer to corresponding Boolean expression node.
Definition: bool-expr.cpp:253
void count(Home home, const IntVarArgs &x, int n, IntRelType irt, int m, IntConLevel)
Post propagator for .
Definition: count.cpp:44
virtual size_t dispose(Space &home)
Delete actor and return its size.
Definition: core.hpp:2877
Propagation cost.
Definition: core.hpp:537
ExecStatus
Definition: core.hpp:523
int s
Stable Set pointer.
Definition: bnd-sup.hpp:488
bool assigned(View x, int v)
Whether x is assigned to value v.
Definition: single.hpp:47
static ModEvent me(const ModEventDelta &med)
Return modification event for view type in med.
#define forceinline
Definition: config.hpp:132
int pathmax_s(const HallInfo hall[], int i)
Path maximum for stable set pointer structure.
Definition: bnd-sup.hpp:591
int med(void) const
Return median of domain (greatest element not greater than the median)
Definition: int.hpp:66
Execution is okay.
Definition: core.hpp:527
Propagation has not computed fixpoint.
Definition: core.hpp:526
ViewArray< IntView > y
Views on which to perform value-propagation (subset of x)
Definition: gcc.hh:120
int size(void) const
Return size of array (number of elements)
Definition: array.hpp:1215
int ps
Potentially Stable Set pointer.
Definition: bnd-sup.hpp:490
Gecode toplevel namespace
virtual ExecStatus propagate(Space &home, const ModEventDelta &med)
Perform propagation.
Definition: bnd.hpp:593
ViewArray< IntView > x
Views on which to perform bounds-propagation.
Definition: gcc.hh:118
int ModEventDelta
Modification event deltas.
Definition: core.hpp:173
Compares two cardinality views according to the index.
Definition: bnd-sup.hpp:225
Home class for posting propagators
Definition: core.hpp:717
Bounds consistent global cardinality propagator.
Definition: gcc.hh:115
ExecStatus lbc(Space &home, int &nb, HallInfo hall[], Rank rank[], int mu[], int nu[])
Lower Bounds constraint (LBC) stating Hence the lbc constraints the variables such that every value ...
Definition: bnd.hpp:97
void pathset_ps(HallInfo hall[], int start, int end, int to)
Path compression for potentially stable set structure.
Definition: bnd-sup.hpp:511