Generated on Sat May 25 2013 18:00:36 for Gecode by doxygen 1.8.3.1
lq.hpp
Go to the documentation of this file.
1 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2 /*
3  * Main authors:
4  * Guido Tack <tack@gecode.org>
5  *
6  * Copyright:
7  * Guido Tack, 2011
8  *
9  * Last modified:
10  * $Date: 2013-02-08 16:47:00 +0100 (Fri, 08 Feb 2013) $ by $Author: schulte $
11  * $Revision: 13278 $
12  *
13  * This file is part of Gecode, the generic constraint
14  * development environment:
15  * http://www.gecode.org
16  *
17  * Permission is hereby granted, free of charge, to any person obtaining
18  * a copy of this software and associated documentation files (the
19  * "Software"), to deal in the Software without restriction, including
20  * without limitation the rights to use, copy, modify, merge, publish,
21  * distribute, sublicense, and/or sell copies of the Software, and to
22  * permit persons to whom the Software is furnished to do so, subject to
23  * the following conditions:
24  *
25  * The above copyright notice and this permission notice shall be
26  * included in all copies or substantial portions of the Software.
27  *
28  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35  *
36  */
37 
38 namespace Gecode { namespace Set { namespace Rel {
39 
44  protected:
46  unsigned int xsize;
50  int* ub;
52  bool xlm;
54  bool xum;
56  bool ylm;
58  bool yum;
60  void set(int i, bool j) {
61  if (j)
62  b.set(i);
63  else
64  b.clear(i);
65  }
66 
68  class CSIter {
69  public:
73  unsigned int i;
75  int xoff;
77  int yoff;
79  void operator++ (void) {
80  i++;
81  while (i<cs->xsize && !cs->b.get(xoff+2*i+yoff))
82  i++;
83  }
85  CSIter(void) {}
87  CSIter(CharacteristicSets& cs0, int xoff0, int yoff0)
88  : cs(&cs0), i(static_cast<unsigned int>(-1)),
89  xoff(xoff0), yoff(yoff0) {
90  ++(*this);
91  }
93  bool operator() (void) const { return i<cs->xsize; }
95  int val(void) const { return cs->ub[i]; }
96  };
97 
98  public:
100  template<class View0, class View1>
101  CharacteristicSets(Region& re, View0 x, View1 y);
102 
104  bool xmin(int i) const { return b.get(2*i); }
106  bool xmax(int i) const { return b.get(2*i+1); }
108  bool ymin(int i) const { return b.get(2*xsize+2*i); }
110  bool ymax(int i) const { return b.get(2*xsize+2*i+1); }
111 
113  void xmin(int i, bool j) { set(2*i,j); }
115  void xmax(int i, bool j) { set(2*i+1,j); }
117  void ymin(int i, bool j) { set(2*xsize+2*i,j); }
119  void ymax(int i, bool j) { set(2*xsize+2*i+1,j); }
120 
122  ModEvent xlq(int i, bool j) {
123  if (!j) {
124  if (xmin(i)) return ME_SET_FAILED;
125  if (xmax(i)) {
126  xmax(i,false);
127  xum=true;
128  }
129  }
130  return ME_SET_NONE;
131  }
133  ModEvent xgq(int i, bool j) {
134  if (j) {
135  if (!xmax(i)) return ME_SET_FAILED;
136  if (!xmin(i)) {
137  xmin(i,true);
138  xlm=true;
139  }
140  }
141  return ME_SET_NONE;
142  }
144  ModEvent ylq(int i, bool j) {
145  if (!j) {
146  if (ymin(i)) return ME_SET_FAILED;
147  if (ymax(i)) {
148  ymax(i,false);
149  yum=true;
150  }
151  }
152  return ME_SET_NONE;
153  }
155  ModEvent ygq(int i, bool j) {
156  if (j) {
157  if (!ymax(i)) return ME_SET_FAILED;
158  if (!ymin(i)) {
159  ymin(i,true);
160  ylm=true;
161  }
162  }
163  return ME_SET_NONE;
164  }
165 
167  int size(void) const { return xsize; }
168 
170  template<class View0, class View1>
171  ExecStatus prune(Space& home, View0 x, View1 y) {
172  if (xlm) {
173  CSIter i(*this,0,0);
175  GECODE_ME_CHECK(x.includeI(home,ir));
176  }
177  if (xum) {
178  CSIter i(*this,0,1);
180  GECODE_ME_CHECK(x.intersectI(home,ir));
181  }
182  if (ylm) {
183  CSIter i(*this,2*xsize,0);
185  GECODE_ME_CHECK(y.includeI(home,ir));
186  }
187  if (yum) {
188  CSIter i(*this,2*xsize,1);
190  GECODE_ME_CHECK(y.intersectI(home,ir));
191  }
192  return ES_OK;
193  }
194 
195  };
196 
197  template<class View0, class View1>
199  : xlm(false), xum(false), ylm(false), yum(false) {
200  LubRanges<View0> xlub(x);
201  LubRanges<View1> ylub(y);
203  Iter::Ranges::Cache xylubc(re,xylub);
204  xsize = Iter::Ranges::size(xylubc);
205  b.init(re,4*xsize);
206  ub = re.alloc<int>(xsize);
207  xylubc.reset();
209  LubRanges<View0> xur(x);
210  GlbRanges<View0> xlr(x);
211  LubRanges<View1> yur(y);
212  GlbRanges<View1> ylr(y);
217  for (int i=0; xylubv(); ++xylubv, ++i) {
218  ub[i] = xylubv.val();
219  if (xlv() && xylubv.val()==xlv.val()) {
220  b.set(2*i);
221  ++xlv;
222  }
223  if (xuv() && xylubv.val()==xuv.val()) {
224  b.set(2*i+1);
225  ++xuv;
226  }
227  if (ylv() && xylubv.val()==ylv.val()) {
228  b.set(2*xsize+2*i);
229  ++ylv;
230  }
231  if (yuv() && xylubv.val()==yuv.val()) {
232  b.set(2*xsize+2*i+1);
233  ++yuv;
234  }
235  }
236  }
237 
238  template<class View0, class View1, bool strict>
240  Lq<View0,View1,strict>::Lq(Home home, View0 x, View1 y)
241  : MixBinaryPropagator<View0,PC_SET_ANY,View1,PC_SET_ANY>(home,x,y) {}
242 
243  template<class View0, class View1, bool strict>
245  Lq<View0,View1,strict>::Lq(Space& home, bool share, Lq& p)
246  : MixBinaryPropagator<View0,PC_SET_ANY,View1,PC_SET_ANY>(home,share,p) {}
247 
248  template<class View0, class View1, bool strict>
249  ExecStatus
250  Lq<View0,View1,strict>::post(Home home, View0 x, View1 y) {
251  if (strict)
252  GECODE_ME_CHECK(y.cardMin(home,1));
253  (void) new (home) Lq(home,x,y);
254  return ES_OK;
255  }
256 
257  template<class View0, class View1, bool strict>
258  Actor*
259  Lq<View0,View1,strict>::copy(Space& home, bool share) {
260  return new (home) Lq(home,share,*this);
261  }
262 
263  template<class View0, class View1, bool strict>
264  ExecStatus
266  if ( (!strict) && x1.cardMax()==0) {
267  GECODE_ME_CHECK(x0.cardMax(home,0));
268  }
269 
270  if (x0.cardMax()==0) {
271  return home.ES_SUBSUMED(*this);
272  }
273 
274  if (x0.glbMin() < x1.lubMin())
275  return ES_FAILED;
276  if (x1.glbMin() < x0.lubMin())
277  return home.ES_SUBSUMED(*this);
278 
279  bool assigned = x0.assigned() && x1.assigned();
280 
281  Region re(home);
282  CharacteristicSets cs(re,x0,x1);
283 
284  /*
285  * State 1
286  *
287  */
288  int i=0;
289  int firsti=0;
290  int n=cs.size();
291  while ((i<n) && cs.xmin(i) == cs.ymax(i)) {
292  // case: =, >=
293  GECODE_ME_CHECK(cs.xlq(i,cs.ymax(i)));
294  GECODE_ME_CHECK(cs.ygq(i,cs.xmin(i)));
295  i++;
296  }
297 
298  if (i == n) {// case: $
299  if (strict) {
300  return ES_FAILED;
301  } else {
302  GECODE_ES_CHECK(cs.prune(home,x0,x1));
303  return home.ES_SUBSUMED(*this);
304  }
305  }
306 
307  // Possible cases left: <, <=, > (yields failure), ?
308  GECODE_ME_CHECK(cs.xlq(i,cs.ymax(i)));
309  GECODE_ME_CHECK(cs.ygq(i,cs.xmin(i)));
310 
311  if (cs.xmax(i) < cs.ymin(i)) { // case: < (after tell)
312  GECODE_ES_CHECK(cs.prune(home,x0,x1));
313  return home.ES_SUBSUMED(*this);
314  }
315 
316  firsti=i;
317 
318  /*
319  * State 2
320  * prefix: (?|<=)
321  *
322  */
323  i++;
324 
325  while ((i < n) &&
326  (cs.xmin(i) == cs.ymax(i)) &&
327  (cs.xmax(i) == cs.ymin(i))) { // case: =
328  i++;
329  }
330 
331  if (i == n) { // case: $
332  if (strict)
333  goto rewrite_le;
334  else
335  goto rewrite_lq;
336  }
337 
338  if (cs.xmax(i) < cs.ymin(i)) // case: <
339  goto rewrite_lq;
340 
341  if (cs.xmin(i) > cs.ymax(i)) // case: >
342  goto rewrite_le;
343 
344  if (cs.xmax(i) <= cs.ymin(i)) {
345  // case: <= (invariant: not =, <)
346  /*
347  * State 3
348  * prefix: (?|<=),<=
349  *
350  */
351  i++;
352 
353  while ((i < n) && (cs.xmax(i) == cs.ymin(i))) {// case: <=, =
354  i++;
355  }
356 
357  if (i == n) { // case: $
358  if (strict) {
359  GECODE_ES_CHECK(cs.prune(home,x0,x1));
360  return assigned ? home.ES_SUBSUMED(*this) : ES_NOFIX;
361  } else {
362  goto rewrite_lq;
363  }
364  }
365 
366  if (cs.xmax(i) < cs.ymin(i)) // case: <
367  goto rewrite_lq;
368 
369  GECODE_ES_CHECK(cs.prune(home,x0,x1));
370  return assigned ? home.ES_SUBSUMED(*this) : ES_NOFIX;
371  }
372 
373  if (cs.xmin(i) >= cs.ymax(i)) {
374  // case: >= (invariant: not =, >)
375  /*
376  * State 4
377  * prefix: (?|<=) >=
378  *
379  */
380  i++;
381 
382  while ((i < n) && (cs.xmin(i) == cs.ymax(i))) {
383  // case: >=, =
384  i++;
385  }
386 
387  if (i == n) { // case: $
388  if (strict) {
389  goto rewrite_le;
390  } else {
391  GECODE_ES_CHECK(cs.prune(home,x0,x1));
392  return assigned ? home.ES_SUBSUMED(*this) : ES_NOFIX;
393  }
394  }
395 
396  if (cs.xmin(i) > cs.ymax(i)) // case: >
397  goto rewrite_le;
398 
399  GECODE_ES_CHECK(cs.prune(home,x0,x1));
400  return assigned ? home.ES_SUBSUMED(*this) : ES_NOFIX;
401  }
402 
403  GECODE_ES_CHECK(cs.prune(home,x0,x1));
404  return assigned ? home.ES_SUBSUMED(*this) : ES_NOFIX;
405 
406  rewrite_le:
407  GECODE_ME_CHECK(cs.xlq(firsti,false));
408  GECODE_ME_CHECK(cs.ygq(firsti,true));
409  GECODE_ES_CHECK(cs.prune(home,x0,x1));
410  return home.ES_SUBSUMED(*this);
411  rewrite_lq:
412  GECODE_ES_CHECK(cs.prune(home,x0,x1));
413  return assigned ? home.ES_SUBSUMED(*this) : ES_NOFIX;
414  }
415 
416 }}}
417 
418 // STATISTICS: set-prop