Generated on for Gecode by doxygen 1.15.0
extensional-tuple-set.cpp
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 * Mikael Zayenz Lagerkvist <lagerkvist@gecode.dev>
6 * Christian Schulte <schulte@gecode.dev>
7 *
8 * Copyright:
9 * Linnea Ingmar, 2017
10 * Mikael Zayenz Lagerkvist, 2007
11 * Christian Schulte, 2017
12 *
13 * This file is part of Gecode, the generic constraint
14 * development environment:
15 * http://www.gecode.dev
16 *
17 * Permission is hereby granted, free of charge, to any person obtaining
18 * a copy of this software and associated documentation files (the
19 * "Software"), to deal in the Software without restriction, including
20 * without limitation the rights to use, copy, modify, merge, publish,
21 * distribute, sublicense, and/or sell copies of the Software, and to
22 * permit persons to whom the Software is furnished to do so, subject to
23 * the following conditions:
24 *
25 * The above copyright notice and this permission notice shall be
26 * included in all copies or substantial portions of the Software.
27 *
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 *
36 */
37
39
40namespace Gecode { namespace Int { namespace Extensional {
41
49 protected:
52 int upper;
53 int value;
54 int last;
55
56 void
57 set_range(int lower) {
58 if ((r == e) || (r->min > upper)) {
59 r = e;
60 return;
61 }
62 value = (r->min < lower) ? lower : r->min;
63 last = (r->max < upper) ? r->max : upper;
64 }
65
66 public:
67 SparseDeltaValues(const TupleSet& ts, int i, int lower, int upper0)
68 : r(ts.fst(i)), e(ts.lst(i)+1), upper(upper0), value(0), last(0) {
69 const TupleSet::Range* l = r;
70 const TupleSet::Range* u = e;
71 while (l < u) {
72 const TupleSet::Range* m = l + (u-l) / 2;
73 if (m->max < lower)
74 l = m + 1;
75 else
76 u = m;
77 }
78 r = l;
79 set_range(lower);
80 }
81
82 bool
83 operator ()(void) const {
84 return r != e;
85 }
86
87 void
89 if (value != last) {
90 value++;
91 return;
92 }
93 r++;
94 set_range(r == e ? 0 : r->min);
95 }
96
97 int
98 val(void) const {
99 assert(r != e);
100 return value;
101 }
102 };
103
105 template<class View>
106 class SparseAdvisor : public ViewAdvisor<View> {
107 public:
108 using ViewAdvisor<View>::view;
109 protected:
111 public:
113 View x, int variable0)
114 : ViewAdvisor<View>(home,p,c,x), variable(variable0) {}
116 : ViewAdvisor<View>(home,advisor), variable(advisor.variable) {}
117 int index(void) const {
118 return variable;
119 }
121 (void) ViewAdvisor<View>::dispose(home,c);
122 }
123 };
124
126 template<class View>
127 unsigned long long
128 domain_product(const ViewArray<View>& x, unsigned long long limit,
129 int excluded=-1) {
130 unsigned long long product = 1ULL;
131 for (int i=0; i<x.size(); i++) {
132 if (i == excluded)
133 continue;
134 const unsigned long long size =
135 static_cast<unsigned long long>(x[i].size());
136 if ((product > limit) ||
137 ((size > 0ULL) && (product > limit / size)))
138 return limit + 1ULL;
139 product *= size;
140 }
141 return product;
142 }
143
150 template<class Derived, class View>
152 protected:
154 int arity;
155 unsigned int n_tuples;
156 unsigned int n_vals;
157 unsigned int* active_ids;
158 unsigned int* pos_in_active;
159 unsigned int active_limit;
161 const unsigned int* tv;
162
163 forceinline Derived&
164 derived(void) {
165 return static_cast<Derived&>(*this);
166 }
167
168 forceinline const unsigned int*
169 tuple_gids(unsigned int tid) const {
170 const unsigned long long index =
171 static_cast<unsigned long long>(tid) *
172 static_cast<unsigned long long>(arity);
173 return tv + index;
174 }
175
176 forceinline unsigned int
177 tuple_gid(unsigned int tid, int variable) const {
178 const unsigned int gid = tuple_gids(tid)[variable];
179 assert(gid < n_vals);
180 return gid;
181 }
182
183 bool
184 remove_tuple(unsigned int tid) {
185 if (tid >= n_tuples)
186 return false;
187 const unsigned int position = pos_in_active[tid];
188 if ((position >= active_limit) ||
189 (active_ids[position] != tid))
190 return false;
191
192 const unsigned int last = active_limit - 1U;
193 const unsigned int last_tid = active_ids[last];
194 active_ids[position] = last_tid;
195 pos_in_active[last_tid] = position;
196 active_limit = last;
197 return true;
198 }
199
200 void
201 deactivate_value_support(int variable, int value) {
202 const unsigned int* begin = nullptr;
203 const unsigned int* end = nullptr;
204 unsigned int gid = 0U;
205 if (TupleSetAccess::sparse_support(ts,variable,value,begin,end,gid) &&
206 derived().support_active(gid))
207 for (const unsigned int* tuple=begin; tuple<end; tuple++)
208 derived().deactivate_tuple(*tuple);
209 }
210
211 void
212 deactivate_for_domain(int variable, const View& view) {
213 unsigned int position = 0U;
214 while (position < active_limit) {
215 const unsigned int tid = active_ids[position];
216 const unsigned int gid = tuple_gid(tid,variable);
217 if (!view.in(gid_val[gid]))
218 derived().deactivate_tuple(tid);
219 else
220 position++;
221 }
222 }
223
224 void
225 deactivate_removed_values(int variable, const View& view,
226 const Delta& delta) {
227 if (view.assigned() || view.any(delta)) {
228 deactivate_for_domain(variable,view);
229 return;
230 }
231 const unsigned int scan_limit = active_limit;
232 unsigned int scanned = 0U;
233 for (SparseDeltaValues values(ts,variable,view.min(delta),
234 view.max(delta)); values(); ++values) {
235 if (scanned == scan_limit) {
236 deactivate_for_domain(variable,view);
237 return;
238 }
239 scanned++;
240 const int value = values.val();
241 if (!view.in(value)) {
242 deactivate_value_support(variable,value);
243 if (active_limit == 0U)
244 return;
245 }
246 }
247 }
248
249 void
251 unsigned int position = 0U;
252 while (position < active_limit) {
253 const unsigned int tid = active_ids[position];
254 const unsigned int* row = tuple_gids(tid);
255 bool keep = true;
256 for (int variable=0; variable<arity; variable++)
257 if (!x[variable].in(gid_val[row[variable]])) {
258 keep = false;
259 break;
260 }
261 if (keep)
262 position++;
263 else
264 derived().deactivate_tuple(tid);
265 }
266 }
267
269 : ts(ts0), arity(x.size()),
270 n_tuples(static_cast<unsigned int>(ts0.tuples())),
271 n_vals(TupleSetAccess::sparse_values(ts0)),
272 active_ids(static_cast<Space&>(home).alloc<unsigned int>(n_tuples)),
273 pos_in_active(static_cast<Space&>(home).alloc<unsigned int>(n_tuples)),
275 gid_val(static_cast<Space&>(home).alloc<int>(n_vals)),
276 tv(TupleSetAccess::sparse_tuple_value_ids(ts0)) {
277 assert(tv != nullptr);
278 for (unsigned int i=0U; i<n_tuples; i++) {
279 active_ids[i] = i;
280 pos_in_active[i] = i;
281 }
282 for (unsigned int i=0U; i<n_vals; i++)
283 gid_val[i] = 0;
284 for (int variable=0; variable<x.size(); variable++)
285 for (const TupleSet::Range* range=ts.fst(variable);
286 range<=ts.lst(variable); range++) {
287 unsigned int gid = 0U;
288 if (!TupleSetAccess::support_id(ts,variable,range->min,gid))
290 int value = range->min;
291 while (true) {
292 assert(gid < n_vals);
293 gid_val[gid] = value;
294 if (value == range->max)
295 break;
296 value++;
297 gid++;
298 }
299 }
300 }
301
303 : ts(state.ts), arity(state.arity), n_tuples(state.n_tuples),
304 n_vals(state.n_vals),
305 active_ids(home.alloc<unsigned int>(state.n_tuples)),
306 pos_in_active(home.alloc<unsigned int>(state.n_tuples)),
307 active_limit(state.active_limit), gid_val(home.alloc<int>(state.n_vals)),
308 tv(TupleSetAccess::sparse_tuple_value_ids(ts)) {
309 for (unsigned int i=0U; i<n_tuples; i++) {
310 active_ids[i] = state.active_ids[i];
311 pos_in_active[i] = state.pos_in_active[i];
312 }
313 for (unsigned int i=0U; i<n_vals; i++)
314 gid_val[i] = state.gid_val[i];
315 }
316 };
317
318 template<class View, bool pos>
320 : public Propagator,
321 protected SparseTupleState<SparseInc<View,pos>,View> {
322 protected:
325 friend class SparseTupleState<SparseInc<View,pos>,View>;
327 using State::arity;
331 using State::gid_val;
332 using State::n_tuples;
333 using State::n_vals;
335 using State::ts;
336 using State::tuple_gids;
337 using State::tv;
338
341 unsigned int* support_count;
343 unsigned int* zero_queue;
344 unsigned int zero_queue_size;
345 unsigned char* queued;
347
348 void
349 enqueue_zero(unsigned int gid) {
350 if ((gid < n_vals) && (queued[gid] == 0U)) {
351 queued[gid] = 1U;
353 }
354 }
355
356 void
358 for (unsigned int i=0U; i<n_vals; i++)
359 gid_var[i] = -1;
360 for (int a=0; a<x.size(); a++) {
361 for (const TupleSet::Range* r=ts.fst(a); r<=ts.lst(a); r++) {
362 unsigned int gid = 0U;
363 if (!TupleSetAccess::support_id(ts,a,r->min,gid))
365 int n = r->min;
366 while (true) {
367 assert(gid < n_vals);
368 gid_var[gid] = a;
369 if (n == r->max)
370 break;
371 n++;
372 gid++;
373 }
374 }
375 }
376 }
377
378 void
380 assert(tv != nullptr);
381 const unsigned int* offsets = TupleSetAccess::sparse_support_offsets(ts);
382 if (offsets != nullptr) {
383 for (unsigned int i=0U; i<n_vals; i++)
384 support_count[i] = offsets[i+1U] - offsets[i];
385 } else {
386 for (unsigned int i=0U; i<n_vals; i++)
387 support_count[i] = 0U;
388 const unsigned long long n_tv =
389 static_cast<unsigned long long>(n_tuples) *
390 static_cast<unsigned long long>(arity);
391 for (unsigned long long i=0ULL; i<n_tv; i++) {
392 const unsigned int gid = tv[i];
393 assert(gid < n_vals);
394 support_count[gid]++;
395 }
396 }
397 }
398
399 void
400 deactivate_tuple(unsigned int tid) {
401 if (!remove_tuple(tid))
402 return;
403
404 const unsigned int* row = tuple_gids(tid);
405 for (int a=0; a<arity; a++) {
406 const unsigned int gid = row[a];
407 assert(gid < n_vals);
408 assert(support_count[gid] > 0U);
409 support_count[gid]--;
410 if (pos && (support_count[gid] == 0U))
411 enqueue_zero(gid);
412 }
413 }
414
415 forceinline bool
416 support_active(unsigned int gid) const {
417 assert(gid < n_vals);
418 return support_count[gid] != 0U;
419 }
420
423 if (zero_queue_size == 0U)
424 return ES_OK;
425
426 Region r;
427 const int arity = x.size();
428 unsigned int* n_rm = r.alloc<unsigned int>(arity);
429 unsigned int* p_rm = r.alloc<unsigned int>(arity);
430 int** rm = r.alloc<int*>(arity);
431 for (int i=0; i<arity; i++) {
432 n_rm[i] = 0U;
433 p_rm[i] = 0U;
434 rm[i] = nullptr;
435 }
436
437 for (unsigned int i=0U; i<zero_queue_size; i++) {
438 const unsigned int gid = zero_queue[i];
439 assert(gid < n_vals);
440 queued[gid] = 0U;
441 const int a = gid_var[gid];
442 if ((a < 0) || (a >= arity))
443 continue;
444 if (x[a].in(gid_val[gid]))
445 n_rm[a]++;
446 }
447
448 for (int i=0; i<arity; i++)
449 if (n_rm[i] > 0U)
450 rm[i] = r.alloc<int>(n_rm[i]);
451
452 for (unsigned int i=0U; i<zero_queue_size; i++) {
453 const unsigned int gid = zero_queue[i];
454 assert(gid < n_vals);
455 const int a = gid_var[gid];
456 if ((a < 0) || (a >= arity))
457 continue;
458 if (x[a].in(gid_val[gid]))
459 rm[a][p_rm[a]++] = gid_val[gid];
460 }
461
462 zero_queue_size = 0U;
463
464 for (int i=0; i<arity; i++) {
465 if (p_rm[i] == 0U)
466 continue;
467 if (x[i].assigned())
468 continue;
469 if (p_rm[i] == 1U) {
470 GECODE_ME_CHECK(x[i].nq(home,rm[i][0]));
471 continue;
472 }
473 Support::quicksort(rm[i], static_cast<int>(p_rm[i]));
474 unsigned int j = 1U;
475 for (unsigned int k=1U; k<p_rm[i]; k++)
476 if (rm[i][k] != rm[i][j-1U])
477 rm[i][j++] = rm[i][k];
478 if (j == 1U) {
479 GECODE_ME_CHECK(x[i].nq(home,rm[i][0]));
480 } else {
481 Iter::Values::Array iv(rm[i],j);
482 GECODE_ASSUME(j >= 2U);
483 GECODE_ME_CHECK(x[i].minus_v(home,iv,false));
484 }
485 }
486 return ES_OK;
487 }
488
489 bool
490 atmostone(void) const {
492 if (!as())
493 return true;
494 ++as;
495 return !as();
496 }
497
498 public:
499 SparseInc(Home home, ViewArray<View>& x0, const TupleSet& ts0)
500 : Propagator(home), State(home,x0,ts0), x(home,x0), c(home),
501 support_count(static_cast<Space&>(home).alloc<unsigned int>(n_vals)),
502 gid_var(static_cast<Space&>(home).alloc<int>(n_vals)),
503 zero_queue(static_cast<Space&>(home).alloc<unsigned int>(n_vals)),
504 zero_queue_size(0U),
505 queued(static_cast<Space&>(home).alloc<unsigned char>(n_vals)),
506 in_propagate(false) {
507 home.notice(*this, AP_DISPOSE);
508 for (unsigned int i=0U; i<n_vals; i++)
509 queued[i] = 0U;
510
513
514 for (int i=0; i<arity; i++)
515 if (!x[i].assigned())
516 (void) new (home) SparseAdvisor(home,*this,c,x[i],i);
517
519 }
520
522 : Propagator(home,p), State(home,p), x(), c(home),
523 support_count(home.alloc<unsigned int>(p.n_vals)),
524 gid_var(home.alloc<int>(p.n_vals)),
525 zero_queue(home.alloc<unsigned int>(p.n_vals)),
527 queued(home.alloc<unsigned char>(p.n_vals)),
528 in_propagate(false) {
529 x.update(home,p.x);
530 c.update(home,p.c);
531 for (unsigned int i=0U; i<n_vals; i++) {
533 gid_var[i] = p.gid_var[i];
534 queued[i] = p.queued[i];
535 }
536 for (unsigned int i=0U; i<zero_queue_size; i++)
537 zero_queue[i] = p.zero_queue[i];
538 }
539
540 static ExecStatus
542 bool assigned = true;
543 for (int i=0; i<x.size(); i++)
544 if (!x[i].assigned()) {
545 assigned = false;
546 break;
547 }
548 if (assigned) {
549 bool in_table = false;
550 for (int t=0; t<ts.tuples() && !in_table; t++) {
551 TupleSet::Tuple tuple = ts[t];
552 bool same = true;
553 for (int i=0; i<x.size(); i++)
554 if (tuple[i] != x[i].val()) {
555 same = false;
556 break;
557 }
558 in_table = same;
559 }
560 if (pos)
561 return in_table ? ES_OK : ES_FAILED;
562 return in_table ? ES_FAILED : ES_OK;
563 }
564
565 if (pos) {
566 if (x.size() == 0)
567 return (ts.tuples() == 0) ? ES_FAILED : ES_OK;
568 if (ts.tuples() == 0)
569 return ES_FAILED;
570
571 for (int i=0; i<x.size(); i++) {
572 TupleSet::Ranges r(ts,i);
573 GECODE_ME_CHECK(x[i].inter_r(home, r, false));
574 }
575
576 if ((x.size() <= 1) || (ts.tuples() <= 1))
577 return ES_OK;
578
579 SparseInc<View,pos>* p = new (home) SparseInc<View,pos>(home,x,ts);
580 if (p->active_limit == 0U)
581 return ES_FAILED;
582 View::schedule(home,*p,ME_INT_DOM);
583 return ES_OK;
584 }
585
586 if (x.size() == 0)
587 return (ts.tuples() == 0) ? ES_OK : ES_FAILED;
588 if (ts.tuples() == 0)
589 return ES_OK;
590
591 SparseInc<View,pos>* p = new (home) SparseInc<View,pos>(home,x,ts);
592 View::schedule(home,*p,ME_INT_DOM);
593 return ES_OK;
594 }
595
596 virtual Actor*
597 copy(Space& home) {
598 return new (home) SparseInc<View,pos>(home,*this);
599 }
600
601 virtual PropCost
602 cost(const Space&, const ModEventDelta&) const {
603 return PropCost::quadratic(PropCost::HI,x.size());
604 }
605
606 virtual void
608 View::schedule(home,*this,ME_INT_DOM);
609 }
610
611 virtual size_t
612 dispose(Space& home) {
613 home.ignore(*this, AP_DISPOSE);
614 c.dispose(home);
615 ts.~TupleSet();
616 (void) Propagator::dispose(home);
617 return sizeof(*this);
618 }
619
620 virtual ExecStatus
622 if (pos) {
623 if (active_limit == 0U)
624 return ES_FAILED;
625
626 in_propagate = true;
628 in_propagate = false;
629 if (es != ES_OK)
630 return es;
631
632 if (active_limit == 0U)
633 return ES_FAILED;
634 return atmostone() ? home.ES_SUBSUMED(*this) : ES_FIX;
635 }
636
637 if (active_limit == 0U)
638 return home.ES_SUBSUMED(*this);
639
640 const unsigned long long cap_all =
641 static_cast<unsigned long long>(active_limit);
642 const unsigned long long all = domain_product(x,cap_all);
643 if (all == cap_all)
644 return ES_FAILED;
645
646 Region r;
647 in_propagate = true;
648 for (int i=0; i<x.size(); i++) {
649 if (x[i].assigned())
650 continue;
651 const unsigned long long cap =
652 static_cast<unsigned long long>(active_limit);
653 const unsigned long long other = domain_product(x,cap,i);
654 if (other > cap)
655 continue;
656
657 int* rm = r.alloc<int>(x[i].size());
658 unsigned int n_rm = 0U;
659 for (const TupleSet::Range* rg=ts.fst(i); rg<=ts.lst(i); rg++) {
660 unsigned int gid = 0U;
661 if (!TupleSetAccess::support_id(ts,i,rg->min,gid))
663 int v = rg->min;
664 while (true) {
665 assert(gid < n_vals);
666 if (x[i].in(v) &&
667 (support_count[gid] ==
668 static_cast<unsigned int>(other)))
669 rm[n_rm++] = v;
670 if (v == rg->max)
671 break;
672 v++;
673 gid++;
674 }
675 }
676 if (n_rm == 0U)
677 continue;
678 if (n_rm == 1U) {
679 GECODE_ME_CHECK(x[i].nq(home,rm[0]));
680 } else {
681 Iter::Values::Array iv(rm,n_rm);
682 GECODE_ASSUME(n_rm >= 2U);
683 GECODE_ME_CHECK(x[i].minus_v(home,iv,false));
684 }
686 if (active_limit == 0U) {
687 in_propagate = false;
688 return home.ES_SUBSUMED(*this);
689 }
690 r.free();
691 }
692 in_propagate = false;
693 return ES_FIX;
694 }
695
696 virtual ExecStatus
697 advise(Space& home, Advisor& a0, const Delta& d) {
698 SparseAdvisor& sa = static_cast<SparseAdvisor&>(a0);
699 if (active_limit == 0U) {
700 if (pos)
701 return disabled() ? home.ES_NOFIX_DISPOSE(c,sa) : ES_FAILED;
702 return ES_NOFIX;
703 }
704
705 View xv = sa.view();
706 if (in_propagate)
707 return xv.assigned() ? home.ES_FIX_DISPOSE(c,sa) : ES_FIX;
708
709 const int i = sa.index();
710
711 if (xv.assigned()) {
713 if ((active_limit == 0U) && pos)
714 return disabled() ? home.ES_NOFIX_DISPOSE(c,sa) : ES_FAILED;
715 return home.ES_NOFIX_DISPOSE(c,sa);
716 }
718
719 if ((active_limit == 0U) && pos)
720 return disabled() ? home.ES_NOFIX_DISPOSE(c,sa) : ES_FAILED;
721 return ES_NOFIX;
722 }
723 };
724
725 template<class View, class CtrlView, ReifyMode rm>
727 : public Propagator,
728 protected SparseTupleState<SparseReifInc<View,CtrlView,rm>,View> {
729 protected:
732 friend class SparseTupleState<SparseReifInc<View,CtrlView,rm>,View>;
734 using State::arity;
738 using State::n_tuples;
740 using State::ts;
741
743 CtrlView b;
745
746 void
747 deactivate_tuple(unsigned int tid) {
748 (void) remove_tuple(tid);
749 }
750
751 forceinline bool
752 support_active(unsigned int) const {
753 return true;
754 }
755
756 public:
757 static ExecStatus
759 return SparseInc<View,true>::post(home,x,ts);
760 }
761
762 static ExecStatus
764 return SparseInc<View,false>::post(home,x,ts);
765 }
766
767 SparseReifInc(Home home, ViewArray<View>& x0, const TupleSet& ts0, CtrlView b0)
768 : Propagator(home), State(home,x0,ts0), x(home,x0), b(b0), c(home) {
769 home.notice(*this, AP_DISPOSE);
770
771 b.subscribe(home,*this,PC_BOOL_VAL);
772 for (int i=0; i<arity; i++)
773 if (!x[i].assigned())
774 (void) new (home) SparseAdvisor(home,*this,c,x[i],i);
775
777 }
778
780 : Propagator(home,p), State(home,p), x(), b(), c(home) {
781 x.update(home,p.x);
782 b.update(home,p.b);
783 c.update(home,p.c);
784 }
785
786 static ExecStatus
787 post(Home home, ViewArray<View>& x, const TupleSet& ts, CtrlView b) {
788 if (b.one()) {
789 if (rm == RM_PMI)
790 return ES_OK;
791 return SparseInc<View,true>::post(home,x,ts);
792 }
793 if (b.zero()) {
794 if (rm == RM_IMP)
795 return ES_OK;
796 return SparseInc<View,false>::post(home,x,ts);
797 }
799 new (home) SparseReifInc<View,CtrlView,rm>(home,x,ts,b);
800 View::schedule(home,*p,ME_INT_DOM);
801 return ES_OK;
802 }
803
804 virtual Actor*
805 copy(Space& home) {
806 return new (home) SparseReifInc<View,CtrlView,rm>(home,*this);
807 }
808
809 virtual PropCost
810 cost(const Space&, const ModEventDelta&) const {
811 return PropCost::quadratic(PropCost::HI,x.size());
812 }
813
814 virtual void
816 View::schedule(home,*this,ME_INT_DOM);
817 }
818
819 virtual size_t
820 dispose(Space& home) {
821 home.ignore(*this, AP_DISPOSE);
822 c.dispose(home);
823 b.cancel(home,*this,PC_BOOL_VAL);
824 ts.~TupleSet();
825 (void) Propagator::dispose(home);
826 return sizeof(*this);
827 }
828
829 virtual ExecStatus
831 if (b.one()) {
832 if (rm == RM_PMI)
833 return home.ES_SUBSUMED(*this);
834 TupleSet keep(ts);
835 GECODE_REWRITE(*this,post_pos(home(*this),x,keep));
836 }
837 if (b.zero()) {
838 if (rm == RM_IMP)
839 return home.ES_SUBSUMED(*this);
840 TupleSet keep(ts);
841 GECODE_REWRITE(*this,post_neg(home(*this),x,keep));
842 }
843
844 if (active_limit == 0U) {
845 if (rm != RM_PMI)
846 GECODE_ME_CHECK(b.zero_none(home));
847 return home.ES_SUBSUMED(*this);
848 }
849
850 const unsigned long long cap_all =
851 static_cast<unsigned long long>(active_limit);
852 const unsigned long long all = domain_product(x,cap_all);
853 if (all == cap_all) {
854 if (rm != RM_IMP)
855 GECODE_ME_CHECK(b.one_none(home));
856 return home.ES_SUBSUMED(*this);
857 }
858 return ES_FIX;
859 }
860
861 virtual ExecStatus
862 advise(Space& home, Advisor& a0, const Delta& d) {
863 SparseAdvisor& sa = static_cast<SparseAdvisor&>(a0);
864 if (b.assigned())
865 return home.ES_NOFIX_DISPOSE(c,sa);
866
867 if (active_limit == 0U)
868 return ES_NOFIX;
869
870 View xv = sa.view();
871 const int i = sa.index();
872 if (xv.assigned()) {
874 return home.ES_NOFIX_DISPOSE(c,sa);
875 }
877 return ES_NOFIX;
878 }
879 };
880
881 template<class View>
883 post_tuple_set(Home home, ViewArray<View>& x, const TupleSet& t, bool pos) {
884 switch (t.representation()) {
885 case EPK_DENSE:
886 return pos ? postposcompact<View>(home,x,t) :
887 postnegcompact<View>(home,x,t);
888 case EPK_SPARSE:
889 return pos ? SparseInc<View,true>::post(home,x,t) :
891 case EPK_DENSE_COMPRESSED:
892 return pos ? postposcompact_compressed<View>(home,x,t) :
894 case EPK_AUTO:
895 default:
897 return ES_FAILED;
898 }
899 }
900
903 switch (mode) {
904 case RM_EQV: return RM_EQV;
905 case RM_IMP: return RM_PMI;
906 case RM_PMI: return RM_IMP;
907 default:
909 return RM_EQV;
910 }
911 }
912
913 template<class View, class CtrlView>
916 CtrlView b, ReifyMode mode) {
917 switch (mode) {
918 case RM_EQV:
920 case RM_IMP:
922 case RM_PMI:
924 default:
925 throw UnknownReifyMode("Int::extensional");
926 }
927 }
928
929 template<class View, class CtrlView>
932 CtrlView b, ReifyMode mode) {
933 switch (mode) {
934 case RM_EQV: return postrecompact<View,CtrlView,RM_EQV>(home,x,t,b);
935 case RM_IMP: return postrecompact<View,CtrlView,RM_IMP>(home,x,t,b);
936 case RM_PMI: return postrecompact<View,CtrlView,RM_PMI>(home,x,t,b);
937 default:
938 throw UnknownReifyMode("Int::extensional");
939 }
940 }
941
942 template<class View, class CtrlView>
945 CtrlView b, ReifyMode mode) {
946 switch (mode) {
947 case RM_EQV:
949 case RM_IMP:
951 case RM_PMI:
953 default:
954 throw UnknownReifyMode("Int::extensional");
955 }
956 }
957
958 template<class View, class CtrlView>
961 CtrlView b, ReifyMode mode) {
962 switch (t.representation()) {
963 case EPK_DENSE:
964 return post_dense_reified(home,x,t,b,mode);
965 case EPK_SPARSE:
966 return post_sparse_reified(home,x,t,b,mode);
967 case EPK_DENSE_COMPRESSED:
968 return post_compressed_reified(home,x,t,b,mode);
969 case EPK_AUTO:
970 default:
972 return ES_FAILED;
973 }
974 }
975
977 post_reified_constant(Home home, BoolView b, ReifyMode mode, bool value) {
978 switch (mode) {
979 case RM_EQV:
980 if (value)
981 GECODE_ME_CHECK(b.one(home));
982 else
983 GECODE_ME_CHECK(b.zero(home));
984 break;
985 case RM_IMP:
986 if (!value)
987 GECODE_ME_CHECK(b.zero(home));
988 break;
989 case RM_PMI:
990 if (value)
991 GECODE_ME_CHECK(b.one(home));
992 break;
993 default:
995 return ES_FAILED;
996 }
997 return ES_OK;
998 }
999
1000}}}
1001
1002namespace Gecode {
1003
1004 void
1005 extensional(Home home, const IntVarArgs& x, const TupleSet& t, bool pos,
1006 IntPropLevel) {
1007 using namespace Int;
1008 if (!t.finalized())
1009 throw NotYetFinalized("Int::extensional");
1010 if (t.arity() != x.size())
1011 throw ArgumentSizeMismatch("Int::extensional");
1012 if (same(x))
1013 throw ArgumentSame("Int::extensional");
1015
1016 if (x.size() == 0) {
1017 if (pos ? (t.tuples() > 0) : (t.tuples() == 0))
1018 return;
1019 home.fail();
1020 return;
1021 }
1022 if (t.tuples() == 0) {
1023 if (!pos)
1024 return;
1025 home.fail();
1026 return;
1027 }
1028
1029 ViewArray<IntView> views(home,x);
1030 GECODE_ES_FAIL((Extensional::post_tuple_set(home,views,t,pos)));
1031 }
1032
1033 void
1034 extensional(Home home, const IntVarArgs& x, const TupleSet& t, bool pos,
1035 Reify r, IntPropLevel) {
1036 using namespace Int;
1037 if (!t.finalized())
1038 throw NotYetFinalized("Int::extensional");
1039 if (t.arity() != x.size())
1040 throw ArgumentSizeMismatch("Int::extensional");
1041 if (same(x))
1042 throw ArgumentSame("Int::extensional");
1044
1045 if ((x.size() == 0) || (t.tuples() == 0)) {
1046 const bool value = (x.size() == 0) ?
1047 (pos ? (t.tuples() > 0) : (t.tuples() == 0)) : !pos;
1048 BoolView control(r.var());
1050 (home,control,r.mode(),value)));
1051 return;
1052 }
1053
1054 ViewArray<IntView> views(home,x);
1055 if (pos) {
1056 BoolView control(r.var());
1058 (home,views,t,control,r.mode())));
1059 } else {
1060 NegBoolView control(r.var());
1062 (home,views,t,control,
1064 }
1065 }
1066
1067 void
1068 extensional(Home home, const BoolVarArgs& x, const TupleSet& t, bool pos,
1069 IntPropLevel) {
1070 using namespace Int;
1071 if (!t.finalized())
1072 throw NotYetFinalized("Int::extensional");
1073 if (t.arity() != x.size())
1074 throw ArgumentSizeMismatch("Int::extensional");
1075 if ((t.min() < 0) || (t.max() > 1))
1076 throw NotZeroOne("Int::extensional");
1077 if (same(x))
1078 throw ArgumentSame("Int::extensional");
1080
1081 if (x.size() == 0) {
1082 if (pos ? (t.tuples() > 0) : (t.tuples() == 0))
1083 return;
1084 home.fail();
1085 return;
1086 }
1087 if (t.tuples() == 0) {
1088 if (!pos)
1089 return;
1090 home.fail();
1091 return;
1092 }
1093
1094 ViewArray<BoolView> views(home,x);
1095 GECODE_ES_FAIL((Extensional::post_tuple_set(home,views,t,pos)));
1096 }
1097
1098 void
1099 extensional(Home home, const BoolVarArgs& x, const TupleSet& t, bool pos,
1100 Reify r, IntPropLevel) {
1101 using namespace Int;
1102 if (!t.finalized())
1103 throw NotYetFinalized("Int::extensional");
1104 if (t.arity() != x.size())
1105 throw ArgumentSizeMismatch("Int::extensional");
1106 if ((t.min() < 0) || (t.max() > 1))
1107 throw NotZeroOne("Int::extensional");
1108 if (same(x))
1109 throw ArgumentSame("Int::extensional");
1111
1112 if ((x.size() == 0) || (t.tuples() == 0)) {
1113 const bool value = (x.size() == 0) ?
1114 (pos ? (t.tuples() > 0) : (t.tuples() == 0)) : !pos;
1115 BoolView control(r.var());
1117 (home,control,r.mode(),value)));
1118 return;
1119 }
1120
1121 ViewArray<BoolView> views(home,x);
1122 if (pos) {
1123 BoolView control(r.var());
1125 (home,views,t,control,r.mode())));
1126 } else {
1127 NegBoolView control(r.var());
1129 (home,views,t,control,
1131 }
1132 }
1133
1134}
1135
1136// STATISTICS: int-post
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
friend class Council
Definition core.hpp:1303
Class to iterate over advisors of a council.
Definition core.hpp:1275
int size(void) const
Return size of array (number of elements).
Definition array.hpp:1597
Passing Boolean variables.
Definition int.hh:738
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
void fail(void)
Mark space as failed.
Definition core.hpp:4176
Passing integer variables.
Definition int.hh:680
Exception: Arguments contain same variable multiply
Definition exception.hpp:80
Exception: Arguments are of different size
Definition exception.hpp:73
Boolean view for Boolean variables.
Definition view.hpp:1378
Advisor shared by the sparse positive, negative, and reified actors.
void dispose(Space &home, Council< SparseAdvisor > &c)
SparseAdvisor(Space &home, SparseAdvisor &advisor)
SparseAdvisor(Space &home, Propagator &p, Council< SparseAdvisor > &c, View x, int variable0)
Iterate table values in a delta interval.
SparseDeltaValues(const TupleSet &ts, int i, int lower, int upper0)
const unsigned int * tuple_gids(unsigned int tid) const
void deactivate_removed_values(int variable, const View &view, const Delta &delta)
bool support_active(unsigned int gid) const
virtual void reschedule(Space &home)
Schedule function.
virtual PropCost cost(const Space &, const ModEventDelta &) const
Cost function.
SparseTupleState< SparseInc< View, pos >, View > State
Extensional::SparseAdvisor< View > SparseAdvisor
static ExecStatus post(Home home, ViewArray< View > &x, const TupleSet &ts)
virtual ExecStatus propagate(Space &home, const ModEventDelta &)
Propagation function.
virtual size_t dispose(Space &home)
Delete actor and return its size.
virtual ExecStatus advise(Space &home, Advisor &a0, const Delta &d)
Advise function.
void deactivate_for_all_domains(const ViewArray< View > &x)
void deactivate_for_domain(int variable, const View &view)
SparseInc(Space &home, SparseInc< View, pos > &p)
virtual Actor * copy(Space &home)
Create copy.
SparseInc(Home home, ViewArray< View > &x0, const TupleSet &ts0)
void deactivate_for_all_domains(const ViewArray< View > &x)
virtual Actor * copy(Space &home)
Create copy.
virtual void reschedule(Space &home)
Schedule function.
virtual size_t dispose(Space &home)
Delete actor and return its size.
static ExecStatus post_neg(Home home, ViewArray< View > &x, const TupleSet &ts)
virtual ExecStatus advise(Space &home, Advisor &a0, const Delta &d)
Advise function.
virtual PropCost cost(const Space &, const ModEventDelta &) const
Cost function.
void deactivate_removed_values(int variable, const View &view, const Delta &delta)
SparseReifInc(Space &home, SparseReifInc< View, CtrlView, rm > &p)
void deactivate_for_domain(int variable, const View &view)
static ExecStatus post(Home home, ViewArray< View > &x, const TupleSet &ts, CtrlView b)
SparseTupleState< SparseReifInc< View, CtrlView, rm >, View > State
Extensional::SparseAdvisor< View > SparseAdvisor
virtual ExecStatus propagate(Space &home, const ModEventDelta &)
Propagation function.
static ExecStatus post_pos(Home home, ViewArray< View > &x, const TupleSet &ts)
SparseReifInc(Home home, ViewArray< View > &x0, const TupleSet &ts0, CtrlView b0)
unsigned int tuple_gid(unsigned int tid, int variable) const
void deactivate_removed_values(int variable, const View &view, const Delta &delta)
SparseTupleState(Space &home, const SparseTupleState &state)
void deactivate_for_all_domains(const ViewArray< View > &x)
void deactivate_value_support(int variable, int value)
const unsigned int * tuple_gids(unsigned int tid) const
SparseTupleState(Home home, ViewArray< View > &x, const TupleSet &ts0)
void deactivate_for_domain(int variable, const View &view)
Internal access to finalized tuple-set support representations.
Definition int.hh:2686
static bool support_id(const TupleSet &ts, int p, int n, unsigned int &gid)
Return support id for position/value.
static bool sparse_support(const TupleSet &ts, int p, int n, const unsigned int *&b, const unsigned int *&e, unsigned int &gid)
Return sparse support tuple id range for position/value.
static const unsigned int * sparse_support_offsets(const TupleSet &ts)
Return sparse support offsets.
Negated Boolean view.
Definition view.hpp:1572
Exception: Tuple set not yet finalized
Exception: Not 0/1 integer
Definition exception.hpp:51
Exception: Unknown reification mode passed as argument
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
friend class Space
Definition core.hpp:1075
friend class Advisor
Definition core.hpp:1077
friend class Council
Definition core.hpp:1078
bool disabled(void) const
Whether propagator is currently disabled.
Definition core.hpp:3585
Propagator(Home home)
Constructor for posting.
Definition core.hpp:3607
Handle to region.
Definition region.hpp:55
Reification specification.
Definition int.hh:910
Computation spaces.
Definition core.hpp:1775
Range information.
Definition int.hh:2399
int max
Maximum value.
Definition int.hh:2404
Iterator over ranges.
Definition int.hh:2649
Class representing a set of tuples.
Definition int.hh:2382
int tuples(void) const
Number of tuples.
int max(void) const
Return maximal value in all tuples.
bool finalized(void) const
Is tuple set successfully finalized.
ExtensionalPropKind representation(void) const
Return materialized tuple-set representation.
int * Tuple
Type of a tuple.
Definition int.hh:2389
int min(void) const
Return minimal value in all tuples.
int arity(void) const
Arity of tuple set.
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 x
The single view.
Definition advisor.hpp:46
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
#define GECODE_POST
Check for failure in a constraint post function.
Definition macros.hpp:40
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
#define GECODE_ES_FAIL(es)
Check whether execution status es is failed, and fail space home.
Definition macros.hpp:103
@ AP_DISPOSE
Actor must always be disposed.
Definition core.hpp:569
void extensional(Home home, const IntVarArgs &x, DFA d, IntPropLevel ipl=IPL_DEF)
Post domain consistent propagator for extensional constraint described by a DFA.
ReifyMode
Mode for reification.
Definition int.hh:882
IntPropLevel
Propagation levels for integer propagators.
Definition int.hh:1008
@ RM_IMP
Implication for reification.
Definition int.hh:896
@ RM_PMI
Inverse implication for reification.
Definition int.hh:903
@ RM_EQV
Equivalence for reification (default).
Definition int.hh:889
Extensional propagators
Definition int.hh:2335
ExecStatus post_reified_tuple_set(Home home, ViewArray< View > &x, const TupleSet &t, CtrlView b, ReifyMode mode)
unsigned long long domain_product(const ViewArray< View > &x, unsigned long long limit, int excluded=-1)
Return the domain-size product, saturated just above limit.
ExecStatus postnegcompact(Home home, ViewArray< View > &x, const TupleSet &ts)
Post function for compact table propagator.
Definition compact.hpp:1143
ExecStatus post_reified_constant(Home home, BoolView b, ReifyMode mode, bool value)
ExecStatus postposcompact(Home home, ViewArray< View > &x, const TupleSet &ts)
Post function for positive compact table propagator.
Definition compact.hpp:1034
ExecStatus postrecompact(Home home, ViewArray< View > &x, const TupleSet &ts, CtrlView b)
Post function for compact table propagator.
Definition compact.hpp:1281
ExecStatus postposcompact_compressed(Home home, ViewArray< View > &x, const TupleSet &ts)
Post function for positive compact table with compressed supports.
Definition compact.hpp:1606
ExecStatus post_compressed_reified(Home home, ViewArray< View > &x, const TupleSet &t, CtrlView b, ReifyMode mode)
ExecStatus post_dense_reified(Home home, ViewArray< View > &x, const TupleSet &t, CtrlView b, ReifyMode mode)
ExecStatus post_tuple_set(Home home, ViewArray< View > &x, const TupleSet &t, bool pos)
ReifyMode negated_reify_mode(ReifyMode mode)
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
ExecStatus post_sparse_reified(Home home, ViewArray< View > &x, const TupleSet &t, CtrlView b, ReifyMode mode)
Finite domain integers.
Definition lastval.hh:52
const Gecode::PropCond PC_BOOL_VAL
Propagate when a view becomes assigned (single value).
Definition var-type.hpp:134
const Gecode::ModEvent ME_INT_DOM
Domain operation has changed the domain.
Definition var-type.hpp:80
void quicksort(Type *l, Type *r, Less &less)
Standard quick sort.
Definition sort.hpp:130
Gecode toplevel namespace
void range(Home home, const IntVarArgs &x, SetVar y, SetVar z)
Post constraint .
Definition aliases.hpp:158
bool same(VarArgArray< Var > x, VarArgArray< Var > y)
Definition array.hpp:1927
void values(Home home, const IntVarArgs &x, IntSet y, IntPropLevel ipl=IPL_DEF)
Post constraint .
Definition aliases.hpp:143
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
#define forceinline
Definition config.hpp:141
#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