Generated on for Gecode by doxygen 1.15.0
extensional.cpp
Go to the documentation of this file.
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Mikael Zayenz Lagerkvist <lagerkvist@gecode.dev>
5 * Linnea Ingmar <linnea.ingmar@hotmail.com>
6 * Christian Schulte <schulte@gecode.dev>
7 *
8 * Copyright:
9 * Linnea Ingmar, 2017
10 * Mikael Zayenz Lagerkvist, 2007
11 * Christian Schulte, 2005
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
38#include "test/int.hh"
39
40#include <gecode/minimodel.hh>
41#include <climits>
42#include <cstdlib>
43#include <iostream>
44#include <string>
45
46namespace Test { namespace Int {
47
49 namespace Extensional {
50
56 std::string
58 switch (epk) {
59 case Gecode::EPK_DENSE:
60 return "Dense";
61 case Gecode::EPK_SPARSE:
62 return "Sparse";
63 case Gecode::EPK_DENSE_COMPRESSED:
64 return "DenseCompressed";
65 case Gecode::EPK_AUTO:
66 return "Auto";
67 default:
69 return "Unknown";
70 }
71 }
72
74 class RegSimpleA : public Test {
75 public:
77 RegSimpleA(void) : Test("Extensional::Reg::Simple::A",4,2,2) {}
79 virtual bool solution(const Assignment& x) const {
80 return (((x[0] == 0) || (x[0] == 2)) &&
81 ((x[1] == -1) || (x[1] == 1)) &&
82 ((x[2] == 0) || (x[2] == 1)) &&
83 ((x[3] == 0) || (x[3] == 1)));
84 }
85
86 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
87 using namespace Gecode;
88 extensional(home, x,
89 (REG(0) | REG(2)) +
90 (REG(-1) | REG(1)) +
91 (REG(7) | REG(0) | REG(1)) +
92 (REG(0) | REG(1)));
93 }
94 };
95
97 class RegSimpleB : public Test {
98 public:
100 RegSimpleB(void) : Test("Extensional::Reg::Simple::B",4,2,2) {}
102 virtual bool solution(const Assignment& x) const {
103 return (x[0]<x[1]) && (x[1]<x[2]) && (x[2]<x[3]);
104 }
105
106 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
107 using namespace Gecode;
108 extensional(home, x,
109 (REG(-2) + REG(-1) + REG(0) + REG(1)) |
110 (REG(-2) + REG(-1) + REG(0) + REG(2)) |
111 (REG(-2) + REG(-1) + REG(1) + REG(2)) |
112 (REG(-2) + REG(0) + REG(1) + REG(2)) |
113 (REG(-1) + REG(0) + REG(1) + REG(2)));
114 }
115 };
116
118 class RegSimpleC : public Test {
119 public:
121 RegSimpleC(void) : Test("Extensional::Reg::Simple::C",6,0,1) {}
123 virtual bool solution(const Assignment& x) const {
124 int pos = 0;
125 int s = x.size();
126
127 while (pos < s && x[pos] == 0) ++pos;
128 if (pos + 4 > s) return false;
129
130 for (int i = 0; i < 2; ++i, ++pos)
131 if (x[pos] != 1) return false;
132 if (pos + 2 > s) return false;
133
134 for (int i = 0; i < 1; ++i, ++pos)
135 if (x[pos] != 0) return false;
136 while (pos < s && x[pos] == 0) ++pos;
137 if (pos + 1 > s) return false;
138
139 for (int i = 0; i < 1; ++i, ++pos)
140 if (x[pos] != 1) return false;
141 while (pos < s) if (x[pos++] != 0) return false;
142 return true;
143
144 }
145
146 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
147 using namespace Gecode;
148 extensional(home, x,
149 *REG(0) + REG(1)(2,2) + +REG(0) + REG(1)(1,1) + *REG(0));
150 }
151 };
152
154 class RegDistinct : public Test {
155 public:
157 RegDistinct(void) : Test("Extensional::Reg::Distinct",4,-1,4) {}
159 virtual bool solution(const Assignment& x) const {
160 for (int i=0; i<x.size(); i++) {
161 if ((x[i] < 0) || (x[i] > 3))
162 return false;
163 for (int j=i+1; j<x.size(); j++)
164 if (x[i]==x[j])
165 return false;
166 }
167 return true;
168 }
169
170 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
171 using namespace Gecode;
172 extensional(home, x,
173 (REG(0)+REG(1)+REG(2)+REG(3)) |
174 (REG(0)+REG(1)+REG(3)+REG(2)) |
175 (REG(0)+REG(2)+REG(1)+REG(3)) |
176 (REG(0)+REG(2)+REG(3)+REG(1)) |
177 (REG(0)+REG(3)+REG(1)+REG(2)) |
178 (REG(0)+REG(3)+REG(2)+REG(1)) |
179 (REG(1)+REG(0)+REG(2)+REG(3)) |
180 (REG(1)+REG(0)+REG(3)+REG(2)) |
181 (REG(1)+REG(2)+REG(0)+REG(3)) |
182 (REG(1)+REG(2)+REG(3)+REG(0)) |
183 (REG(1)+REG(3)+REG(0)+REG(2)) |
184 (REG(1)+REG(3)+REG(2)+REG(0)) |
185 (REG(2)+REG(0)+REG(1)+REG(3)) |
186 (REG(2)+REG(0)+REG(3)+REG(1)) |
187 (REG(2)+REG(1)+REG(0)+REG(3)) |
188 (REG(2)+REG(1)+REG(3)+REG(0)) |
189 (REG(2)+REG(3)+REG(0)+REG(1)) |
190 (REG(2)+REG(3)+REG(1)+REG(0)) |
191 (REG(3)+REG(0)+REG(1)+REG(2)) |
192 (REG(3)+REG(0)+REG(2)+REG(1)) |
193 (REG(3)+REG(1)+REG(0)+REG(2)) |
194 (REG(3)+REG(1)+REG(2)+REG(0)) |
195 (REG(3)+REG(2)+REG(0)+REG(1)) |
196 (REG(3)+REG(2)+REG(1)+REG(0)));
197 }
198 };
199
201 class RegRoland : public Test {
202 public:
205 : Test("Extensional::Reg::Roland::"+str(n),n,0,1) {}
206
207 virtual bool solution(const Assignment& x) const {
208 int n = x.size();
209 return
210 ((n > 1) && (x[n-2] == 0)) ||
211 ((n > 0) && (x[n-1] == 0));
212 }
213
214 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
215 using namespace Gecode;
216 REG r0(0), r1(1);
217 REG r01 = r0 | r1;
218 extensional(home, x, *r01 + r0 + r01(0,1));
219 }
220 };
221
223 class RegSharedA : public Test {
224 public:
226 RegSharedA(void) : Test("Extensional::Reg::Shared::A",4,2,2) {}
228 virtual bool solution(const Assignment& x) const {
229 return (((x[0] == 0) || (x[0] == 2)) &&
230 ((x[1] == -1) || (x[1] == 1)) &&
231 ((x[2] == 0) || (x[2] == 1)) &&
232 ((x[3] == 0) || (x[3] == 1)));
233 }
234
235 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
236 using namespace Gecode;
237 IntVarArgs y(8);
238 for (int i=0; i<4; i++)
239 y[i]=y[i+4]=x[i];
240 unshare(home,y);
241 extensional(home, y,
242 ((REG(0) | REG(2)) +
243 (REG(-1) | REG(1)) +
244 (REG(7) | REG(0) | REG(1)) +
245 (REG(0) | REG(1)))(2,2));
246 }
247 };
248
250 class RegSharedB : public Test {
251 public:
253 RegSharedB(void) : Test("Extensional::Reg::Shared::B",4,2,2) {}
255 virtual bool solution(const Assignment& x) const {
256 return (((x[0] == 0) || (x[0] == 2)) &&
257 ((x[1] == -1) || (x[1] == 1)) &&
258 ((x[2] == 0) || (x[2] == 1)) &&
259 ((x[3] == 0) || (x[3] == 1)));
260 }
261
262 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
263 using namespace Gecode;
264 IntVarArgs y(12);
265 for (int i=0; i<4; i++)
266 y[i]=y[i+4]=y[i+8]=x[i];
267 unshare(home,y);
268 extensional(home, y,
269 ((REG(0) | REG(2)) +
270 (REG(-1) | REG(1)) +
271 (REG(7) | REG(0) | REG(1)) +
272 (REG(0) | REG(1)))(3,3));
273 }
274 };
275
277 class RegSharedC : public Test {
278 public:
280 RegSharedC(void) : Test("Extensional::Reg::Shared::C",4,0,1) {}
282 virtual bool solution(const Assignment& x) const {
283 return (x[1]==1) && (x[2]==0) && (x[3]==1);
284 }
285
286 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
287 using namespace Gecode;
289 for (int i=0; i<4; i++)
290 y[i]=y[i+4]=channel(home,x[i]);
291 unshare(home,y);
292 extensional(home,y,
293 ((REG(0) | REG(1)) + REG(1) + REG(0) + REG(1))(2,2));
294 }
295 };
296
298 class RegSharedD : public Test {
299 public:
301 RegSharedD(void) : Test("Extensional::Reg::Shared::D",4,0,1) {}
303 virtual bool solution(const Assignment& x) const {
304 return (x[1]==1) && (x[2]==0) && (x[3]==1);
305 }
306
307 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
308 using namespace Gecode;
310 for (int i=0; i<4; i++)
311 y[i]=y[i+4]=y[i+8]=channel(home,x[i]);
312 unshare(home, y);
313 extensional(home, y,
314 ((REG(0) | REG(1)) + REG(1) + REG(0) + REG(1))(3,3));
315 }
316 };
317
319 class RegEmptyDFA : public Test {
320 public:
322 RegEmptyDFA(void) : Test("Extensional::Reg::Empty::DFA",1,0,0) {
323 testsearch = false;
324 }
325
326 virtual bool solution(const Assignment& x) const {
327 (void)x;
328 return false;
329 }
330
331 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
332 Gecode::DFA d;
333 Gecode::extensional(home, x, d);
334 }
335 };
336
338 class RegEmptyREG : public Test {
339 public:
341 RegEmptyREG(void) : Test("Extensional::Reg::Empty::REG",1,0,0) {
342 testsearch = false;
343 }
344
345 virtual bool solution(const Assignment& x) const {
346 (void)x;
347 return false;
348 }
349
350 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
352 Gecode::extensional(home, x, r);
353 }
354 };
355
357 class RegOpt : public Test {
358 protected:
360 int n;
361 public:
363 RegOpt(int n0)
364 : Test("Extensional::Reg::Opt::"+str(n0),1,0,15), n(n0) {}
365
366 virtual bool solution(const Assignment& x) const {
367 return (x[0] < n) && ((x[0] & 1) == 0);
368 }
369
370 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
371 using namespace Gecode;
373 DFA::Transition* ti = t;
374 int* f = new int[n+1];
375 int* fi = f;
376 for (int i=0; i<n; i++) {
377 ti->i_state = 0;
378 ti->symbol = i;
379 ti->o_state = i+1;
380 ti++;
381 if ((i & 1) == 0) {
382 *fi = i+1; fi++;
383 }
384 }
385 ti->i_state = -1;
386 *fi = -1;
387 DFA d(0, t, f, false);
388 delete [] t;
389 delete [] f;
390 extensional(home, x, d);
391 }
392
393 };
394
397 using namespace Gecode;
398 REG expression;
399 for (int i = 0; i<ts.tuples(); i++) {
400 REG r;
401 for (int j = 0; j<ts.arity(); j++) {
402 r += REG(ts[i][j]);
403 }
404 expression |= r;
405 }
406 DFA dfa(expression);
407 return dfa;
408 }
409
411 class TupleSetBase : public Test {
412 protected:
416 bool pos;
419 public:
422 : Test("Extensional::TupleSet::" + extensional_kind_name(epk0) +
423 "::" + str(p) + "::Base",
424 4,1,5,true,Gecode::IPL_DOM),
425 t(4), pos(p), epk(epk0) {
426 using namespace Gecode;
427 IntArgs t1({2, 1, 2, 4});
428 IntArgs t2({2, 2, 1, 4});
429 IntArgs t3({4, 3, 4, 1});
430 IntArgs t4({1, 3, 2, 3});
431 IntArgs t5({3, 3, 3, 2});
432 t.add(t1).add(t1).add(t2).add(t2)
433 .add(t3).add(t3).add(t4).add(t4)
434 .add(t5).add(t5).add(t5).add(t5)
435 .add(t5).add(t5).add(t5).add(t5)
436 .add(t1).add(t1).add(t2).add(t2)
437 .add(t3).add(t3).add(t4).add(t4)
438 .add(t5).add(t5).add(t5).add(t5)
439 .add(t5).add(t5).add(t5).add(t5)
440 .finalize(epk);
441 }
442
443 virtual bool solution(const Assignment& x) const {
444 return pos == ((x[0] == 1 && x[1] == 3 && x[2] == 2 && x[3] == 3) ||
445 (x[0] == 2 && x[1] == 1 && x[2] == 2 && x[3] == 4) ||
446 (x[0] == 2 && x[1] == 2 && x[2] == 1 && x[3] == 4) ||
447 (x[0] == 3 && x[1] == 3 && x[2] == 3 && x[3] == 2) ||
448 (x[0] == 4 && x[1] == 3 && x[2] == 4 && x[3] == 1));
449 }
450
451 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
452 using namespace Gecode;
453 TupleSet ts = TupleSet(t.arity(),tupleset2dfa(t),epk);
454 assert(t == ts);
455 assert(ts.representation() == epk);
456 extensional(home, x, t, pos, ipl);
457 }
458
459 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x,
461 extensional(home, x, t, pos, r, ipl);
462 }
463 };
464
466 class TupleSetTest : public Test {
467 protected:
469 bool pos;
475 bool toDFA;
476 public:
478 TupleSetTest(const std::string& s, bool p,
479 Gecode::IntSet d0, Gecode::TupleSet ts0, bool td,
481 : Test("Extensional::TupleSet::" + extensional_kind_name(epk0) +
482 "::" + str(p) + "::" + s,
483 ts0.arity(),d0,true,Gecode::IPL_DOM),
484 pos(p), epk(epk0), ts(ts0), toDFA(td) {
485 }
486
487 virtual bool solution(const Assignment& x) const {
488 using namespace Gecode;
489 for (int i=ts.tuples(); i--; ) {
490 TupleSet::Tuple t = ts[i];
491 bool same = true;
492 for (int j=0; (j < ts.arity()) && same; j++)
493 if (t[j] != x[j])
494 same = false;
495 if (same)
496 return pos;
497 }
498 return !pos;
499 }
500
501 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
502 using namespace Gecode;
503 if (toDFA) {
504 TupleSet t = TupleSet(ts.arity(),tupleset2dfa(ts),epk);
505 assert(ts == t);
506 assert(t.representation() == epk);
507 }
508 extensional(home, x, ts, pos, ipl);
509 }
510
511 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x,
513 using namespace Gecode;
514 extensional(home, x, ts, pos, r, ipl);
515 }
516 };
517
519 public:
521 RandomTupleSetTest(const std::string& s, bool p,
524 : TupleSetTest(s,p,d0,ts0,false,epk0) {
525 testsearch = false;
526 }
527
528 virtual Assignment* assignment(void) const {
529 using namespace Gecode;
530 return new RandomAssignment(arity, dom, 1000, _rand);
531 }
532 };
533
536 public:
538 : ::Test::Base("Int::Extensional::TupleSet::Sparse::Unary") {}
539
540 virtual bool run(void) {
541 using namespace Gecode;
542
543 const int n = 2000;
544 TupleSet ts(1);
545 for (int i=0; i<n; i++)
546 ts.add(IntArgs({i}));
547 ts.finalize(EPK_SPARSE);
548
549 if (ts.representation() != EPK_SPARSE) {
550 std::cerr << "ERROR: TupleSet did not select sparse support"
551 << std::endl;
552 return false;
553 }
554
555 class SparseUnarySpace : public Space {
556 public:
557 IntVarArray x;
558 SparseUnarySpace(const TupleSet& t, int n0)
559 : x(*this,1,0,n0-1) {
560 extensional(*this, x, t, true, IPL_DOM);
561 branch(*this, x, INT_VAR_NONE(), INT_VAL_MIN());
562 }
563 SparseUnarySpace(SparseUnarySpace& s)
564 : Space(s) {
565 x.update(*this,s.x);
566 }
567 virtual Space*
568 copy(void) {
569 return new SparseUnarySpace(*this);
570 }
571 };
572
573 SparseUnarySpace* root = new SparseUnarySpace(ts,n);
574 DFS<SparseUnarySpace> e(root);
575 delete root;
576
577 SparseUnarySpace* sol = e.next();
578 if (sol == nullptr)
579 return false;
580 const bool ok = sol->x[0].assigned() && (sol->x[0].val() == 0);
581 delete sol;
582 return ok;
583 }
584 };
585
588 public:
590 : ::Test::Base("Int::Extensional::TupleSet::Sparse::Ternary") {}
591
592 virtual bool run(void) {
593 using namespace Gecode;
594
595 const int n = 1500;
596 TupleSet ts(3);
597 for (int i=0; i<n; i++)
598 ts.add(IntArgs({i, (i*7) % n, (i*11) % n}));
599 ts.finalize(EPK_SPARSE);
600
601 if (ts.representation() != EPK_SPARSE) {
602 std::cerr << "ERROR: Ternary TupleSet did not select sparse support"
603 << std::endl;
604 return false;
605 }
606
607 class SparseTernarySpace : public Space {
608 public:
609 IntVarArray x;
610 SparseTernarySpace(const TupleSet& t, int n0)
611 : x(*this,3,0,n0-1) {
612 extensional(*this, x, t, true, IPL_DOM);
613 branch(*this, x, INT_VAR_NONE(), INT_VAL_MIN());
614 }
615 SparseTernarySpace(SparseTernarySpace& s)
616 : Space(s) {
617 x.update(*this,s.x);
618 }
619 virtual Space*
620 copy(void) {
621 return new SparseTernarySpace(*this);
622 }
623 };
624
625 SparseTernarySpace* root = new SparseTernarySpace(ts,n);
627 delete root;
628
629 SparseTernarySpace* sol = e.next();
630 if (sol == nullptr)
631 return false;
632 const int a = sol->x[0].val();
633 const int b = sol->x[1].val();
634 const int c = sol->x[2].val();
635 delete sol;
636 return (b == ((a*7) % n)) && (c == ((a*11) % n));
637 }
638 };
639
642 public:
644 : ::Test::Base("Int::Extensional::TupleSet::Sparse::HighArity") {}
645
646 virtual bool run(void) {
647 using namespace Gecode;
648
649 const int n = 1000;
650 TupleSet ts(6);
651 for (int i=0; i<n; i++)
652 ts.add(IntArgs({i, (i*3) % n, (i*5) % n,
653 (i*7) % n, (i*11) % n, (i*13) % n}));
654 ts.finalize(EPK_SPARSE);
655
656 if (ts.representation() != EPK_SPARSE) {
657 std::cerr << "ERROR: High-arity TupleSet did not select sparse support"
658 << std::endl;
659 return false;
660 }
661
662 class SparseHighAritySpace : public Space {
663 public:
664 IntVarArray x;
665 SparseHighAritySpace(const TupleSet& t, int n0)
666 : x(*this,6,0,n0-1) {
667 extensional(*this, x, t, true, IPL_DOM);
668 branch(*this, x, INT_VAR_NONE(), INT_VAL_MIN());
669 }
670 SparseHighAritySpace(SparseHighAritySpace& s)
671 : Space(s) {
672 x.update(*this,s.x);
673 }
674 virtual Space*
675 copy(void) {
676 return new SparseHighAritySpace(*this);
677 }
678 };
679
680 SparseHighAritySpace* root = new SparseHighAritySpace(ts,n);
682 delete root;
683
684 SparseHighAritySpace* sol = e.next();
685 if (sol == nullptr)
686 return false;
687 const int a = sol->x[0].val();
688 const int b = sol->x[1].val();
689 const int c = sol->x[2].val();
690 const int d = sol->x[3].val();
691 const int e0 = sol->x[4].val();
692 const int f = sol->x[5].val();
693 delete sol;
694 return (b == ((a*3) % n)) &&
695 (c == ((a*5) % n)) &&
696 (d == ((a*7) % n)) &&
697 (e0 == ((a*11) % n)) &&
698 (f == ((a*13) % n));
699 }
700 };
701
704 public:
706 : ::Test::Base("Int::Extensional::TupleSet::Sparse::Nullary") {}
707
708 virtual bool run(void) {
709 using namespace Gecode;
710
711 class SparseNullarySpace : public Space {
712 public:
713 IntVarArray x;
714 SparseNullarySpace(const TupleSet& t)
715 : x(*this,0,0,0) {
716 extensional(*this, x, t, true, IPL_DOM);
717 }
718 SparseNullarySpace(SparseNullarySpace& s)
719 : Space(s) {
720 x.update(*this,s.x);
721 }
722 virtual Space*
723 copy(void) {
724 return new SparseNullarySpace(*this);
725 }
726 };
727
728 TupleSet sat(0);
729 sat.add(IntArgs(0));
730 sat.finalize(EPK_SPARSE);
731 if (sat.representation() != EPK_SPARSE) {
732 std::cerr << "ERROR: Nullary sat table not sparse" << std::endl;
733 return false;
734 }
735 SparseNullarySpace* sat_root = new SparseNullarySpace(sat);
736 DFS<SparseNullarySpace> sat_engine(sat_root);
737 delete sat_root;
738 SparseNullarySpace* sat_sol = sat_engine.next();
739 if (sat_sol == nullptr) {
740 std::cerr << "ERROR: Nullary sat table produced no solution"
741 << std::endl;
742 return false;
743 }
744 delete sat_sol;
745
746 TupleSet unsat(0);
747 unsat.finalize(EPK_SPARSE);
748 SparseNullarySpace* unsat_root = new SparseNullarySpace(unsat);
749 DFS<SparseNullarySpace> unsat_engine(unsat_root);
750 delete unsat_root;
751 SparseNullarySpace* unsat_sol = unsat_engine.next();
752 const bool ok = (unsat_sol == nullptr);
753 if (!ok)
754 std::cerr << "ERROR: Nullary empty table unexpectedly satisfiable"
755 << std::endl;
756 delete unsat_sol;
757 return ok;
758 }
759 };
760
763 public:
765 : ::Test::Base("Int::Extensional::TupleSet::Sparse::IncrementalDelta") {}
766
767 virtual bool run(void) {
768 using namespace Gecode;
769
770 class SparseDeltaSpace : public Space {
771 public:
772 IntVarArray x;
773 SparseDeltaSpace(const TupleSet& t)
774 : x(*this,2,0,3) {
775 extensional(*this, x, t, true, IPL_DOM);
776 rel(*this, x[0], IRT_NQ, 0);
777 rel(*this, x[0], IRT_NQ, 1);
778 rel(*this, x[1], IRT_NQ, 3);
779 branch(*this, x, INT_VAR_NONE(), INT_VAL_MIN());
780 }
781 SparseDeltaSpace(SparseDeltaSpace& s)
782 : Space(s) {
783 x.update(*this,s.x);
784 }
785 virtual Space*
786 copy(void) {
787 return new SparseDeltaSpace(*this);
788 }
789 };
790
791 TupleSet ts(2);
792 ts.add(IntArgs({0,0})).add(IntArgs({1,1}))
793 .add(IntArgs({2,2})).add(IntArgs({3,3}));
794 ts.finalize(EPK_SPARSE);
795 if (ts.representation() != EPK_SPARSE)
796 return false;
797
798 SparseDeltaSpace* root = new SparseDeltaSpace(ts);
799 DFS<SparseDeltaSpace> e(root);
800 delete root;
801
802 SparseDeltaSpace* sol = e.next();
803 if (sol == nullptr)
804 return false;
805 SparseDeltaSpace* extra = e.next();
806 const bool ok = sol->x[0].assigned() && sol->x[1].assigned() &&
807 (sol->x[0].val() == 2) && (sol->x[1].val() == 2) &&
808 (extra == nullptr);
809 delete sol;
810 delete extra;
811 return ok;
812 }
813 };
814
817 public:
819 : ::Test::Base("Int::Extensional::TupleSet::Sparse::IncrementalAssign") {}
820
821 virtual bool run(void) {
822 using namespace Gecode;
823
824 class SparseAssignSpace : public Space {
825 public:
826 IntVarArray x;
827 SparseAssignSpace(const TupleSet& t)
828 : x(*this,2,0,3) {
829 extensional(*this, x, t, true, IPL_DOM);
830 rel(*this, x[0], IRT_EQ, 2);
831 rel(*this, x[1], IRT_NQ, 1);
832 branch(*this, x, INT_VAR_NONE(), INT_VAL_MIN());
833 }
834 SparseAssignSpace(SparseAssignSpace& s)
835 : Space(s) {
836 x.update(*this,s.x);
837 }
838 virtual Space*
839 copy(void) {
840 return new SparseAssignSpace(*this);
841 }
842 };
843
844 TupleSet ts(2);
845 ts.add(IntArgs({0,0})).add(IntArgs({1,1}))
846 .add(IntArgs({2,1})).add(IntArgs({3,3}));
847 ts.finalize(EPK_SPARSE);
848 if (ts.representation() != EPK_SPARSE)
849 return false;
850
851 SparseAssignSpace* root = new SparseAssignSpace(ts);
853 delete root;
854 SparseAssignSpace* sol = e.next();
855 const bool ok = (sol == nullptr);
856 delete sol;
857 return ok;
858 }
859 };
860
863 public:
865 : ::Test::Base("Int::Extensional::TupleSet::Sparse::IncrementalBool") {}
866
867 virtual bool run(void) {
868 using namespace Gecode;
869
870 class SparseBoolSpace : public Space {
871 public:
872 BoolVarArray x;
873 SparseBoolSpace(const TupleSet& t)
874 : x(*this,2,0,1) {
875 extensional(*this, x, t, true, IPL_DOM);
876 rel(*this, x[0], IRT_NQ, 0);
877 branch(*this, x, BOOL_VAR_NONE(), BOOL_VAL_MIN());
878 }
879 SparseBoolSpace(SparseBoolSpace& s)
880 : Space(s) {
881 x.update(*this,s.x);
882 }
883 virtual Space*
884 copy(void) {
885 return new SparseBoolSpace(*this);
886 }
887 };
888
889 TupleSet ts(2);
890 ts.add(IntArgs({0,1})).add(IntArgs({1,0}));
891 ts.finalize(EPK_SPARSE);
892 if (ts.representation() != EPK_SPARSE)
893 return false;
894
895 SparseBoolSpace* root = new SparseBoolSpace(ts);
896 DFS<SparseBoolSpace> e(root);
897 delete root;
898
899 SparseBoolSpace* sol = e.next();
900 if (sol == nullptr)
901 return false;
902 SparseBoolSpace* extra = e.next();
903 const bool ok = sol->x[0].assigned() && sol->x[1].assigned() &&
904 (sol->x[0].val() == 1) && (sol->x[1].val() == 0) &&
905 (extra == nullptr);
906 delete sol;
907 delete extra;
908 return ok;
909 }
910 };
911
914 public:
916 : ::Test::Base("Int::Extensional::TupleSet::Sparse::DisabledFailure") {}
917
918 virtual bool run(void) {
919 using namespace Gecode;
920
921 class DisabledSpace : public Space {
922 public:
923 IntVarArray x;
924 DisabledSpace(const TupleSet& t)
925 : x(*this,2,0,1) {
926 extensional(*this,x,t,true,IPL_DOM);
927 }
928 DisabledSpace(DisabledSpace& s)
929 : Space(s) {
930 x.update(*this,s.x);
931 }
932 virtual Space* copy(void) {
933 return new DisabledSpace(*this);
934 }
935 };
936
937 TupleSet ts(2);
938 ts.add(IntArgs({0,0})).add(IntArgs({1,1}));
939 ts.finalize(EPK_SPARSE);
940
941 DisabledSpace* s = new DisabledSpace(ts);
942 if (s->status() == SS_FAILED) {
943 delete s;
944 return false;
945 }
946 PropagatorGroup::all.disable(*s);
947 rel(*s,s->x[0],IRT_EQ,0);
948 rel(*s,s->x[1],IRT_EQ,1);
949 if (s->status() == SS_FAILED) {
950 delete s;
951 return false;
952 }
953
954 PropagatorGroup::all.enable(*s);
955 const bool failed = (s->status() == SS_FAILED);
956 delete s;
957 return failed;
958 }
959 };
960
963 public:
965 : ::Test::Base("Int::Extensional::TupleSet::Sparse::WideDelta") {}
966
967 virtual bool run(void) {
968 using namespace Gecode;
969
970 const int gap = 1000000000;
971 const int lower = gap / 2;
972 TupleSet ts(1);
973 ts.add(IntArgs({0})).add(IntArgs({gap}));
974 ts.finalize(EPK_SPARSE);
975
976 class NegativeSpace : public Space {
977 public:
978 IntVar x;
979 NegativeSpace(const TupleSet& t, int gap0, int lower0)
980 : x(*this,0,gap0) {
981 extensional(*this,IntVarArgs({x}),t,false,IPL_DOM);
982 rel(*this,x,IRT_GQ,lower0);
983 }
984 NegativeSpace(NegativeSpace& s)
985 : Space(s) {
986 x.update(*this,s.x);
987 }
988 virtual Space* copy(void) {
989 return new NegativeSpace(*this);
990 }
991 };
992
993 NegativeSpace* n = new NegativeSpace(ts,gap,lower);
994 if ((n->status() == SS_FAILED) ||
995 (n->x.min() != lower) || (n->x.max() != gap-1)) {
996 delete n;
997 return false;
998 }
999 delete n;
1000
1001 class ReifiedSpace : public Space {
1002 public:
1003 IntVar x;
1004 BoolVar b;
1005 ReifiedSpace(const TupleSet& t, int gap0, int lower0)
1006 : x(*this,0,gap0), b(*this,0,1) {
1007 extensional(*this,IntVarArgs({x}),t,true,
1008 Reify(b,RM_EQV),IPL_DOM);
1009 rel(*this,x,IRT_GQ,lower0);
1010 }
1011 ReifiedSpace(ReifiedSpace& s)
1012 : Space(s) {
1013 x.update(*this,s.x);
1014 b.update(*this,s.b);
1015 }
1016 virtual Space* copy(void) {
1017 return new ReifiedSpace(*this);
1018 }
1019 };
1020
1021 ReifiedSpace* r = new ReifiedSpace(ts,gap,lower);
1022 const bool ok = (r->status() != SS_FAILED) &&
1023 (r->x.min() == lower) && (r->x.max() == gap) &&
1024 !r->b.assigned();
1025 delete r;
1026 return ok;
1027 }
1028 };
1029
1032 public:
1034 : ::Test::Base("Int::Extensional::TupleSet::Sparse::Negative") {}
1035
1036 virtual bool run(void) {
1037 using namespace Gecode;
1038
1039 class SparseNegativeSpace : public Space {
1040 public:
1041 IntVarArray x;
1042 SparseNegativeSpace(const TupleSet& t)
1043 : x(*this,2,0,1) {
1044 extensional(*this, x, t, false, IPL_DOM);
1045 branch(*this, x, INT_VAR_NONE(), INT_VAL_MIN());
1046 }
1047 SparseNegativeSpace(SparseNegativeSpace& s)
1048 : Space(s) {
1049 x.update(*this,s.x);
1050 }
1051 virtual Space*
1052 copy(void) {
1053 return new SparseNegativeSpace(*this);
1054 }
1055 };
1056
1057 TupleSet ts(2);
1058 ts.add(IntArgs({0,0})).add(IntArgs({1,1}));
1059 ts.finalize(EPK_SPARSE);
1060
1061 SparseNegativeSpace* root = new SparseNegativeSpace(ts);
1063 delete root;
1064
1065 int n = 0;
1066 while (SparseNegativeSpace* sol = e.next()) {
1067 if (sol->x[0].val() == sol->x[1].val()) {
1068 delete sol;
1069 return false;
1070 }
1071 n++;
1072 delete sol;
1073 }
1074 return n == 2;
1075 }
1076 };
1077
1080 public:
1082 : ::Test::Base("Int::Extensional::TupleSet::Sparse::Reified") {}
1083
1084 virtual bool run(void) {
1085 using namespace Gecode;
1086
1087 class SparseReifiedSpace : public Space {
1088 public:
1089 IntVarArray x;
1090 BoolVar b;
1091 SparseReifiedSpace(const TupleSet& t)
1092 : x(*this,2,0,1), b(*this,0,1) {
1093 extensional(*this, x, t, true, Reify(b,RM_EQV), IPL_DOM);
1094 rel(*this, b, IRT_EQ, 1);
1095 branch(*this, x, INT_VAR_NONE(), INT_VAL_MIN());
1096 }
1097 SparseReifiedSpace(SparseReifiedSpace& s)
1098 : Space(s) {
1099 x.update(*this,s.x);
1100 b.update(*this,s.b);
1101 }
1102 virtual Space*
1103 copy(void) {
1104 return new SparseReifiedSpace(*this);
1105 }
1106 };
1107
1108 TupleSet ts(2);
1109 ts.add(IntArgs({0,0})).add(IntArgs({1,1}));
1110 ts.finalize(EPK_SPARSE);
1111
1112 SparseReifiedSpace* root = new SparseReifiedSpace(ts);
1114 delete root;
1115
1116 int n = 0;
1117 while (SparseReifiedSpace* sol = e.next()) {
1118 if (sol->x[0].val() != sol->x[1].val()) {
1119 delete sol;
1120 return false;
1121 }
1122 n++;
1123 delete sol;
1124 }
1125 return n == 2;
1126 }
1127 };
1128
1131 public:
1133 : ::Test::Base("Int::Extensional::TupleSet::Support::SingleRepresentation") {}
1134
1135 virtual bool run(void) {
1136 using namespace Gecode;
1137 TupleSet ts(2);
1138 for (int i=0; i<100; i++)
1139 ts.add(IntArgs({i, (i*3) % 100}));
1140 ts.finalize(EPK_SPARSE);
1141 if (ts.representation() != EPK_SPARSE) {
1142 std::cerr << "ERROR: Sparse support not available" << std::endl;
1143 return false;
1144 }
1145 if (ts.fst(0)->supports(ts.words(),ts.fst(0)->min) != nullptr) {
1146 std::cerr << "ERROR: Sparse range exposed dense support"
1147 << std::endl;
1148 return false;
1149 }
1150
1151 TupleSet tc(2);
1152 for (int i=0; i<100; i++)
1153 tc.add(IntArgs({i, (i*7) % 100}));
1154 tc.finalize(EPK_DENSE_COMPRESSED);
1155 if (tc.representation() != EPK_DENSE_COMPRESSED) {
1156 std::cerr << "ERROR: Compressed support not available" << std::endl;
1157 return false;
1158 }
1159 if (tc.fst(0)->supports(tc.words(),tc.fst(0)->min) != nullptr) {
1160 std::cerr << "ERROR: Compressed range exposed dense support"
1161 << std::endl;
1162 return false;
1163 }
1164
1165 TupleSet td(2);
1166 for (int i=0; i<100; i++)
1167 td.add(IntArgs({i, (i*11) % 100}));
1168 td.finalize();
1169 if (td.representation() != EPK_DENSE) {
1170 std::cerr << "ERROR: Default finalize did not keep dense support"
1171 << std::endl;
1172 return false;
1173 }
1174 if (td.fst(0)->supports(td.words(),td.fst(0)->min) == nullptr) {
1175 std::cerr << "ERROR: Dense range lost support data" << std::endl;
1176 return false;
1177 }
1178
1179 TupleSet empty_sparse(2);
1180 empty_sparse.finalize(EPK_SPARSE);
1181 if (empty_sparse.representation() != EPK_SPARSE) {
1182 std::cerr << "ERROR: Empty sparse table forgot representation"
1183 << std::endl;
1184 return false;
1185 }
1186 TupleSet empty_compressed(2);
1187 empty_compressed.finalize(EPK_DENSE_COMPRESSED);
1188 if (empty_compressed.representation() != EPK_DENSE_COMPRESSED) {
1189 std::cerr << "ERROR: Empty compressed table forgot representation"
1190 << std::endl;
1191 return false;
1192 }
1193 return true;
1194 }
1195 };
1196
1199 public:
1201 : ::Test::Base(
1202 "Int::Extensional::TupleSet::Support::OffsetBoundary") {}
1203
1204 virtual bool run(void) {
1206 const unsigned long long max =
1207 static_cast<unsigned long long>
1208 (std::numeric_limits<unsigned int>::max());
1209 unsigned int n_offsets = 0U;
1210 if (!support_offsets_size(max-1ULL,n_offsets) ||
1211 (n_offsets != std::numeric_limits<unsigned int>::max()))
1212 return false;
1213 if (support_offsets_size(max,n_offsets))
1214 return false;
1215 return !support_offsets_size(max+1ULL,n_offsets);
1216 }
1217 };
1218
1221 public:
1223 : ::Test::Base(
1224 "Int::Extensional::TupleSet::Support::TerminalFailure") {}
1225
1226 virtual bool run(void) {
1227 using namespace Gecode;
1228
1229 const int n = 371000;
1230 TupleSet ts(2);
1231 for (int i=0; i<n; i++)
1232 ts.add(IntArgs({i,n+i}));
1233
1234 bool rejected = false;
1235 try {
1236 ts.finalize(EPK_DENSE);
1237 } catch (const Gecode::Int::OutOfLimits&) {
1238 rejected = true;
1239 }
1240 if (!rejected || !ts.failed() || ts.finalized())
1241 return false;
1242
1243 try {
1244 (void) ts.representation();
1245 return false;
1246 } catch (const Gecode::Int::NotYetFinalized&) {
1247 }
1248
1249 try {
1250 ts.finalize(EPK_SPARSE);
1251 return false;
1252 } catch (const Gecode::Int::AlreadyFinalized&) {
1253 }
1254
1255 try {
1256 ts.add(IntArgs({0,0}));
1257 return false;
1258 } catch (const Gecode::Int::AlreadyFinalized&) {
1259 }
1260
1261 class PostingSpace : public Space {
1262 public:
1263 IntVarArray x;
1264 PostingSpace(const TupleSet& t)
1265 : x(*this,2,0,1) {
1266 extensional(*this,x,t);
1267 }
1268 PostingSpace(PostingSpace& s)
1269 : Space(s) {
1270 x.update(*this,s.x);
1271 }
1272 virtual Space* copy(void) {
1273 return new PostingSpace(*this);
1274 }
1275 };
1276
1277 try {
1278 PostingSpace* s = new PostingSpace(ts);
1279 delete s;
1280 return false;
1281 } catch (const Gecode::Int::NotYetFinalized&) {
1282 }
1283 return true;
1284 }
1285 };
1286
1289 public:
1291 : ::Test::Base(
1292 "Int::Extensional::TupleSet::Support::DFARepresentation") {}
1293
1294 virtual bool run(void) {
1295 using namespace Gecode;
1296
1297 DFA dfa((REG(0) + REG(1)) | (REG(2) + REG(3)));
1298 TupleSet sparse(2,dfa,EPK_SPARSE);
1299 if ((sparse.representation() != EPK_SPARSE) ||
1300 (sparse.tuples() != 2))
1301 return false;
1302
1303 TupleSet compressed(2,dfa,EPK_DENSE_COMPRESSED);
1304 if ((compressed.representation() != EPK_DENSE_COMPRESSED) ||
1305 (compressed.tuples() != 2))
1306 return false;
1307
1308 TupleSet dense(2,dfa);
1309 if ((dense.representation() != EPK_DENSE) || (dense.tuples() != 2))
1310 return false;
1311
1312 TupleSet empty(3,dfa,EPK_SPARSE);
1313 return (empty.representation() == EPK_SPARSE) &&
1314 (empty.tuples() == 0);
1315 }
1316 };
1317
1320 public:
1322 : ::Test::Base(
1323 "Int::Extensional::TupleSet::Support::DisabledClone") {}
1324
1325 virtual bool run(void) {
1326 using namespace Gecode;
1327
1328 enum Mode {
1329 MODE_POSITIVE,
1330 MODE_NEGATIVE,
1331 MODE_REIFIED
1332 };
1333
1334 class CloneSpace : public Space {
1335 public:
1336 IntVarArray x;
1337 BoolVar b;
1338 CloneSpace(const TupleSet& t, Mode mode)
1339 : x(*this,2,0,2), b(*this,0,1) {
1340 if (mode == MODE_REIFIED)
1341 extensional(*this,x,t,true,Reify(b,RM_EQV),IPL_DOM);
1342 else
1343 extensional(*this,x,t,mode == MODE_POSITIVE,IPL_DOM);
1344 }
1345 CloneSpace(CloneSpace& s)
1346 : Space(s) {
1347 x.update(*this,s.x);
1348 b.update(*this,s.b);
1349 }
1350 virtual Space* copy(void) {
1351 return new CloneSpace(*this);
1352 }
1353 };
1354
1355 auto check = [](ExtensionalPropKind epk) {
1356 TupleSet ts(2);
1357 ts.add(IntArgs({0,0})).add(IntArgs({1,1})).add(IntArgs({2,2}));
1358 ts.finalize(epk);
1359
1360 CloneSpace* source = new CloneSpace(ts,MODE_POSITIVE);
1361 if (source->status() == SS_FAILED) {
1362 delete source;
1363 return false;
1364 }
1365 PropagatorGroup::all.disable(*source);
1366 rel(*source,source->x[0],IRT_EQ,1);
1367 if ((source->status() == SS_FAILED) ||
1368 !source->x[0].assigned() || (source->x[0].val() != 1) ||
1369 (source->x[1].size() != 3)) {
1370 delete source;
1371 return false;
1372 }
1373
1374 CloneSpace* clone = static_cast<CloneSpace*>(source->clone());
1375 PropagatorGroup::all.enable(*clone);
1376 const bool clone_ok = (clone->status() != SS_FAILED) &&
1377 clone->x[1].assigned() && (clone->x[1].val() == 1);
1378 delete clone;
1379
1380 PropagatorGroup::all.enable(*source);
1381 const bool source_ok = (source->status() != SS_FAILED) &&
1382 source->x[1].assigned() && (source->x[1].val() == 1);
1383 delete source;
1384 return clone_ok && source_ok;
1385 };
1386
1387 auto check_empty = [](ExtensionalPropKind epk, Mode mode) {
1388 TupleSet ts(2);
1389 ts.add(IntArgs({0,0})).add(IntArgs({1,1}));
1390 ts.finalize(epk);
1391
1392 CloneSpace* source = new CloneSpace(ts,mode);
1393 if (source->status() == SS_FAILED) {
1394 delete source;
1395 return false;
1396 }
1397 PropagatorGroup::all.disable(*source);
1398 if (mode == MODE_NEGATIVE) {
1399 rel(*source,source->x[0],IRT_EQ,2);
1400 } else {
1401 rel(*source,source->x[0],IRT_EQ,0);
1402 rel(*source,source->x[1],IRT_EQ,1);
1403 }
1404 if (source->status() == SS_FAILED) {
1405 delete source;
1406 return false;
1407 }
1408
1409 auto verify = [mode](CloneSpace& s) {
1410 const SpaceStatus status = s.status();
1411 if (mode == MODE_POSITIVE)
1412 return status == SS_FAILED;
1413 if (status == SS_FAILED)
1414 return false;
1415 if (mode == MODE_REIFIED)
1416 return s.b.assigned() && (s.b.val() == 0);
1417 return s.x[1].size() == 3;
1418 };
1419
1420 CloneSpace* clone = static_cast<CloneSpace*>(source->clone());
1421 PropagatorGroup::all.enable(*clone);
1422 const bool clone_ok = verify(*clone);
1423 delete clone;
1424
1425 PropagatorGroup::all.enable(*source);
1426 const bool source_ok = verify(*source);
1427 delete source;
1428 return clone_ok && source_ok;
1429 };
1430
1431 for (ExtensionalPropKind epk :
1432 {EPK_DENSE,EPK_DENSE_COMPRESSED}) {
1433 if (!check(epk))
1434 return false;
1435 for (Mode mode : {MODE_POSITIVE,MODE_NEGATIVE,MODE_REIFIED})
1436 if (!check_empty(epk,mode))
1437 return false;
1438 }
1439 return true;
1440 }
1441 };
1442
1445 public:
1447 : ::Test::Base("Int::Extensional::TupleSet::Auto::DefaultDispatch") {}
1448
1449 virtual bool run(void) {
1450 using namespace Gecode;
1451
1452 TupleSet dense(2);
1453 dense.add(IntArgs({0,0})).add(IntArgs({1,1}));
1454 dense.finalize(EPK_AUTO);
1455 if (dense.representation() != EPK_DENSE) {
1456 std::cerr << "ERROR: Small AUTO table did not select dense"
1457 << std::endl;
1458 return false;
1459 }
1460
1461 class PositiveSpace : public Space {
1462 public:
1463 IntVarArray x;
1464 PositiveSpace(const TupleSet& t) : x(*this,2,0,1) {
1465 extensional(*this, x, t);
1466 branch(*this, x, INT_VAR_NONE(), INT_VAL_MIN());
1467 }
1468 PositiveSpace(PositiveSpace& s) : Space(s) {
1469 x.update(*this,s.x);
1470 }
1471 virtual Space* copy(void) {
1472 return new PositiveSpace(*this);
1473 }
1474 };
1475
1476 PositiveSpace* dense_root = new PositiveSpace(dense);
1477 DFS<PositiveSpace> dense_engine(dense_root);
1478 delete dense_root;
1479 int dense_solutions = 0;
1480 while (PositiveSpace* sol = dense_engine.next()) {
1481 if (sol->x[0].val() != sol->x[1].val()) {
1482 delete sol;
1483 return false;
1484 }
1485 dense_solutions++;
1486 delete sol;
1487 }
1488 if (dense_solutions != 2)
1489 return false;
1490
1491 const int n = 5000;
1492 TupleSet compressed(2);
1493 for (int i=0; i<n; i++)
1494 compressed.add(IntArgs({i, (i*7) % n}));
1495 compressed.finalize(EPK_AUTO);
1496 if (compressed.representation() != EPK_DENSE_COMPRESSED) {
1497 std::cerr << "ERROR: Large AUTO table did not select compressed"
1498 << std::endl;
1499 return false;
1500 }
1501
1502 class ReifiedSpace : public Space {
1503 public:
1504 IntVarArray x;
1505 BoolVar b;
1506 ReifiedSpace(const TupleSet& t, int n0)
1507 : x(*this,2,0,n0-1), b(*this,0,1) {
1508 extensional(*this, x, t, Reify(b,RM_EQV));
1509 rel(*this, b, IRT_EQ, 1);
1510 rel(*this, x[0], IRT_EQ, 3);
1511 branch(*this, x, INT_VAR_NONE(), INT_VAL_MIN());
1512 }
1513 ReifiedSpace(ReifiedSpace& s) : Space(s) {
1514 x.update(*this,s.x);
1515 b.update(*this,s.b);
1516 }
1517 virtual Space* copy(void) {
1518 return new ReifiedSpace(*this);
1519 }
1520 };
1521
1522 ReifiedSpace* compressed_root = new ReifiedSpace(compressed,n);
1523 DFS<ReifiedSpace> compressed_engine(compressed_root);
1524 delete compressed_root;
1525 ReifiedSpace* compressed_sol = compressed_engine.next();
1526 if (compressed_sol == nullptr)
1527 return false;
1528 const bool ok =
1529 (compressed_sol->x[0].val() == 3) &&
1530 (compressed_sol->x[1].val() == ((3*7) % n));
1531 delete compressed_sol;
1532 ReifiedSpace* extra = compressed_engine.next();
1533 const bool no_extra = (extra == nullptr);
1534 delete extra;
1535 return ok && no_extra;
1536 }
1537 };
1538
1541 public:
1543 : ::Test::Base("Int::Extensional::TupleSet::DenseCompressed::WideGap") {}
1544
1545 virtual bool run(void) {
1546 using namespace Gecode;
1547
1548 const int gap = 1000000000;
1549 TupleSet ts(1);
1550 ts.add(IntArgs({0})).add(IntArgs({gap}));
1551 ts.finalize(EPK_DENSE_COMPRESSED);
1552
1553 class NegativeSpace : public Space {
1554 public:
1555 IntVar x;
1556 NegativeSpace(const TupleSet& t, int gap0)
1557 : x(*this,0,gap0) {
1558 extensional(*this, IntVarArgs({x}), t, false, IPL_DOM);
1559 }
1560 NegativeSpace(NegativeSpace& s) : Space(s) {
1561 x.update(*this,s.x);
1562 }
1563 virtual Space* copy(void) {
1564 return new NegativeSpace(*this);
1565 }
1566 };
1567
1568 NegativeSpace* ns = new NegativeSpace(ts,gap);
1569 if (ns->status() == SS_FAILED) {
1570 delete ns;
1571 return false;
1572 }
1573 if (ns->x.in(0) || ns->x.in(gap)) {
1574 delete ns;
1575 return false;
1576 }
1577 delete ns;
1578
1579 class ReifiedSpace : public Space {
1580 public:
1581 IntVar x;
1582 BoolVar b;
1583 ReifiedSpace(const TupleSet& t, int gap0, bool force)
1584 : x(*this,0,gap0), b(*this,0,1) {
1585 extensional(*this, IntVarArgs({x}), t, true,
1586 Reify(b,RM_EQV), IPL_DOM);
1587 if (force) {
1588 rel(*this, b, IRT_EQ, 1);
1589 rel(*this, x, IRT_EQ, 0);
1590 }
1591 }
1592 ReifiedSpace(ReifiedSpace& s) : Space(s) {
1593 x.update(*this,s.x);
1594 b.update(*this,s.b);
1595 }
1596 virtual Space* copy(void) {
1597 return new ReifiedSpace(*this);
1598 }
1599 };
1600
1601 ReifiedSpace* rs = new ReifiedSpace(ts,gap,false);
1602 if (rs->status() == SS_FAILED) {
1603 delete rs;
1604 return false;
1605 }
1606 delete rs;
1607
1608 ReifiedSpace* rfs = new ReifiedSpace(ts,gap,true);
1609 if (rfs->status() == SS_FAILED) {
1610 delete rfs;
1611 return false;
1612 }
1613 if (!rfs->x.assigned() || (rfs->x.val() != 0) ||
1614 !rfs->b.assigned() || (rfs->b.val() != 1)) {
1615 delete rfs;
1616 return false;
1617 }
1618 delete rfs;
1619
1620 class PositiveDeltaSpace : public Space {
1621 public:
1622 IntVar x;
1623 PositiveDeltaSpace(const TupleSet& t, int gap0)
1624 : x(*this,0,gap0) {
1625 extensional(*this, IntVarArgs({x}), t, true, IPL_DOM);
1626 rel(*this, x, IRT_NQ, 0);
1627 }
1628 PositiveDeltaSpace(PositiveDeltaSpace& s) : Space(s) {
1629 x.update(*this,s.x);
1630 }
1631 virtual Space* copy(void) {
1632 return new PositiveDeltaSpace(*this);
1633 }
1634 };
1635
1636 PositiveDeltaSpace* ps = new PositiveDeltaSpace(ts,gap);
1637 if (ps->status() == SS_FAILED) {
1638 delete ps;
1639 return false;
1640 }
1641 if (!ps->x.assigned() || (ps->x.val() != gap)) {
1642 delete ps;
1643 return false;
1644 }
1645 delete ps;
1646
1647 return true;
1648 }
1649 };
1650
1653 public:
1655 : ::Test::Base("Int::Extensional::TupleSet::Sparse::NegativeFail") {}
1656
1657 virtual bool run(void) {
1658 using namespace Gecode;
1659 class NegativeFailSpace : public Space {
1660 public:
1661 IntVarArray x;
1662 NegativeFailSpace(const TupleSet& t)
1663 : x(*this,2,0,1) {
1664 extensional(*this, x, t, false, IPL_DOM);
1665 branch(*this, x, INT_VAR_NONE(), INT_VAL_MIN());
1666 }
1667 NegativeFailSpace(NegativeFailSpace& s)
1668 : Space(s) {
1669 x.update(*this,s.x);
1670 }
1671 virtual Space* copy(void) {
1672 return new NegativeFailSpace(*this);
1673 }
1674 };
1675 TupleSet ts(2);
1676 ts.add(IntArgs({0,0})).add(IntArgs({0,1}))
1677 .add(IntArgs({1,0})).add(IntArgs({1,1}));
1678 ts.finalize(EPK_SPARSE);
1679 if (ts.representation() != EPK_SPARSE)
1680 return false;
1681 NegativeFailSpace* root = new NegativeFailSpace(ts);
1682 DFS<NegativeFailSpace> e(root);
1683 delete root;
1684 NegativeFailSpace* sol = e.next();
1685 const bool ok = (sol == nullptr);
1686 delete sol;
1687 return ok;
1688 }
1689 };
1690
1693 public:
1695 : ::Test::Base("Int::Extensional::TupleSet::Sparse::NegativePrune") {}
1696
1697 virtual bool run(void) {
1698 using namespace Gecode;
1699 class NegativePruneSpace : public Space {
1700 public:
1701 IntVarArray x;
1702 NegativePruneSpace(const TupleSet& t)
1703 : x(*this,2,0,1) {
1704 extensional(*this, x, t, false, IPL_DOM);
1705 branch(*this, x, INT_VAR_NONE(), INT_VAL_MIN());
1706 }
1707 NegativePruneSpace(NegativePruneSpace& s)
1708 : Space(s) {
1709 x.update(*this,s.x);
1710 }
1711 virtual Space* copy(void) {
1712 return new NegativePruneSpace(*this);
1713 }
1714 };
1715 TupleSet ts(2);
1716 ts.add(IntArgs({0,0})).add(IntArgs({0,1}));
1717 ts.finalize(EPK_SPARSE);
1718 if (ts.representation() != EPK_SPARSE)
1719 return false;
1720 NegativePruneSpace* root = new NegativePruneSpace(ts);
1722 delete root;
1723
1724 int n = 0;
1725 while (NegativePruneSpace* sol = e.next()) {
1726 if (sol->x[0].val() != 1) {
1727 delete sol;
1728 return false;
1729 }
1730 n++;
1731 delete sol;
1732 }
1733 return n == 2;
1734 }
1735 };
1736
1739 public:
1741 : ::Test::Base("Int::Extensional::TupleSet::Sparse::ReifiedModes") {}
1742
1743 virtual bool run(void) {
1744 using namespace Gecode;
1745 class ReifModeSpace : public Space {
1746 public:
1747 IntVarArray x;
1748 BoolVar b;
1749 ReifModeSpace(const TupleSet& t, bool pos, ReifyMode rm, int bv)
1750 : x(*this,2,0,1), b(*this,0,1) {
1751 extensional(*this, x, t, pos, Reify(b,rm), IPL_DOM);
1752 rel(*this, b, IRT_EQ, bv);
1753 branch(*this, x, INT_VAR_NONE(), INT_VAL_MIN());
1754 }
1755 ReifModeSpace(ReifModeSpace& s)
1756 : Space(s) {
1757 x.update(*this,s.x);
1758 b.update(*this,s.b);
1759 }
1760 virtual Space* copy(void) {
1761 return new ReifModeSpace(*this);
1762 }
1763 };
1764
1765 TupleSet ts(2);
1766 ts.add(IntArgs({0,0}));
1767 ts.finalize(EPK_SPARSE);
1768 if (ts.representation() != EPK_SPARSE)
1769 return false;
1770
1771 auto count = [&ts](bool pos, ReifyMode rm, int bv,
1772 bool must_equal) {
1773 ReifModeSpace* root = new ReifModeSpace(ts,pos,rm,bv);
1774 DFS<ReifModeSpace> e(root);
1775 delete root;
1776 int n = 0;
1777 while (ReifModeSpace* sol = e.next()) {
1778 const bool eq = (sol->x[0].val() == 0) && (sol->x[1].val() == 0);
1779 if (must_equal != eq) {
1780 delete sol;
1781 return -1;
1782 }
1783 n++;
1784 delete sol;
1785 }
1786 return n;
1787 };
1788
1789 if (count(true,RM_EQV,1,true) != 1)
1790 return false;
1791 if (count(true,RM_EQV,0,false) != 3)
1792 return false;
1793 if (count(true,RM_IMP,1,true) != 1)
1794 return false;
1795 if (count(true,RM_PMI,0,false) != 3)
1796 return false;
1797 if (count(false,RM_EQV,0,true) != 1)
1798 return false;
1799 if (count(false,RM_EQV,1,false) != 3)
1800 return false;
1801
1802 return true;
1803 }
1804 };
1805
1807 class TupleSetLarge : public Test {
1808 protected:
1810 bool pos;
1815 public:
1818 : Test("Extensional::TupleSet::" + extensional_kind_name(epk0) +
1819 "::" + str(p) + "::Large",
1820 5,1,5,true,Gecode::IPL_DOM),
1821 pos(p), epk(epk0), t(5) {
1822 using namespace Gecode;
1823
1824 CpltAssignment ass(5, IntSet(1, 5));
1825 while (ass.has_more()) {
1826 if (_rand(100) <= prob*100) {
1827 IntArgs tuple(5);
1828 for (int i = 5; i--; ) tuple[i] = ass[i];
1829 t.add(tuple);
1830 }
1831 ass.next(_rand);
1832 }
1833 t.finalize(epk);
1834 }
1835
1836 virtual bool solution(const Assignment& x) const {
1837 using namespace Gecode;
1838 for (int i = 0; i < t.tuples(); ++i) {
1839 TupleSet::Tuple l = t[i];
1840 bool same = true;
1841 for (int j = 0; j < t.arity() && same; ++j)
1842 if (l[j] != x[j]) same = false;
1843 if (same)
1844 return pos;
1845 }
1846 return !pos;
1847 }
1848
1849 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
1850 using namespace Gecode;
1851 extensional(home, x, t, pos, ipl);
1852 }
1853
1855 Gecode::Reify r) {
1856 using namespace Gecode;
1857 extensional(home, x, t, pos, r, ipl);
1858 }
1859 };
1860
1862 class TupleSetBool : public Test {
1863 protected:
1865 bool pos;
1870 public:
1873 : Test("Extensional::TupleSet::" + extensional_kind_name(epk0) +
1874 "::" + str(p) + "::Bool",
1875 5,0,1,true), pos(p), epk(epk0), t(5) {
1876 using namespace Gecode;
1877
1878 CpltAssignment ass(5, IntSet(0, 1));
1879 while (ass.has_more()) {
1880 if (_rand(100) <= prob*100) {
1881 IntArgs tuple(5);
1882 for (int i = 5; i--; ) tuple[i] = ass[i];
1883 t.add(tuple);
1884 }
1885 ass.next(_rand);
1886 }
1887 t.finalize(epk);
1888 }
1889
1890 virtual bool solution(const Assignment& x) const {
1891 using namespace Gecode;
1892 for (int i = 0; i < t.tuples(); ++i) {
1893 TupleSet::Tuple l = t[i];
1894 bool same = true;
1895 for (int j = 0; j < t.arity() && same; ++j)
1896 if (l[j] != x[j])
1897 same = false;
1898 if (same)
1899 return pos;
1900 }
1901 return !pos;
1902 }
1903
1904 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
1905 using namespace Gecode;
1906 BoolVarArgs y(x.size());
1907 for (int i = x.size(); i--; )
1908 y[i] = channel(home, x[i]);
1909 extensional(home, y, t, pos, ipl);
1910 }
1911
1913 Gecode::Reify r) {
1914 using namespace Gecode;
1915 BoolVarArgs y(x.size());
1916 for (int i = x.size(); i--; )
1917 y[i] = channel(home, x[i]);
1918 extensional(home, y, t, pos, r, ipl);
1919 }
1920 };
1921
1924 public:
1928 using namespace Gecode;
1930 int arity = 2;
1931 int n_tuples = 5*5;
1932 while (n_tuples < size) {
1933 arity++;
1934 n_tuples*=5;
1935 }
1937 TupleSet ts(arity);
1938 CpltAssignment ass(arity, IntSet(0, 4));
1939 for (int i = size; i--; ) {
1940 assert(ass.has_more());
1941 IntArgs tuple(arity);
1942 for (int j = arity; j--; ) tuple[j] = ass[j];
1943 ts.add(tuple);
1944 ass.next(rand);
1945 }
1946 ts.finalize(epk);
1947 assert(ts.tuples() == size);
1948 // Create and register test
1949 (void) new TupleSetTest(std::to_string(size),pos,IntSet(0,4),ts,
1950 size <= 128, epk);
1951 }
1952 };
1953
1954 Gecode::TupleSet randomTupleSet(int n, int min, int max, double prob,
1957 using namespace Gecode;
1958 TupleSet t(n);
1959 CpltAssignment ass(n, IntSet(min, max));
1960 while (ass.has_more()) {
1961 if (rand(100) <= prob*100) {
1962 IntArgs tuple(n);
1963 for (int i = n; i--; ) tuple[i] = ass[i];
1964 t.add(tuple);
1965 }
1966 ass.next(rand);
1967 }
1968 t.finalize(epk);
1969 return t;
1970 }
1971
1973 class Create {
1974 public:
1976 Create(void) {
1977 // This code is executed on load, and thus a random number generator source from the supplied
1978 // seed is not available.
1979 // In order to get interesting data her, but still have deterministic and repeatable execution, a fixed seed
1980 // is used for a local random number generator.
1981 // TODO: Make this code later on test run, and use the supplied seed/random number generator.
1983
1984 using namespace Gecode;
1985 for (ExtensionalPropKind epk :
1986 { EPK_DENSE, EPK_SPARSE, EPK_DENSE_COMPRESSED }) {
1987 for (bool pos : { false, true }) {
1988 {
1989 TupleSet ts(4);
1990 ts.add({2, 1, 2, 4}).add({2, 2, 1, 4})
1991 .add({4, 3, 4, 1}).add({1, 3, 2, 3})
1992 .add({3, 3, 3, 2}).add({5, 1, 4, 4})
1993 .add({2, 5, 1, 5}).add({4, 3, 5, 1})
1994 .add({1, 5, 2, 5}).add({5, 3, 3, 2})
1995 .finalize(epk);
1996 (void) new TupleSetTest("A",pos,IntSet(0,6),ts,true,epk);
1997 }
1998 {
1999 TupleSet ts(4);
2000 ts.finalize(epk);
2001 (void) new TupleSetTest("Empty",pos,IntSet(1,2),ts,true,epk);
2002 }
2003 {
2004 TupleSet ts(4);
2005 for (int n=1024*16; n--; )
2006 ts.add({1,2,3,4});
2007 ts.finalize(epk);
2008 (void) new TupleSetTest("Assigned",pos,IntSet(1,4),ts,true,epk);
2009 }
2010 {
2011 TupleSet ts(1);
2012 ts.add({1}).add({2}).add({3}).finalize(epk);
2013 (void) new TupleSetTest("Single",pos,IntSet(-4,4),ts,true,epk);
2014 }
2015 {
2017 TupleSet ts(3);
2018 ts.add({m+0,m+1,m+2}).add({m+4,m+1,m+3})
2019 .add({m+2,m+3,m+0}).add({m+2,m+3,m+0})
2020 .add({m+1,m+2,m+5}).add({m+2,m+3,m+0})
2021 .add({m+3,m+6,m+5}).finalize(epk);
2022 (void) new TupleSetTest("Min",pos,IntSet(m,m+7),ts,true,epk);
2023 }
2024 {
2026 TupleSet ts(3);
2027 ts.add({M-0,M-1,M-2}).add({M-4,M-1,M-3})
2028 .add({M-2,M-3,M-0}).add({M-2,M-3,M-0})
2029 .add({M-1,M-2,M-5}).add({M-2,M-3,M-0})
2030 .add({M-3,M-6,M-5}).finalize(epk);
2031 (void) new TupleSetTest("Max",pos,IntSet(M-7,M),ts,true,epk);
2032 }
2033 {
2036 TupleSet ts(3);
2037 ts.add({M-0,m+1,M-2}).add({m+4,M-1,M-3})
2038 .add({m+2,M-3,m+0}).add({M-2,M-3,M-0})
2039 .finalize(epk);
2040 (void) new TupleSetTest("MinMax",pos,
2041 IntSet(IntArgs({m,m+1,m+4,M-3,M-2,M})),
2042 ts,true,epk);
2043 }
2044 {
2045 TupleSet ts(7);
2046 const int triangle_tuples =
2047 (epk == EPK_DENSE) ? 10000 : 1000;
2048 for (int i = 0; i < triangle_tuples; i++) {
2049 IntArgs tuple(7);
2050 for (int j = 0; j < 7; j++) {
2051 tuple[j] = rand(j+1);
2052 }
2053 ts.add(tuple);
2054 }
2055 ts.finalize(epk);
2056 (void) new RandomTupleSetTest("Triangle",pos,IntSet(0,6),ts,epk);
2057 }
2058 {
2059 for (int i = 0; i <= 64*6; i+=32)
2060 (void) new TupleSetTestSize(i, pos, epk, rand);
2061 }
2062 {
2063 const double prob_small =
2064 (epk == EPK_DENSE) ? 0.05 : 0.01;
2065 (void) new RandomTupleSetTest("Rand(10,-1,2)", pos,
2066 IntSet(-1,2),
2067 randomTupleSet(10, -1, 2, prob_small,
2068 epk, rand),
2069 epk);
2070 if (epk == EPK_DENSE)
2071 (void) new RandomTupleSetTest("Rand(5,-10,10)", pos,
2072 IntSet(-10,10),
2073 randomTupleSet(5, -10, 10, 0.05,
2074 epk, rand),
2075 epk);
2076 }
2077 {
2078 TupleSet t(5);
2079 CpltAssignment ass(4, IntSet(1, 4));
2080 while (ass.has_more()) {
2081 IntArgs tuple(5);
2082 tuple[4] = 1;
2083 for (int i = 4; i--; ) tuple[i] = ass[i];
2084 t.add(tuple);
2085 ass.next(rand);
2086 }
2087 t.add({2,2,4,3,4});
2088 t.finalize(epk);
2089 (void) new TupleSetTest("FewLast",pos,IntSet(1,4),t,false,epk);
2090 }
2091 {
2092 TupleSet t(4);
2093 CpltAssignment ass(4, IntSet(1, 6));
2094 while (ass.has_more()) {
2095 t.add({ass[0],0,ass[1],ass[2]});
2096 ass.next(rand);
2097 }
2098 t.add({2,-1,3,4});
2099 t.finalize(epk);
2100 (void) new TupleSetTest("FewMiddle",pos,IntSet(-1,6),t,false,epk);
2101 }
2102 if (epk == EPK_DENSE) {
2103 TupleSet t(10);
2104 CpltAssignment ass(9, IntSet(1, 4));
2105 while (ass.has_more()) {
2106 if (rand(100) <= 0.25*100) {
2107 IntArgs tuple(10);
2108 tuple[0] = 2;
2109 for (int i = 9; i--; )
2110 tuple[i+1] = ass[i];
2111 t.add(tuple);
2112 }
2113 ass.next(rand);
2114 }
2115 t.add({1,1,1,1,1,1,1,1,1,1});
2116 t.add({1,2,3,4,4,2,1,2,3,3});
2117 t.finalize(epk);
2118 (void) new RandomTupleSetTest("FewHuge",pos,IntSet(1,4),t,epk);
2119 }
2120 (void) new TupleSetBase(pos,epk);
2121 (void) new TupleSetLarge(0.05,pos,epk);
2122 (void) new TupleSetBool(0.3,pos,epk);
2123 }
2124 }
2125 }
2126 };
2127
2129
2133
2135
2140
2145
2148
2149 RegOpt ro0(CHAR_MAX-1);
2150 RegOpt ro1(CHAR_MAX);
2151 RegOpt ro2(static_cast<int>(UCHAR_MAX-1));
2152 RegOpt ro3(static_cast<int>(UCHAR_MAX));
2153 RegOpt ro4(SHRT_MAX-1);
2154 RegOpt ro5(SHRT_MAX);
2155 RegOpt ro6(static_cast<int>(USHRT_MAX-1));
2156 RegOpt ro7(static_cast<int>(USHRT_MAX));
2157
2180
2181 }
2182}}
2183
2184
2185// STATISTICS: test-int
Passing Boolean variables.
Definition int.hh:738
Boolean variable array.
Definition int.hh:839
Boolean integer variables.
Definition int.hh:533
Specification of a DFA transition.
Definition int.hh:2212
int i_state
input state
Definition int.hh:2214
int o_state
output state Default constructor
Definition int.hh:2216
Deterministic finite automaton (DFA).
Definition int.hh:2203
Depth-first search engine.
Definition search.hh:1080
Passing integer arguments.
Definition int.hh:652
Integer sets.
Definition int.hh:178
Passing integer variables.
Definition int.hh:680
Integer variable array.
Definition int.hh:791
Integer variables.
Definition int.hh:389
Exception: Tuple set already finalized
Exception: Tuple set not yet finalized
Exception: Value out of limits
Definition exception.hpp:44
static PropagatorGroup all
Group of all propagators.
Definition core.hpp:796
Regular expressions over integer values.
Reification specification.
Definition int.hh:910
virtual T * next(void)
Return next solution (nullptr, if none exists or search has been stopped).
Definition base.hpp:46
Computation spaces.
Definition core.hpp:1775
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
Class representing a set of tuples.
Definition int.hh:2382
bool failed(void) const
Has tuple-set finalization failed.
int tuples(void) const
Number of tuples.
bool finalized(void) const
Is tuple set successfully finalized.
ExtensionalPropKind representation(void) const
Return materialized tuple-set representation.
TupleSet & add(const IntArgs &t)
Add tuple t to tuple set.
int * Tuple
Type of a tuple.
Definition int.hh:2389
void finalize(void)
Finalize tuple set with dense support data.
const Range * fst(int i) const
Return first range for position i.
unsigned int words(void) const
Return number of required bit set words.
int arity(void) const
Arity of tuple set.
int size(void) const
Return size of array (number of elements).
Definition array.hpp:936
void update(Space &home, VarArray< Var > &a)
Update array to be a clone of array a.
Definition array.hpp:1023
void update(Space &home, VarImpVar< VarImp > &y)
Update this variable to be a clone of variable y.
Definition var.hpp:116
Gecode::Support::RandomGenerator _rand
Random number generator.
Definition test.hh:164
Base(std::string s)
Create and register test with name s.
Definition test.cpp:60
Base class for assignments
Definition int.hh:59
int size(void) const
Return number of variables.
Definition int.hpp:46
Generate all assignments.
Definition int.hh:79
virtual void next(Gecode::Support::RandomGenerator &rand)
Move to next assignment.
Definition int.cpp:48
virtual bool has_more(void) const
Test whether all assignments have been iterated.
Definition int.hpp:61
Help class to create and register tests.
Create(void)
Perform creation and registration.
Dense-compressed iterators should skip unsupported value gaps.
RandomTupleSetTest(const std::string &s, bool p, Gecode::IntSet d0, Gecode::TupleSet ts0, Gecode::ExtensionalPropKind epk0)
Create and register test.
virtual Assignment * assignment(void) const
Create and register initial assignment.
Test with regular expression for distinct constraint
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x)
Post constraint on x.
RegDistinct(void)
Create and register test.
virtual bool solution(const Assignment &x) const
Test whether x is solution
RegEmptyDFA(void)
Create and register test.
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x)
Post constraint on x.
virtual bool solution(const Assignment &x) const
Test whether x is solution
Test for empty regular expression
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x)
Post constraint on x.
RegEmptyREG(void)
Create and register test.
virtual bool solution(const Assignment &x) const
Test whether x is solution
Test for optimizations
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x)
Post constraint on x.
virtual bool solution(const Assignment &x) const
Test whether x is solution
RegOpt(int n0)
Create and register test.
int n
DFA size characteristic.
Test with simple regular expression from Roland Yap
virtual bool solution(const Assignment &x) const
Test whether x is solution
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x)
Post constraint on x.
RegRoland(int n)
Create and register test.
Test with simple regular expression and shared variables (uses unsharing)
virtual bool solution(const Assignment &x) const
Test whether x is solution
RegSharedA(void)
Create and register test.
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x)
Post constraint on x.
Test with simple regular expression and shared variables (uses unsharing)
RegSharedB(void)
Create and register test.
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x)
Post constraint on x.
virtual bool solution(const Assignment &x) const
Test whether x is solution
Test with simple regular expression and shared variables (uses unsharing)
virtual bool solution(const Assignment &x) const
Test whether x is solution
RegSharedC(void)
Create and register test.
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x)
Post constraint on x.
Test with simple regular expression and shared variables (uses unsharing)
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x)
Post constraint on x.
RegSharedD(void)
Create and register test.
virtual bool solution(const Assignment &x) const
Test whether x is solution
Test with simple regular expression
virtual bool solution(const Assignment &x) const
Test whether x is solution
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x)
Post constraint on x.
RegSimpleA(void)
Create and register test.
Test with simple regular expression
virtual bool solution(const Assignment &x) const
Test whether x is solution
RegSimpleB(void)
Create and register test.
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x)
Post constraint on x.
Test with simple regular expression
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x)
Post constraint on x.
RegSimpleC(void)
Create and register test.
virtual bool solution(const Assignment &x) const
Test whether x is solution
Disabled sparse propagators must defer failure until re-enabled.
Sparse smoke test for low-density higher-arity tuple sets.
Sparse incremental test for assigned-variable advisor updates.
Sparse incremental test for BoolView specialization.
Sparse incremental smoke test for repeated and mixed delta updates.
Sparse negative should fail if all combinations are forbidden.
Sparse negative should prune values whose completions are all forbidden.
Sparse smoke test for negative tuple-set posting.
Sparse smoke test for nullary tuple sets.
Sparse reified posting should support all reify modes for positive/negative.
Sparse smoke test for reified tuple-set posting.
Sparse smoke test for low-density ternary tuple sets.
Sparse smoke test for very low-density unary tuple sets.
Sparse delta processing must depend on supports, not numeric width.
AUTO finalization should work with default tuple-set posting overloads.
bool pos
Whether the table is positive or negative.
TupleSetBase(bool p, Gecode::ExtensionalPropKind epk0)
Create and register test.
virtual bool solution(const Assignment &x) const
Test whether x is solution
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x, Gecode::Reify r)
Post reified constraint on x for r.
Gecode::TupleSet t
Simple test tupleset.
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x)
Post constraint on x.
Gecode::ExtensionalPropKind epk
Support representation.
Gecode::TupleSet t
Tupleset used for testing.
Gecode::ExtensionalPropKind epk
Support representation.
TupleSetBool(double prob, bool p, Gecode::ExtensionalPropKind epk0)
Create and register test.
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x)
Post constraint on x.
virtual bool solution(const Assignment &x) const
Test whether x is solution
bool pos
Whether the table is positive or negative.
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x, Gecode::Reify r)
Post reified constraint on x for r.
DFA-derived tuple sets preserve the requested support representation.
Disabled compact propagators preserve pending work when cloned.
bool pos
Whether the table is positive or negative.
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x, Gecode::Reify r)
Post reified constraint on x for r.
TupleSetLarge(double prob, bool p, Gecode::ExtensionalPropKind epk0)
Create and register test.
Gecode::ExtensionalPropKind epk
Support representation.
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x)
Post constraint on x.
Gecode::TupleSet t
Tupleset used for testing.
virtual bool solution(const Assignment &x) const
Test whether x is solution
Sparse/compressed tuplesets should materialize only requested support.
Sparse offset arrays need a representable terminal entry.
Failed finalization is terminal and cannot expose partial support data.
Help class to create and register tests with a fixed table size.
TupleSetTestSize(int size, bool pos, Gecode::ExtensionalPropKind epk, Gecode::Support::RandomGenerator &rand)
Perform creation and registration.
virtual bool solution(const Assignment &x) const
Test whether x is solution
TupleSetTest(const std::string &s, bool p, Gecode::IntSet d0, Gecode::TupleSet ts0, bool td, Gecode::ExtensionalPropKind epk0)
Create and register test.
bool toDFA
Whether to validate dfa2tupleset.
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x, Gecode::Reify r)
Post reified constraint on x for r.
Gecode::TupleSet ts
The tuple set to use.
bool pos
Whether the table is positive or negative.
Gecode::ExtensionalPropKind epk
Support representation.
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x)
Post constraint on x.
Generate random selection of assignments.
Definition int.hh:96
bool testsearch
Whether to perform search test.
Definition int.hh:238
static std::string str(bool b)
Map bool to string.
Definition int.hpp:255
Gecode::IntPropLevel ipl
Propagation level.
Definition int.hh:234
int arity
Number of variables.
Definition int.hh:226
Gecode::IntSet dom
Domain of variables.
Definition int.hh:228
LinearCongruentialGenerator< 2147483647, 48271, 44488, 3399 > RandomGenerator
Default values for linear congruential generator.
Definition random.hpp:183
void branch(Home home, const FloatVarArgs &x, FloatVarBranch vars, FloatValBranch vals, FloatBranchFilter bf=nullptr, FloatVarValPrint vvp=nullptr)
Branch over x with variable selection vars and value selection vals.
Definition branch.cpp:39
void rel(Home home, FloatVar x0, FloatRelType frt, FloatVar x1)
Post propagator for .
Definition rel.cpp:68
ExtensionalPropKind
Support representation selection for extensional tuple sets.
Definition int.hh:2355
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
@ IRT_EQ
Equality ( ).
Definition int.hh:960
@ IRT_NQ
Disequality ( ).
Definition int.hh:961
@ IRT_GQ
Greater or equal ( ).
Definition int.hh:964
@ 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
@ IPL_DOM
Domain propagation Options: basic versus advanced propagation.
Definition int.hh:1013
SpaceStatus
Space status
Definition core.hpp:1714
@ SS_FAILED
Space is failed
Definition core.hpp:1715
bool support_offsets_size(unsigned long long n_vals, unsigned int &n_offsets)
const int min
Smallest allowed integer value.
Definition int.hh:122
const int max
Largest allowed integer value.
Definition int.hh:120
Gecode toplevel namespace
void count(Home home, const IntVarArgs &x, int n, IntRelType irt, int m, IntPropLevel ipl=IPL_DEF)
Post propagator for .
Definition count.cpp:40
void channel(Home home, FloatVar x0, IntVar x1)
Post propagator for channeling a float and an integer variable .
Definition channel.cpp:41
void min(Home home, FloatVar x0, FloatVar x1, FloatVar x2)
Post propagator for .
BoolValBranch BOOL_VAL_MIN(void)
Select smallest value.
Definition val.hpp:130
IntVarBranch INT_VAR_NONE(void)
Select first unassigned variable.
Definition var.hpp:96
BoolVarBranch BOOL_VAR_NONE(void)
Select first unassigned variable.
Definition var.hpp:364
bool same(VarArgArray< Var > x, VarArgArray< Var > y)
Definition array.hpp:1927
IntValBranch INT_VAL_MIN(void)
Select smallest value.
Definition val.hpp:55
void unshare(Home home, IntVarArgs &x, IntPropLevel ipl=IPL_DEF)
Replace multiple variable occurrences in x by fresh variables.
Definition unshare.cpp:136
void max(Home home, FloatVar x0, FloatVar x1, FloatVar x2)
Post propagator for .
Tests for extensional (relation) constraints
TupleSetSupportOffsetBoundary tuple_set_support_offset_boundary
SparseTupleSetWideDelta sparse_tuple_set_wide_delta
TupleSetSingleRepresentation tuple_set_single_representation
TupleSetDisabledClone tuple_set_disabled_clone
RegOpt ro0(CHAR_MAX-1)
SparseTupleSetTernary sparse_tuple_set_ternary
SparseTupleSetUnary sparse_tuple_set_unary
SparseTupleSetNegative sparse_tuple_set_negative
SparseTupleSetNullary sparse_tuple_set_nullary
TupleSetAutoDefaultDispatch tuple_set_auto_default_dispatch
std::string extensional_kind_name(Gecode::ExtensionalPropKind epk)
Gecode::DFA tupleset2dfa(Gecode::TupleSet ts)
% Transform a TupleSet into a DFA
RegOpt ro7(static_cast< int >(USHRT_MAX))
SparseTupleSetIncrementalBool sparse_tuple_set_incremental_bool
SparseTupleSetReified sparse_tuple_set_reified
SparseTupleSetIncrementalAssign sparse_tuple_set_incremental_assign
RegOpt ro2(static_cast< int >(UCHAR_MAX-1))
SparseTupleSetNegativePrune sparse_tuple_set_negative_prune
TupleSetDFARepresentation tuple_set_dfa_representation
SparseTupleSetHighArity sparse_tuple_set_high_arity
RegOpt ro6(static_cast< int >(USHRT_MAX-1))
SparseTupleSetReifiedModes sparse_tuple_set_reified_modes
SparseTupleSetDisabledFailure sparse_tuple_set_disabled_failure
SparseTupleSetIncrementalDelta sparse_tuple_set_incremental_delta
SparseTupleSetNegativeFail sparse_tuple_set_negative_fail
Gecode::TupleSet randomTupleSet(int n, int min, int max, double prob, Gecode::ExtensionalPropKind epk, Gecode::Support::RandomGenerator &rand)
RegOpt ro4(SHRT_MAX-1)
RegOpt ro1(CHAR_MAX)
TupleSetTerminalFinalizationFailure tuple_set_terminal_failure
RegOpt ro3(static_cast< int >(UCHAR_MAX))
RegOpt ro5(SHRT_MAX)
DenseCompressedTupleSetWideGap dense_compressed_tuple_set_wide_gap
Testing finite domain integers.
Definition int.cpp:40
General test support.
Definition afc.cpp:39
Region r
Definition region.cpp:65
#define GECODE_NEVER
Assert that this command is never executed.
Definition macros.hpp:56