Generated on Tue Oct 22 2013 00:49:01 for Gecode by doxygen 1.8.4
lq-le.hpp
Go to the documentation of this file.
1 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2 /*
3  * Main authors:
4  * Christian Schulte <schulte@gecode.org>
5  * Gabor Szokoli <szokoli@gecode.org>
6  *
7  * Copyright:
8  * Christian Schulte, 2003
9  * Gabor Szokoli, 2003
10  *
11  * Last modified:
12  * $Date: 2012-09-07 17:31:22 +0200 (Fri, 07 Sep 2012) $ by $Author: schulte $
13  * $Revision: 13068 $
14  *
15  * This file is part of Gecode, the generic constraint
16  * development environment:
17  * http://www.gecode.org
18  *
19  * Permission is hereby granted, free of charge, to any person obtaining
20  * a copy of this software and associated documentation files (the
21  * "Software"), to deal in the Software without restriction, including
22  * without limitation the rights to use, copy, modify, merge, publish,
23  * distribute, sublicense, and/or sell copies of the Software, and to
24  * permit persons to whom the Software is furnished to do so, subject to
25  * the following conditions:
26  *
27  * The above copyright notice and this permission notice shall be
28  * included in all copies or substantial portions of the Software.
29  *
30  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
31  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
32  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
33  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
34  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
35  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
36  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37  *
38  */
39 
40 namespace Gecode { namespace Int { namespace Rel {
41 
42  /*
43  * Less or equal propagator
44  *
45  */
46 
47  template<class View>
49  Lq<View>::Lq(Home home, View x0, View x1)
50  : BinaryPropagator<View,PC_INT_BND>(home,x0,x1) {}
51 
52  template<class View>
54  Lq<View>::post(Home home, View x0, View x1) {
55  GECODE_ME_CHECK(x0.lq(home,x1.max()));
56  GECODE_ME_CHECK(x1.gq(home,x0.min()));
57  if (!same(x0,x1) && (x0.max() > x1.min()))
58  (void) new (home) Lq<View>(home,x0,x1);
59  return ES_OK;
60  }
61 
62  template<class View>
64  Lq<View>::Lq(Space& home, bool share, Lq<View>& p)
65  : BinaryPropagator<View,PC_INT_BND>(home,share,p) {}
66 
67  template<class View>
68  Actor*
69  Lq<View>::copy(Space& home, bool share) {
70  return new (home) Lq<View>(home,share,*this);
71  }
72 
73  template<class View>
76  GECODE_ME_CHECK(x0.lq(home,x1.max()));
77  GECODE_ME_CHECK(x1.gq(home,x0.min()));
78  return (x0.max() <= x1.min()) ? home.ES_SUBSUMED(*this) : ES_FIX;
79  }
80 
81 
82 
83 
84  /*
85  * Less propagator
86  *
87  */
88  template<class View>
90  Le<View>::Le(Home home, View x0, View x1)
91  : BinaryPropagator<View,PC_INT_BND>(home,x0,x1) {}
92 
93  template<class View>
95  Le<View>::post(Home home, View x0, View x1) {
96  if (same(x0,x1))
97  return ES_FAILED;
98  GECODE_ME_CHECK(x0.le(home,x1.max()));
99  GECODE_ME_CHECK(x1.gr(home,x0.min()));
100  if (x0.max() >= x1.min())
101  (void) new (home) Le<View>(home,x0,x1);
102  return ES_OK;
103  }
104 
105  template<class View>
107  Le<View>::Le(Space& home, bool share, Le<View>& p)
108  : BinaryPropagator<View,PC_INT_BND>(home,share,p) {}
109 
110  template<class View>
111  Actor*
112  Le<View>::copy(Space& home, bool share) {
113  return new (home) Le<View>(home,share,*this);
114  }
115 
116  template<class View>
117  ExecStatus
119  GECODE_ME_CHECK(x0.le(home,x1.max()));
120  GECODE_ME_CHECK(x1.gr(home,x0.min()));
121  return (x0.max() < x1.min()) ? home.ES_SUBSUMED(*this) : ES_FIX;
122  }
123 
124 
125 
126  /*
127  * Nary less and less or equal propagator
128  *
129  */
130 
131  template<class View, int o>
134  Council<Index>& c, int i0)
135  : Advisor(home,p,c), i(i0) {}
136 
137  template<class View, int o>
140  : Advisor(home,share,a), i(a.i) {}
141 
142 
143 
144  template<class View, int o>
147  : FreeList(n), p(p0) {}
148 
149  template<class View, int o>
152  return static_cast<Pos*>(FreeList::next());
153  }
154 
155  template<class View, int o>
156  forceinline void
158 
159  template<class View, int o>
160  forceinline void
162  GECODE_NEVER;
163  }
164 
165  template<class View, int o>
166  forceinline void*
168  return home.fl_alloc<sizeof(Pos)>();
169  }
170 
171  template<class View, int o>
172  forceinline void
174  home.fl_dispose<sizeof(Pos)>(this,this);
175  }
176 
177 
178  template<class View, int o>
179  forceinline bool
181  return pos == NULL;
182  }
183  template<class View, int o>
184  forceinline void
186  // Try to avoid entering same position twice
187  if ((pos != NULL) && (pos->p == p))
188  return;
189  pos = new (home) Pos(p,pos);
190  }
191  template<class View, int o>
192  forceinline int
194  Pos* t = pos;
195  int p = t->p;
196  pos = pos->next();
197  t->dispose(home);
198  return p;
199  }
200 
201  template<class View, int o>
204  : NaryPropagator<View,PC_INT_NONE>(home,x),
205  c(home), pos(NULL), run(false), n_subsumed(0) {
206  for (int i=x.size(); i--; )
207  x[i].subscribe(home, *new (home) Index(home,*this,c,i));
208  }
209 
210  template<class View, int o>
211  ExecStatus
213  assert((o == 0) || (o == 1));
214  // Check for sharing
215  if (x.same(home)) {
216  if (o == 1)
217  return ES_FAILED;
218  /*
219  * Eliminate sharing: if a view occurs twice, all views in between
220  * must be equal.
221  */
222  int n = x.size();
223  for (int i=0; i<n; i++)
224  for (int j=n-1; j>i; j--)
225  if (same(x[i],x[j])) {
226  if (i+1 != j) {
227  // Create equality propagator for elements i+1 ... j
228  ViewArray<View> y(home,j-i);
229  for (int k=j-i; k--; )
230  y[k] = x[i+1+k];
232  }
233  for (int k=0; k<n-1-j-1+1; k++)
234  x[i+1+k]=x[j+1+k];
235  n -= j-i;
236  }
237  x.size(n);
238  }
239 
240  // Propagate one round
241  for (int i=1; i<x.size(); i++)
242  GECODE_ME_CHECK(x[i].gq(home,x[i-1].min()+o));
243  for (int i=x.size()-1; i--;)
244  GECODE_ME_CHECK(x[i].lq(home,x[i+1].max()-o));
245  // Eliminate redundant variables
246  {
247  // Eliminate at beginning
248  {
249  int i=0;
250  while ((i+1 < x.size()) && (x[i].max()+o <= x[i+1].min()))
251  i++;
252  x.drop_fst(i);
253  }
254  // Eliminate at end
255  {
256  int i=x.size()-1;
257  while ((i > 0) && (x[i-1].max()+o <= x[i].min()))
258  i--;
259  x.drop_lst(i);
260  }
261  // Eliminate in the middle
262  if (x.size() > 1) {
263  int j=1;
264  for (int i=1; i+1<x.size(); i++)
265  if ((x[j-1].max()+o > x[i].min()) ||
266  (x[i].max()+o > x[i+1].min()))
267  x[j++]=x[i];
268  x[j++]=x[x.size()-1];
269  x.size(j);
270  }
271  }
272  if (x.size() == 2) {
273  if (o == 0)
274  return Lq<View>::post(home,x[0],x[1]);
275  else
276  return Le<View>::post(home,x[0],x[1]);
277  } else if (x.size() >= 2) {
278  (void) new (home) NaryLqLe<View,o>(home,x);
279  }
280  return ES_OK;
281  }
282 
283  template<class View, int o>
286  : NaryPropagator<View,PC_INT_NONE>(home,share,p),
287  pos(NULL), run(false), n_subsumed(p.n_subsumed) {
288  assert(p.pos == NULL);
289  c.update(home, share, p.c);
290  }
291 
292  template<class View, int o>
293  Actor*
294  NaryLqLe<View,o>::copy(Space& home, bool share) {
295  if (n_subsumed > n_threshold) {
296  Region r(home);
297  // Record for which views there is an advisor
298  Support::BitSet<Region> a(r,static_cast<unsigned int>(x.size()));
299  for (Advisors<Index> as(c); as(); ++as)
300  a.set(static_cast<unsigned int>(as.advisor().i));
301  // Compact view array and compute map for advisors
302  int* m = r.alloc<int>(x.size());
303  int j=0;
304  for (int i=0; i<x.size(); i++)
305  if (a.get(static_cast<unsigned int>(i))) {
306  m[i] = j; x[j++] = x[i];
307  }
308  x.size(j);
309  // Remap advisors
310  for (Advisors<Index> as(c); as(); ++as)
311  as.advisor().i = m[as.advisor().i];
312 
313  n_subsumed = 0;
314  }
315  return new (home) NaryLqLe<View,o>(home,share,*this);
316  }
317 
318  template<class View, int o>
319  PropCost
322  }
323 
324  template<class View, int o>
325  forceinline size_t
327  for (Advisors<Index> as(c); as(); ++as)
328  x[as.advisor().i].cancel(home,as.advisor());
329  c.dispose(home);
330  while (!empty())
331  (void) pop(home);
333  return sizeof(*this);
334  }
335 
336 
337  template<class View, int o>
338  ExecStatus
340  Index& a = static_cast<Index&>(_a);
341  const int i = a.i;
342  switch (View::modevent(d)) {
343  case ME_INT_VAL:
344  a.dispose(home,c);
345  n_subsumed++;
346  break;
347  case ME_INT_BND:
348  if (((i == 0) || (x[i-1].max()+o <= x[i].min())) &&
349  ((i == x.size()-1) || (x[i].max()+o <= x[i+1].min()))) {
350  x[i].cancel(home,a);
351  a.dispose(home,c);
352  n_subsumed++;
353  return (run || (n_subsumed + 1 < x.size())) ? ES_FIX : ES_NOFIX;
354  }
355  break;
356  default:
357  return ES_FIX;
358  }
359  if (run)
360  return ES_FIX;
361  if (((i < x.size()-1) && (x[i+1].min() < x[i].min()+o)) ||
362  ((i > 0) && (x[i-1].max() > x[i].max()-o))) {
363  push(home,i);
364  return ES_NOFIX;
365  }
366  return (n_subsumed+1 >= x.size()) ? ES_NOFIX : ES_FIX;
367  }
368 
369  template<class View, int o>
370  ExecStatus
372  run = true;
373  int n = x.size();
374  while (!empty()) {
375  int p = pop(home);
376  for (int i=p; i<n-1; i++) {
377  ModEvent me = x[i+1].gq(home,x[i].min()+o);
378  if (me_failed(me))
379  return ES_FAILED;
380  if (!me_modified(me))
381  break;
382  }
383  for (int i=p; i>0; i--) {
384  ModEvent me = x[i-1].lq(home,x[i].max()-o);
385  if (me_failed(me))
386  return ES_FAILED;
387  if (!me_modified(me))
388  break;
389  }
390  }
391 #ifdef GECODE_AUDIT
392  for (int i=0; i<n-1; i++)
393  assert(!me_modified(x[i+1].gq(home,x[i].min()+o)));
394  for (int i=n-1; i>0; i--)
395  assert(!me_modified(x[i-1].lq(home,x[i].max()-o)));
396 #endif
397  if (n_subsumed+1 >= n)
398  return home.ES_SUBSUMED(*this);
399  run = false;
400  return ES_FIX;
401  }
402 
403 
404 
405  /*
406  * Reified less or equal propagator
407  *
408  */
409 
410  template<class View, class CtrlView, ReifyMode rm>
412  ReLq<View,CtrlView,rm>::ReLq(Home home, View x0, View x1, CtrlView b)
413  : ReBinaryPropagator<View,PC_INT_BND,CtrlView>(home,x0,x1,b) {}
414 
415  template<class View, class CtrlView, ReifyMode rm>
416  ExecStatus
417  ReLq<View,CtrlView,rm>::post(Home home, View x0, View x1, CtrlView b) {
418  if (b.one()) {
419  if (rm == RM_PMI)
420  return ES_OK;
421  return Lq<View>::post(home,x0,x1);
422  }
423  if (b.zero()) {
424  if (rm == RM_IMP)
425  return ES_OK;
426  return Le<View>::post(home,x1,x0);
427  }
428  if (!same(x0,x1)) {
429  switch (rtest_lq(x0,x1)) {
430  case RT_TRUE:
431  if (rm != RM_IMP)
432  GECODE_ME_CHECK(b.one_none(home));
433  break;
434  case RT_FALSE:
435  if (rm != RM_PMI)
436  GECODE_ME_CHECK(b.zero_none(home));
437  break;
438  case RT_MAYBE:
439  (void) new (home) ReLq<View,CtrlView,rm>(home,x0,x1,b);
440  break;
441  default: GECODE_NEVER;
442  }
443  } else if (rm != RM_IMP) {
444  GECODE_ME_CHECK(b.one_none(home));
445  }
446  return ES_OK;
447  }
448 
449  template<class View, class CtrlView, ReifyMode rm>
452  : ReBinaryPropagator<View,PC_INT_BND,CtrlView>(home,share,p) {}
453 
454  template<class View, class CtrlView, ReifyMode rm>
455  Actor*
456  ReLq<View,CtrlView,rm>::copy(Space& home, bool share) {
457  return new (home) ReLq<View,CtrlView,rm>(home,share,*this);
458  }
459 
460  template<class View, class CtrlView, ReifyMode rm>
461  ExecStatus
463  if (b.one()) {
464  if (rm != RM_PMI)
465  GECODE_REWRITE(*this,Lq<View>::post(home(*this),x0,x1));
466  } else if (b.zero()) {
467  if (rm != RM_IMP)
468  GECODE_REWRITE(*this,Le<View>::post(home(*this),x1,x0));
469  } else {
470  switch (rtest_lq(x0,x1)) {
471  case RT_TRUE:
472  if (rm != RM_IMP)
473  GECODE_ME_CHECK(b.one_none(home));
474  break;
475  case RT_FALSE:
476  if (rm != RM_PMI)
477  GECODE_ME_CHECK(b.zero_none(home));
478  break;
479  case RT_MAYBE:
480  return ES_FIX;
481  default: GECODE_NEVER;
482  }
483  }
484  return home.ES_SUBSUMED(*this);
485  }
486 
487  /*
488  * Reified less or equal propagator involving one variable
489  *
490  */
491 
492  template<class View, class CtrlView, ReifyMode rm>
494  ReLqInt<View,CtrlView,rm>::ReLqInt(Home home, View x, int c0, CtrlView b)
495  : ReUnaryPropagator<View,PC_INT_BND,CtrlView>(home,x,b), c(c0) {}
496 
497  template<class View, class CtrlView, ReifyMode rm>
498  ExecStatus
499  ReLqInt<View,CtrlView,rm>::post(Home home, View x, int c, CtrlView b) {
500  if (b.one()) {
501  if (rm != RM_PMI)
502  GECODE_ME_CHECK(x.lq(home,c));
503  } else if (b.zero()) {
504  if (rm != RM_IMP)
505  GECODE_ME_CHECK(x.gr(home,c));
506  } else {
507  switch (rtest_lq(x,c)) {
508  case RT_TRUE:
509  if (rm != RM_IMP)
510  GECODE_ME_CHECK(b.one_none(home));
511  break;
512  case RT_FALSE:
513  if (rm != RM_PMI)
514  GECODE_ME_CHECK(b.zero_none(home));
515  break;
516  case RT_MAYBE:
517  (void) new (home) ReLqInt<View,CtrlView,rm>(home,x,c,b);
518  break;
519  default: GECODE_NEVER;
520  }
521  }
522  return ES_OK;
523  }
524 
525 
526  template<class View, class CtrlView, ReifyMode rm>
529  : ReUnaryPropagator<View,PC_INT_BND,CtrlView>(home,share,p), c(p.c) {}
530 
531  template<class View, class CtrlView, ReifyMode rm>
532  Actor*
534  return new (home) ReLqInt<View,CtrlView,rm>(home,share,*this);
535  }
536 
537  template<class View, class CtrlView, ReifyMode rm>
538  ExecStatus
540  if (b.one()) {
541  if (rm != RM_PMI)
542  GECODE_ME_CHECK(x0.lq(home,c));
543  } else if (b.zero()) {
544  if (rm != RM_IMP)
545  GECODE_ME_CHECK(x0.gr(home,c));
546  } else {
547  switch (rtest_lq(x0,c)) {
548  case RT_TRUE:
549  if (rm != RM_IMP)
550  GECODE_ME_CHECK(b.one_none(home));
551  break;
552  case RT_FALSE:
553  if (rm != RM_PMI)
554  GECODE_ME_CHECK(b.zero_none(home));
555  break;
556  case RT_MAYBE:
557  return ES_FIX;
558  default: GECODE_NEVER;
559  }
560  }
561  return home.ES_SUBSUMED(*this);
562  }
563 
564 }}}
565 
566 // STATISTICS: int-prop
567