this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Christian Schulte <schulte@gecode.org>
5 * Mikael Lagerkvist <lagerkvist@gecode.org>
6 *
7 * Copyright:
8 * Christian Schulte, 2005
9 * Mikael Lagerkvist, 2005
10 *
11 * This file is part of Gecode, the generic constraint
12 * development environment:
13 * http://www.gecode.org
14 *
15 * Permission is hereby granted, free of charge, to any person obtaining
16 * a copy of this software and associated documentation files (the
17 * "Software"), to deal in the Software without restriction, including
18 * without limitation the rights to use, copy, modify, merge, publish,
19 * distribute, sublicense, and/or sell copies of the Software, and to
20 * permit persons to whom the Software is furnished to do so, subject to
21 * the following conditions:
22 *
23 * The above copyright notice and this permission notice shall be
24 * included in all copies or substantial portions of the Software.
25 *
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 *
34 */
35
36#include "test/int.hh"
37
38#include <algorithm>
39
40namespace Test { namespace Int {
41
42
43 /*
44 * Complete assignments
45 *
46 */
47 void
48 CpltAssignment::operator++(void) {
49 int i = n-1;
50 while (true) {
51 ++dsv[i];
52 if (dsv[i]() || (i == 0))
53 return;
54 dsv[i--].init(d);
55 }
56 }
57
58 /*
59 * Random assignments
60 *
61 */
62 void
63 RandomAssignment::operator++(void) {
64 for (int i = n; i--; )
65 vals[i]=randval();
66 a--;
67 }
68
69 void
70 RandomMixAssignment::operator++(void) {
71 for (int i=n-_n1; i--; )
72 vals[i] = randval(d);
73 for (int i=_n1; i--; )
74 vals[n-_n1+i] = randval(_d1);
75 a--;
76 }
77
78}}
79
80std::ostream&
81operator<<(std::ostream& os, const Test::Int::Assignment& a) {
82 int n = a.size();
83 os << "{";
84 for (int i=0; i<n; i++)
85 os << a[i] << ((i!=n-1) ? "," : "}");
86 return os;
87}
88
89namespace Test { namespace Int {
90
91 TestSpace::TestSpace(int n, Gecode::IntSet& d0, Test* t)
92 : d(d0), x(*this,n,Gecode::Int::Limits::min,Gecode::Int::Limits::max),
93 test(t), reified(false) {
94 Gecode::IntVarArgs _x(*this,n,d);
95 if (x.size() == 1)
96 Gecode::dom(*this,x[0],_x[0]);
97 else
98 Gecode::dom(*this,x,_x);
99 Gecode::BoolVar b(*this,0,1);
100 r = Gecode::Reify(b,Gecode::RM_EQV);
101 if (opt.log)
102 olog << ind(2) << "Initial: x[]=" << x
103 << std::endl;
104 }
105
106 TestSpace::TestSpace(int n, Gecode::IntSet& d0, Test* t,
107 Gecode::ReifyMode rm)
108 : d(d0), x(*this,n,Gecode::Int::Limits::min,Gecode::Int::Limits::max),
109 test(t), reified(true) {
110 Gecode::IntVarArgs _x(*this,n,d);
111 if (x.size() == 1)
112 Gecode::dom(*this,x[0],_x[0]);
113 else
114 Gecode::dom(*this,x,_x);
115 Gecode::BoolVar b(*this,0,1);
116 r = Gecode::Reify(b,rm);
117 if (opt.log)
118 olog << ind(2) << "Initial: x[]=" << x
119 << " b=" << r.var() << std::endl;
120 }
121
122 TestSpace::TestSpace(TestSpace& s)
123 : Gecode::Space(s), d(s.d), test(s.test), reified(s.reified) {
124 x.update(*this, s.x);
125 Gecode::BoolVar b;
126 Gecode::BoolVar sr(s.r.var());
127 b.update(*this, sr);
128 r.var(b); r.mode(s.r.mode());
129 }
130
131 Gecode::Space*
132 TestSpace::copy(void) {
133 return new TestSpace(*this);
134 }
135
136 bool
137 TestSpace::assigned(void) const {
138 for (int i=x.size(); i--; )
139 if (!x[i].assigned())
140 return false;
141 return true;
142 }
143
144 void
145 TestSpace::post(void) {
146 if (reified){
147 test->post(*this,x,r);
148 if (opt.log)
149 olog << ind(3) << "Posting reified propagator" << std::endl;
150 } else {
151 test->post(*this,x);
152 if (opt.log)
153 olog << ind(3) << "Posting propagator" << std::endl;
154 }
155 }
156
157 bool
158 TestSpace::failed(void) {
159 if (opt.log) {
160 olog << ind(3) << "Fixpoint: " << x;
161 bool f=(status() == Gecode::SS_FAILED);
162 olog << std::endl << ind(3) << " --> " << x << std::endl;
163 return f;
164 } else {
165 return status() == Gecode::SS_FAILED;
166 }
167 }
168
169 int
170 TestSpace::rndvar(void) {
171 assert(!assigned());
172 // Select variable to be pruned
173 int i = static_cast<int>(Base::rand(static_cast<unsigned int>(x.size())));
174 while (x[i].assigned()) {
175 i = (i+1) % x.size();
176 }
177 return i;
178 }
179
180 void
181 TestSpace::rndrel(const Assignment& a, int i,
182 Gecode::IntRelType& irt, int& v) {
183 using namespace Gecode;
184 // Select mode for pruning
185 irt = IRT_EQ; // Means do nothing!
186 switch (Base::rand(3)) {
187 case 0:
188 if (a[i] < x[i].max()) {
189 v=a[i]+1+
190 static_cast<int>(Base::rand(static_cast
191 <unsigned int>(x[i].max()-a[i])));
192 assert((v > a[i]) && (v <= x[i].max()));
193 irt = IRT_LE;
194 }
195 break;
196 case 1:
197 if (a[i] > x[i].min()) {
198 v=x[i].min()+
199 static_cast<int>(Base::rand(static_cast
200 <unsigned int>(a[i]-x[i].min())));
201 assert((v < a[i]) && (v >= x[i].min()));
202 irt = IRT_GR;
203 }
204 break;
205 default:
206 {
207 Gecode::Int::ViewRanges<Gecode::Int::IntView> it(x[i]);
208 unsigned int skip =
209 Base::rand(static_cast<unsigned int>(x[i].size()-1));
210 while (true) {
211 if (it.width() > skip) {
212 v = it.min() + static_cast<int>(skip);
213 if (v == a[i]) {
214 if (it.width() == 1) {
215 ++it; v = it.min();
216 } else if (v < it.max()) {
217 ++v;
218 } else {
219 --v;
220 }
221 }
222 break;
223 }
224 skip -= it.width(); ++it;
225 }
226 irt = IRT_NQ;
227 break;
228 }
229 }
230 }
231
232 void
233 TestSpace::rel(int i, Gecode::IntRelType irt, int n) {
234 if (opt.log) {
235 olog << ind(4) << "x[" << i << "] ";
236 switch (irt) {
237 case Gecode::IRT_EQ: olog << "="; break;
238 case Gecode::IRT_NQ: olog << "!="; break;
239 case Gecode::IRT_LQ: olog << "<="; break;
240 case Gecode::IRT_LE: olog << "<"; break;
241 case Gecode::IRT_GQ: olog << ">="; break;
242 case Gecode::IRT_GR: olog << ">"; break;
243 }
244 olog << " " << n << std::endl;
245 }
246 Gecode::rel(*this, x[i], irt, n);
247 }
248
249 void
250 TestSpace::rel(bool sol) {
251 int n = sol ? 1 : 0;
252 assert(reified);
253 if (opt.log)
254 olog << ind(4) << "b = " << n << std::endl;
255 Gecode::rel(*this, r.var(), Gecode::IRT_EQ, n);
256 }
257
258 void
259 TestSpace::assign(const Assignment& a, bool skip) {
260 using namespace Gecode;
261 int i = skip ?
262 static_cast<int>(Base::rand(static_cast<unsigned int>(a.size()))) : -1;
263 for (int j=a.size(); j--; )
264 if (i != j) {
265 rel(j, IRT_EQ, a[j]);
266 if (Base::fixpoint() && failed())
267 return;
268 }
269 }
270
271 void
272 TestSpace::bound(void) {
273 using namespace Gecode;
274 int i = rndvar();
275 bool min = Base::rand(2);
276 rel(i, IRT_EQ, min ? x[i].min() : x[i].max());
277 }
278
279 void
280 TestSpace::prune(int i, bool bounds_only) {
281 using namespace Gecode;
282 // Prune values
283 if (bounds_only) {
284 if (Base::rand(2) && !x[i].assigned()) {
285 int v=x[i].min()+1+
286 static_cast<int>(Base::rand(static_cast
287 <unsigned int>(x[i].max()-x[i].min())));
288 assert((v > x[i].min()) && (v <= x[i].max()));
289 rel(i, Gecode::IRT_LE, v);
290 }
291 if (Base::rand(2) && !x[i].assigned()) {
292 int v=x[i].min()+
293 static_cast<int>(Base::rand(static_cast
294 <unsigned int>(x[i].max()-x[i].min())));
295 assert((v < x[i].max()) && (v >= x[i].min()));
296 rel(i, Gecode::IRT_GR, v);
297 }
298 } else {
299 for (int vals =
300 static_cast<int>(Base::rand(static_cast<unsigned int>(x[i].size()-1))+1); vals--; ) {
301 int v;
302 Gecode::Int::ViewRanges<Gecode::Int::IntView> it(x[i]);
303 unsigned int skip = Base::rand(x[i].size()-1);
304 while (true) {
305 if (it.width() > skip) {
306 v = it.min() + static_cast<int>(skip); break;
307 }
308 skip -= it.width(); ++it;
309 }
310 rel(i, IRT_NQ, v);
311 }
312 }
313 }
314
315 void
316 TestSpace::prune(void) {
317 prune(rndvar(), false);
318 }
319
320 bool
321 TestSpace::prune(const Assignment& a, bool testfix) {
322 using namespace Gecode;
323 // Select variable to be pruned
324 int i = rndvar();
325 // Select mode for pruning
326 IntRelType irt;
327 int v;
328 rndrel(a,i,irt,v);
329 if (irt != IRT_EQ)
330 rel(i, irt, v);
331 if (Base::fixpoint()) {
332 if (failed() || !testfix)
333 return true;
334 TestSpace* c = static_cast<TestSpace*>(clone());
335 if (opt.log)
336 olog << ind(3) << "Testing fixpoint on copy" << std::endl;
337 c->post();
338 if (c->failed()) {
339 if (opt.log)
340 olog << ind(4) << "Copy failed after posting" << std::endl;
341 delete c; return false;
342 }
343 for (int j=x.size(); j--; )
344 if (x[j].size() != c->x[j].size()) {
345 if (opt.log)
346 olog << ind(4) << "Different domain size" << std::endl;
347 delete c; return false;
348 }
349 if (reified && (r.var().size() != c->r.var().size())) {
350 if (opt.log)
351 olog << ind(4) << "Different control variable" << std::endl;
352 delete c; return false;
353 }
354 if (opt.log)
355 olog << ind(3) << "Finished testing fixpoint on copy" << std::endl;
356 delete c;
357 }
358 return true;
359 }
360
361 void
362 TestSpace::enable(void) {
363 Gecode::PropagatorGroup::all.enable(*this);
364 }
365
366 void
367 TestSpace::disable(void) {
368 Gecode::PropagatorGroup::all.disable(*this);
369 (void) status();
370 }
371
372 bool
373 TestSpace::disabled(const Assignment& a, TestSpace& c,
374 bool testfix) {
375 using namespace Gecode;
376 // Disable propagators
377 c.disable();
378 // Select variable to be pruned
379 int i = rndvar();
380 // Select mode for pruning
381 IntRelType irt;
382 int v;
383 rndrel(a,i,irt,v);
384 if (irt != IRT_EQ) {
385 rel(i, irt, v);
386 c.rel(i, irt, v);
387 }
388 // Enable propagators
389 c.enable();
390 if (!testfix)
391 return true;
392 if (failed()) {
393 if (!c.failed()) {
394 if (opt.log)
395 olog << ind(3) << "No failure on disabled copy" << std::endl;
396 return false;
397 }
398 return true;
399 }
400 if (c.failed()) {
401 if (opt.log)
402 olog << ind(3) << "Failure on disabled copy" << std::endl;
403 return false;
404 }
405 for (int j=x.size(); j--; ) {
406 if (x[j].size() != c.x[j].size()) {
407 if (opt.log)
408 olog << ind(4) << "Different domain size" << std::endl;
409 return false;
410 }
411 if (reified && (r.var().size() != c.r.var().size())) {
412 if (opt.log)
413 olog << ind(4) << "Different control variable" << std::endl;
414 return false;
415 }
416 }
417 return true;
418 }
419
420 unsigned int
421 TestSpace::propagators(void) {
422 return Gecode::PropagatorGroup::all.size(*this);
423 }
424
425 const Gecode::IntPropLevel IntPropLevels::ipls[] =
426 {Gecode::IPL_DOM,Gecode::IPL_BND,Gecode::IPL_VAL};
427
428 const Gecode::IntPropLevel IntPropBasicAdvanced::ipls[] =
429 {Gecode::IPL_BASIC_ADVANCED,Gecode::IPL_ADVANCED,Gecode::IPL_BASIC};
430
431 const Gecode::IntRelType IntRelTypes::irts[] =
432 {Gecode::IRT_EQ,Gecode::IRT_NQ,Gecode::IRT_LQ,
433 Gecode::IRT_LE,Gecode::IRT_GQ,Gecode::IRT_GR};
434
435 const Gecode::BoolOpType BoolOpTypes::bots[] =
436 {Gecode::BOT_AND,Gecode::BOT_OR,Gecode::BOT_IMP,
437 Gecode::BOT_EQV,Gecode::BOT_XOR};
438
439 Assignment*
440 Test::assignment(void) const {
441 return new CpltAssignment(arity,dom);
442 }
443
444
445 /// Check the test result and handle failed test
446#define CHECK_TEST(T,M) \
447if (opt.log) \
448 olog << ind(3) << "Check: " << (M) << std::endl; \
449if (!(T)) { \
450 problem = (M); delete s; goto failed; \
451}
452
453 /// Start new test
454#define START_TEST(T) \
455 if (opt.log) { \
456 olog.str(""); \
457 olog << ind(2) << "Testing: " << (T) << std::endl; \
458 } \
459 test = (T);
460
461 bool
462 Test::ignore(const Assignment&) const {
463 return false;
464 }
465
466 void
467 Test::post(Gecode::Space&, Gecode::IntVarArray&,
468 Gecode::Reify) {}
469
470 bool
471 Test::run(void) {
472 using namespace Gecode;
473 const char* test = "NONE";
474 const char* problem = "NONE";
475
476 // Set up assignments
477 Assignment* ap = assignment();
478 Assignment& a = *ap;
479
480 // Set up space for all solution search
481 TestSpace* search_s = new TestSpace(arity,dom,this);
482 post(*search_s,search_s->x);
483 branch(*search_s,search_s->x,INT_VAR_NONE(),INT_VAL_MIN());
484 Search::Options search_o;
485 search_o.threads = 1;
486 DFS<TestSpace> e_s(search_s,search_o);
487 delete search_s;
488
489 while (a()) {
490 bool sol = solution(a);
491 if (opt.log) {
492 olog << ind(1) << "Assignment: " << a
493 << (sol ? " (solution)" : " (no solution)")
494 << std::endl;
495 }
496
497 START_TEST("Assignment (after posting)");
498 {
499 TestSpace* s = new TestSpace(arity,dom,this);
500 TestSpace* sc = nullptr;
501 s->post();
502 switch (Base::rand(2)) {
503 case 0:
504 if (opt.log)
505 olog << ind(3) << "No copy" << std::endl;
506 sc = s;
507 s = nullptr;
508 break;
509 case 1:
510 if (opt.log)
511 olog << ind(3) << "Copy" << std::endl;
512 if (s->status() != SS_FAILED) {
513 sc = static_cast<TestSpace*>(s->clone());
514 } else {
515 sc = s; s = nullptr;
516 }
517 break;
518 default: assert(false);
519 }
520 sc->assign(a);
521 if (sol) {
522 CHECK_TEST(!sc->failed(), "Failed on solution");
523 CHECK_TEST(sc->propagators()==0, "No subsumption");
524 } else {
525 CHECK_TEST(sc->failed(), "Solved on non-solution");
526 }
527 delete s; delete sc;
528 }
529 START_TEST("Partial assignment (after posting)");
530 {
531 TestSpace* s = new TestSpace(arity,dom,this);
532 s->post();
533 s->assign(a,true);
534 (void) s->failed();
535 s->assign(a);
536 if (sol) {
537 CHECK_TEST(!s->failed(), "Failed on solution");
538 CHECK_TEST(s->propagators()==0, "No subsumption");
539 } else {
540 CHECK_TEST(s->failed(), "Solved on non-solution");
541 }
542 delete s;
543 }
544 START_TEST("Assignment (after posting, disable)");
545 {
546 TestSpace* s = new TestSpace(arity,dom,this);
547 s->post();
548 s->disable();
549 s->assign(a);
550 s->enable();
551 if (sol) {
552 CHECK_TEST(!s->failed(), "Failed on solution");
553 CHECK_TEST(s->propagators()==0, "No subsumption");
554 } else {
555 CHECK_TEST(s->failed(), "Solved on non-solution");
556 }
557 delete s;
558 }
559 START_TEST("Partial assignment (after posting, disable)");
560 {
561 TestSpace* s = new TestSpace(arity,dom,this);
562 s->post();
563 s->assign(a,true);
564 s->disable();
565 (void) s->failed();
566 s->assign(a);
567 s->enable();
568 if (sol) {
569 CHECK_TEST(!s->failed(), "Failed on solution");
570 CHECK_TEST(s->propagators()==0, "No subsumption");
571 } else {
572 CHECK_TEST(s->failed(), "Solved on non-solution");
573 }
574 delete s;
575 }
576 START_TEST("Assignment (before posting)");
577 {
578 TestSpace* s = new TestSpace(arity,dom,this);
579 s->assign(a);
580 s->post();
581 if (sol) {
582 CHECK_TEST(!s->failed(), "Failed on solution");
583 CHECK_TEST(s->propagators()==0, "No subsumption");
584 } else {
585 CHECK_TEST(s->failed(), "Solved on non-solution");
586 }
587 delete s;
588 }
589 START_TEST("Partial assignment (before posting)");
590 {
591 TestSpace* s = new TestSpace(arity,dom,this);
592 s->assign(a,true);
593 s->post();
594 (void) s->failed();
595 s->assign(a);
596 if (sol) {
597 CHECK_TEST(!s->failed(), "Failed on solution");
598 CHECK_TEST(s->propagators()==0, "No subsumption");
599 } else {
600 CHECK_TEST(s->failed(), "Solved on non-solution");
601 }
602 delete s;
603 }
604 START_TEST("Prune");
605 {
606 TestSpace* s = new TestSpace(arity,dom,this);
607 s->post();
608 while (!s->failed() && !s->assigned())
609 if (!s->prune(a,testfix)) {
610 problem = "No fixpoint";
611 delete s;
612 goto failed;
613 }
614 s->assign(a);
615 if (sol) {
616 CHECK_TEST(!s->failed(), "Failed on solution");
617 CHECK_TEST(s->propagators()==0, "No subsumption");
618 } else {
619 CHECK_TEST(s->failed(), "Solved on non-solution");
620 }
621 delete s;
622 }
623 START_TEST("Prune (disable)");
624 {
625 TestSpace* s = new TestSpace(arity,dom,this);
626 TestSpace* c = static_cast<TestSpace*>(s->clone());
627 s->post(); c->post();
628 while (!s->failed() && !s->assigned())
629 if (!s->disabled(a,*c,testfix)) {
630 problem = "Different result after re-enable";
631 delete s; delete c;
632 goto failed;
633 }
634 if (testfix && (s->failed() != c->failed())) {
635 problem = "Different failure after re-enable";
636 delete s; delete c;
637 goto failed;
638 }
639 delete s; delete c;
640 }
641 if (!ignore(a)) {
642 if (eqv()) {
643 {
644 START_TEST("Assignment reified (rewrite after post, <=>)");
645 TestSpace* s = new TestSpace(arity,dom,this,RM_EQV);
646 s->post();
647 s->rel(sol);
648 s->assign(a);
649 CHECK_TEST(!s->failed(), "Failed");
650 CHECK_TEST(s->propagators()==0, "No subsumption");
651 delete s;
652 }
653 {
654 START_TEST("Assignment reified (rewrite failure, <=>)");
655 TestSpace* s = new TestSpace(arity,dom,this,RM_EQV);
656 s->post();
657 s->rel(!sol);
658 s->assign(a);
659 CHECK_TEST(s->failed(), "Not failed");
660 delete s;
661 }
662 {
663 START_TEST("Assignment reified (immediate rewrite, <=>)");
664 TestSpace* s = new TestSpace(arity,dom,this,RM_EQV);
665 s->rel(sol);
666 s->post();
667 s->assign(a);
668 CHECK_TEST(!s->failed(), "Failed");
669 CHECK_TEST(s->propagators()==0, "No subsumption");
670 delete s;
671 }
672 {
673 START_TEST("Assignment reified (immediate failure, <=>)");
674 TestSpace* s = new TestSpace(arity,dom,this,RM_EQV);
675 s->rel(!sol);
676 s->post();
677 s->assign(a);
678 CHECK_TEST(s->failed(), "Not failed");
679 delete s;
680 }
681 {
682 START_TEST("Assignment reified (before posting, <=>)");
683 TestSpace* s = new TestSpace(arity,dom,this,RM_EQV);
684 s->assign(a);
685 s->post();
686 CHECK_TEST(!s->failed(), "Failed");
687 CHECK_TEST(s->propagators()==0, "No subsumption");
688 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
689 if (sol) {
690 CHECK_TEST(s->r.var().val()==1, "Zero on solution");
691 } else {
692 CHECK_TEST(s->r.var().val()==0, "One on non-solution");
693 }
694 delete s;
695 }
696 {
697 START_TEST("Assignment reified (after posting, <=>)");
698 TestSpace* s = new TestSpace(arity,dom,this,RM_EQV);
699 s->post();
700 s->assign(a);
701 CHECK_TEST(!s->failed(), "Failed");
702 CHECK_TEST(s->propagators()==0, "No subsumption");
703 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
704 if (sol) {
705 CHECK_TEST(s->r.var().val()==1, "Zero on solution");
706 } else {
707 CHECK_TEST(s->r.var().val()==0, "One on non-solution");
708 }
709 delete s;
710 }
711 {
712 START_TEST("Assignment reified (after posting, <=>, disable)");
713 TestSpace* s = new TestSpace(arity,dom,this,RM_EQV);
714 s->post();
715 s->disable();
716 s->assign(a);
717 s->enable();
718 CHECK_TEST(!s->failed(), "Failed");
719 CHECK_TEST(s->propagators()==0, "No subsumption");
720 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
721 if (sol) {
722 CHECK_TEST(s->r.var().val()==1, "Zero on solution");
723 } else {
724 CHECK_TEST(s->r.var().val()==0, "One on non-solution");
725 }
726 delete s;
727 }
728 {
729 START_TEST("Prune reified, <=>");
730 TestSpace* s = new TestSpace(arity,dom,this,RM_EQV);
731 s->post();
732 while (!s->failed() &&
733 (!s->assigned() || !s->r.var().assigned()))
734 if (!s->prune(a,testfix)) {
735 problem = "No fixpoint";
736 delete s;
737 goto failed;
738 }
739 CHECK_TEST(!s->failed(), "Failed");
740 CHECK_TEST(s->propagators()==0, "No subsumption");
741 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
742 if (sol) {
743 CHECK_TEST(s->r.var().val()==1, "Zero on solution");
744 } else {
745 CHECK_TEST(s->r.var().val()==0, "One on non-solution");
746 }
747 delete s;
748 }
749 {
750 START_TEST("Prune reified, <=>, disable");
751 TestSpace* s = new TestSpace(arity,dom,this,RM_EQV);
752 TestSpace* c = static_cast<TestSpace*>(s->clone());
753 s->post(); c->post();
754 while (!s->failed() &&
755 (!s->assigned() || !s->r.var().assigned()))
756 if (!s->disabled(a,*c,testfix)) {
757 problem = "No fixpoint";
758 delete s;
759 delete c;
760 goto failed;
761 }
762 CHECK_TEST(!c->failed(), "Failed");
763 CHECK_TEST(c->propagators()==0, "No subsumption");
764 CHECK_TEST(c->r.var().assigned(), "Control variable unassigned");
765 if (sol) {
766 CHECK_TEST(c->r.var().val()==1, "Zero on solution");
767 } else {
768 CHECK_TEST(c->r.var().val()==0, "One on non-solution");
769 }
770 delete s;
771 delete c;
772 }
773 }
774
775 if (imp()) {
776 {
777 START_TEST("Assignment reified (rewrite after post, =>)");
778 TestSpace* s = new TestSpace(arity,dom,this,RM_IMP);
779 s->post();
780 s->rel(sol);
781 s->assign(a);
782 CHECK_TEST(!s->failed(), "Failed");
783 CHECK_TEST(s->propagators()==0, "No subsumption");
784 delete s;
785 }
786 {
787 START_TEST("Assignment reified (rewrite failure, =>)");
788 TestSpace* s = new TestSpace(arity,dom,this,RM_IMP);
789 s->post();
790 s->rel(!sol);
791 s->assign(a);
792 if (sol) {
793 CHECK_TEST(!s->failed(), "Failed");
794 CHECK_TEST(s->propagators()==0, "No subsumption");
795 } else {
796 CHECK_TEST(s->failed(), "Not failed");
797 }
798 delete s;
799 }
800 {
801 START_TEST("Assignment reified (immediate rewrite, =>)");
802 TestSpace* s = new TestSpace(arity,dom,this,RM_IMP);
803 s->rel(sol);
804 s->post();
805 s->assign(a);
806 CHECK_TEST(!s->failed(), "Failed");
807 CHECK_TEST(s->propagators()==0, "No subsumption");
808 delete s;
809 }
810 {
811 START_TEST("Assignment reified (immediate failure, =>)");
812 TestSpace* s = new TestSpace(arity,dom,this,RM_IMP);
813 s->rel(!sol);
814 s->post();
815 s->assign(a);
816 if (sol) {
817 CHECK_TEST(!s->failed(), "Failed");
818 CHECK_TEST(s->propagators()==0, "No subsumption");
819 } else {
820 CHECK_TEST(s->failed(), "Not failed");
821 }
822 delete s;
823 }
824 {
825 START_TEST("Assignment reified (before posting, =>)");
826 TestSpace* s = new TestSpace(arity,dom,this,RM_IMP);
827 s->assign(a);
828 s->post();
829 CHECK_TEST(!s->failed(), "Failed");
830 CHECK_TEST(s->propagators()==0, "No subsumption");
831 if (sol) {
832 CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
833 } else {
834 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
835 CHECK_TEST(s->r.var().val()==0, "One on non-solution");
836 }
837 delete s;
838 }
839 {
840 START_TEST("Assignment reified (after posting, =>)");
841 TestSpace* s = new TestSpace(arity,dom,this,RM_IMP);
842 s->post();
843 s->assign(a);
844 CHECK_TEST(!s->failed(), "Failed");
845 CHECK_TEST(s->propagators()==0, "No subsumption");
846 if (sol) {
847 CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
848 } else {
849 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
850 CHECK_TEST(s->r.var().val()==0, "One on non-solution");
851 }
852 delete s;
853 }
854 {
855 START_TEST("Assignment reified (after posting, =>, disable)");
856 TestSpace* s = new TestSpace(arity,dom,this,RM_IMP);
857 s->post();
858 s->disable();
859 s->assign(a);
860 s->enable();
861 CHECK_TEST(!s->failed(), "Failed");
862 CHECK_TEST(s->propagators()==0, "No subsumption");
863 if (sol) {
864 CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
865 } else {
866 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
867 CHECK_TEST(s->r.var().val()==0, "One on non-solution");
868 }
869 delete s;
870 }
871 {
872 START_TEST("Prune reified, =>");
873 TestSpace* s = new TestSpace(arity,dom,this,RM_IMP);
874 s->post();
875 while (!s->failed() &&
876 (!s->assigned() || (!sol && !s->r.var().assigned())))
877 if (!s->prune(a,testfix)) {
878 problem = "No fixpoint";
879 delete s;
880 goto failed;
881 }
882 CHECK_TEST(!s->failed(), "Failed");
883 CHECK_TEST(s->propagators()==0, "No subsumption");
884 if (sol) {
885 CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
886 } else {
887 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
888 CHECK_TEST(s->r.var().val()==0, "One on non-solution");
889 }
890 delete s;
891 }
892 {
893 START_TEST("Prune reified, =>, disable");
894 TestSpace* s = new TestSpace(arity,dom,this,RM_IMP);
895 TestSpace* c = static_cast<TestSpace*>(s->clone());
896 s->post(); c->post();
897 while (!s->failed() &&
898 (!s->assigned() || (!sol && !s->r.var().assigned())))
899 if (!s->disabled(a,*c,testfix)) {
900 problem = "No fixpoint";
901 delete s;
902 delete c;
903 goto failed;
904 }
905 CHECK_TEST(!c->failed(), "Failed");
906 CHECK_TEST(c->propagators()==0, "No subsumption");
907 if (sol) {
908 CHECK_TEST(!c->r.var().assigned(), "Control variable assigned");
909 } else {
910 CHECK_TEST(c->r.var().assigned(), "Control variable unassigned");
911 CHECK_TEST(c->r.var().val()==0, "One on non-solution");
912 }
913 delete s;
914 delete c;
915 }
916 }
917
918 if (pmi()) {
919 {
920 START_TEST("Assignment reified (rewrite after post, <=)");
921 TestSpace* s = new TestSpace(arity,dom,this,RM_PMI);
922 s->post();
923 s->rel(sol);
924 s->assign(a);
925 CHECK_TEST(!s->failed(), "Failed");
926 CHECK_TEST(s->propagators()==0, "No subsumption");
927 delete s;
928 }
929 {
930 START_TEST("Assignment reified (rewrite failure, <=)");
931 TestSpace* s = new TestSpace(arity,dom,this,RM_PMI);
932 s->post();
933 s->rel(!sol);
934 s->assign(a);
935 if (sol) {
936 CHECK_TEST(s->failed(), "Not failed");
937 } else {
938 CHECK_TEST(!s->failed(), "Failed");
939 CHECK_TEST(s->propagators()==0, "No subsumption");
940 }
941 delete s;
942 }
943 {
944 START_TEST("Assignment reified (immediate rewrite, <=)");
945 TestSpace* s = new TestSpace(arity,dom,this,RM_PMI);
946 s->rel(sol);
947 s->post();
948 s->assign(a);
949 CHECK_TEST(!s->failed(), "Failed");
950 CHECK_TEST(s->propagators()==0, "No subsumption");
951 delete s;
952 }
953 {
954 START_TEST("Assignment reified (immediate failure, <=)");
955 TestSpace* s = new TestSpace(arity,dom,this,RM_PMI);
956 s->rel(!sol);
957 s->post();
958 s->assign(a);
959 if (sol) {
960 CHECK_TEST(s->failed(), "Not failed");
961 } else {
962 CHECK_TEST(!s->failed(), "Failed");
963 CHECK_TEST(s->propagators()==0, "No subsumption");
964 }
965 delete s;
966 }
967 {
968 START_TEST("Assignment reified (before posting, <=)");
969 TestSpace* s = new TestSpace(arity,dom,this,RM_PMI);
970 s->assign(a);
971 s->post();
972 CHECK_TEST(!s->failed(), "Failed");
973 CHECK_TEST(s->propagators()==0, "No subsumption");
974 if (sol) {
975 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
976 CHECK_TEST(s->r.var().val()==1, "Zero on solution");
977 } else {
978 CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
979 }
980 delete s;
981 }
982 {
983 START_TEST("Assignment reified (after posting, <=)");
984 TestSpace* s = new TestSpace(arity,dom,this,RM_PMI);
985 s->post();
986 s->assign(a);
987 CHECK_TEST(!s->failed(), "Failed");
988 CHECK_TEST(s->propagators()==0, "No subsumption");
989 if (sol) {
990 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
991 CHECK_TEST(s->r.var().val()==1, "Zero on solution");
992 } else {
993 CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
994 }
995 delete s;
996 }
997 {
998 START_TEST("Assignment reified (after posting, <=, disable)");
999 TestSpace* s = new TestSpace(arity,dom,this,RM_PMI);
1000 s->post();
1001 s->disable();
1002 s->assign(a);
1003 s->enable();
1004 CHECK_TEST(!s->failed(), "Failed");
1005 CHECK_TEST(s->propagators()==0, "No subsumption");
1006 if (sol) {
1007 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
1008 CHECK_TEST(s->r.var().val()==1, "Zero on solution");
1009 } else {
1010 CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
1011 }
1012 delete s;
1013 }
1014 {
1015 START_TEST("Prune reified, <=");
1016 TestSpace* s = new TestSpace(arity,dom,this,RM_PMI);
1017 s->post();
1018 while (!s->failed() &&
1019 (!s->assigned() || (sol && !s->r.var().assigned())))
1020 if (!s->prune(a,testfix)) {
1021 problem = "No fixpoint";
1022 delete s;
1023 goto failed;
1024 }
1025 CHECK_TEST(!s->failed(), "Failed");
1026 CHECK_TEST(s->propagators()==0, "No subsumption");
1027 if (sol) {
1028 CHECK_TEST(s->r.var().assigned(), "Control variable unassigned");
1029 CHECK_TEST(s->r.var().val()==1, "Zero on solution");
1030 } else {
1031 CHECK_TEST(!s->r.var().assigned(), "Control variable assigned");
1032 }
1033 delete s;
1034 }
1035 {
1036 START_TEST("Prune reified, <=, disable");
1037 TestSpace* s = new TestSpace(arity,dom,this,RM_PMI);
1038 TestSpace* c = static_cast<TestSpace*>(s->clone());
1039 s->post(); c->post();
1040 while (!s->failed() &&
1041 (!s->assigned() || (sol && !s->r.var().assigned())))
1042 if (!s->disabled(a,*c,testfix)) {
1043 problem = "No fixpoint";
1044 delete s;
1045 delete c;
1046 goto failed;
1047 }
1048 CHECK_TEST(!c->failed(), "Failed");
1049 CHECK_TEST(c->propagators()==0, "No subsumption");
1050 if (sol) {
1051 CHECK_TEST(c->r.var().assigned(), "Control variable unassigned");
1052 CHECK_TEST(c->r.var().val()==1, "Zero on solution");
1053 } else {
1054 CHECK_TEST(!c->r.var().assigned(), "Control variable assigned");
1055 }
1056 delete s;
1057 delete c;
1058 }
1059 }
1060 }
1061
1062 if (testsearch) {
1063 if (sol) {
1064 START_TEST("Search");
1065 TestSpace* s = e_s.next();
1066 CHECK_TEST(s != nullptr, "Solutions exhausted");
1067 CHECK_TEST(s->propagators()==0, "No subsumption");
1068 for (int i=a.size(); i--; ) {
1069 CHECK_TEST(s->x[i].assigned(), "Unassigned variable");
1070 CHECK_TEST(a[i] == s->x[i].val(), "Wrong value in solution");
1071 }
1072 delete s;
1073 }
1074 }
1075
1076 ++a;
1077 }
1078
1079 if (testsearch) {
1080 test = "Search";
1081 if (e_s.next() != nullptr) {
1082 problem = "Excess solutions";
1083 goto failed;
1084 }
1085 }
1086
1087 switch (contest) {
1088 case CTL_NONE: break;
1089 case CTL_DOMAIN: {
1090 START_TEST("Full domain consistency");
1091 TestSpace* s = new TestSpace(arity,dom,this);
1092 s->post();
1093 if (!s->failed()) {
1094 while (!s->failed() && !s->assigned())
1095 s->prune();
1096 CHECK_TEST(!s->failed(), "Failed");
1097 CHECK_TEST(s->propagators()==0, "No subsumption");
1098 }
1099 delete s;
1100 // Fall-through -- domain implies bounds(d) and bounds(z)
1101 }
1102 case CTL_BOUNDS_D: {
1103 START_TEST("Bounds(D)-consistency");
1104 TestSpace* s = new TestSpace(arity,dom,this);
1105 s->post();
1106 for (int i = s->x.size(); i--; )
1107 s->prune(i, false);
1108 if (!s->failed()) {
1109 while (!s->failed() && !s->assigned())
1110 s->bound();
1111 CHECK_TEST(!s->failed(), "Failed");
1112 CHECK_TEST(s->propagators()==0, "No subsumption");
1113 }
1114 delete s;
1115 // Fall-through -- bounds(d) implies bounds(z)
1116 }
1117 case CTL_BOUNDS_Z: {
1118 START_TEST("Bounds(Z)-consistency");
1119 TestSpace* s = new TestSpace(arity,dom,this);
1120 s->post();
1121 for (int i = s->x.size(); i--; )
1122 s->prune(i, true);
1123 if (!s->failed()) {
1124 while (!s->failed() && !s->assigned())
1125 s->bound();
1126 CHECK_TEST(!s->failed(), "Failed");
1127 CHECK_TEST(s->propagators()==0, "No subsumption");
1128 }
1129 delete s;
1130 break;
1131 }
1132 }
1133
1134 delete ap;
1135 return true;
1136
1137 failed:
1138 if (opt.log)
1139 olog << "FAILURE" << std::endl
1140 << ind(1) << "Test: " << test << std::endl
1141 << ind(1) << "Problem: " << problem << std::endl;
1142 if (a() && opt.log)
1143 olog << ind(1) << "Assignment: " << a << std::endl;
1144 delete ap;
1145
1146 return false;
1147 }
1148
1149}}
1150
1151#undef START_TEST
1152#undef CHECK_TEST
1153
1154// STATISTICS: test-int