Generated on for Gecode by doxygen 1.17.0
int.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.dev>
5 *
6 * Contributing authors:
7 * Guido Tack <tack@gecode.dev>
8 * Mikael Zayenz Lagerkvist <lagerkvist@gecode.dev>
9 *
10 * Copyright:
11 * Christian Schulte, 2003
12 * Guido Tack, 2004
13 * Mikael Zayenz Lagerkvist, 2026
14 *
15 * This file is part of Gecode, the generic constraint
16 * development environment:
17 * http://www.gecode.dev
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
40namespace Gecode { namespace Int {
41
42 /*
43 * Range lists
44 *
45 */
46
47#define GECODE_INT_RL2PD(r) reinterpret_cast<ptrdiff_t>(r)
48#define GECODE_INT_PD2RL(p) reinterpret_cast<RangeList*>(p)
49
50 forceinline unsigned int
51 range_width(int min, int max) {
52 return static_cast<unsigned int>(max) -
53 static_cast<unsigned int>(min) + 1U;
54 }
55
56 forceinline
58
59 forceinline
62
63 forceinline
68
69 forceinline IntVarImp::RangeList*
73 forceinline IntVarImp::RangeList*
77 forceinline void
81 forceinline void
86 forceinline void
91 forceinline void
95
96 forceinline void
98 _min = n;
99 }
100 forceinline void
102 _max = n;
103 }
104
105 forceinline int
107 return _min;
108 }
109 forceinline int
111 return _max;
112 }
113 forceinline unsigned int
115 return range_width(_min,_max);
116 }
117
118
119 forceinline void
120 IntVarImp::RangeList::operator delete(void*) {}
121
122 forceinline void
123 IntVarImp::RangeList::operator delete(void*, Space&) {
125 }
126 forceinline void
127 IntVarImp::RangeList::operator delete(void*, void*) {
129 }
130
131 forceinline void*
132 IntVarImp::RangeList::operator new(size_t, Space& home) {
133 return home.fl_alloc<sizeof(RangeList)>();
134 }
135
136 forceinline void*
137 IntVarImp::RangeList::operator new(size_t, void* p) {
138 return p;
139 }
140
141 forceinline void
143 RangeList* c = this;
144 while (c != l) {
145 RangeList* n = c->next(p);
146 c->fix(n);
147 p=c; c=n;
148 }
149 home.fl_dispose<sizeof(RangeList)>(this,l);
150 }
151
152 forceinline void
154 home.fl_dispose<sizeof(RangeList)>(this,l);
155 }
156
157 forceinline void
159 home.fl_dispose<sizeof(RangeList)>(this,this);
160 }
161
162#undef GECODE_INT_RL2PD
163#undef GECODE_INT_PD2RL
164
165 /*
166 * Mainitaining range lists for variable domain
167 *
168 */
169
170 forceinline IntVarImp::RangeList*
171 IntVarImp::fst(void) const {
172 return dom.next(nullptr);
173 }
174
175 forceinline void
177 dom.prevnext(nullptr,f);
178 }
179
180 forceinline IntVarImp::RangeList*
181 IntVarImp::lst(void) const {
182 return _lst;
183 }
184
185 forceinline void
189
190 /*
191 * Creation of new variable implementations
192 *
193 */
194
195 forceinline
197 : IntVarImpBase(home), dom(min,max,nullptr,nullptr), holes(0) {}
198
199 forceinline
201 : IntVarImpBase(home), dom(d.min(),d.max()) {
202 if (d.ranges() > 1) {
203 int n = d.ranges();
204 assert(n >= 2);
205 RangeList* r = home.alloc<RangeList>(n);
206 fst(r); lst(r+n-1);
207 unsigned int h = range_width(d.min(),d.max());
208 h -= d.width(0);
209 r[0].min(d.min(0)); r[0].max(d.max(0));
210 r[0].prevnext(nullptr,&r[1]);
211 for (int i = 1; i < n-1; i++) {
212 h -= d.width(i);
213 r[i].min(d.min(i)); r[i].max(d.max(i));
214 r[i].prevnext(&r[i-1],&r[i+1]);
215 }
216 h -= d.width(n-1);
217 r[n-1].min(d.min(n-1)); r[n-1].max(d.max(n-1));
218 r[n-1].prevnext(&r[n-2],nullptr);
219 holes = h;
220 } else {
221 fst(nullptr); holes = 0;
222 }
223 }
224
225
226 /*
227 * Operations on integer variable implementations
228 *
229 */
230
231 forceinline int
232 IntVarImp::min(void) const {
233 return dom.min();
234 }
235 forceinline int
236 IntVarImp::max(void) const {
237 return dom.max();
238 }
239 forceinline int
240 IntVarImp::val(void) const {
241 assert(dom.min() == dom.max());
242 return dom.min();
243 }
244
245 forceinline bool
246 IntVarImp::range(void) const {
247 return fst() == nullptr;
248 }
249 forceinline bool
251 return dom.min() == dom.max();
252 }
253
254
255 forceinline unsigned int
256 IntVarImp::width(void) const {
257 return dom.width();
258 }
259
260 forceinline unsigned int
261 IntVarImp::size(void) const {
262 return dom.width() - holes;
263 }
264
265 forceinline unsigned int
267 if (fst() == nullptr) {
268 return (dom.min() == dom.max()) ? 0U : 1U;
269 } else if (dom.min() == fst()->max()) {
270 return static_cast<unsigned int>(fst()->next(nullptr)->min()) -
271 static_cast<unsigned int>(dom.min());
272 } else {
273 return 1U;
274 }
275 }
276 forceinline unsigned int
278 if (fst() == nullptr) {
279 return (dom.min() == dom.max()) ? 0U : 1U;
280 } else if (dom.max() == lst()->min()) {
281 return static_cast<unsigned int>(dom.max()) -
282 static_cast<unsigned int>(lst()->prev(nullptr)->max());
283 } else {
284 return 1U;
285 }
286 }
287
288
289
290 /*
291 * Tests
292 *
293 */
294
295 forceinline bool
296 IntVarImp::in(int n) const {
297 if ((n < dom.min()) || (n > dom.max()))
298 return false;
299 return (fst() == nullptr) || in_full(n);
300 }
301 forceinline bool
302 IntVarImp::in(long long int n) const {
303 if ((n < dom.min()) || (n > dom.max()))
304 return false;
305 return (fst() == nullptr) || in_full(static_cast<int>(n));
306 }
307
308
309 /*
310 * Accessing rangelists for iteration
311 *
312 */
313
314 forceinline const IntVarImp::RangeList*
316 return (fst() == nullptr) ? &dom : fst();
317 }
318
319 forceinline const IntVarImp::RangeList*
321 return (fst() == nullptr) ? &dom : lst();
322 }
323
324
325
326 /*
327 * Support for delta information
328 *
329 */
330 forceinline int
332 return static_cast<const IntDelta&>(d).min();
333 }
334 forceinline int
336 return static_cast<const IntDelta&>(d).max();
337 }
338 forceinline unsigned int
340 return static_cast<const IntDelta&>(d).width();
341 }
342 forceinline bool
344 return static_cast<const IntDelta&>(d).any();
345 }
346
347
348 /*
349 * Tell operations (to be inlined: performing bounds checks first)
350 *
351 */
352
353 forceinline ModEvent
354 IntVarImp::gq(Space& home, int n) {
355 if (n <= dom.min()) return ME_INT_NONE;
356 if (n > dom.max()) return fail(home);
357 ModEvent me = gq_full(home,n);
359 (me == ME_INT_VAL) |
360 (me == ME_INT_BND));
361 return me;
362 }
363 forceinline ModEvent
364 IntVarImp::gq(Space& home, long long int n) {
365 if (n <= dom.min()) return ME_INT_NONE;
366 if (n > dom.max()) return fail(home);
367 ModEvent me = gq_full(home,static_cast<int>(n));
369 (me == ME_INT_VAL) |
370 (me == ME_INT_BND));
371 return me;
372 }
373
374 forceinline ModEvent
375 IntVarImp::lq(Space& home, int n) {
376 if (n >= dom.max()) return ME_INT_NONE;
377 if (n < dom.min()) return fail(home);
378 ModEvent me = lq_full(home,n);
380 (me == ME_INT_VAL) |
381 (me == ME_INT_BND));
382 return me;
383 }
384 forceinline ModEvent
385 IntVarImp::lq(Space& home, long long int n) {
386 if (n >= dom.max()) return ME_INT_NONE;
387 if (n < dom.min()) return fail(home);
388 ModEvent me = lq_full(home,static_cast<int>(n));
390 (me == ME_INT_VAL) |
391 (me == ME_INT_BND));
392 return me;
393 }
394
395 forceinline ModEvent
396 IntVarImp::eq(Space& home, int n) {
397 if ((n < dom.min()) || (n > dom.max()))
398 return fail(home);
399 if ((n == dom.min()) && (n == dom.max()))
400 return ME_INT_NONE;
401 ModEvent me = eq_full(home,n);
403 return me;
404 }
405 forceinline ModEvent
406 IntVarImp::eq(Space& home, long long int m) {
407 if ((m < dom.min()) || (m > dom.max()))
408 return fail(home);
409 int n = static_cast<int>(m);
410 if ((n == dom.min()) && (n == dom.max()))
411 return ME_INT_NONE;
412 ModEvent me = eq_full(home,n);
414 return me;
415 }
416
417 forceinline ModEvent
418 IntVarImp::nq(Space& home, int n) {
419 if ((n < dom.min()) || (n > dom.max()))
420 return ME_INT_NONE;
421 return nq_full(home,n);
422 }
423 forceinline ModEvent
424 IntVarImp::nq(Space& home, long long int d) {
425 if ((d < dom.min()) || (d > dom.max()))
426 return ME_INT_NONE;
427 return nq_full(home,static_cast<int>(d));
428 }
429
430
431 /*
432 * Forward range iterator for rangelists
433 *
434 */
435
436 forceinline
438 forceinline
440 : p(nullptr), c(x->ranges_fwd()) {}
441 forceinline void
443 p=nullptr; c=x->ranges_fwd();
444 }
445
446 forceinline bool
448 return c != nullptr;
449 }
450 forceinline void
452 const IntVarImp::RangeList* n=c->next(p); p=c; c=n;
453 }
454
455 forceinline int
456 IntVarImpFwd::min(void) const {
457 return c->min();
458 }
459 forceinline int
460 IntVarImpFwd::max(void) const {
461 return c->max();
462 }
463 forceinline unsigned int
465 return c->width();
466 }
467
468
469 /*
470 * Backward range iterator for rangelists
471 *
472 */
473
474 forceinline
476 forceinline
478 : n(nullptr), c(x->ranges_bwd()) {}
479 forceinline void
481 n=nullptr; c=x->ranges_bwd();
482 }
483
484 forceinline bool
486 return c != nullptr;
487 }
488 forceinline void
490 const IntVarImp::RangeList* p=c->prev(n); n=c; c=p;
491 }
492
493 forceinline int
494 IntVarImpBwd::min(void) const {
495 return c->min();
496 }
497 forceinline int
498 IntVarImpBwd::max(void) const {
499 return c->max();
500 }
501 forceinline unsigned int
503 return c->width();
504 }
505
506
507 /*
508 * Iterator-based domain operations
509 *
510 */
511 template<class I>
512 forceinline ModEvent
513 IntVarImp::narrow_r(Space& home, I& ri, bool depends) {
514 // Is new domain empty?
515 if (!ri())
516 return fail(home);
517
518 int min0 = ri.min();
519 int max0 = ri.max();
520 ++ri;
521
522 ModEvent me;
523
524 // Is new domain range?
525 if (!ri()) {
526 // Remove possible rangelist (if it was not a range, the domain
527 // must have been narrowed!)
528 if (fst()) {
529 fst()->dispose(home,nullptr,lst());
530 fst(nullptr); holes = 0;
531 }
532 const int min1 = dom.min(); dom.min(min0);
533 const int max1 = dom.max(); dom.max(max0);
534 if ((min0 == min1) && (max0 == max1))
535 return ME_INT_NONE;
536 me = (min0 == max0) ? ME_INT_VAL : ME_INT_BND;
537 goto notify;
538 }
539
540 if (depends || range()) {
541 // Construct new rangelist
542 RangeList* f = new (home) RangeList(min0,max0,nullptr,nullptr);
543 RangeList* l = f;
544 unsigned int s = range_width(min0,max0);
545 do {
546 RangeList* n = new (home) RangeList(ri.min(),ri.max(),l,nullptr);
547 l->next(nullptr,n);
548 l = n;
549 s += ri.width();
550 ++ri;
551 } while (ri());
552 if (fst() != nullptr)
553 fst()->dispose(home,nullptr,lst());
554 fst(f); lst(l);
555
556 // Check for modification
557 if (size() == s)
558 return ME_INT_NONE;
559
560 const int min1 = dom.min(); min0 = f->min(); dom.min(min0);
561 const int max1 = dom.max(); max0 = l->max(); dom.max(max0);
562 holes = width() - s;
563
564 me = ((min0 == min1) && (max0 == max1)) ? ME_INT_DOM : ME_INT_BND;
565 goto notify;
566 } else {
567 // Set up two sentinel elements
568 RangeList f, l;
569 // Put all ranges between sentinels
570 f.prevnext(nullptr,fst()); l.prevnext(lst(),nullptr);
571 fst()->prev(nullptr,&f); lst()->next(nullptr,&l);
572
573 // Number of values removed (potential holes)
574 unsigned int h = 0;
575 // The previous range
576 RangeList* p = &f;
577 // The current range
578 RangeList* r = f.next(nullptr);
579
580 while (true) {
581 assert((r != &f) && (r != &l));
582 if (r->max() < min0) {
583 // Entire range removed
584 h += r->width();
585 RangeList* n=r->next(p);
586 p->next(r,n); n->prev(r,p);
587 r->dispose(home);
588 r=n;
589 if (r == &l)
590 goto done;
591 } else if ((r->min() == min0) && (r->max() == max0)) {
592 // Range unchanged
593 RangeList* n=r->next(p); p=r; r=n;
594 if (r == &l)
595 goto done;
596 if (!ri())
597 goto done;
598 min0=ri.min(); max0=ri.max(); ++ri;
599 } else {
600 // Range might have been split into many small ranges
601 assert((r->min() <= min0) && (max0 <= r->max()));
602 h += r->width();
603 int end = r->max();
604 // Copy first range
605 r->min(min0); r->max(max0);
606 assert(h > r->width());
607 h -= r->width();
608 {
609 RangeList* n=r->next(p); p=r; r=n;
610 }
611 while (true) {
612 if (!ri())
613 goto done;
614 min0=ri.min(); max0=ri.max(); ++ri;
615 if (max0 > end)
616 break;
617 unsigned int w = range_width(min0,max0);
618 assert(h > w);
619 h -= w;
620 RangeList* n = new (home) RangeList(min0,max0,p,r);
621 p->next(r,n); r->prev(p,n);
622 p=n;
623 }
624 if (r == &l)
625 goto done;
626 }
627 }
628 done:
629
630 // Remove remaining ranges
631 while (r != &l) {
632 h += r->width();
633 RangeList* n=r->next(p);
634 p->next(r,n); n->prev(r,p);
635 r->dispose(home);
636 r=n;
637 }
638
639 assert((r == &l) && !ri());
640
641 // New first and last ranges
642 RangeList* fn = f.next(nullptr);
643 RangeList* ln = l.prev(nullptr);
644
645 // All ranges pruned?
646 assert(fn != &l);
647
648 // Only a single range left?
649 assert(fn != ln);
650
651 // The number of removed values
652 holes += h;
653 // Unlink sentinel ranges
654 fn->prev(&f,nullptr); ln->next(&l,nullptr);
655 // How many values where removed at the bounds
656 unsigned int b = (static_cast<unsigned int>(fn->min()) -
657 static_cast<unsigned int>(dom.min()) +
658 static_cast<unsigned int>(dom.max()) -
659 static_cast<unsigned int>(ln->max()));
660 // Set new first and last ranges
661 fst(fn); lst(ln);
662
663 if (b > 0) {
664 assert((dom.min() != fn->min()) || (dom.max() != ln->max()));
665 dom.min(fn->min()); dom.max(ln->max());
666 holes -= b;
667 me = ME_INT_BND; goto notify;
668 }
669
670 if (h > 0) {
671 assert((dom.min() == fn->min()) && (dom.max() == ln->max()));
672 me = ME_INT_DOM; goto notify;
673 }
674 return ME_INT_NONE;
675 }
676 notify:
677 IntDelta d;
678 return notify(home,me,d);
679 }
680
681 template<class I>
682 forceinline ModEvent
683 IntVarImp::inter_r(Space& home, I& i, bool) {
684 IntVarImpFwd j(this);
686 return narrow_r(home,ij,true);
687 }
688
689 template<class I>
690 forceinline ModEvent
691 IntVarImp::minus_r(Space& home, I& i, bool depends) {
692 if (depends) {
693 IntVarImpFwd j(this);
695 return narrow_r(home,ij,true);
696 }
697
698 // Skip all ranges that are too small
699 while (i() && (i.max() < dom.min()))
700 ++i;
701
702 // Is there no range left or all are too large?
703 if (!i() || (i.min() > dom.max()))
704 return ME_INT_NONE;
705
706 int i_min = i.min();
707 int i_max = i.max();
708 ++i;
709
710 if ((i_min <= dom.min()) && (i_max >= dom.max()))
711 return fail(home);
712
713 if ((i_min > dom.min()) && (i_max >= dom.max()))
714 return lq(home,i_min-1);
715
716 if ((i_min <= dom.min()) && (i_max < dom.max()) &&
717 (!i() || (i.min() > dom.max())))
718 return gq(home,i_max+1);
719
720 // Set up two sentinel elements
721 RangeList f, l;
722 // Put all ranges between sentinels
723 if (range()) {
724 // Create a new rangelist just for simplicity
725 RangeList* n = new (home) RangeList(min(),max(),&f,&l);
726 f.prevnext(nullptr,n); l.prevnext(n,nullptr);
727 } else {
728 // Link the two sentinel elements
729 f.prevnext(nullptr,fst()); l.prevnext(lst(),nullptr);
730 fst()->prev(nullptr,&f); lst()->next(nullptr,&l);
731 }
732
733 // Number of values removed (potential holes)
734 unsigned int h = 0;
735 // The previous range
736 RangeList* p = &f;
737 // The current range
738 RangeList* r = f.next(nullptr);
739
740 while (true) {
741 assert((r != &f) && (r != &l));
742 if (i_min > r->max()) {
743 RangeList* n=r->next(p); p=r; r=n;
744 if (r == &l)
745 break;
746 } else if (i_max < r->min()) {
747 if (!i())
748 break;
749 i_min = i.min();
750 i_max = i.max();
751 ++i;
752 } else if ((i_min <= r->min()) && (r->max() <= i_max)) {
753 // r is included in i: remove entire range r
754 h += r->width();
755 RangeList* n=r->next(p);
756 p->next(r,n); n->prev(r,p);
757 r->dispose(home);
758 r=n;
759 if (r == &l)
760 break;
761 } else if ((i_min > r->min()) && (i_max < r->max())) {
762 // i is included in r: create new range before the current one
763 h += range_width(i_min,i_max);
764 RangeList* n = new (home) RangeList(r->min(),i_min-1,p,r);
765 r->min(i_max+1);
766 p->next(r,n); r->prev(p,n);
767 p=n;
768 if (!i())
769 break;
770 i_min = i.min();
771 i_max = i.max();
772 ++i;
773 } else if (i_max < r->max()) {
774 assert(i_min <= r->min());
775 // i ends before r: adjust minimum of r
776 h += range_width(r->min(),i_max);
777 r->min(i_max+1);
778 if (!i())
779 break;
780 i_min = i.min();
781 i_max = i.max();
782 ++i;
783 } else {
784 assert((i_max >= r->max()) && (r->min() < i_min));
785 // r ends before i: adjust maximum of r
786 h += range_width(i_min,r->max());
787 r->max(i_min-1);
788 RangeList* n=r->next(p); p=r; r=n;
789 if (r == &l)
790 break;
791 }
792 }
793
794 // New first and last ranges
795 RangeList* fn = f.next(nullptr);
796 RangeList* ln = l.prev(nullptr);
797
798 // All ranges pruned?
799 if (fn == &l) {
800 fst(nullptr); lst(nullptr); holes=0;
801 return fail(home);
802 }
803
804 ModEvent me;
805 unsigned int b;
806
807 // Only a single range left?
808 if (fn == ln) {
809 assert(h > 0);
810 dom.min(fn->min()); dom.max(fn->max());
811 fn->dispose(home);
812 fst(nullptr); lst(nullptr);
813 holes = 0;
815 goto notify;
816 }
817
818 // The number of removed values
819 holes += h;
820 // Unlink sentinel ranges
821 fn->prev(&f,nullptr); ln->next(&l,nullptr);
822 // How many values where removed at the bounds
823 b = (static_cast<unsigned int>(fn->min()) -
824 static_cast<unsigned int>(dom.min()) +
825 static_cast<unsigned int>(dom.max()) -
826 static_cast<unsigned int>(ln->max()));
827 // Set new first and last ranges
828 fst(fn); lst(ln);
829
830 if (b > 0) {
831 assert((dom.min() != fn->min()) || (dom.max() != ln->max()));
832 dom.min(fn->min()); dom.max(ln->max());
833 holes -= b;
834 me = ME_INT_BND; goto notify;
835 }
836
837 if (h > 0) {
838 assert((dom.min() == fn->min()) && (dom.max() == ln->max()));
839 me = ME_INT_DOM; goto notify;
840 }
841
842 return ME_INT_NONE;
843 notify:
844 IntDelta d;
845 return notify(home,me,d);
846 }
847
848 template<class I>
849 forceinline ModEvent
850 IntVarImp::narrow_v(Space& home, I& i, bool depends) {
852 return narrow_r(home,r,depends);
853 }
854
855 template<class I>
856 forceinline ModEvent
857 IntVarImp::inter_v(Space& home, I& i, bool depends) {
859 return inter_r(home,r,depends);
860 }
861
862 template<class I>
863 forceinline ModEvent
864 IntVarImp::minus_v(Space& home, I& i, bool depends) {
865 if (depends) {
867 return minus_r(home, r, true);
868 }
869
870 // Skip all values that are too small
871 while (i() && (i.val() < dom.min()))
872 ++i;
873
874 // Is there no value left or all are too large?
875 if (!i() || (i.val() > dom.max()))
876 return ME_INT_NONE;
877
878 int v = i.val();
879 // Skip values that are the same
880 do {
881 ++i;
882 } while (i() && (i.val() == v));
883
884 // Is there only a single value to be pruned?
885 if (!i() || (i.val() > dom.max()))
886 return nq_full(home,v);
887
888 // Set up two sentinel elements
889 RangeList f, l;
890 // Put all ranges between sentinels
891 if (range()) {
892 // Create a new rangelist just for simplicity
893 RangeList* n = new (home) RangeList(min(),max(),&f,&l);
894 f.prevnext(nullptr,n); l.prevnext(n,nullptr);
895 } else {
896 // Link the two sentinel elements
897 f.prevnext(nullptr,fst()); l.prevnext(lst(),nullptr);
898 fst()->prev(nullptr,&f); lst()->next(nullptr,&l);
899 }
900
901 // Number of values removed (potential holes)
902 unsigned int h = 0;
903 // The previous range
904 RangeList* p = &f;
905 // The current range
906 RangeList* r = f.next(nullptr);
907
908 while (true) {
909 assert((r != &f) && (r != &l));
910 if (v > r->max()) {
911 // Move to next range
912 RangeList* n=r->next(p); p=r; r=n;
913 if (r == &l)
914 break;
915 } else {
916 if ((v == r->min()) && (v == r->max())) {
917 // Remove range
918 h++;
919 RangeList* n=r->next(p);
920 p->next(r,n); n->prev(r,p);
921 r->dispose(home);
922 r=n;
923 if (r == &l)
924 break;
925 } else if (v == r->min()) {
926 h++; r->min(v+1);
927 } else if (v == r->max()) {
928 h++; r->max(v-1);
929 RangeList* n=r->next(p); p=r; r=n;
930 if (r == &l)
931 break;
932 } else if (v > r->min()) {
933 // Create new range before the current one
934 assert(v < r->max());
935 h++;
936 RangeList* n = new (home) RangeList(r->min(),v-1,p,r);
937 r->min(v+1);
938 p->next(r,n); r->prev(p,n);
939 p=n;
940 }
941 if (!i())
942 break;
943 // Move to next value
944 v = i.val(); ++i;
945 }
946 }
947 assert((r == &l) || !i());
948
949 // New first and last ranges
950 RangeList* fn = f.next(nullptr);
951 RangeList* ln = l.prev(nullptr);
952
953 // All ranges pruned?
954 if (fn == &l) {
955 fst(nullptr); lst(nullptr); holes=0;
956 return fail(home);
957 }
958
959 IntDelta d;
960
961 // Only a single range left?
962 if (fn == ln) {
963 assert(h > 0);
964 dom.min(fn->min()); dom.max(fn->max());
965 fn->dispose(home);
966 fst(nullptr); lst(nullptr);
967 holes = 0;
968 if (assigned())
969 return notify(home,ME_INT_VAL,d);
970 else
971 return notify(home,ME_INT_BND,d);
972 }
973
974 // The number of removed values
975 holes += h;
976 // Unlink sentinel ranges
977 fn->prev(&f,nullptr); ln->next(&l,nullptr);
978 // How many values where removed at the bounds
979 unsigned int b = (static_cast<unsigned int>(fn->min()) -
980 static_cast<unsigned int>(dom.min()) +
981 static_cast<unsigned int>(dom.max()) -
982 static_cast<unsigned int>(ln->max()));
983 // Set new first and last ranges
984 fst(fn); lst(ln);
985
986 if (b > 0) {
987 assert((dom.min() != fn->min()) || (dom.max() != ln->max()));
988 dom.min(fn->min()); dom.max(ln->max());
989 holes -= b;
990 return notify(home,ME_INT_BND,d);
991 }
992
993 if (h > 0) {
994 assert((dom.min() == fn->min()) && (dom.max() == ln->max()));
995 return notify(home,ME_INT_DOM,d);
996 }
997
998 return ME_INT_NONE;
999 }
1000
1001
1002 /*
1003 * Copying a variable
1004 *
1005 */
1006
1007 forceinline IntVarImp*
1009 return copied() ? static_cast<IntVarImp*>(forward())
1010 : perform_copy(home);
1011 }
1012
1013
1014 forceinline ModEventDelta
1018
1019}}
1020
1021// STATISTICS: int-var
Generic domain change information to be supplied to advisors.
Definition core.hpp:209
FreeList * next(void) const
Return next freelist object.
Definition manager.hpp:250
FreeList * _next
Pointer to next freelist object.
Definition manager.hpp:103
Integer sets.
Definition int.hh:178
int min(int i) const
Return minimum of range at position i.
int max(int i) const
Return maximum of range at position i.
int ranges(void) const
Return number of ranges of the specification.
unsigned int width(int i) const
Return width of range at position i.
Integer delta information for advisors.
Definition var-imp.hpp:51
IntVarImpBase(Gecode::Space &home, IntVarImpBase &x)
Constructor for cloning x.
Definition var-imp.hpp:247
Gecode::ModEvent notify(Gecode::Space &home, Gecode::ModEvent me, Gecode::Delta &d)
Notify that variable implementation has been modified with modification event me and delta informatio...
Definition var-imp.hpp:269
unsigned int width(void) const
Return width of range (distance between minimum and maximum).
Definition int.hpp:502
void operator++(void)
Move iterator to previous range (if possible).
Definition int.hpp:489
int max(void) const
Return largest value of range.
Definition int.hpp:498
bool operator()(void) const
Test whether iterator is still at a range or done.
Definition int.hpp:485
int min(void) const
Return smallest value of range.
Definition int.hpp:494
void init(const IntVarImp *x)
Initialize with ranges from variable implementation x.
Definition int.hpp:480
IntVarImpBwd(void)
Default constructor.
Definition int.hpp:475
void init(const IntVarImp *x)
Initialize with ranges from variable implementation x.
Definition int.hpp:442
IntVarImpFwd(void)
Default constructor.
Definition int.hpp:437
bool operator()(void) const
Test whether iterator is still at a range or done.
Definition int.hpp:447
unsigned int width(void) const
Return width of range (distance between minimum and maximum).
Definition int.hpp:464
int min(void) const
Return smallest value of range.
Definition int.hpp:456
void operator++(void)
Move iterator to next range (if possible).
Definition int.hpp:451
int max(void) const
Return largest value of range.
Definition int.hpp:460
Lists of ranges (intervals).
Definition var-imp.hpp:102
unsigned int width(void) const
Return width (distance between maximum and minimum).
Definition int.hpp:114
void fix(RangeList *n)
Restore simple link to next element (so that it becomes a true free list).
Definition int.hpp:92
int _max
Maximum of range.
Definition var-imp.hpp:107
int _min
Minimum of range.
Definition var-imp.hpp:105
RangeList(void)
Default constructor (noop).
Definition int.hpp:57
int min(void) const
Return minimum.
Definition int.hpp:106
void prevnext(RangeList *p, RangeList *n)
Set previous element to p and next element to n.
Definition int.hpp:78
RangeList * prev(const RangeList *n) const
Return previous element (from next n).
Definition int.hpp:74
RangeList * next(const RangeList *p) const
Return next element (from previous p).
Definition int.hpp:70
int max(void) const
Return maximum.
Definition int.hpp:110
void dispose(Space &home, RangeList *p, RangeList *l)
Free memory for all elements between this and l (inclusive).
Definition int.hpp:142
Integer variable implementation.
Definition var-imp.hpp:89
const RangeList * ranges_bwd(void) const
Return range list for backward iteration.
Definition int.hpp:320
RangeList * _lst
Link the last element.
Definition var-imp.hpp:190
RangeList * lst(void) const
Return last element of rangelist.
Definition int.hpp:181
unsigned int width(void) const
Return width of domain (distance between maximum and minimum).
Definition int.hpp:256
ModEvent eq(Space &home, int n)
Restrict domain values to be equal to n.
Definition int.hpp:396
int med(void) const
Return median of domain (greatest element not greater than the median).
ModEvent narrow_v(Space &home, I &i, bool depends=true)
Replace domain by values described by i.
Definition int.hpp:850
unsigned int regret_max(void) const
Return regret of domain maximum (distance to next smaller value).
Definition int.hpp:277
ModEvent inter_v(Space &home, I &i, bool depends=true)
Intersect domain with values described by i.
Definition int.hpp:857
bool in(int n) const
Test whether n is contained in domain.
Definition int.hpp:296
IntVarImp * copy(Space &home)
Return copy of this variable.
Definition int.hpp:1008
bool assigned(void) const
Test whether variable is assigned.
Definition int.hpp:250
ModEvent lq(Space &home, int n)
Restrict domain values to be less or equal than n.
Definition int.hpp:375
ModEvent nq(Space &home, int n)
Restrict domain values to be different from n.
Definition int.hpp:418
int max(void) const
Return maximum of domain.
Definition int.hpp:236
ModEvent minus_v(Space &home, I &i, bool depends=true)
Remove from domain the values described by i.
Definition int.hpp:864
int val(void) const
Return assigned value (only if assigned).
Definition int.hpp:240
RangeList * fst(void) const
Return first element of rangelist.
Definition int.hpp:171
unsigned int size(void) const
Return size (cardinality) of domain.
Definition int.hpp:261
int min(void) const
Return minimum of domain.
Definition int.hpp:232
unsigned int regret_min(void) const
Return regret of domain minimum (distance to next larger value).
Definition int.hpp:266
RangeList dom
Domain information.
Definition var-imp.hpp:188
unsigned int holes
Size of holes in the domain.
Definition var-imp.hpp:200
bool range(void) const
Test whether domain is a range.
Definition int.hpp:246
ModEvent narrow_r(Space &home, I &i, bool depends=true)
Replace domain by ranges described by i.
Definition int.hpp:513
IntVarImp(Space &home, IntVarImp &x)
Constructor for cloning x.
ModEvent inter_r(Space &home, I &i, bool depends=true)
Intersect domain with ranges described by i.
Definition int.hpp:683
friend class IntVarImpFwd
Definition var-imp.hpp:90
ModEvent minus_r(Space &home, I &i, bool depends=true)
Remove from domain the ranges described by i.
Definition int.hpp:691
ModEvent gq(Space &home, int n)
Restrict domain values to be greater or equal than n.
Definition int.hpp:354
const RangeList * ranges_fwd(void) const
Return range list for forward iteration.
Definition int.hpp:315
static bool any(const Delta &d)
Test whether arbitrary values got pruned.
Definition int.hpp:343
Range iterator for computing set difference.
Range iterator for computing intersection (binary).
Range iterator from value iterator.
Computation spaces.
Definition core.hpp:1775
void fl_dispose(FreeList *f, FreeList *l)
Return freelist-managed memory to freelist.
Definition core.hpp:2891
static ModEvent me(const ModEventDelta &med)
Definition core.hpp:4415
static ModEventDelta med(ModEvent me)
Definition core.hpp:4421
#define GECODE_INT_RL2PD(r)
Definition int.hpp:47
#define GECODE_INT_PD2RL(p)
Definition int.hpp:48
int ModEventDelta
Modification event deltas.
Definition core.hpp:94
Finite domain integers.
Definition lastval.hh:52
const Gecode::ModEvent ME_INT_BND
Domain operation has changed the minimum or maximum of the domain.
Definition var-type.hpp:73
const Gecode::ModEvent ME_INT_FAILED
Domain operation has resulted in failure.
Definition var-type.hpp:60
unsigned int range_width(int min, int max)
Definition int.hpp:51
const Gecode::ModEvent ME_INT_VAL
Domain operation has resulted in a value (assigned variable).
Definition var-type.hpp:64
const Gecode::ModEvent ME_INT_DOM
Domain operation has changed the domain.
Definition var-type.hpp:80
const Gecode::ModEvent ME_INT_NONE
Domain operation has not changed domain.
Definition var-type.hpp:62
Gecode toplevel namespace
void min(Home home, FloatVar x0, FloatVar x1, FloatVar x2)
Post propagator for .
void max(Home home, FloatVar x0, FloatVar x1, FloatVar x2)
Post propagator for .
int ModEvent
Type for modification events.
Definition core.hpp:67
#define GECODE_NEVER
Assert that this command is never executed.
Definition macros.hpp:56
#define GECODE_ASSUME(p)
Assert certain property.
Definition macros.hpp:114