Generated on for Gecode by doxygen 1.17.0
compact.hpp
Go to the documentation of this file.
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Linnea Ingmar <linnea.ingmar@hotmail.com>
5 * Christian Schulte <schulte@gecode.dev>
6 *
7 * Copyright:
8 * Linnea Ingmar, 2017
9 * Christian Schulte, 2017
10 *
11 * This file is part of Gecode, the generic constraint
12 * development environment:
13 * http://www.gecode.dev
14 *
15 * Permission is hereby granted, free of charge, to any person obtaining
16 * a copy of this software and associated documentation files (the
17 * "Software"), to deal in the Software without restriction, including
18 * without limitation the rights to use, copy, modify, merge, publish,
19 * distribute, sublicense, and/or sell copies of the Software, and to
20 * permit persons to whom the Software is furnished to do so, subject to
21 * the following conditions:
22 *
23 * The above copyright notice and this permission notice shall be
24 * included in all copies or substantial portions of the Software.
25 *
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 *
34 */
35
36#include <algorithm>
37#include <type_traits>
38
39namespace Gecode { namespace Int { namespace Extensional {
40
41 /*
42 * Shared compact-table advisor
43 *
44 */
45 forceinline
47
48 forceinline int
50 return 0;
51 }
52
53 forceinline
56
57 forceinline int
59 return _index;
60 }
61
62 template<class View, bool pos, bool indexed>
63 forceinline void
65 if (pos) {
66 {
67 int n = view().min();
68 assert((_fst->min <= n) && (n <= _lst->max));
69 while (n > _fst->max)
70 _fst++;
71 assert((_fst->min <= n) && (n <= _lst->max));
72 }
73 {
74 int n = view().max();
75 assert((_fst->min <= n) && (n <= _lst->max));
76 while (n < _lst->min)
77 _lst--;
78 assert((_fst->min <= n) && (n <= _lst->max));
79 }
80 } else {
81 {
82 int n = view().min();
83 while ((_fst <= _lst) && (n > _fst->max))
84 _fst++;
85 }
86 if (_fst > _lst)
87 return;
88 {
89 int n = view().max();
90 while ((_fst < _lst) && (n < _lst->min))
91 _lst--;
92 if (n < _lst->min)
93 _fst = _lst + 1;
94 }
95 }
96 }
97
98 template<class View, bool pos, bool indexed>
99 forceinline
101 (Space& home, Propagator& p,
102 Council<CompactAdvisor>& c, const TupleSet& ts, View x0, int i)
103 : ViewAdvisor<View>(home,p,c,x0), CompactAdvisorIndex<indexed>(i),
104 _fst(ts.fst(i)), _lst(ts.lst(i)) {
105 adjust();
106 }
107
108 template<class View, bool pos, bool indexed>
109 forceinline
114
115 template<class View, bool pos, bool indexed>
116 forceinline int
120
121 template<class View, bool pos, bool indexed>
122 forceinline const typename CompactAdvisor<View,pos,indexed>::Range*
124 return _fst;
125 }
126
127 template<class View, bool pos, bool indexed>
128 forceinline const typename CompactAdvisor<View,pos,indexed>::Range*
130 return _lst;
131 }
132
133 template<class View, bool pos, bool indexed>
134 forceinline void
139
140
141 /*
142 * Shared positive propagator status
143 *
144 */
145 template<class Advisor>
146 forceinline
149
150 template<class Advisor>
151 forceinline
154
155 template<class Advisor>
156 forceinline typename CompactStatus<Advisor>::StatusType
158 return static_cast<StatusType>(s & 3);
159 }
160
161 template<class Advisor>
162 forceinline bool
164 return (type() == SINGLE) &&
165 (reinterpret_cast<Advisor*>(s) == &a);
166 }
167
168 template<class Advisor>
169 forceinline void
171 if (type() == NONE) {
172 s = reinterpret_cast<ptrdiff_t>(&a);
173 assert((s & 3) == SINGLE);
174 } else if ((type() == SINGLE) && !single(a)) {
175 s = MULTIPLE;
176 }
177 }
178
179 template<class Advisor>
180 forceinline void
182 s = NONE;
183 }
184
185 template<class Advisor>
186 forceinline void
190
191
192 /*
193 * Shared clone-time table selection
194 *
195 */
196 template<template<class, class> class TablePropagator, class View>
198 public:
199 template<class Table, class Source>
200 static Actor* copy(Space& home, Source& source) {
201 return new (home) TablePropagator<View,Table>(home,source);
202 }
203 };
204
205 template<template<class, class, class, ReifyMode> class TablePropagator,
206 class View, class CtrlView, ReifyMode rm>
208 public:
209 template<class Table, class Source>
210 static Actor* copy(Space& home, Source& source) {
211 return new (home) TablePropagator<View,Table,CtrlView,rm>(home,source);
212 }
213 };
214
215 template<class Factory, class Table, class Source>
216 Actor*
217 compact_copy(Space& home, Source& source) {
218 // A disabled actor can become empty before it is cloned. Keep the
219 // concrete table type: width-based selection requires an active word.
220 if (source.table.empty())
221 return Factory::template copy<Table>(home,source);
222
223 const unsigned int words = source.table.words();
224 const unsigned int width = source.table.width();
225 assert((words > 0U) && (width >= words));
226
227 if (words <= 4U) {
228 switch (width) {
229 case 0U: GECODE_NEVER; break;
230 case 1U: return Factory::template copy<TinyBitSet<1U>>(home,source);
231 case 2U: return Factory::template copy<TinyBitSet<2U>>(home,source);
232 case 3U: return Factory::template copy<TinyBitSet<3U>>(home,source);
233 case 4U: return Factory::template copy<TinyBitSet<4U>>(home,source);
234 default: break;
235 }
236 }
237
238 if (std::is_same<Table,BitSet<unsigned char>>::value)
239 return Factory::template copy<BitSet<unsigned char>>(home,source);
240
241 switch (Gecode::Support::u_type(width)) {
243 return Factory::template copy<BitSet<unsigned char>>(home,source);
245 return Factory::template copy<BitSet<unsigned short int>>(home,source);
247 if (std::is_same<Table,BitSet<unsigned int>>::value)
248 return Factory::template copy<BitSet<unsigned int>>(home,source);
250 default:
252 }
254 return nullptr;
255 }
256
257 template<class Advisor>
258 forceinline bool
260 Advisors<Advisor> advisors(council);
261 return !advisors();
262 }
263
264 template<class Advisor>
265 forceinline bool
267 Advisors<Advisor> advisors(council);
268 if (!advisors())
269 return true;
270 ++advisors;
271 return !advisors();
272 }
273
274 template<class View, class Advisor, class ValidSupports, class Table>
275 void
277 Council<Advisor>& council, const TupleSet& ts,
278 Table& table, ViewArray<View>& x) {
279 ModEvent me = ME_INT_BND;
280 Region region;
281 BitSetData* mask = region.alloc<BitSetData>(table.size());
282
283 for (int i=0; i<x.size(); i++) {
284 table.clear_mask(mask);
285 for (ValidSupports supports(ts,i,x[i]); supports(); ++supports)
286 table.add_to_mask(supports.support(),mask);
287 table.template intersect_with_mask<false>(mask);
288 if (table.empty())
289 goto schedule;
290 }
291
292 for (int i=0; i<x.size(); i++) {
293 if (!x[i].assigned())
294 (void) new (home) Advisor(home,propagator,council,ts,x[i],i);
295 else
296 me = ME_INT_VAL;
297 }
298
299 schedule:
300 View::schedule(home,propagator,me);
301 }
302
303 template<class Advisor, class Table>
304 forceinline bool
305 compact_full(const Council<Advisor>& council, const Table& table) {
306 unsigned long long int size = 1U;
307 for (Advisors<Advisor> advisors(council); advisors(); ++advisors) {
308 size *= static_cast<unsigned long long int>
309 (advisors.advisor().view().size());
310 if (size > table.bits())
311 return false;
312 }
313 return size == table.ones();
314 }
315
316 template<class Advisor>
317 forceinline PropCost
319 int n = 0;
320 // The value of 3 is cheating from the Gecode kernel...
321 for (Advisors<Advisor> advisors(council);
322 advisors() && (n <= 3); ++advisors)
323 n++;
325 }
326
327 template<class Support>
329
330 template<>
332 public:
333 static bool empty(const BitSetData* support) {
334 return support == nullptr;
335 }
336 template<class Table>
337 static void intersect(Table& table, const BitSetData* support) {
338 table.template intersect_with_mask<true>(support);
339 }
340 };
341
342 template<>
344 public:
345 static bool empty(const CompressedSupport& support) {
346 return support.empty();
347 }
348 template<class Table>
349 static void intersect(Table& table, const CompressedSupport& support) {
350 table.intersect_with_mask(support);
351 }
352 };
353
354 template<class Support>
355 forceinline bool
358 }
359
360 template<class Table, class Support>
361 forceinline void
362 compact_intersect(Table& table, const Support& support) {
364 }
365
366
367 /*
368 * The propagator base class
369 *
370 */
371 template<class View, bool pos>
372 const typename Compact<View,pos>::Range*
374 assert((n > a.fst()->max) && (n < a.lst()->min));
375
376 const Range* f=a.fst()+1;
377 const Range* l=a.lst()-1;
378
379 assert(!pos || (f<=l));
380
381 while (f < l) {
382 const Range* m = f + ((l-f) >> 1);
383 if (n < m->min) {
384 l=m-1;
385 } else if (n > m->max) {
386 f=m+1;
387 } else {
388 f=m; break;
389 }
390 }
391
392 if (pos) {
393 assert((f->min <= n) && (n <= f->max));
394 return f;
395 } else {
396 if ((f <= l) && (f->min <= n) && (n <= f->max))
397 return f;
398 else
399 return nullptr;
400 }
401 }
402
403 template<class View, bool pos>
404 forceinline const BitSetData*
406 const Range* fnd;
407 const Range* fst=a.fst();
408 const Range* lst=a.lst();
409 if (!pos && (fst > lst))
410 return nullptr;
411 if (pos) {
412 if (n <= fst->max) {
413 fnd=fst;
414 } else if (n >= lst->min) {
415 fnd=lst;
416 } else {
417 fnd=range(a,n);
418 }
419 } else {
420 if ((n < fst->min) || (n > lst->max))
421 return nullptr;
422 if (n <= fst->max) {
423 fnd=fst;
424 } else if (n >= lst->min) {
425 fnd=lst;
426 } else {
427 fnd=range(a,n);
428 if (!fnd)
429 return nullptr;
430 }
431 }
432 assert((fnd->min <= n) && (n <= fnd->max));
433 return fnd->supports(n_words,n);
434 }
435
436 template<class View, bool pos>
437 forceinline void
439 assert(!pos);
440 assert(value <= max_value);
441 while (true) {
442 while (view_ranges() && (value > view_ranges.max()))
443 ++view_ranges;
444 if (!view_ranges()) {
445 value = max_value+1; return;
446 }
447 assert(value <= view_ranges.max());
448 value = std::max(value,view_ranges.min());
449
450 while ((support_range <= last_support_range) &&
451 (value > support_range->max))
454 value = max_value+1; return;
455 }
457 value = std::max(value,support_range->min);
458
459 if ((view_ranges.min() <= value) && (value <= view_ranges.max())) {
461 return;
462 }
463 }
465 }
466
467 template<class View, bool pos>
468 forceinline
470 CTAdvisor& a)
471 : n_words(p.n_words), max_value(a.view().max()),
472 view_ranges(a.view()), support_range(a.fst()),
474 if (pos) {
475 while (value > support_range->max)
478 } else {
479 support_words = nullptr; // To avoid warnings
480 find();
481 }
482 }
483 template<class View, bool pos>
484 forceinline
486 int i, View x)
487 : n_words(ts.words()), max_value(x.max()),
488 view_ranges(x), support_range(ts.fst(i)),
490 if (pos) {
491 while (value > support_range->max)
494 } else {
495 support_words = nullptr; // To avoid warnings
496 find();
497 }
498 }
499 template<class View, bool pos>
500 forceinline void
502 value++;
503 if (pos) {
504 if (value <= view_ranges.max()) {
505 assert(value <= support_range->max);
507 } else if (value <= max_value) {
508 while (value > view_ranges.max())
509 ++view_ranges;
510 value = view_ranges.min();
511 while (value > support_range->max)
514 assert((view_ranges.min() <= value) &&
515 (value <= view_ranges.max()));
516 assert((support_range->min <= value) &&
517 (value <= support_range->max));
518 assert(support_range->min <= view_ranges.min());
519 }
520 } else {
521 if ((value <= support_range->max) &&
522 (value <= view_ranges.max())) {
524 } else if (value <= max_value) {
525 find();
526 }
527 }
528 }
529 template<class View, bool pos>
530 forceinline bool
534 template<class View, bool pos>
535 forceinline const BitSetData*
538 return support_words;
539 }
540 template<class View, bool pos>
541 forceinline int
545
546 /*
547 * Lost supports iterator
549 */
550 template<class View, bool pos>
551 forceinline
553 (const Compact<View,pos>& p, CTAdvisor& a,
554 int first_value, int last_value0)
555 : n_words(p.n_words), support_range(a.fst()),
556 last_support_range(a.lst()), value(first_value),
557 last_value(last_value0) {
558 assert(pos);
559 // Move to first value for which there is support
560 while (value > support_range->max)
562 value = std::max(value,support_range->min);
564 }
565 template<class View, bool pos>
566 forceinline void
568 value++;
570 while ((value <= last_value) && (value > support_range->max)) {
575 }
576 template<class View, bool pos>
577 forceinline bool
581 template<class View, bool pos>
582 forceinline const TupleSet::BitSetData*
584 assert((value >= support_range->min) && (value <= support_range->max));
585 assert(support_words == support_range->supports(n_words,value));
586 return support_words;
587 }
588
589 template<class View, bool pos>
590 forceinline bool
592 return compact_all(c);
593 }
594 template<class View, bool pos>
595 forceinline bool
597 return compact_atmostone(c);
598 }
600 template<class View, bool pos>
601 forceinline
603 : Propagator(home,p), n_words(p.n_words), ts(p.ts) {
604 c.update(home,p.c);
605 }
607 template<class View, bool pos>
608 forceinline
610 : Propagator(home), n_words(ts0.words()), ts(ts0), c(home) {
611 home.notice(*this, AP_DISPOSE);
612 }
613
614 template<class View, bool pos>
615 template<class Table>
616 void
619 (home,*this,c,ts,table,x);
620 }
621
622 template<class View, bool pos>
623 template<class Table>
624 forceinline bool
625 Compact<View,pos>::full(const Table& table) const {
626 return compact_full(c,table);
627 }
628
629 template<class View, bool pos>
632 return compact_cost(c);
633 }
634
635 template<class View, bool pos>
636 forceinline size_t
638 home.ignore(*this,AP_DISPOSE);
639 c.dispose(home);
640 ts.~TupleSet();
641 (void) Propagator::dispose(home);
642 return sizeof(*this);
643 }
644
645 template<class Actor>
647 public:
648 static void reschedule(Actor& actor, Space& home) {
649 if ((actor.status.type() != Actor::StatusType::NONE) ||
650 actor.all() || actor.table.empty())
651 Actor::ViewType::schedule(home,actor,ME_INT_DOM);
652 }
653
654 static ExecStatus propagate(Actor& actor, Space& home) {
655 if (actor.table.empty())
656 return ES_FAILED;
657 if (actor.all())
658 return home.ES_SUBSUMED(actor);
659
660 typename Actor::Status touched(actor.status);
661 actor.status.propagating();
662 Region region;
663 for (Advisors<typename Actor::CTAdvisor> advisors(actor.c);
664 advisors(); ++advisors) {
665 typename Actor::CTAdvisor& advisor = advisors.advisor();
666 typename Actor::ViewType view = advisor.view();
667 if (touched.single(advisor) || view.assigned())
668 continue;
669
670 if (view.size() == 2) {
671 if (!actor.table.intersects(actor.supports(advisor,view.min())))
672 GECODE_ME_CHECK(view.eq(home,view.max()));
673 else if (!actor.table.intersects(actor.supports(advisor,view.max())))
674 GECODE_ME_CHECK(view.eq(home,view.min()));
675 if (!view.assigned())
676 advisor.adjust();
677 } else {
678 int* remove = region.alloc<int>(view.size());
679 unsigned int n_remove = 0U;
680 int last_support = 0;
681 for (typename Actor::ValidSupports supports(actor,advisor);
682 supports(); ++supports)
683 if (!actor.table.intersects(supports.support()))
684 remove[n_remove++] = supports.val();
685 else
686 last_support = supports.val();
687 if (n_remove > 0U) {
688 if (n_remove == 1U) {
689 GECODE_ME_CHECK(view.nq(home,remove[0]));
690 } else if (n_remove == view.size() - 1U) {
691 GECODE_ME_CHECK(view.eq(home,last_support));
692 goto noadjust;
693 } else {
694 Iter::Values::Array values(remove,n_remove);
695 GECODE_ASSUME(n_remove >= 2U);
696 GECODE_ME_CHECK(view.minus_v(home,values,false));
697 }
698 advisor.adjust();
699 noadjust: ;
700 }
701 region.free();
702 }
703 }
704 actor.status.none();
705 assert(!actor.table.empty());
706 return actor.atmostone() ? home.ES_SUBSUMED(actor) : ES_FIX;
707 }
708
709 static ExecStatus advise(Actor& actor, Space& home, Advisor& advisor0,
710 const Delta& delta) {
711 typename Actor::CTAdvisor& advisor =
712 static_cast<typename Actor::CTAdvisor&>(advisor0);
713 if (actor.table.empty())
714 return actor.disabled() ?
715 home.ES_NOFIX_DISPOSE(actor.c,advisor) : ES_FAILED;
716
717 typename Actor::ViewType view = advisor.view();
718 if (actor.status.type() == Actor::StatusType::PROPAGATING)
719 return view.assigned() ?
720 home.ES_FIX_DISPOSE(actor.c,advisor) : ES_FIX;
721 actor.status.touched(advisor);
722
723 if (view.assigned()) {
724 const auto support = actor.supports(advisor,view.val());
725 if (compact_support_empty(support))
726 actor.table.flush();
727 else
728 compact_intersect(actor.table,support);
729 return home.ES_NOFIX_DISPOSE(actor.c,advisor);
730 }
731
732 if (!view.any(delta) && (view.min(delta) == view.max(delta))) {
733 const auto support = actor.supports(advisor,view.min(delta));
734 if (!compact_support_empty(support))
735 actor.table.nand_with_mask(support);
736 advisor.adjust();
737 } else if (!view.any(delta) &&
738 (view.width(delta) <= view.size())) {
739 for (typename Actor::LostSupports supports
740 (actor,advisor,view.min(delta),view.max(delta));
741 supports(); ++supports) {
742 actor.table.nand_with_mask(supports.support());
743 if (actor.table.empty())
744 return actor.disabled() ?
745 home.ES_NOFIX_DISPOSE(actor.c,advisor) : ES_FAILED;
746 }
747 advisor.adjust();
748 } else {
749 advisor.adjust();
750 if (view.size() == 2) {
751 const auto min_support = actor.supports(advisor,view.min());
752 const auto max_support = actor.supports(advisor,view.max());
753 const bool has_min = !compact_support_empty(min_support);
754 const bool has_max = !compact_support_empty(max_support);
755 if (has_min && has_max)
756 actor.table.intersect_with_masks(min_support,max_support);
757 else if (has_min)
758 compact_intersect(actor.table,min_support);
759 else if (has_max)
760 compact_intersect(actor.table,max_support);
761 else
762 actor.table.flush();
763 } else {
764 Region region;
765 BitSetData* mask = region.alloc<BitSetData>(actor.table.size());
766 actor.table.clear_mask(mask);
767 for (typename Actor::ValidSupports supports(actor,advisor);
768 supports(); ++supports)
769 actor.table.add_to_mask(supports.support(),mask);
770 actor.table.template intersect_with_mask<false>(mask);
771 }
772 }
773
774 if (actor.table.empty())
775 return actor.disabled() ?
776 home.ES_NOFIX_DISPOSE(actor.c,advisor) : ES_FAILED;
777 return ES_NOFIX;
778 }
779 };
780
781 template<class Actor>
783 public:
784 static void reschedule(Actor& actor, Space& home) {
785 Actor::ViewType::schedule(home,actor,ME_INT_DOM);
786 }
787
788 static ExecStatus propagate(Actor& actor, Space& home) {
789#ifndef NDEBUG
790 if (!actor.table.empty())
791 for (Advisors<typename Actor::CTAdvisor> advisors(actor.c);
792 advisors(); ++advisors) {
793 typename Actor::ValidSupports supports(actor,advisors.advisor());
794 assert(supports());
795 }
796#endif
797 if (actor.table.empty())
798 return home.ES_SUBSUMED(actor);
799
800 unsigned long long product_without_largest = 1U;
801 unsigned long long largest_domain = 1U;
802 for (Advisors<typename Actor::CTAdvisor> advisors(actor.c);
803 advisors(); ++advisors) {
804 const unsigned long long size = advisors.advisor().view().size();
805 if (size > largest_domain) {
806 product_without_largest *= largest_domain;
807 largest_domain = size;
808 } else {
809 product_without_largest *= size;
810 }
811 if (product_without_largest > actor.table.bits())
812 return ES_FIX;
813 }
814 if (product_without_largest > actor.table.ones())
815 return ES_FIX;
816
817 unsigned long long product = product_without_largest * largest_domain;
818 Region region;
819 for (Advisors<typename Actor::CTAdvisor> advisors(actor.c);
820 advisors(); ++advisors) {
821 assert(!actor.table.empty());
822 typename Actor::CTAdvisor& advisor = advisors.advisor();
823 typename Actor::ViewType view = advisor.view();
824 product /= static_cast<unsigned long long>(view.size());
825 if ((product <= actor.table.bits()) &&
826 (product <= actor.table.ones())) {
827 int* remove = region.alloc<int>(view.size());
828 unsigned int n_remove = 0U;
829 for (typename Actor::ValidSupports supports(actor,advisor);
830 supports(); ++supports)
831 if (product == actor.table.ones(supports.support()))
832 remove[n_remove++] = supports.val();
833 if (n_remove > 0U) {
834 if (n_remove == 1U) {
835 GECODE_ME_CHECK(view.nq(home,remove[0]));
836 } else {
837 Iter::Values::Array values(remove,n_remove);
838 GECODE_ASSUME(n_remove >= 2U);
839 GECODE_ME_CHECK(view.minus_v(home,values,false));
840 }
841 if (actor.table.empty())
842 return home.ES_SUBSUMED(actor);
843 advisor.adjust();
844 }
845 region.free();
846 }
847 product *= static_cast<unsigned long long>(view.size());
848 }
849
850 if (actor.table.ones() == product)
851 return ES_FAILED;
852 if (actor.table.empty() || actor.atmostone())
853 return home.ES_SUBSUMED(actor);
854 return ES_FIX;
855 }
856
857 static ExecStatus advise(Actor& actor, Space& home, Advisor& advisor0) {
858 typename Actor::CTAdvisor& advisor =
859 static_cast<typename Actor::CTAdvisor&>(advisor0);
860 if (actor.table.empty())
861 return home.ES_NOFIX_DISPOSE(actor.c,advisor);
862
863 typename Actor::ViewType view = advisor.view();
864 advisor.adjust();
865 if (view.assigned()) {
866 const auto support = actor.supports(advisor,view.val());
867 if (compact_support_empty(support))
868 actor.table.flush();
869 else
870 compact_intersect(actor.table,support);
871 return home.ES_NOFIX_DISPOSE(actor.c,advisor);
872 }
873
874 typename Actor::ValidSupports supports(actor,advisor);
875 if (!supports()) {
876 actor.table.flush();
877 return home.ES_NOFIX_DISPOSE(actor.c,advisor);
878 }
879 Region region;
880 BitSetData* mask = region.alloc<BitSetData>(actor.table.size());
881 actor.table.clear_mask(mask);
882 do {
883 actor.table.add_to_mask(supports.support(),mask);
884 ++supports;
885 } while (supports());
886 actor.table.template intersect_with_mask<false>(mask);
887
888 if (actor.table.empty())
889 return home.ES_NOFIX_DISPOSE(actor.c,advisor);
890 return ES_NOFIX;
891 }
892 };
893
894 template<class Actor>
896 public:
897 static void reschedule(Actor& actor, Space& home) {
898 Actor::ViewType::schedule(home,actor,ME_INT_DOM);
899 }
900
901 static ExecStatus propagate(Actor& actor, Space& home) {
902 if (actor.b.one()) {
903 if (Actor::mode == RM_PMI)
904 return home.ES_SUBSUMED(actor);
905 TupleSet keep(actor.ts);
906 GECODE_REWRITE(actor,Actor::post_pos(home(actor),actor.y,keep));
907 }
908 if (actor.b.zero()) {
909 if (Actor::mode == RM_IMP)
910 return home.ES_SUBSUMED(actor);
911 TupleSet keep(actor.ts);
912 GECODE_REWRITE(actor,Actor::post_neg(home(actor),actor.y,keep));
913 }
914
915 if (actor.table.empty()) {
916 if (Actor::mode != RM_PMI)
917 GECODE_ME_CHECK(actor.b.zero_none(home));
918 return home.ES_SUBSUMED(actor);
919 }
920 if (actor.full(actor.table)) {
921 if (Actor::mode != RM_IMP)
922 GECODE_ME_CHECK(actor.b.one_none(home));
923 return home.ES_SUBSUMED(actor);
924 }
925 return ES_FIX;
926 }
927
928 static ExecStatus advise(Actor& actor, Space& home, Advisor& advisor0) {
929 typename Actor::CTAdvisor& advisor =
930 static_cast<typename Actor::CTAdvisor&>(advisor0);
931 if (actor.table.empty() || actor.b.assigned())
932 return home.ES_NOFIX_DISPOSE(actor.c,advisor);
933
934 typename Actor::ViewType view = advisor.view();
935 advisor.adjust();
936 if (view.assigned()) {
937 const auto support = actor.supports(advisor,view.val());
938 if (compact_support_empty(support))
939 actor.table.flush();
940 else
941 compact_intersect(actor.table,support);
942 return home.ES_NOFIX_DISPOSE(actor.c,advisor);
943 }
944
945 typename Actor::ValidSupports supports(actor,advisor);
946 if (!supports()) {
947 actor.table.flush();
948 return home.ES_NOFIX_DISPOSE(actor.c,advisor);
949 }
950 Region region;
951 BitSetData* mask = region.alloc<BitSetData>(actor.table.size());
952 actor.table.clear_mask(mask);
953 do {
954 actor.table.add_to_mask(supports.support(),mask);
955 ++supports;
956 } while (supports());
957 actor.table.template intersect_with_mask<false>(mask);
958
959 if (actor.table.empty())
960 return home.ES_NOFIX_DISPOSE(actor.c,advisor);
961 return ES_NOFIX;
962 }
963 };
964
965
966 /*
967 * The propagator proper
968 *
969 */
970 template<class View, class Table>
971 template<class TableProp>
972 forceinline
974 : Compact<View,true>(home,p),
975 status(p.status.type() == StatusType::NONE ?
976 Status::NONE : Status::MULTIPLE),
977 table(home,p.table) {}
978
979 template<class View, class Table>
980 Actor*
985
986 template<class View, class Table>
987 forceinline
989 const TupleSet& ts)
990 : Compact<View,true>(home,ts), status(Status::MULTIPLE),
991 table(home,ts.words()) {
992 setup(home,table,x);
993 }
994
995 template<class View, class Table>
996 forceinline ExecStatus
998 const TupleSet& ts) {
999 auto ct = new (home) PosCompact(home,x,ts);
1000 assert((x.size() > 1) && (ts.tuples() > 1));
1001 return ct->table.empty() ? ES_FAILED : ES_OK;
1002 }
1003
1004 template<class View, class Table>
1005 forceinline size_t
1007 (void) Compact<View,true>::dispose(home);
1008 return sizeof(*this);
1009 }
1010 template<class View, class Table>
1011 void
1015
1016 template<class View, class Table>
1021
1022 template<class View, class Table>
1025 const Delta& delta) {
1027 (*this,home,advisor,delta);
1028 }
1029 /*
1030 * Post function
1031 */
1032 template<class View>
1035 if (ts.tuples() == 0)
1036 return (x.size() == 0) ? ES_OK : ES_FAILED;
1037
1038 // All variables pruned to correct domain
1039 for (int i=0; i<x.size(); i++) {
1040 TupleSet::Ranges r(ts,i);
1041 GECODE_ME_CHECK(x[i].inter_r(home, r, false));
1042 }
1043
1044 if ((x.size() <= 1) || (ts.tuples() <= 1))
1045 return ES_OK;
1046
1047 // Choose the right bit set implementation
1048 switch (ts.words()) {
1049 case 0U:
1050 GECODE_NEVER; return ES_OK;
1051 case 1U:
1052 return PosCompact<View,TinyBitSet<1U>>::post(home,x,ts);
1053 case 2U:
1054 return PosCompact<View,TinyBitSet<2U>>::post(home,x,ts);
1055 case 3U:
1056 return PosCompact<View,TinyBitSet<3U>>::post(home,x,ts);
1057 case 4U:
1058 return PosCompact<View,TinyBitSet<4U>>::post(home,x,ts);
1059 default:
1060 switch (Gecode::Support::u_type(ts.words())) {
1063 ::post(home,x,ts);
1066 ::post(home,x,ts);
1069 ::post(home,x,ts);
1070 default: GECODE_NEVER;
1071 }
1072 }
1074 return ES_OK;
1075 }
1076
1077
1078 /*
1079 * The negative propagator
1080 *
1081 */
1082 template<class View, class Table>
1083 template<class TableProp>
1084 forceinline
1086 : Compact<View,false>(home,p), table(home,p.table) {}
1087
1088 template<class View, class Table>
1089 Actor*
1092 return compact_copy<Factory,Table>(home,*this);
1093 }
1094
1095 template<class View, class Table>
1096 forceinline
1098 const TupleSet& ts)
1099 : Compact<View,false>(home,ts), table(home,ts.words()) {
1100 setup(home,table,x);
1101 }
1102
1103 template<class View, class Table>
1104 forceinline ExecStatus
1106 const TupleSet& ts) {
1107 auto ct = new (home) NegCompact(home,x,ts);
1108 return ct->full(ct->table) ? ES_FAILED : ES_OK;
1109 }
1110
1111 template<class View, class Table>
1112 forceinline size_t
1114 (void) Compact<View,false>::dispose(home);
1115 return sizeof(*this);
1116 }
1117
1118 template<class View, class Table>
1119 void
1123
1124 template<class View, class Table>
1129
1130 template<class View, class Table>
1133 const Delta&) {
1134 return NegCompactAlgorithm<NegCompact>::advise(*this,home,advisor);
1135 }
1136
1137
1138 /*
1139 * Post function
1140 */
1141 template<class View>
1144 if (ts.tuples() == 0)
1145 return ES_OK;
1146
1147 // Check whether a variable does not overlap with supported values
1148 for (int i=0; i<x.size(); i++) {
1149 TupleSet::Ranges rs(ts,i);
1150 ViewRanges<View> rx(x[i]);
1151 if (Iter::Ranges::disjoint(rs,rx))
1152 return ES_OK;
1153 }
1154
1155 // Choose the right bit set implementation
1156 switch (ts.words()) {
1157 case 0U:
1158 GECODE_NEVER; return ES_OK;
1159 case 1U:
1160 return NegCompact<View,TinyBitSet<1U>>::post(home,x,ts);
1161 case 2U:
1162 return NegCompact<View,TinyBitSet<2U>>::post(home,x,ts);
1163 case 3U:
1164 return NegCompact<View,TinyBitSet<3U>>::post(home,x,ts);
1165 case 4U:
1166 return NegCompact<View,TinyBitSet<4U>>::post(home,x,ts);
1167 default:
1168 switch (Gecode::Support::u_type(ts.words())) {
1171 ::post(home,x,ts);
1174 ::post(home,x,ts);
1177 ::post(home,x,ts);
1178 default: GECODE_NEVER;
1179 }
1180 }
1182 return ES_OK;
1183 }
1184
1185
1186 /*
1187 * The reified propagator
1188 *
1189 */
1190 template<class View, class Table, class CtrlView, ReifyMode rm>
1191 template<class TableProp>
1192 forceinline
1194 : Compact<View,false>(home,p), table(home,p.table) {
1195 b.update(home,p.b);
1196 y.update(home,p.y);
1197 }
1198
1199 template<class View, class Table, class CtrlView, ReifyMode rm>
1200 Actor*
1205
1206 template<class View, class Table, class CtrlView, ReifyMode rm>
1207 forceinline
1209 const TupleSet& ts, CtrlView b0)
1210 : Compact<View,false>(home,ts), table(home,ts.words()), b(b0), y(x) {
1211 b.subscribe(home,*this,PC_BOOL_VAL);
1212 setup(home,table,x);
1213 }
1214
1215 template<class View, class Table, class CtrlView, ReifyMode rm>
1216 forceinline ExecStatus
1218 const TupleSet& ts, CtrlView b) {
1219 if (b.one()) {
1220 if (rm == RM_PMI)
1221 return ES_OK;
1222 return postposcompact(home,x,ts);
1223 }
1224 if (b.zero()) {
1225 if (rm == RM_IMP)
1226 return ES_OK;
1227 return postnegcompact(home,x,ts);
1228 }
1229 (void) new (home) ReCompact(home,x,ts,b);
1230 return ES_OK;
1231 }
1232
1233 template<class View, class Table, class CtrlView, ReifyMode rm>
1236 (Home home, ViewArray<View>& x, const TupleSet& ts) {
1237 return postposcompact(home,x,ts);
1238 }
1239
1240 template<class View, class Table, class CtrlView, ReifyMode rm>
1243 (Home home, ViewArray<View>& x, const TupleSet& ts) {
1244 return postnegcompact(home,x,ts);
1245 }
1246
1247 template<class View, class Table, class CtrlView, ReifyMode rm>
1248 forceinline size_t
1250 b.cancel(home,*this,PC_BOOL_VAL);
1251 (void) Compact<View,false>::dispose(home);
1252 return sizeof(*this);
1253 }
1254
1255 template<class View, class Table, class CtrlView, ReifyMode rm>
1256 void
1260
1261 template<class View, class Table, class CtrlView, ReifyMode rm>
1267
1268 template<class View, class Table, class CtrlView, ReifyMode rm>
1271 (Space& home, Advisor& advisor, const Delta&) {
1272 return ReCompactAlgorithm<ReCompact>::advise(*this,home,advisor);
1273 }
1274
1275
1276 /*
1277 * Post function
1278 */
1279 template<class View, class CtrlView, ReifyMode rm>
1282 CtrlView b) {
1283 // Enforce invariant that there is at least one tuple...
1284 if (ts.tuples() == 0) {
1285 if (x.size() != 0) {
1286 if (rm != RM_PMI)
1287 GECODE_ME_CHECK(b.zero(home));
1288 } else {
1289 if (rm != RM_IMP)
1290 GECODE_ME_CHECK(b.one(home));
1291 }
1292 return ES_OK;
1293 }
1294 // Check whether a variable does not overlap with supported values
1295 for (int i=0; i<x.size(); i++) {
1296 TupleSet::Ranges rs(ts,i);
1297 ViewRanges<View> rx(x[i]);
1298 if (Iter::Ranges::disjoint(rs,rx)) {
1299 if (rm != RM_PMI)
1300 GECODE_ME_CHECK(b.zero(home));
1301 return ES_OK;
1302 }
1303 }
1304 // Choose the right bit set implementation
1305 switch (ts.words()) {
1306 case 0U:
1307 GECODE_NEVER; return ES_OK;
1308 case 1U:
1309 return ReCompact<View,TinyBitSet<1U>,CtrlView,rm>::post(home,x,ts,b);
1310 case 2U:
1311 return ReCompact<View,TinyBitSet<2U>,CtrlView,rm>::post(home,x,ts,b);
1312 case 3U:
1313 return ReCompact<View,TinyBitSet<3U>,CtrlView,rm>::post(home,x,ts,b);
1314 case 4U:
1315 return ReCompact<View,TinyBitSet<4U>,CtrlView,rm>::post(home,x,ts,b);
1316 default:
1317 switch (Gecode::Support::u_type(ts.words())) {
1319 return ReCompact<View,BitSet<unsigned char>,CtrlView,rm>
1320 ::post(home,x,ts,b);
1323 ::post(home,x,ts,b);
1325 return ReCompact<View,BitSet<unsigned int>,CtrlView,rm>
1326 ::post(home,x,ts,b);
1327 default: GECODE_NEVER;
1328 }
1329 }
1331 return ES_OK;
1332 }
1333
1334 /*
1335 * Compact table with compressed supports
1336 *
1337 */
1338 template<class View, bool pos>
1340 protected:
1344
1346 protected:
1355 bool valid;
1356 void find(void) {
1357 while (view_ranges() && (support_range <= last_support_range)) {
1358 if (value < view_ranges.min())
1359 value = view_ranges.min();
1360 if (value > view_ranges.max()) {
1361 ++view_ranges;
1362 if (view_ranges())
1363 value = view_ranges.min();
1364 continue;
1365 }
1366 while ((support_range <= last_support_range) &&
1367 (value > support_range->max))
1368 support_range++;
1370 break;
1372 value = support_range->min;
1373 continue;
1374 }
1375 if (value > view_ranges.max()) {
1376 ++view_ranges;
1377 if (view_ranges())
1378 value = view_ranges.min();
1379 continue;
1380 }
1383 support_end)) {
1384 valid = true;
1385 return;
1386 }
1387 value++;
1388 }
1389 valid = false;
1390 }
1391 public:
1393 : tuple_set(p.ts), view_ranges(a.view()), variable(a.index()),
1394 support_range(a.fst()), last_support_range(a.lst()), value(0),
1395 support_begin(nullptr), support_end(nullptr), valid(false) {
1396 if (view_ranges()) {
1397 value = view_ranges.min();
1398 find();
1399 }
1400 }
1401 ValidSupports(const TupleSet& ts0, int i0, View x)
1402 : tuple_set(ts0), view_ranges(x), variable(i0),
1403 support_range(ts0.fst(i0)), last_support_range(ts0.lst(i0)),
1404 value(0), support_begin(nullptr), support_end(nullptr),
1405 valid(false) {
1406 if (view_ranges()) {
1407 value = view_ranges.min();
1408 find();
1409 }
1410 }
1411 void operator ++(void) {
1412 value++;
1413 find();
1414 }
1415 bool operator ()(void) const {
1416 return valid;
1417 }
1418 int val(void) const {
1419 return value;
1420 }
1424 };
1425
1427 protected:
1436 bool valid;
1437 void find(void) {
1438 while ((value <= last_value) &&
1441 value = support_range->min;
1442 if (value > last_value)
1443 break;
1444 while ((support_range <= last_support_range) &&
1445 (value > support_range->max))
1446 support_range++;
1448 break;
1450 continue;
1452 advisor.index(),value,
1454 support_end)) {
1455 valid = true;
1456 return;
1457 }
1458 value++;
1459 }
1460 valid = false;
1461 }
1462 public:
1464 int first_value, int last_value0)
1465 : propagator(p0), advisor(a0), support_range(a0.fst()),
1466 last_support_range(a0.lst()), value(first_value),
1467 last_value(last_value0),
1468 support_begin(nullptr), support_end(nullptr), valid(false) {
1469 assert(pos);
1470 find();
1471 }
1472 void operator ++(void) {
1473 value++;
1474 find();
1475 }
1476 bool operator ()(void) const {
1477 return valid;
1478 }
1482 };
1483
1484 bool all(void) const {
1485 return compact_all(c);
1486 }
1487 bool atmostone(void) const {
1488 return compact_atmostone(c);
1489 }
1490
1491 protected:
1492 const unsigned int n_words;
1495
1497 : Propagator(home,p), n_words(p.n_words), ts(p.ts), c(home) {
1498 c.update(home,p.c);
1499 }
1501 : Propagator(home), n_words(ts0.words()), ts(ts0), c(home) {
1502 home.notice(*this, AP_DISPOSE);
1503 }
1504
1506 const CSupportWord* begin = nullptr;
1507 const CSupportWord* end = nullptr;
1509 (ts,a.index(),n,begin,end))
1510 return CompressedSupport();
1511 return CompressedSupport(begin,end);
1512 }
1513
1514 template<class Table>
1515 void setup(Space& home, Table& table, ViewArray<View>& x) {
1517 (home,*this,c,ts,table,x);
1518 }
1519
1520 template<class Table>
1521 bool full(const Table& table) const {
1522 return compact_full(c,table);
1523 }
1524
1525 public:
1526 virtual PropCost cost(const Space&, const ModEventDelta&) const {
1527 return compact_cost(c);
1528 }
1529 size_t dispose(Space& home) {
1530 home.ignore(*this,AP_DISPOSE);
1531 c.dispose(home);
1532 ts.~TupleSet();
1533 (void) Propagator::dispose(home);
1534 return sizeof(*this);
1535 }
1536 };
1537
1538 template<class View, class Table>
1539 class PosCompactCompressed : public CompactCompressed<View,true> {
1540 template<class Actor> friend class PosCompactAlgorithm;
1541 public:
1544 typedef typename Base::ValidSupports ValidSupports;
1545 typedef typename Base::CTAdvisor CTAdvisor;
1546 typedef typename Base::LostSupports LostSupports;
1547
1548 using Base::setup;
1549 using Base::supports;
1550 using Base::all;
1551 using Base::atmostone;
1552 using Base::c;
1553 using Base::ts;
1554
1557
1559 Table table;
1560
1561 template<class TableProp>
1562 PosCompactCompressed(Space& home, TableProp& p)
1563 : Base(home,p),
1564 status(p.status.type() == StatusType::NONE ?
1565 Status::NONE : Status::MULTIPLE),
1566 table(home,p.table) {}
1568 : Base(home,ts), status(Status::MULTIPLE),
1569 table(home,ts.words(),true) {
1570 setup(home,table,x);
1571 }
1572
1573 virtual Actor* copy(Space& home) {
1575 return compact_copy<Factory,Table>(home,*this);
1576 }
1577
1578 static ExecStatus post(Home home, ViewArray<View>& x, const TupleSet& ts) {
1579 auto ct = new (home) PosCompactCompressed(home,x,ts);
1580 assert((x.size() > 1) && (ts.tuples() > 1));
1581 return ct->table.empty() ? ES_FAILED : ES_OK;
1582 }
1583
1584 virtual size_t dispose(Space& home) {
1585 (void) Base::dispose(home);
1586 return sizeof(*this);
1587 }
1588
1589 virtual void reschedule(Space& home) {
1591 }
1592
1593 virtual ExecStatus propagate(Space& home, const ModEventDelta&) {
1595 }
1596
1597 virtual ExecStatus advise(Space& home, Advisor& advisor,
1598 const Delta& delta) {
1600 (*this,home,advisor,delta);
1601 }
1602 };
1603
1604 template<class View>
1607 if (ts.tuples() == 0)
1608 return (x.size() == 0) ? ES_OK : ES_FAILED;
1609
1610 for (int i=0; i<x.size(); i++) {
1611 TupleSet::Ranges r(ts,i);
1612 GECODE_ME_CHECK(x[i].inter_r(home, r, false));
1613 }
1614 if ((x.size() <= 1) || (ts.tuples() <= 1))
1615 return ES_OK;
1616
1617 switch (ts.words()) {
1618 case 0U: GECODE_NEVER; return ES_OK;
1619 case 1U: return PosCompactCompressed<View,TinyBitSet<1U>>::post(home,x,ts);
1620 case 2U: return PosCompactCompressed<View,TinyBitSet<2U>>::post(home,x,ts);
1621 case 3U: return PosCompactCompressed<View,TinyBitSet<3U>>::post(home,x,ts);
1622 case 4U: return PosCompactCompressed<View,TinyBitSet<4U>>::post(home,x,ts);
1623 default:
1624 switch (Gecode::Support::u_type(ts.words())) {
1631 default:
1633 }
1634 }
1636 return ES_OK;
1637 }
1638
1639 template<class View, class Table>
1640 class NegCompactCompressed : public CompactCompressed<View,false> {
1641 template<class Actor> friend class NegCompactAlgorithm;
1642 public:
1645 typedef typename Base::ValidSupports ValidSupports;
1646 typedef typename Base::CTAdvisor CTAdvisor;
1647
1648 using Base::setup;
1649 using Base::full;
1650 using Base::supports;
1651 using Base::atmostone;
1652 using Base::c;
1653 using Base::ts;
1654
1655 Table table;
1656
1657 template<class TableProp>
1658 NegCompactCompressed(Space& home, TableProp& p)
1659 : Base(home,p), table(home,p.table) {}
1661 : Base(home,ts), table(home,ts.words(),true) {
1662 setup(home,table,x);
1663 }
1664
1665 virtual Actor* copy(Space& home) {
1667 return compact_copy<Factory,Table>(home,*this);
1668 }
1669
1670 static ExecStatus post(Home home, ViewArray<View>& x, const TupleSet& ts) {
1671 auto ct = new (home) NegCompactCompressed(home,x,ts);
1672 return ct->full(ct->table) ? ES_FAILED : ES_OK;
1673 }
1674
1675 virtual size_t dispose(Space& home) {
1676 (void) Base::dispose(home);
1677 return sizeof(*this);
1678 }
1679
1680 virtual void reschedule(Space& home) {
1682 }
1683
1684 virtual ExecStatus propagate(Space& home, const ModEventDelta&) {
1686 }
1687
1688 virtual ExecStatus advise(Space& home, Advisor& advisor, const Delta&) {
1690 (*this,home,advisor);
1691 }
1692 };
1693
1694 template<class View>
1697 if (ts.tuples() == 0)
1698 return ES_OK;
1699
1700 for (int i=0; i<x.size(); i++) {
1701 TupleSet::Ranges rs(ts,i);
1702 ViewRanges<View> rx(x[i]);
1703 if (Iter::Ranges::disjoint(rs,rx))
1704 return ES_OK;
1705 }
1706
1707 switch (ts.words()) {
1708 case 0U: GECODE_NEVER; return ES_OK;
1709 case 1U: return NegCompactCompressed<View,TinyBitSet<1U>>::post(home,x,ts);
1710 case 2U: return NegCompactCompressed<View,TinyBitSet<2U>>::post(home,x,ts);
1711 case 3U: return NegCompactCompressed<View,TinyBitSet<3U>>::post(home,x,ts);
1712 case 4U: return NegCompactCompressed<View,TinyBitSet<4U>>::post(home,x,ts);
1713 default:
1714 switch (Gecode::Support::u_type(ts.words())) {
1721 default:
1723 }
1724 }
1726 return ES_OK;
1727 }
1728
1729 template<class View, class Table, class CtrlView, ReifyMode rm>
1730 class ReCompactCompressed : public CompactCompressed<View,false> {
1731 template<class Actor> friend class ReCompactAlgorithm;
1732 public:
1734 static constexpr ReifyMode mode = rm;
1736 typedef typename Base::ValidSupports ValidSupports;
1737 typedef typename Base::CTAdvisor CTAdvisor;
1738
1739 using Base::setup;
1740 using Base::full;
1741 using Base::supports;
1742 using Base::c;
1743 using Base::ts;
1744
1745 Table table;
1746 CtrlView b;
1748
1749 template<class TableProp>
1750 ReCompactCompressed(Space& home, TableProp& p)
1751 : Base(home,p), table(home,p.table) {
1752 b.update(home,p.b);
1753 y.update(home,p.y);
1754 }
1756 CtrlView b0)
1757 : Base(home,ts), table(home,ts.words(),true), b(b0), y(x) {
1758 b.subscribe(home,*this,PC_BOOL_VAL);
1759 setup(home,table,x);
1760 }
1761
1762 virtual Actor* copy(Space& home) {
1763 typedef ReCompactActorFactory
1764 <ReCompactCompressed,View,CtrlView,rm> Factory;
1765 return compact_copy<Factory,Table>(home,*this);
1766 }
1767
1769 CtrlView b) {
1770 if (b.one()) {
1771 if (rm == RM_PMI)
1772 return ES_OK;
1773 return postposcompact_compressed(home,x,ts);
1774 }
1775 if (b.zero()) {
1776 if (rm == RM_IMP)
1777 return ES_OK;
1778 return postnegcompact_compressed(home,x,ts);
1779 }
1780 (void) new (home) ReCompactCompressed(home,x,ts,b);
1781 return ES_OK;
1782 }
1783
1785 const TupleSet& ts) {
1786 return postposcompact_compressed(home,x,ts);
1787 }
1788
1790 const TupleSet& ts) {
1791 return postnegcompact_compressed(home,x,ts);
1792 }
1793
1794 virtual size_t dispose(Space& home) {
1795 b.cancel(home,*this,PC_BOOL_VAL);
1796 (void) Base::dispose(home);
1797 return sizeof(*this);
1798 }
1799
1800 virtual void reschedule(Space& home) {
1802 }
1803
1804 virtual ExecStatus propagate(Space& home, const ModEventDelta&) {
1806 }
1807
1808 virtual ExecStatus advise(Space& home, Advisor& advisor, const Delta&) {
1810 (*this,home,advisor);
1811 }
1812 };
1813
1814 template<class View, class CtrlView, ReifyMode rm>
1817 CtrlView b) {
1818 if (ts.tuples() == 0) {
1819 if (x.size() != 0) {
1820 if (rm != RM_PMI)
1821 GECODE_ME_CHECK(b.zero(home));
1822 } else {
1823 if (rm != RM_IMP)
1824 GECODE_ME_CHECK(b.one(home));
1825 }
1826 return ES_OK;
1827 }
1828 for (int i=0; i<x.size(); i++) {
1829 TupleSet::Ranges rs(ts,i);
1830 ViewRanges<View> rx(x[i]);
1831 if (Iter::Ranges::disjoint(rs,rx)) {
1832 if (rm != RM_PMI)
1833 GECODE_ME_CHECK(b.zero(home));
1834 return ES_OK;
1835 }
1836 }
1837
1838 switch (ts.words()) {
1839 case 0U: GECODE_NEVER; return ES_OK;
1840 case 1U:
1841 return ReCompactCompressed<View,TinyBitSet<1U>,CtrlView,rm>::post(home,x,ts,b);
1842 case 2U:
1843 return ReCompactCompressed<View,TinyBitSet<2U>,CtrlView,rm>::post(home,x,ts,b);
1844 case 3U:
1845 return ReCompactCompressed<View,TinyBitSet<3U>,CtrlView,rm>::post(home,x,ts,b);
1846 case 4U:
1847 return ReCompactCompressed<View,TinyBitSet<4U>,CtrlView,rm>::post(home,x,ts,b);
1848 default:
1849 switch (Gecode::Support::u_type(ts.words())) {
1852 ::post(home,x,ts,b);
1855 ::post(home,x,ts,b);
1858 ::post(home,x,ts,b);
1859 default:
1861 }
1862 }
1864 return ES_OK;
1865 }
1866
1867}}}
1868
1869// STATISTICS: int-prop
Base-class for both propagators and branchers.
Definition core.hpp:635
virtual size_t dispose(Space &home)
Delete actor and return its size.
Definition core.hpp:3358
Base-class for advisors.
Definition core.hpp:1301
friend class Council
Definition core.hpp:1303
Class to iterate over advisors of a council.
Definition core.hpp:1275
Council of advisors
Definition core.hpp:1250
Generic domain change information to be supplied to advisors.
Definition core.hpp:209
Home class for posting propagators
Definition core.hpp:863
void notice(Actor &a, ActorProperty p, bool duplicate=false)
Notice actor property.
Definition core.hpp:3301
static Actor * copy(Space &home, Source &source)
Definition compact.hpp:200
CompactAdvisorIndex(int i)
Initialize without storing i.
Definition compact.hpp:46
CompactAdvisorIndex(int i)
Initialize with index i.
Definition compact.hpp:54
Optional variable index stored by a compact-table advisor.
Advisor shared by compact-table support representations.
TupleSet::Range Range
Range type for supports.
const Range * _fst
First range of support data structure.
void dispose(Space &home, Council< CompactAdvisor > &c)
Dispose advisor.
Definition compact.hpp:136
const Range * lst(void) const
Return last range of support data structure.
Definition compact.hpp:129
const Range * _lst
Last range of support data structure.
const Range * fst(void) const
Return first range of support data structure.
Definition compact.hpp:123
int index(void) const
Return the variable index.
Definition compact.hpp:117
CompactAdvisor(Space &home, Propagator &p, Council< CompactAdvisor > &c, const TupleSet &ts, View x, int i)
Initialize from parameters.
Definition compact.hpp:101
void adjust(void)
Adjust supports to the current view bounds.
Definition compact.hpp:64
const CompactCompressed< View, pos > & propagator
Definition compact.hpp:1428
LostSupports(const CompactCompressed< View, pos > &p0, CTAdvisor &a0, int first_value, int last_value0)
Definition compact.hpp:1463
ValidSupports(const CompactCompressed< View, pos > &p, CTAdvisor &a)
Definition compact.hpp:1392
ValidSupports(const TupleSet &ts0, int i0, View x)
Definition compact.hpp:1401
CompactCompressed(Home home, const TupleSet &ts0)
Definition compact.hpp:1500
virtual PropCost cost(const Space &, const ModEventDelta &) const
Cost function.
Definition compact.hpp:1526
bool full(const Table &table) const
Definition compact.hpp:1521
CompactAdvisor< View, pos, true > CTAdvisor
Definition compact.hpp:1343
CompactCompressed(Space &home, CompactCompressed &p)
Definition compact.hpp:1496
CompressedSupport supports(CTAdvisor &a, int n) const
Definition compact.hpp:1505
void setup(Space &home, Table &table, ViewArray< View > &x)
Definition compact.hpp:1515
size_t dispose(Space &home)
Delete actor and return its size.
Definition compact.hpp:1529
Touched-advisor status shared by positive compact-table propagators.
ptrdiff_t s
A tagged advisor pointer or a status value.
void propagating(void)
Record that propagation is in progress.
Definition compact.hpp:187
@ PROPAGATING
The propagator is currently running.
@ NONE
No view has been touched.
@ SINGLE
A single view has been touched.
@ MULTIPLE
Multiple views have been touched.
CompactStatus(StatusType t)
Initialize with status t.
Definition compact.hpp:147
void touched(Advisor &a)
Record that advisor a was touched.
Definition compact.hpp:170
void none(void)
Record that no advisor has been touched.
Definition compact.hpp:181
bool single(Advisor &a) const
Test whether only advisor a was touched.
Definition compact.hpp:163
StatusType type(void) const
Return status type.
Definition compact.hpp:157
static bool empty(const CompressedSupport &support)
Definition compact.hpp:345
static void intersect(Table &table, const CompressedSupport &support)
Definition compact.hpp:349
static void intersect(Table &table, const BitSetData *support)
Definition compact.hpp:337
const Range * support_range
Range information.
const BitSetData * support(void) const
Return support representation.
Definition compact.hpp:583
LostSupports(const Compact< View, pos > &p, CTAdvisor &a, int first_value, int last_value)
Initialize iterator for values between first_value and last_value.
Definition compact.hpp:553
bool operator()(void) const
Whether iterator is done.
Definition compact.hpp:578
void operator++(void)
Move iterator to next value.
Definition compact.hpp:567
const unsigned int n_words
Number of words.
const BitSetData * support_words
The lost value's support.
const Range * last_support_range
The last range.
ViewRanges< View > view_ranges
Range iterator.
bool operator()(void) const
Whether there are still supports left.
Definition compact.hpp:531
const BitSetData * support(void) const
Return support representation.
Definition compact.hpp:536
void operator++(void)
Move to next supports.
Definition compact.hpp:501
ValidSupports(const Compact< View, pos > &p, CTAdvisor &a)
Initialize from initialized propagator.
Definition compact.hpp:469
const BitSetData * support_words
The value's support.
void find(void)
Find a new value (only for negative case).
Definition compact.hpp:438
const unsigned int n_words
Number of words.
int val(void) const
Return supported value.
Definition compact.hpp:542
const Range * support_range
Support iterator.
Compact(Space &home, Compact &p)
Constructor for cloning p.
Definition compact.hpp:602
size_t dispose(Space &home)
Delete propagator and return its size.
Definition compact.hpp:637
const BitSetData * supports(CTAdvisor &a, int n)
Return supports for value n.
Definition compact.hpp:405
CompactAdvisor< View, pos, false > CTAdvisor
Advisor for updating current table.
bool full(const Table &table) const
Check whether the table covers the whole Cartedion product.
Definition compact.hpp:625
void setup(Space &home, Table &table, ViewArray< View > &x)
Setup the actual table.
Definition compact.hpp:617
const unsigned int n_words
Number of words in supports.
virtual PropCost cost(const Space &home, const ModEventDelta &med) const
Cost function.
Definition compact.hpp:631
bool all(void) const
Whether all variables are assigned.
Definition compact.hpp:591
const Range * range(CTAdvisor &a, int n)
Find range for n.
Definition compact.hpp:373
bool atmostone(void) const
Whether at most one variable is unassigned.
Definition compact.hpp:596
TupleSet::Range Range
Range type for supports.
Council< CTAdvisor > c
The advisor council.
Compressed tuple-word support list.
bool empty(void) const
Whether support list is empty.
Definition bit-set.hpp:60
Shared implementation of negative compact-table propagation.
Definition compact.hpp:782
static ExecStatus propagate(Actor &actor, Space &home)
Definition compact.hpp:788
static ExecStatus advise(Actor &actor, Space &home, Advisor &advisor0)
Definition compact.hpp:857
static void reschedule(Actor &actor, Space &home)
Definition compact.hpp:784
NegCompactCompressed(Home home, ViewArray< View > &x, const TupleSet &ts)
Definition compact.hpp:1660
virtual ExecStatus propagate(Space &home, const ModEventDelta &)
Propagation function.
Definition compact.hpp:1684
void setup(Space &home, Table &table, ViewArray< View > &x)
Definition compact.hpp:1515
virtual ExecStatus advise(Space &home, Advisor &advisor, const Delta &)
Advise function.
Definition compact.hpp:1688
CompactCompressed< View, false > Base
Definition compact.hpp:1644
virtual Actor * copy(Space &home)
Create copy.
Definition compact.hpp:1665
NegCompactCompressed(Space &home, TableProp &p)
Definition compact.hpp:1658
virtual void reschedule(Space &home)
Schedule function.
Definition compact.hpp:1680
static ExecStatus post(Home home, ViewArray< View > &x, const TupleSet &ts)
Definition compact.hpp:1670
virtual size_t dispose(Space &home)
Delete actor and return its size.
Definition compact.hpp:1675
Domain consistent negative extensional propagator.
virtual Actor * copy(Space &home)
Copy propagator during cloning.
Definition compact.hpp:1090
virtual ExecStatus advise(Space &home, Advisor &a, const Delta &d)
Give advice to propagator.
Definition compact.hpp:1132
virtual ExecStatus propagate(Space &home, const ModEventDelta &med)
Perform propagation.
Definition compact.hpp:1126
NegCompact(Space &home, TableProp &p)
Constructor for cloning p.
Definition compact.hpp:1085
size_t dispose(Space &home)
Delete propagator and return its size.
Definition compact.hpp:1113
virtual void reschedule(Space &home)
Schedule function.
Definition compact.hpp:1120
static ExecStatus post(Home home, ViewArray< View > &x, const TupleSet &ts)
Post propagator for views x and table t.
Definition compact.hpp:1105
Shared implementation of positive compact-table propagation.
Definition compact.hpp:646
static void reschedule(Actor &actor, Space &home)
Definition compact.hpp:648
static ExecStatus advise(Actor &actor, Space &home, Advisor &advisor0, const Delta &delta)
Definition compact.hpp:709
static ExecStatus propagate(Actor &actor, Space &home)
Definition compact.hpp:654
virtual Actor * copy(Space &home)
Create copy.
Definition compact.hpp:1573
PosCompactCompressed(Space &home, TableProp &p)
Definition compact.hpp:1562
CompactCompressed< View, true > Base
Definition compact.hpp:1543
PosCompactCompressed(Home home, ViewArray< View > &x, const TupleSet &ts)
Definition compact.hpp:1567
static ExecStatus post(Home home, ViewArray< View > &x, const TupleSet &ts)
Definition compact.hpp:1578
void setup(Space &home, Table &table, ViewArray< View > &x)
Definition compact.hpp:1515
virtual void reschedule(Space &home)
Schedule function.
Definition compact.hpp:1589
virtual size_t dispose(Space &home)
Delete actor and return its size.
Definition compact.hpp:1584
virtual ExecStatus propagate(Space &home, const ModEventDelta &)
Propagation function.
Definition compact.hpp:1593
virtual ExecStatus advise(Space &home, Advisor &advisor, const Delta &delta)
Advise function.
Definition compact.hpp:1597
Domain consistent positive extensional propagator.
size_t dispose(Space &home)
Delete propagator and return its size.
Definition compact.hpp:1006
virtual Actor * copy(Space &home)
Copy propagator during cloning.
Definition compact.hpp:981
virtual ExecStatus advise(Space &home, Advisor &a, const Delta &d)
Give advice to propagator.
Definition compact.hpp:1024
virtual ExecStatus propagate(Space &home, const ModEventDelta &med)
Perform propagation.
Definition compact.hpp:1018
Status status
Propagator status.
CompactStatus< CTAdvisor > Status
Status management.
static ExecStatus post(Home home, ViewArray< View > &x, const TupleSet &ts)
Post propagator for views x and table t.
Definition compact.hpp:997
virtual void reschedule(Space &home)
Schedule function.
Definition compact.hpp:1012
PosCompact(Space &home, TableProp &p)
Constructor for cloning p.
Definition compact.hpp:973
Status::StatusType StatusType
Status type.
static Actor * copy(Space &home, Source &source)
Definition compact.hpp:210
Shared implementation of reified compact-table propagation.
Definition compact.hpp:895
static ExecStatus propagate(Actor &actor, Space &home)
Definition compact.hpp:901
static ExecStatus advise(Actor &actor, Space &home, Advisor &advisor0)
Definition compact.hpp:928
static void reschedule(Actor &actor, Space &home)
Definition compact.hpp:897
virtual Actor * copy(Space &home)
Create copy.
Definition compact.hpp:1762
ReCompactCompressed(Space &home, TableProp &p)
Definition compact.hpp:1750
static ExecStatus post(Home home, ViewArray< View > &x, const TupleSet &ts, CtrlView b)
Definition compact.hpp:1768
static ExecStatus post_neg(Home home, ViewArray< View > &x, const TupleSet &ts)
Definition compact.hpp:1789
CompactCompressed< View, false > Base
Definition compact.hpp:1735
virtual size_t dispose(Space &home)
Delete actor and return its size.
Definition compact.hpp:1794
static ExecStatus post_pos(Home home, ViewArray< View > &x, const TupleSet &ts)
Definition compact.hpp:1784
void setup(Space &home, Table &table, ViewArray< View > &x)
Definition compact.hpp:1515
virtual ExecStatus propagate(Space &home, const ModEventDelta &)
Propagation function.
Definition compact.hpp:1804
ReCompactCompressed(Home home, ViewArray< View > &x, const TupleSet &ts, CtrlView b0)
Definition compact.hpp:1755
virtual ExecStatus advise(Space &home, Advisor &advisor, const Delta &)
Advise function.
Definition compact.hpp:1808
virtual void reschedule(Space &home)
Schedule function.
Definition compact.hpp:1800
Domain consistent reified extensional propagator.
virtual Actor * copy(Space &home)
Copy propagator during cloning.
Definition compact.hpp:1201
ViewArray< View > y
The views (for rewriting).
virtual ExecStatus advise(Space &home, Advisor &a, const Delta &d)
Give advice to propagator.
Definition compact.hpp:1271
virtual ExecStatus propagate(Space &home, const ModEventDelta &med)
Perform propagation.
Definition compact.hpp:1264
ReCompact(Space &home, TableProp &p)
Constructor for cloning p.
Definition compact.hpp:1193
static ExecStatus post(Home home, ViewArray< View > &x, const TupleSet &ts, CtrlView b)
Post propagator for views x and table t.
Definition compact.hpp:1217
static ExecStatus post_neg(Home home, ViewArray< View > &x, const TupleSet &ts)
Definition compact.hpp:1243
static ExecStatus post_pos(Home home, ViewArray< View > &x, const TupleSet &ts)
Definition compact.hpp:1236
CtrlView b
Boolean control view.
virtual void reschedule(Space &home)
Schedule function.
Definition compact.hpp:1257
size_t dispose(Space &home)
Delete propagator and return its size.
Definition compact.hpp:1249
static bool dense_compressed_support(const TupleSet &ts, int p, int n, const TupleSet::CSupportWord *&b, const TupleSet::CSupportWord *&e)
Return compressed support words for position/value.
Range iterator for integer views.
Definition view.hpp:54
Value iterator for array of integers
Propagation cost.
Definition core.hpp:493
static PropCost quadratic(PropCost::Mod m, unsigned int n)
Quadratic complexity for modifier m and size measure n.
Definition core.hpp:4963
@ HI
Expensive.
Definition core.hpp:521
Base-class for propagators.
Definition core.hpp:1073
friend class Space
Definition core.hpp:1075
friend class Advisor
Definition core.hpp:1077
friend class Council
Definition core.hpp:1078
Propagator(Home home)
Constructor for posting.
Definition core.hpp:3607
Handle to region.
Definition region.hpp:55
void free(void)
Free allocate memory.
Definition region.hpp:356
T * alloc(long unsigned int n)
Allocate block of n objects of type T from region.
Definition region.hpp:386
Computation spaces.
Definition core.hpp:1775
Compressed support data for one tuple-word block.
Definition int.hh:2393
Range information.
Definition int.hh:2399
int max
Maximum value.
Definition int.hh:2404
int min
Minimum value.
Definition int.hh:2402
const BitSetData * supports(unsigned int n_words, int n) const
Return the dense supports for value n.
Definition tuple-set.hpp:50
Iterator over ranges.
Definition int.hh:2649
Class representing a set of tuples.
Definition int.hh:2382
int tuples(void) const
Number of tuples.
unsigned int words(void) const
Return number of required bit set words.
Gecode::Support::BitSetData BitSetData
Import bit set data type.
Definition int.hh:2391
ViewAdvisor(Space &home, Propagator &p, Council< A > &c, View x0)
Constructor for creation.
Definition advisor.hpp:66
void dispose(Space &home, Council< A > &c)
Delete advisor.
Definition advisor.hpp:90
View view(void) const
Access view.
Definition advisor.hpp:79
View arrays.
Definition array.hpp:255
int size(void) const
Return size of array (number of elements).
Definition array.hpp:1156
ExecStatus ES_FIX_DISPOSE(Council< A > &c, A &a)
Advisor a must be disposed
Definition core.hpp:4006
ExecStatus ES_NOFIX_DISPOSE(Council< A > &c, A &a)
Advisor a must be disposed and its propagator must be run
Definition core.hpp:4013
ExecStatus ES_SUBSUMED(Propagator &p)
Propagator p is subsumed
Definition core.hpp:3672
void ignore(Actor &a, ActorProperty p, bool duplicate=false)
Ignore actor property.
Definition core.hpp:4213
int ModEventDelta
Modification event deltas.
Definition core.hpp:94
#define GECODE_ME_CHECK(me)
Check whether modification event me is failed, and forward failure.
Definition macros.hpp:52
#define GECODE_REWRITE(prop, post)
Rewrite propagator by executing post function.
Definition macros.hpp:116
@ AP_DISPOSE
Actor must always be disposed.
Definition core.hpp:569
ReifyMode
Mode for reification.
Definition int.hh:882
@ RM_IMP
Implication for reification.
Definition int.hh:896
@ RM_PMI
Inverse implication for reification.
Definition int.hh:903
Extensional propagators
Definition int.hh:2335
PropCost compact_cost(const Council< Advisor > &council)
Definition compact.hpp:318
ExecStatus postnegcompact(Home home, ViewArray< View > &x, const TupleSet &ts)
Post function for compact table propagator.
Definition compact.hpp:1143
void compact_intersect(Table &table, const Support &support)
Definition compact.hpp:362
bool compact_atmostone(const Council< Advisor > &council)
Definition compact.hpp:266
ExecStatus postposcompact(Home home, ViewArray< View > &x, const TupleSet &ts)
Post function for positive compact table propagator.
Definition compact.hpp:1034
Gecode::Support::BitSetData BitSetData
Import type.
ExecStatus postrecompact(Home home, ViewArray< View > &x, const TupleSet &ts, CtrlView b)
Post function for compact table propagator.
Definition compact.hpp:1281
bool compact_support_empty(const Support &support)
Definition compact.hpp:356
bool compact_all(const Council< Advisor > &council)
Definition compact.hpp:259
ExecStatus postposcompact_compressed(Home home, ViewArray< View > &x, const TupleSet &ts)
Post function for positive compact table with compressed supports.
Definition compact.hpp:1606
bool compact_full(const Council< Advisor > &council, const Table &table)
Definition compact.hpp:305
Actor * compact_copy(Space &home, Source &source)
Definition compact.hpp:217
void compact_setup(Space &home, Propagator &propagator, Council< Advisor > &council, const TupleSet &ts, Table &table, ViewArray< View > &x)
Definition compact.hpp:276
ExecStatus postnegcompact_compressed(Home home, ViewArray< View > &x, const TupleSet &ts)
Post function for negative compact table with compressed supports.
Definition compact.hpp:1696
ExecStatus postrecompact_compressed(Home home, ViewArray< View > &x, const TupleSet &ts, CtrlView b)
Post function for reified compact table with compressed supports.
Definition compact.hpp:1816
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::PropCond PC_BOOL_VAL
Propagate when a view becomes assigned (single value).
Definition var-type.hpp:134
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
bool disjoint(I &i, J &j)
Check whether range iterators i and j are disjoint.
Support algorithms and datastructures
IntType u_type(unsigned int n)
Return type required to represent n.
Definition int-type.hpp:147
@ IT_CHAR
char integer type
Definition int-type.hpp:40
@ IT_INT
integer type
Definition int-type.hpp:42
@ IT_SHRT
short integer type
Definition int-type.hpp:41
Gecode toplevel namespace
void min(Home home, FloatVar x0, FloatVar x1, FloatVar x2)
Post propagator for .
void range(Home home, const IntVarArgs &x, SetVar y, SetVar z)
Post constraint .
Definition aliases.hpp:158
void values(Home home, const IntVarArgs &x, IntSet y, IntPropLevel ipl=IPL_DEF)
Post constraint .
Definition aliases.hpp:143
TFE post(PropagatorGroup g)
Only post functions (but not propagators) from g are considered.
TFE propagator(PropagatorGroup g)
Only propagators (but not post functions) from g are considered.
ExecStatus
Definition core.hpp:479
@ ES_OK
Execution is okay.
Definition core.hpp:483
@ ES_FIX
Propagation has computed fixpoint.
Definition core.hpp:484
@ ES_FAILED
Execution has resulted in failure.
Definition core.hpp:481
@ ES_NOFIX
Propagation has not computed fixpoint.
Definition core.hpp:482
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