this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Christopher Mears <chris.mears@monash.edu>
5 *
6 * Copyright:
7 * Christopher Mears, 2012
8 *
9 * This file is part of Gecode, the generic constraint
10 * development environment:
11 * http://www.gecode.org
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining
14 * a copy of this software and associated documentation files (the
15 * "Software"), to deal in the Software without restriction, including
16 * without limitation the rights to use, copy, modify, merge, publish,
17 * distribute, sublicense, and/or sell copies of the Software, and to
18 * permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be
22 * included in all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 *
32 */
33
34#include <gecode/kernel.hh>
35#include <gecode/int.hh>
36#include <gecode/int/branch.hh>
37
38#ifdef GECODE_HAS_SET_VARS
39#include <gecode/set.hh>
40#include <gecode/set/branch.hh>
41#include <stdarg.h>
42#endif
43
44#include <gecode/minimodel.hh>
45
46#include "test/test.hh"
47
48#include <vector>
49
50/**
51 * \namespace Test::LDSB
52 * \brief Testing for LDSB
53 */
54namespace Test { namespace LDSB {
55
56 using namespace Gecode;
57
58 /// Returns true iff a and b are equal (they have the same size and
59 /// the same elements in the same positions).
60 bool
61 equal(const IntArgs& a, const IntArgs& b) {
62 if (a.size() != b.size()) return false;
63 for (int i = 0 ; i < a.size() ; ++i)
64 if (a[i] != b[i])
65 return false;
66 return true;
67 }
68
69#ifdef GECODE_HAS_SET_VARS
70 /// Returns true iff a and b are equal (they have the same size and
71 /// the same elements in the same positions).
72 bool
73 equal(const IntSetArgs& a, const IntSetArgs& b) {
74 if (a.size() != b.size()) return false;
75 for (int i = 0 ; i < a.size() ; ++i) {
76 // Compare the two sets a[i] and b[i].
77 // Perhaps TODO: use Iter::Ranges::equal instead.
78 if (a[i].size() != b[i].size()) return false;
79 IntSetValues x(a[i]);
80 IntSetValues y(b[i]);
81 while (x() && y()) {
82 if (x.val() != y.val()) return false;
83 ++x;
84 ++y;
85 }
86 }
87 return true;
88 }
89#endif
90
91 /**
92 * \brief Checks found solutions against expected solutions
93 *
94 * Iterates through the solutions returned by the search engine and
95 * checks each one against the array of expected solutions. The
96 * order of solutions must be the same. Returns true if the
97 * expected solutions match the found solutions exactly, otherwise
98 * prints an explanation to standard error and returns false.
99 */
100 template <class T, class VarArgsType>
101 bool
102 check(DFS<T>& e, std::vector<VarArgsType> expected) {
103 int nexpected = expected.size();
104 for (int i = 0 ; i < nexpected ; ++i) {
105 T* s = e.next();
106 if (s == nullptr) {
107 if (opt.log) {
108 olog << "Expected a solution but there are no more solutions." << std::endl;
109 olog << "(Expected " << nexpected << " but only found " << i << ")" << std::endl;
110 olog << "Expected: " << expected[i] << std::endl;
111 }
112 return false;
113 }
114 if (!equal(s->solution(), expected[i])) {
115 if (opt.log) {
116 olog << "Solution does not match expected." << std::endl;
117 olog << "Solution: " << s->solution() << std::endl;
118 olog << "Expected: " << expected[i] << std::endl;
119 }
120 return false;
121 }
122 delete s;
123 }
124 T* s = e.next();
125 if (s != nullptr) {
126 if (opt.log) {
127 olog << "More solutions than expected:" << std::endl;
128 olog << "(Expected only " << nexpected << ")" << std::endl;
129 olog << s->solution() << std::endl;
130 }
131 return false;
132 }
133
134 // Nothing went wrong.
135 return true;
136 }
137
138
139 /// %Test space
140 class OneArray : public Space {
141 public:
142 /// Variables
143 IntVarArray xs;
144 /// Constructor for creation
145 OneArray(int n, int l, int u) : xs(*this,n,l,u) {
146 }
147 /// Constructor for cloning \a s
148 OneArray(OneArray& s) : Space(s) {
149 xs.update(*this,s.xs);
150 }
151 /// Copy during cloning
152 virtual Space* copy(void) {
153 return new OneArray(*this);
154 }
155 /// Return the solution as IntArgs
156 IntArgs solution(void) {
157 IntArgs a(xs.size());
158 for (int i = 0 ; i < a.size() ; ++i)
159 a[i] = xs[i].val();
160 return a;
161 }
162 /// Expected solutions
163 virtual IntArgs* expectedSolutions(void) { return nullptr; }
164 };
165
166#ifdef GECODE_HAS_SET_VARS
167 /// %Test space (set version)
168 class OneArraySet : public Space {
169 public:
170 /// Variables
171 SetVarArray xs;
172 /// Constructor for creation
173 OneArraySet(int n, int l, int u) : xs(*this,n, IntSet::empty, l,u) {
174 }
175 /// Constructor for cloning \a s
176 OneArraySet(OneArraySet& s) : Space(s) {
177 xs.update(*this,s.xs);
178 }
179 /// Copy during cloning
180 virtual Space* copy(void) {
181 return new OneArraySet(*this);
182 }
183 /// Return the solution as IntSetArgs
184 IntSetArgs solution(void) {
185 IntSetArgs a(xs.size());
186 for (int i = 0 ; i < a.size() ; ++i) {
187 SetVarGlbRanges glbranges(xs[i]);
188 a[i] = IntSet(glbranges);
189 }
190 return a;
191 }
192 /// Expected solutions
193 virtual IntSetArgs* expectedSolutions(void) { return nullptr; }
194 };
195#endif
196
197 /// %Test for %LDSB infrastructure
198 template <class T>
199 class LDSB : public Base {
200 public:
201 /// Recomputation distance
202 unsigned int c_d;
203 /// Adaptation distance
204 unsigned int a_d;
205 /// Initialize test
206 LDSB(std::string label, unsigned int c=0, unsigned int a=0)
207 : Test::Base("LDSB::" + label),
208 c_d(c), a_d(a) {}
209 /// Perform actual tests
210 bool run(void) {
211 OneArray *s = new OneArray(T::n, T::l, T::u);
212 T::setup(*s, s->xs);
213 Search::Options o = Search::Options::def;
214 if (c_d != 0) o.c_d = c_d;
215 if (a_d != 0) o.a_d = a_d;
216 DFS<OneArray> e(s,o);
217 bool r = check(e, T::expectedSolutions());
218 delete s;
219 return r;
220 }
221 };
222
223#ifdef GECODE_HAS_SET_VARS
224 /// %Test for %LDSB infrastructure
225 template <class T>
226 class LDSBSet : public Base {
227 public:
228 /// Recomputation distance
229 unsigned int c_d;
230 /// Adaptation distance
231 unsigned int a_d;
232 /// Initialize test
233 LDSBSet(std::string label, unsigned int c=0, unsigned int a=0)
234 : Test::Base("LDSB::" + label),
235 c_d(c), a_d(a) {}
236 /// Perform actual tests
237 bool run(void) {
238 OneArraySet *s = new OneArraySet(T::n, T::l, T::u);
239 T::setup(*s, s->xs);
240 Search::Options o = Search::Options::def;
241 if (c_d != 0) o.c_d = c_d;
242 if (a_d != 0) o.a_d = a_d;
243 DFS<OneArraySet> e(s,o);
244 bool r = check(e, T::expectedSolutions());
245 delete s;
246 return r;
247 }
248 };
249#endif
250
251 // Test cases
252
253 /// %Test for variable symmetry
254 class VarSym1 {
255 public:
256 /// Number of variables
257 static const int n = 4;
258 /// Lower bound of values
259 static const int l = 0;
260 /// Upper bound of values
261 static const int u = 3;
262 /// Setup problem constraints and symmetries
263 static void setup(Home home, IntVarArray& xs) {
264 Symmetries syms;
265 IntArgs indices({0,1,2,3});
266 syms << VariableSymmetry(xs, indices);
267 distinct(home, xs);
268 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), syms);
269 }
270 /// Compute list of expected solutions
271 static std::vector<IntArgs> expectedSolutions(void) {
272 static std::vector<IntArgs> expected;
273 expected.clear();
274 expected.push_back(IntArgs({0,1,2,3}));
275 return expected;
276 }
277 };
278
279 /// %Test for variable symmetry
280 class VarSym1b {
281 public:
282 /// Number of variables
283 static const int n = 4;
284 /// Lower bound of values
285 static const int l = 0;
286 /// Upper bound of values
287 static const int u = 3;
288 /// Setup problem constraints and symmetries
289 static void setup(Home home, IntVarArray& xs) {
290 distinct(home, xs);
291 Symmetries syms;
292 syms << VariableSymmetry(xs);
293 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), syms);
294 }
295 /// Compute list of expected solutions
296 static std::vector<IntArgs> expectedSolutions(void) {
297 static std::vector<IntArgs> expected;
298 expected.clear();
299 expected.push_back(IntArgs({0,1,2,3}));
300 return expected;
301 }
302 };
303
304 /// %Test for variable symmetry
305 class VarSym2 {
306 public:
307 /// Number of variables
308 static const int n = 4;
309 /// Lower bound of values
310 static const int l = 0;
311 /// Upper bound of values
312 static const int u = 3;
313 /// Setup problem constraints and symmetries
314 static void setup(Home home, IntVarArray& xs) {
315 Symmetries syms;
316 IntArgs indices({0,1,2,3});
317 syms << VariableSymmetry(xs);
318 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), syms);
319 }
320 /// Compute list of expected solutions
321 static std::vector<IntArgs> expectedSolutions(void) {
322 static std::vector<IntArgs> expected;
323 expected.clear();
324 expected.push_back(IntArgs({0,0,0,0}));
325 expected.push_back(IntArgs({0,0,0,1}));
326 expected.push_back(IntArgs({0,0,0,2}));
327 expected.push_back(IntArgs({0,0,0,3}));
328 expected.push_back(IntArgs({0,0,1,1}));
329 expected.push_back(IntArgs({0,0,1,2}));
330 expected.push_back(IntArgs({0,0,1,3}));
331 expected.push_back(IntArgs({0,0,2,2}));
332 expected.push_back(IntArgs({0,0,2,3}));
333 expected.push_back(IntArgs({0,0,3,3}));
334 expected.push_back(IntArgs({0,1,1,1}));
335 expected.push_back(IntArgs({0,1,1,2}));
336 expected.push_back(IntArgs({0,1,1,3}));
337 expected.push_back(IntArgs({0,1,2,2}));
338 expected.push_back(IntArgs({0,1,2,3}));
339 expected.push_back(IntArgs({0,1,3,3}));
340 expected.push_back(IntArgs({0,2,2,2}));
341 expected.push_back(IntArgs({0,2,2,3}));
342 expected.push_back(IntArgs({0,2,3,3}));
343 expected.push_back(IntArgs({0,3,3,3}));
344 expected.push_back(IntArgs({1,1,1,1}));
345 expected.push_back(IntArgs({1,1,1,2}));
346 expected.push_back(IntArgs({1,1,1,3}));
347 expected.push_back(IntArgs({1,1,2,2}));
348 expected.push_back(IntArgs({1,1,2,3}));
349 expected.push_back(IntArgs({1,1,3,3}));
350 expected.push_back(IntArgs({1,2,2,2}));
351 expected.push_back(IntArgs({1,2,2,3}));
352 expected.push_back(IntArgs({1,2,3,3}));
353 expected.push_back(IntArgs({1,3,3,3}));
354 expected.push_back(IntArgs({2,2,2,2}));
355 expected.push_back(IntArgs({2,2,2,3}));
356 expected.push_back(IntArgs({2,2,3,3}));
357 expected.push_back(IntArgs({2,3,3,3}));
358 expected.push_back(IntArgs({3,3,3,3}));
359 return expected;
360 }
361 };
362
363 /// %Test for variable symmetry
364 class VarSym3 {
365 public:
366 /// Number of variables
367 static const int n = 4;
368 /// Lower bound of values
369 static const int l = 0;
370 /// Upper bound of values
371 static const int u = 3;
372 /// Setup problem constraints and symmetries
373 static void setup(Home home, IntVarArray& xs) {
374 Symmetries syms;
375 distinct(home, xs);
376 syms << VariableSymmetry(IntVarArgs() << xs[0] << xs[1]);
377 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), syms);
378 }
379 /// Compute list of expected solutions
380 static std::vector<IntArgs> expectedSolutions(void) {
381 static std::vector<IntArgs> expected;
382 expected.clear();
383 expected.push_back(IntArgs({0,1,2,3}));
384 expected.push_back(IntArgs({0,1,3,2}));
385 expected.push_back(IntArgs({0,2,1,3}));
386 expected.push_back(IntArgs({0,2,3,1}));
387 expected.push_back(IntArgs({0,3,1,2}));
388 expected.push_back(IntArgs({0,3,2,1}));
389 expected.push_back(IntArgs({1,2,0,3}));
390 expected.push_back(IntArgs({1,2,3,0}));
391 expected.push_back(IntArgs({1,3,0,2}));
392 expected.push_back(IntArgs({1,3,2,0}));
393 expected.push_back(IntArgs({2,3,0,1}));
394 expected.push_back(IntArgs({2,3,1,0}));
395 return expected;
396 }
397 };
398
399 /// %Test for variable symmetry
400 class VarSym4 {
401 public:
402 /// Number of variables
403 static const int n = 3;
404 /// Lower bound of values
405 static const int l = 0;
406 /// Upper bound of values
407 static const int u = 2;
408 /// Setup problem constraints and symmetries
409 static void setup(Home home, IntVarArray& xs) {
410 distinct(home, xs);
411 Symmetries s;
412 IntVarArgs symvars;
413 symvars << xs[0];
414 s << VariableSymmetry(symvars);
415 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
416 }
417 /// Compute list of expected solutions
418 static std::vector<IntArgs> expectedSolutions(void) {
419 static std::vector<IntArgs> expected;
420 expected.clear();
421 expected.push_back(IntArgs({0,1,2}));
422 expected.push_back(IntArgs({0,2,1}));
423 expected.push_back(IntArgs({1,0,2}));
424 expected.push_back(IntArgs({1,2,0}));
425 expected.push_back(IntArgs({2,0,1}));
426 expected.push_back(IntArgs({2,1,0}));
427 return expected;
428 }
429 };
430
431 /// %Test for variable symmetry
432 class VarSym5 {
433 public:
434 /// Number of variables
435 static const int n = 4;
436 /// Lower bound of values
437 static const int l = 0;
438 /// Upper bound of values
439 static const int u = 3;
440 /// Setup problem constraints and symmetries
441 static void setup(Home home, IntVarArray& xs) {
442 distinct(home, xs);
443 Matrix<IntVarArray> m(xs, 4, 1);
444 Symmetries s;
445 s << VariableSymmetry(m.slice(0,2, 0,1));
446 s << VariableSymmetry(m.slice(2,4, 0,1));
447 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
448 }
449 /// Compute list of expected solutions
450 static std::vector<IntArgs> expectedSolutions(void) {
451 static std::vector<IntArgs> expected;
452 expected.clear();
453 expected.push_back(IntArgs({0,1,2,3}));
454 expected.push_back(IntArgs({0,2,1,3}));
455 expected.push_back(IntArgs({0,3,1,2}));
456 expected.push_back(IntArgs({1,2,0,3}));
457 expected.push_back(IntArgs({1,3,0,2}));
458 expected.push_back(IntArgs({2,3,0,1}));
459 return expected;
460 }
461 };
462
463 /// %Test for matrix symmetry
464 class MatSym1 {
465 public:
466 /// Number of variables
467 static const int n = 6;
468 /// Lower bound of values
469 static const int l = 0;
470 /// Upper bound of values
471 static const int u = 1;
472 /// Setup problem constraints and symmetries
473 static void setup(Home home, IntVarArray& xs) {
474 Matrix<IntVarArray> m(xs, 2, 3);
475 Symmetries s;
476 s << rows_interchange(m);
477 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
478 }
479 /// Compute list of expected solutions
480 static std::vector<IntArgs> expectedSolutions(void) {
481 static std::vector<IntArgs> expected;
482 expected.clear();
483 expected.push_back(IntArgs({0,0, 0,0, 0,0}));
484 expected.push_back(IntArgs({0,0, 0,0, 0,1}));
485 expected.push_back(IntArgs({0,0, 0,0, 1,0}));
486 expected.push_back(IntArgs({0,0, 0,0, 1,1}));
487 expected.push_back(IntArgs({0,0, 0,1, 0,0}));
488 expected.push_back(IntArgs({0,0, 0,1, 0,1}));
489 expected.push_back(IntArgs({0,0, 0,1, 1,0}));
490 expected.push_back(IntArgs({0,0, 0,1, 1,1}));
491 expected.push_back(IntArgs({0,0, 1,0, 1,0}));
492 expected.push_back(IntArgs({0,0, 1,0, 1,1}));
493 expected.push_back(IntArgs({0,0, 1,1, 1,1}));
494 expected.push_back(IntArgs({0,1, 0,0, 0,0}));
495 expected.push_back(IntArgs({0,1, 0,0, 0,1}));
496 expected.push_back(IntArgs({0,1, 0,0, 1,0}));
497 expected.push_back(IntArgs({0,1, 0,0, 1,1}));
498 expected.push_back(IntArgs({0,1, 0,1, 0,0}));
499 expected.push_back(IntArgs({0,1, 0,1, 0,1}));
500 expected.push_back(IntArgs({0,1, 0,1, 1,0}));
501 expected.push_back(IntArgs({0,1, 0,1, 1,1}));
502 expected.push_back(IntArgs({0,1, 1,0, 1,0}));
503 expected.push_back(IntArgs({0,1, 1,0, 1,1}));
504 expected.push_back(IntArgs({0,1, 1,1, 1,1}));
505 expected.push_back(IntArgs({1,0, 1,0, 1,0}));
506 expected.push_back(IntArgs({1,0, 1,0, 1,1}));
507 expected.push_back(IntArgs({1,0, 1,1, 1,1}));
508 expected.push_back(IntArgs({1,1, 1,1, 1,1}));
509 return expected;
510 }
511 };
512
513 /// %Test for matrix symmetry
514 class MatSym2 {
515 public:
516 /// Number of variables
517 static const int n = 6;
518 /// Lower bound of values
519 static const int l = 0;
520 /// Upper bound of values
521 static const int u = 1;
522 /// Setup problem constraints and symmetries
523 static void setup(Home home, IntVarArray& xs) {
524 Matrix<IntVarArray> m(xs, 2, 3);
525 Symmetries s;
526 s << columns_interchange(m);
527 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
528 }
529 /// Compute list of expected solutions
530 static std::vector<IntArgs> expectedSolutions(void) {
531 static std::vector<IntArgs> expected;
532 expected.clear();
533 expected.push_back(IntArgs({0,0, 0,0, 0,0}));
534 expected.push_back(IntArgs({0,0, 0,0, 0,1}));
535 expected.push_back(IntArgs({0,0, 0,0, 1,1}));
536 expected.push_back(IntArgs({0,0, 0,1, 0,0}));
537 expected.push_back(IntArgs({0,0, 0,1, 0,1}));
538 expected.push_back(IntArgs({0,0, 0,1, 1,0}));
539 expected.push_back(IntArgs({0,0, 0,1, 1,1}));
540 expected.push_back(IntArgs({0,0, 1,1, 0,0}));
541 expected.push_back(IntArgs({0,0, 1,1, 0,1}));
542 expected.push_back(IntArgs({0,0, 1,1, 1,1}));
543 expected.push_back(IntArgs({0,1, 0,0, 0,0}));
544 expected.push_back(IntArgs({0,1, 0,0, 0,1}));
545 expected.push_back(IntArgs({0,1, 0,0, 1,0}));
546 expected.push_back(IntArgs({0,1, 0,0, 1,1}));
547 expected.push_back(IntArgs({0,1, 0,1, 0,0}));
548 expected.push_back(IntArgs({0,1, 0,1, 0,1}));
549 expected.push_back(IntArgs({0,1, 0,1, 1,0}));
550 expected.push_back(IntArgs({0,1, 0,1, 1,1}));
551 expected.push_back(IntArgs({0,1, 1,0, 0,0}));
552 expected.push_back(IntArgs({0,1, 1,0, 0,1}));
553 expected.push_back(IntArgs({0,1, 1,0, 1,0}));
554 expected.push_back(IntArgs({0,1, 1,0, 1,1}));
555 expected.push_back(IntArgs({0,1, 1,1, 0,0}));
556 expected.push_back(IntArgs({0,1, 1,1, 0,1}));
557 expected.push_back(IntArgs({0,1, 1,1, 1,0}));
558 expected.push_back(IntArgs({0,1, 1,1, 1,1}));
559 expected.push_back(IntArgs({1,1, 0,0, 0,0}));
560 expected.push_back(IntArgs({1,1, 0,0, 0,1}));
561 expected.push_back(IntArgs({1,1, 0,0, 1,1}));
562 expected.push_back(IntArgs({1,1, 0,1, 0,0}));
563 expected.push_back(IntArgs({1,1, 0,1, 0,1}));
564 expected.push_back(IntArgs({1,1, 0,1, 1,0}));
565 expected.push_back(IntArgs({1,1, 0,1, 1,1}));
566 expected.push_back(IntArgs({1,1, 1,1, 0,0}));
567 expected.push_back(IntArgs({1,1, 1,1, 0,1}));
568 expected.push_back(IntArgs({1,1, 1,1, 1,1}));
569 return expected;
570 }
571 };
572
573 /// %Test for matrix symmetry
574 class MatSym3 {
575 public:
576 /// Number of variables
577 static const int n = 6;
578 /// Lower bound of values
579 static const int l = 0;
580 /// Upper bound of values
581 static const int u = 1;
582 /// Setup problem constraints and symmetries
583 static void setup(Home home, IntVarArray& xs) {
584 Matrix<IntVarArray> m(xs, 2, 3);
585 Symmetries s;
586 s << rows_interchange(m);
587 s << columns_interchange(m);
588 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
589 }
590 /// Compute list of expected solutions
591 static std::vector<IntArgs> expectedSolutions(void) {
592 static std::vector<IntArgs> expected;
593 expected.clear();
594 expected.push_back(IntArgs({0,0, 0,0, 0,0}));
595 expected.push_back(IntArgs({0,0, 0,0, 0,1}));
596 expected.push_back(IntArgs({0,0, 0,0, 1,1}));
597 expected.push_back(IntArgs({0,0, 0,1, 0,0}));
598 expected.push_back(IntArgs({0,0, 0,1, 0,1}));
599 expected.push_back(IntArgs({0,0, 0,1, 1,0}));
600 expected.push_back(IntArgs({0,0, 0,1, 1,1}));
601 expected.push_back(IntArgs({0,0, 1,1, 1,1}));
602 expected.push_back(IntArgs({0,1, 0,0, 0,0}));
603 expected.push_back(IntArgs({0,1, 0,0, 0,1}));
604 expected.push_back(IntArgs({0,1, 0,0, 1,0}));
605 expected.push_back(IntArgs({0,1, 0,0, 1,1}));
606 expected.push_back(IntArgs({0,1, 0,1, 0,0}));
607 expected.push_back(IntArgs({0,1, 0,1, 0,1}));
608 expected.push_back(IntArgs({0,1, 0,1, 1,0}));
609 expected.push_back(IntArgs({0,1, 0,1, 1,1}));
610 expected.push_back(IntArgs({0,1, 1,0, 1,0}));
611 expected.push_back(IntArgs({0,1, 1,0, 1,1}));
612 expected.push_back(IntArgs({0,1, 1,1, 1,1}));
613 expected.push_back(IntArgs({1,1, 1,1, 1,1}));
614 return expected;
615 }
616 };
617
618 /// %Test for matrix symmetry
619 class MatSym4 {
620 public:
621 /// Number of variables
622 static const int n = 4;
623 /// Lower bound of values
624 static const int l = 0;
625 /// Upper bound of values
626 static const int u = 1;
627 /// Setup problem constraints and symmetries
628 static void setup(Home home, IntVarArray& xs) {
629 Matrix<IntVarArray> m(xs, 1, 4);
630 Symmetries s;
631 s << rows_reflect(m);
632 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
633 }
634 /// Compute list of expected solutions
635 static std::vector<IntArgs> expectedSolutions(void) {
636 static std::vector<IntArgs> expected;
637 expected.clear();
638 expected.push_back(IntArgs({0, 0, 0, 0}));
639 expected.push_back(IntArgs({0, 0, 0, 1}));
640 expected.push_back(IntArgs({0, 0, 1, 0}));
641 expected.push_back(IntArgs({0, 0, 1, 1}));
642 expected.push_back(IntArgs({0, 1, 0, 0}));
643 expected.push_back(IntArgs({0, 1, 0, 1}));
644 expected.push_back(IntArgs({0, 1, 1, 0}));
645 expected.push_back(IntArgs({0, 1, 1, 1}));
646 expected.push_back(IntArgs({1, 0, 0, 1}));
647 expected.push_back(IntArgs({1, 0, 1, 1}));
648 expected.push_back(IntArgs({1, 1, 1, 1}));
649 return expected;
650 }
651 };
652
653 /// %Test for variable sequence symmetry
654 class SimIntVarSym1 {
655 public:
656 /// Number of variables
657 static const int n = 12;
658 /// Lower bound of values
659 static const int l = 0;
660 /// Upper bound of values
661 static const int u = 3;
662 /// Setup problem constraints and symmetries
663 static void setup(Home home, IntVarArray& xs) {
664 Matrix<IntVarArray> m(xs, 3, 4);
665 // The values in the first column are distinct.
666 distinct(home, m.col(0));
667 // Each row sums to 3.
668 for (int i = 0 ; i < 4 ; ++i)
669 linear(home, m.row(i), IRT_EQ, 3);
670
671 // Rows are interchangeable.
672 Symmetries s;
673 s << VariableSequenceSymmetry(xs, 3);
674 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
675 }
676 /// Compute list of expected solutions
677 static std::vector<IntArgs> expectedSolutions(void) {
678 static std::vector<IntArgs> expected;
679 expected.clear();
680 expected.push_back(IntArgs({0,0,3, 1,0,2, 2,0,1, 3,0,0}));
681 expected.push_back(IntArgs({0,0,3, 1,0,2, 2,1,0, 3,0,0}));
682 expected.push_back(IntArgs({0,0,3, 1,1,1, 2,0,1, 3,0,0}));
683 expected.push_back(IntArgs({0,0,3, 1,1,1, 2,1,0, 3,0,0}));
684 expected.push_back(IntArgs({0,0,3, 1,2,0, 2,0,1, 3,0,0}));
685 expected.push_back(IntArgs({0,0,3, 1,2,0, 2,1,0, 3,0,0}));
686 expected.push_back(IntArgs({0,1,2, 1,0,2, 2,0,1, 3,0,0}));
687 expected.push_back(IntArgs({0,1,2, 1,0,2, 2,1,0, 3,0,0}));
688 expected.push_back(IntArgs({0,1,2, 1,1,1, 2,0,1, 3,0,0}));
689 expected.push_back(IntArgs({0,1,2, 1,1,1, 2,1,0, 3,0,0}));
690 expected.push_back(IntArgs({0,1,2, 1,2,0, 2,0,1, 3,0,0}));
691 expected.push_back(IntArgs({0,1,2, 1,2,0, 2,1,0, 3,0,0}));
692 expected.push_back(IntArgs({0,2,1, 1,0,2, 2,0,1, 3,0,0}));
693 expected.push_back(IntArgs({0,2,1, 1,0,2, 2,1,0, 3,0,0}));
694 expected.push_back(IntArgs({0,2,1, 1,1,1, 2,0,1, 3,0,0}));
695 expected.push_back(IntArgs({0,2,1, 1,1,1, 2,1,0, 3,0,0}));
696 expected.push_back(IntArgs({0,2,1, 1,2,0, 2,0,1, 3,0,0}));
697 expected.push_back(IntArgs({0,2,1, 1,2,0, 2,1,0, 3,0,0}));
698 expected.push_back(IntArgs({0,3,0, 1,0,2, 2,0,1, 3,0,0}));
699 expected.push_back(IntArgs({0,3,0, 1,0,2, 2,1,0, 3,0,0}));
700 expected.push_back(IntArgs({0,3,0, 1,1,1, 2,0,1, 3,0,0}));
701 expected.push_back(IntArgs({0,3,0, 1,1,1, 2,1,0, 3,0,0}));
702 expected.push_back(IntArgs({0,3,0, 1,2,0, 2,0,1, 3,0,0}));
703 expected.push_back(IntArgs({0,3,0, 1,2,0, 2,1,0, 3,0,0}));
704 return expected;
705 }
706 };
707
708 /// %Test for variable sequence symmetry
709 class SimIntVarSym2 {
710 /// Number of rows
711 static const int nrows = 4;
712 /// Number of columns
713 static const int ncols = 3;
714 public:
715 /// Number of variables
716 static const int n = nrows*ncols;
717 /// Lower bound of values
718 static const int l = 0;
719 /// Upper bound of values
720 static const int u = 3;
721 /// Setup problem constraints and symmetries
722 static void setup(Home home, IntVarArray& xs) {
723 Matrix<IntVarArray> m(xs, 3, 4);
724 // The values in the first column are distinct.
725 distinct(home, m.col(0));
726 // Each row sums to 3.
727 for (int i = 0 ; i < nrows ; ++i)
728 linear(home, m.row(i), IRT_EQ, 3);
729
730 Symmetries s;
731
732 IntArgs a = IntArgs::create(n, 0);
733 // Rows are interchangeable.
734 s << VariableSequenceSymmetry(xs, 3);
735 // Elements (i,1) and (i,2) in row i are interchangeable,
736 // separately for each row.
737 for (int i = 0 ; i < nrows ; i++) {
738 IntVarArgs symvars;
739 symvars << m(1,i) << m(2,i);
740 s << VariableSymmetry(symvars);
741 }
742 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
743 }
744 /// Compute list of expected solutions
745 static std::vector<IntArgs> expectedSolutions(void) {
746 static std::vector<IntArgs> expected;
747 expected.clear();
748 expected.push_back(IntArgs({0,0,3, 1,0,2, 2,0,1, 3,0,0}));
749 expected.push_back(IntArgs({0,0,3, 1,1,1, 2,0,1, 3,0,0}));
750 expected.push_back(IntArgs({0,1,2, 1,0,2, 2,0,1, 3,0,0}));
751 expected.push_back(IntArgs({0,1,2, 1,1,1, 2,0,1, 3,0,0}));
752 return expected;
753 }
754 };
755
756 /// %Test for value sequence symmetry
757 class SimIntValSym1 {
758 public:
759 /// Number of variables
760 static const int n = 2;
761 /// Lower bound of values
762 static const int l = 0;
763 /// Upper bound of values
764 static const int u = 6;
765 /// Setup problem constraints and symmetries
766 static void setup(Home home, IntVarArray& xs) {
767 rel(home, xs[0] + xs[1] == 6);
768 // Values 0,1,2 are symmetric with 6,5,4.
769 IntArgs values({0,1,2, 6,5,4});
770 Symmetries s;
771 s << ValueSequenceSymmetry(values, 3);
772 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
773 }
774 /// Compute list of expected solutions
775 static std::vector<IntArgs> expectedSolutions(void) {
776 static std::vector<IntArgs> expected;
777 expected.clear();
778 expected.push_back(IntArgs({0,6}));
779 expected.push_back(IntArgs({1,5}));
780 expected.push_back(IntArgs({2,4}));
781 expected.push_back(IntArgs({3,3}));
782 return expected;
783 }
784 };
785
786 /// %Test for value sequence symmetry
787 class SimIntValSym2 {
788 public:
789 /// Number of variables
790 static const int n = 3;
791 /// Lower bound of values
792 static const int l = 0;
793 /// Upper bound of values
794 static const int u = 8;
795 /// Setup problem constraints and symmetries
796 static void setup(Home home, IntVarArray& xs) {
797 TupleSet tuples(3);
798 tuples.add({1,1,1}).add({4,4,4}).add({7,7,7})
799 .add({0,1,5}).add({0,1,8}).add({3,4,2})
800 .add({3,4,8}).add({6,7,2}).add({6,7,5})
801 .finalize();
802 extensional(home, xs, tuples);
803
804 // Values 0,1,2 are symmetric with 3,4,5, and with 6,7,8.
805 IntArgs values({0,1,2, 3,4,5, 6,7,8});
806 Symmetries s;
807 s << ValueSequenceSymmetry(values, 3);
808 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
809 }
810 /// Compute list of expected solutions
811 static std::vector<IntArgs> expectedSolutions(void) {
812 static std::vector<IntArgs> expected;
813 expected.clear();
814 expected.push_back(IntArgs({0,1,5}));
815 expected.push_back(IntArgs({1,1,1}));
816 return expected;
817 }
818 };
819
820 /// %Test for value sequence symmetry
821 class SimIntValSym3 {
822 public:
823 /// Number of variables
824 static const int n = 2;
825 /// Lower bound of values
826 static const int l = 0;
827 /// Upper bound of values
828 static const int u = 6;
829 /// Setup problem constraints and symmetries
830 static void setup(Home home, IntVarArray& xs) {
831 rel(home, xs[0] + xs[1] == 6);
832 Symmetries s;
833 // Values 0,1,2 are symmetric with 6,5,4.
834 s << values_reflect(0,6);
835 branch(home, xs, INT_VAR_NONE(), INT_VAL_MED(), s);
836 }
837 /// Compute list of expected solutions
838 static std::vector<IntArgs> expectedSolutions(void) {
839 static std::vector<IntArgs> expected;
840 expected.clear();
841 expected.push_back(IntArgs({3,3}));
842 expected.push_back(IntArgs({2,4}));
843 expected.push_back(IntArgs({1,5}));
844 expected.push_back(IntArgs({0,6}));
845 return expected;
846 }
847 };
848
849 /// %Test for value symmetry
850 class ValSym1 {
851 public:
852 /// Number of variables
853 static const int n = 4;
854 /// Lower bound of values
855 static const int l = 0;
856 /// Upper bound of values
857 static const int u = 3;
858 /// Setup problem constraints and symmetries
859 static void setup(Home home, IntVarArray& xs) {
860 distinct(home, xs);
861 Symmetries s;
862 IntArgs indices({0,1,2,3});
863 s << ValueSymmetry(indices);
864 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
865 }
866 /// Compute list of expected solutions
867 static std::vector<IntArgs> expectedSolutions(void) {
868 static std::vector<IntArgs> expected;
869 expected.clear();
870 expected.push_back(IntArgs({0,1,2,3}));
871 return expected;
872 }
873 };
874
875 /// %Test for value symmetry
876 class ValSym1b {
877 public:
878 /// Number of variables
879 static const int n = 4;
880 /// Lower bound of values
881 static const int l = 0;
882 /// Upper bound of values
883 static const int u = 3;
884 /// Setup problem constraints and symmetries
885 static void setup(Home home, IntVarArray& xs) {
886 distinct(home, xs);
887 Symmetries s;
888 s << ValueSymmetry(xs[0]);
889 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
890 }
891 /// Compute list of expected solutions
892 static std::vector<IntArgs> expectedSolutions(void) {
893 static std::vector<IntArgs> expected;
894 expected.clear();
895 expected.push_back(IntArgs({0,1,2,3}));
896 return expected;
897 }
898 };
899
900 /// %Test for value symmetry
901 class ValSym1c {
902 public:
903 /// Number of variables
904 static const int n = 4;
905 /// Lower bound of values
906 static const int l = 0;
907 /// Upper bound of values
908 static const int u = 3;
909 /// Setup problem constraints and symmetries
910 static void setup(Home home, IntVarArray& xs) {
911 distinct(home, xs);
912 Symmetries s;
913 s << ValueSymmetry(xs[0]);
914 branch(home, xs, INT_VAR_NONE(), INT_VAL_MAX(), s);
915 }
916 /// Compute list of expected solutions
917 static std::vector<IntArgs> expectedSolutions(void) {
918 static std::vector<IntArgs> expected;
919 expected.clear();
920 expected.push_back(IntArgs({3,2,1,0}));
921 return expected;
922 }
923 };
924
925 /// %Test for value symmetry
926 class ValSym2 {
927 public:
928 /// Number of variables
929 static const int n = 4;
930 /// Lower bound of values
931 static const int l = 0;
932 /// Upper bound of values
933 static const int u = 3;
934 /// Setup problem constraints and symmetries
935 static void setup(Home home, IntVarArray& xs) {
936 Symmetries s;
937 IntArgs indices({0,1,2,3});
938 s << ValueSymmetry(indices);
939 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
940 }
941 /// Compute list of expected solutions
942 static std::vector<IntArgs> expectedSolutions(void) {
943 static std::vector<IntArgs> expected;
944 expected.clear();
945 expected.push_back(IntArgs({0,0,0,0}));
946 expected.push_back(IntArgs({0,0,0,1}));
947 expected.push_back(IntArgs({0,0,1,0}));
948 expected.push_back(IntArgs({0,0,1,1}));
949 expected.push_back(IntArgs({0,0,1,2}));
950 expected.push_back(IntArgs({0,1,0,0}));
951 expected.push_back(IntArgs({0,1,0,1}));
952 expected.push_back(IntArgs({0,1,0,2}));
953 expected.push_back(IntArgs({0,1,1,0}));
954 expected.push_back(IntArgs({0,1,1,1}));
955 expected.push_back(IntArgs({0,1,1,2}));
956 expected.push_back(IntArgs({0,1,2,0}));
957 expected.push_back(IntArgs({0,1,2,1}));
958 expected.push_back(IntArgs({0,1,2,2}));
959 expected.push_back(IntArgs({0,1,2,3}));
960 return expected;
961 }
962 };
963
964 /// %Test for value symmetry
965 class ValSym2b {
966 public:
967 /// Number of variables
968 static const int n = 4;
969 /// Lower bound of values
970 static const int l = 0;
971 /// Upper bound of values
972 static const int u = 3;
973 /// Setup problem constraints and symmetries
974 static void setup(Home home, IntVarArray& xs) {
975 Symmetries s;
976 s << ValueSymmetry(xs[0]);
977 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
978 }
979 /// Compute list of expected solutions
980 static std::vector<IntArgs> expectedSolutions(void) {
981 static std::vector<IntArgs> expected;
982 expected.clear();
983 expected.push_back(IntArgs({0,0,0,0}));
984 expected.push_back(IntArgs({0,0,0,1}));
985 expected.push_back(IntArgs({0,0,1,0}));
986 expected.push_back(IntArgs({0,0,1,1}));
987 expected.push_back(IntArgs({0,0,1,2}));
988 expected.push_back(IntArgs({0,1,0,0}));
989 expected.push_back(IntArgs({0,1,0,1}));
990 expected.push_back(IntArgs({0,1,0,2}));
991 expected.push_back(IntArgs({0,1,1,0}));
992 expected.push_back(IntArgs({0,1,1,1}));
993 expected.push_back(IntArgs({0,1,1,2}));
994 expected.push_back(IntArgs({0,1,2,0}));
995 expected.push_back(IntArgs({0,1,2,1}));
996 expected.push_back(IntArgs({0,1,2,2}));
997 expected.push_back(IntArgs({0,1,2,3}));
998 return expected;
999 }
1000 };
1001
1002 /// %Test for value symmetry
1003 class ValSym3 {
1004 public:
1005 /// Number of variables
1006 static const int n = 4;
1007 /// Lower bound of values
1008 static const int l = 0;
1009 /// Upper bound of values
1010 static const int u = 3;
1011 /// Setup problem constraints and symmetries
1012 static void setup(Home home, IntVarArray& xs) {
1013 distinct(home, xs);
1014 Symmetries s;
1015 IntArgs indices({0,1});
1016 s << ValueSymmetry(indices);
1017 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
1018 }
1019 /// Compute list of expected solutions
1020 static std::vector<IntArgs> expectedSolutions(void) {
1021 static std::vector<IntArgs> expected;
1022 expected.clear();
1023 expected.push_back(IntArgs({0,1,2,3}));
1024 expected.push_back(IntArgs({0,1,3,2}));
1025 expected.push_back(IntArgs({0,2,1,3}));
1026 expected.push_back(IntArgs({0,2,3,1}));
1027 expected.push_back(IntArgs({0,3,1,2}));
1028 expected.push_back(IntArgs({0,3,2,1}));
1029 expected.push_back(IntArgs({2,0,1,3}));
1030 expected.push_back(IntArgs({2,0,3,1}));
1031 expected.push_back(IntArgs({2,3,0,1}));
1032 expected.push_back(IntArgs({3,0,1,2}));
1033 expected.push_back(IntArgs({3,0,2,1}));
1034 expected.push_back(IntArgs({3,2,0,1}));
1035 return expected;
1036 }
1037 };
1038
1039 /// %Test for value symmetry
1040 class ValSym4 {
1041 public:
1042 /// Number of variables
1043 static const int n = 3;
1044 /// Lower bound of values
1045 static const int l = 0;
1046 /// Upper bound of values
1047 static const int u = 2;
1048 /// Setup problem constraints and symmetries
1049 static void setup(Home home, IntVarArray& xs) {
1050 distinct(home, xs);
1051 Symmetries s;
1052 IntArgs indices({0});
1053 s << ValueSymmetry(indices);
1054 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
1055 }
1056 /// Compute list of expected solutions
1057 static std::vector<IntArgs> expectedSolutions(void) {
1058 static std::vector<IntArgs> expected;
1059 expected.clear();
1060 expected.push_back(IntArgs({0,1,2}));
1061 expected.push_back(IntArgs({0,2,1}));
1062 expected.push_back(IntArgs({1,0,2}));
1063 expected.push_back(IntArgs({1,2,0}));
1064 expected.push_back(IntArgs({2,0,1}));
1065 expected.push_back(IntArgs({2,1,0}));
1066 return expected;
1067 }
1068 };
1069
1070 /// %Test for value symmetry
1071 class ValSym5 {
1072 public:
1073 /// Number of variables
1074 static const int n = 4;
1075 /// Lower bound of values
1076 static const int l = 0;
1077 /// Upper bound of values
1078 static const int u = 3;
1079 /// Setup problem constraints and symmetries
1080 static void setup(Home home, IntVarArray& xs) {
1081 distinct(home, xs);
1082 Symmetries s;
1083 IntArgs indices0({0,1});
1084 IntArgs indices1({2,3});
1085 s << ValueSymmetry(indices0);
1086 s << ValueSymmetry(indices1);
1087 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
1088 }
1089 /// Compute list of expected solutions
1090 static std::vector<IntArgs> expectedSolutions(void) {
1091 static std::vector<IntArgs> expected;
1092 expected.clear();
1093 expected.push_back(IntArgs({0,1,2,3}));
1094 expected.push_back(IntArgs({0,2,1,3}));
1095 expected.push_back(IntArgs({0,2,3,1}));
1096 expected.push_back(IntArgs({2,0,1,3}));
1097 expected.push_back(IntArgs({2,0,3,1}));
1098 expected.push_back(IntArgs({2,3,0,1}));
1099 return expected;
1100 }
1101 };
1102
1103 /// %Test for variable and value symmetry
1104 class VarValSym1 {
1105 public:
1106 /// Number of variables
1107 static const int n = 4;
1108 /// Lower bound of values
1109 static const int l = 0;
1110 /// Upper bound of values
1111 static const int u = 3;
1112 /// Setup problem constraints and symmetries
1113 static void setup(Home home, IntVarArray& xs) {
1114 Symmetries s;
1115 s << VariableSymmetry(xs);
1116 s << ValueSymmetry(IntArgs::create(4,0));
1117 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
1118 }
1119 /// Compute list of expected solutions
1120 static std::vector<IntArgs> expectedSolutions(void) {
1121 static std::vector<IntArgs> expected;
1122 expected.clear();
1123 expected.push_back(IntArgs({0,0,0,0}));
1124 expected.push_back(IntArgs({0,0,0,1}));
1125 expected.push_back(IntArgs({0,0,1,1}));
1126 expected.push_back(IntArgs({0,0,1,2}));
1127 expected.push_back(IntArgs({0,1,1,1}));
1128 expected.push_back(IntArgs({0,1,1,2}));
1129 expected.push_back(IntArgs({0,1,2,2})); // This solution is symmetric to the previous one.
1130 expected.push_back(IntArgs({0,1,2,3}));
1131 return expected;
1132 }
1133 };
1134
1135 /// %Test for %LDSB infrastructure with %Latin square problem
1136 class LDSBLatin : public Base {
1137 public:
1138 /// %Latin square space
1139 class Latin : public Space {
1140 public:
1141 IntVarArray xs;
1142 Latin(int n = 4) : xs(*this, n*n, 1, n)
1143 {
1144 Matrix<IntVarArray> m(xs, n, n);
1145 for (int i = 0 ; i < n ; i++) {
1146 distinct(*this, m.col(i));
1147 distinct(*this, m.row(i));
1148 }
1149 Symmetries s;
1150 s << rows_interchange(m);
1151 s << columns_interchange(m);
1152 s << ValueSymmetry(IntSet(1,n));
1153 branch(*this, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
1154 }
1155 // Search support.
1156 Latin(Latin& s) : Space(s)
1157 { xs.update(*this, s.xs); }
1158 virtual Space* copy(void)
1159 { return new Latin(*this); }
1160 IntArgs solution(void) {
1161 IntArgs a(xs.size());
1162 for (int i = 0 ; i < a.size() ; ++i)
1163 a[i] = xs[i].val();
1164 return a;
1165 }
1166
1167 /// Compute list of expected solutions
1168 static std::vector<IntArgs> expectedSolutions(void) {
1169 static std::vector<IntArgs> expected;
1170 expected.clear();
1171 expected.push_back(IntArgs({1,2,3,4, 2,1,4,3, 3,4,1,2, 4,3,2,1}));
1172 expected.push_back(IntArgs({1,2,3,4, 2,1,4,3, 3,4,2,1, 4,3,1,2}));
1173 expected.push_back(IntArgs({1,2,3,4, 2,3,4,1, 3,4,1,2, 4,1,2,3}));
1174 expected.push_back(IntArgs({1,2,3,4, 2,4,1,3, 3,1,4,2, 4,3,2,1}));
1175 return expected;
1176 }
1177 };
1178 /// Initialize test
1179 LDSBLatin(std::string label) : Test::Base("LDSB::" + label) {}
1180 /// Perform actual tests
1181 bool run(void) {
1182 Latin *s = new Latin();
1183 DFS<Latin> e(s);
1184 bool r = check(e, Latin::expectedSolutions());
1185 delete s;
1186 return r;
1187 }
1188 };
1189
1190 /* This test should fail if the recomputation-handling does not work
1191 * properly.
1192 *
1193 * Why recomputation can be a problem
1194 * ==================================
1195 *
1196 * Every branch point in LDSB is binary, with a left and a right
1197 * branch. Whenever backtracking happens -- when a right branch is
1198 * explored -- LDSB computes a set of symmetric literals to
1199 * exclude.
1200 *
1201 * !!! This calculation may depend on the current domains of the
1202 * !!! variables.
1203 *
1204 * During recomputation, parts of the search tree are replayed. To
1205 * be specific, the branching constraints are posted, but no
1206 * propagation happens. This means that at a given branch point,
1207 * the domains during recomputation may be different (weaker) than
1208 * they were the first time during search.
1209 *
1210 * !!! This *cannot* cause solutions to be missed --- LDSB will not
1211 * !!! be incorrect --- but it *does* change what will be pruned.
1212 *
1213 * If recomputation is not handled properly, the difference in
1214 * domains will cause extra solutions to be found. This is a result
1215 * of symmetries failing to be broken.
1216 *
1217 */
1218
1219 /// %Test for handling of recomputation
1220 class Recomputation {
1221 public:
1222 /// Number of variables
1223 static const int n = 4;
1224 /// Lower bound of values
1225 static const int l = 0;
1226 /// Upper bound of values
1227 static const int u = 1;
1228 /// Setup problem constraints and symmetries
1229 static void setup(Home home, IntVarArray& xs) {
1230 TupleSet t(2);
1231 t.add({0,0}).add({1,1}).finalize();
1232 IntVarArgs va;
1233 va << xs[0] << xs[2];
1234 extensional(home, va, t);
1235 Symmetries syms;
1236 syms << VariableSequenceSymmetry(xs, 2);
1237 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), syms);
1238 }
1239 /// Compute list of expected solutions
1240 static std::vector<IntArgs> expectedSolutions(void) {
1241 static std::vector<IntArgs> expected;
1242 expected.clear();
1243 expected.push_back(IntArgs({0,0,0,0}));
1244 expected.push_back(IntArgs({0,0,0,1}));
1245
1246 // This is the solution that will be found if recomputation is
1247 // not handled. After branching on x[0]=0, we try x[1]=0. When
1248 // x[1]=0 backtracks, the symmetry [x[0],x[1]] <-> [x[2],x[3]]
1249 // is active --- but only after propagation! (Without
1250 // propagation, we do not have x[2]=0.) If propagation happens,
1251 // we know that symmetry is active and we can post x[3]!=0. If
1252 // it doesn't, we don't use the symmetry and we find a solution
1253 // where x[3]=0.
1254
1255 // expected.push_back(IntArgs({0,1,0,0}));
1256
1257 expected.push_back(IntArgs({0,1,0,1}));
1258
1259 expected.push_back(IntArgs({1,0,1,0}));
1260 expected.push_back(IntArgs({1,0,1,1}));
1261 expected.push_back(IntArgs({1,1,1,1}));
1262 return expected;
1263 }
1264 };
1265
1266 double position(const Space& home, IntVar x, int i) {
1267 (void) home;
1268 (void) x;
1269 return i;
1270 }
1271
1272 /// %Test tiebreaking variable heuristic.
1273 class TieBreak {
1274 public:
1275 /// Number of variables
1276 static const int n = 4;
1277 /// Lower bound of values
1278 static const int l = 0;
1279 /// Upper bound of values
1280 static const int u = 3;
1281 /// Setup problem constraints and symmetries
1282 static void setup(Home home, IntVarArray& xs) {
1283 Symmetries syms;
1284 IntArgs indices({0,1,2,3});
1285 syms << VariableSymmetry(xs, indices);
1286 distinct(home, xs);
1287 // This redundant constraint is to trick the variable
1288 // heuristic.
1289 rel(home, xs[1] != xs[2]);
1290 // xs[1] and xs[2] have higher degree than the others, so they
1291 // are considered first. xs[2] is higher than x[1] by the merit
1292 // function, so it is assigned first. Now all remaining
1293 // variables have the same degree, so they are searched in
1294 // reverse order (according to the merit function). So, the
1295 // solution found is {3, 2, 0, 1}.
1296 branch(home, xs, tiebreak(INT_VAR_DEGREE_MAX(), INT_VAR_MERIT_MAX(position)), INT_VAL_MIN(), syms);
1297 }
1298 /// Compute list of expected solutions
1299 static std::vector<IntArgs> expectedSolutions(void) {
1300 static std::vector<IntArgs> expected;
1301 expected.clear();
1302 expected.push_back(IntArgs({3,2,0,1}));
1303 return expected;
1304 }
1305 };
1306
1307#ifdef GECODE_HAS_SET_VARS
1308 /// Convenient way to make IntSetArgs
1309 IntSetArgs ISA(int n, ...) {
1310 IntSetArgs sets;
1311 va_list args;
1312 va_start(args, n);
1313 int i = 0;
1314 IntArgs a;
1315 while (i < n) {
1316 int x = va_arg(args,int);
1317 if (x == -1) {
1318 i++;
1319 sets << IntSet(a);
1320 a = IntArgs();
1321 } else {
1322 a << x;
1323 }
1324 }
1325 va_end(args);
1326 return sets;
1327 }
1328
1329 /// %Test for set variable symmetry
1330 class SetVarSym1 {
1331 public:
1332 /// Number of variables
1333 static const int n = 2;
1334 /// Lower bound of values
1335 static const int l = 0;
1336 /// Upper bound of values
1337 static const int u = 1;
1338 /// Setup problem constraints and symmetries
1339 static void setup(Home home, SetVarArray& xs) {
1340 Symmetries syms;
1341 syms << VariableSymmetry(xs);
1342 branch(home, xs, SET_VAR_NONE(), SET_VAL_MIN_INC(), syms);
1343 }
1344 /// Compute list of expected solutions
1345 static std::vector<IntSetArgs> expectedSolutions(void) {
1346 static std::vector<IntSetArgs> expected;
1347 expected.clear();
1348 expected.push_back(ISA(2, 0,1,-1, 0,1,-1));
1349 expected.push_back(ISA(2, 0,1,-1, 0, -1));
1350 expected.push_back(ISA(2, 0,1,-1, 1,-1));
1351 expected.push_back(ISA(2, 0,1,-1, -1));
1352 expected.push_back(ISA(2, 0, -1, 0,1,-1));
1353 expected.push_back(ISA(2, 0, -1, 0, -1));
1354 expected.push_back(ISA(2, 0, -1, 1,-1));
1355 expected.push_back(ISA(2, 0, -1, -1));
1356 // expected.push_back(ISA(2, 1,-1, 0,1,-1));
1357 // expected.push_back(ISA(2, 1,-1, 0, -1));
1358 expected.push_back(ISA(2, 1,-1, 1,-1));
1359 expected.push_back(ISA(2, 1,-1, -1));
1360 // expected.push_back(ISA(2, -1, 0,1,-1));
1361 // expected.push_back(ISA(2, -1, 0, -1));
1362 // expected.push_back(ISA(2, -1, 1,-1));
1363 expected.push_back(ISA(2, -1, -1));
1364 return expected;
1365 }
1366 };
1367
1368 /*
1369 * This tests the special handling of value symmetries on set
1370 * values. Look at the third solution (commented out) below. The
1371 * first variable has been assigned to {0,1}. If the value symmetry
1372 * is not handled specially, then we will consider the value
1373 * symmetry broken because the search has touched each value.
1374 * However, because both values have been assigned to the same
1375 * variable, 0 and 1 are still symmetric. Therefore, the third
1376 * solution is symmetric to the second one and should be excluded.
1377 */
1378
1379 /// %Test for set value symmetry
1380 class SetValSym1 {
1381 public:
1382 /// Number of variables
1383 static const int n = 2;
1384 /// Lower bound of values
1385 static const int l = 0;
1386 /// Upper bound of values
1387 static const int u = 1;
1388 /// Setup problem constraints and symmetries
1389 static void setup(Home home, SetVarArray& xs) {
1390 Symmetries syms;
1391 syms << ValueSymmetry(IntArgs({0,1}));
1392 branch(home, xs, SET_VAR_NONE(), SET_VAL_MIN_INC(), syms);
1393 }
1394 /// Compute list of expected solutions
1395 static std::vector<IntSetArgs> expectedSolutions(void) {
1396 static std::vector<IntSetArgs> expected;
1397 expected.clear();
1398 expected.push_back(ISA(2, 0,1,-1, 0,1,-1));
1399 expected.push_back(ISA(2, 0,1,-1, 0, -1));
1400 // expected.push_back(ISA(2, 0,1,-1, 1,-1)); // XXXXX bad solution
1401 expected.push_back(ISA(2, 0,1,-1, -1));
1402 expected.push_back(ISA(2, 0, -1, 0,1,-1));
1403 expected.push_back(ISA(2, 0, -1, 0, -1));
1404 expected.push_back(ISA(2, 0, -1, 1,-1));
1405 expected.push_back(ISA(2, 0, -1, -1));
1406 // expected.push_back(ISA(2, 1,-1, 0,1,-1));
1407 // expected.push_back(ISA(2, 1,-1, 0, -1));
1408 // expected.push_back(ISA(2, 1,-1, 1,-1));
1409 // expected.push_back(ISA(2, 1,-1, -1));
1410 expected.push_back(ISA(2, -1, 0,1,-1));
1411 expected.push_back(ISA(2, -1, 0, -1));
1412 // expected.push_back(ISA(2, -1, 1,-1));
1413 expected.push_back(ISA(2, -1, -1));
1414 return expected;
1415 }
1416 };
1417
1418 /// %Test for set value symmetry
1419 class SetValSym2 {
1420 public:
1421 /// Number of variables
1422 static const int n = 3;
1423 /// Lower bound of values
1424 static const int l = 1;
1425 /// Upper bound of values
1426 static const int u = 4;
1427 /// Setup problem constraints and symmetries
1428 static void setup(Home home, SetVarArray& xs) {
1429 Symmetries syms;
1430 syms << ValueSymmetry(IntArgs({1,2,3,4}));
1431 for (int i = 0 ; i < 3 ; i++)
1432 cardinality(home, xs[i], 1, 1);
1433 branch(home, xs, SET_VAR_NONE(), SET_VAL_MIN_INC(), syms);
1434 }
1435 /// Compute list of expected solutions
1436 static std::vector<IntSetArgs> expectedSolutions(void) {
1437 static std::vector<IntSetArgs> expected;
1438 expected.clear();
1439 expected.push_back(ISA(3, 1,-1, 1,-1, 1,-1));
1440 expected.push_back(ISA(3, 1,-1, 1,-1, 2,-1));
1441 expected.push_back(ISA(3, 1,-1, 2,-1, 1,-1));
1442 expected.push_back(ISA(3, 1,-1, 2,-1, 2,-1));
1443 expected.push_back(ISA(3, 1,-1, 2,-1, 3,-1));
1444 return expected;
1445 }
1446 };
1447
1448 /// %Test for set variable sequence symmetry
1449 class SetVarSeqSym1 {
1450 public:
1451 /// Number of variables
1452 static const int n = 4;
1453 /// Lower bound of values
1454 static const int l = 0;
1455 /// Upper bound of values
1456 static const int u = 1;
1457 /// Setup problem constraints and symmetries
1458 static void setup(Home home, SetVarArray& xs) {
1459 Symmetries syms;
1460 syms << VariableSequenceSymmetry(xs,2);
1461 rel(home, xs[0], SOT_INTER, xs[1], SRT_EQ, IntSet::empty);
1462 rel(home, xs[2], SOT_INTER, xs[3], SRT_EQ, IntSet::empty);
1463 for (int i = 0 ; i < 4 ; i++)
1464 cardinality(home, xs[i], 1, 1);
1465 branch(home, xs, SET_VAR_NONE(), SET_VAL_MIN_INC(), syms);
1466 }
1467 /// Compute list of expected solutions
1468 static std::vector<IntSetArgs> expectedSolutions(void) {
1469 static std::vector<IntSetArgs> expected;
1470 expected.clear();
1471 expected.push_back(ISA(4, 0,-1, 1,-1, 0,-1, 1,-1));
1472 expected.push_back(ISA(4, 0,-1, 1,-1, 1,-1, 0,-1));
1473 // expected.push_back(ISA(4, 1,-1, 0,-1, 0,-1, 1,-1));
1474 expected.push_back(ISA(4, 1,-1, 0,-1, 1,-1, 0,-1));
1475 return expected;
1476 }
1477 };
1478
1479 /// %Test for set variable sequence symmetry
1480 class SetVarSeqSym2 {
1481 public:
1482 /// Number of variables
1483 static const int n = 4;
1484 /// Lower bound of values
1485 static const int l = 0;
1486 /// Upper bound of values
1487 static const int u = 0;
1488 /// Setup problem constraints and symmetries
1489 static void setup(Home home, SetVarArray& xs) {
1490 Symmetries syms;
1491 syms << VariableSequenceSymmetry(xs,2);
1492 rel(home, xs[0], SRT_EQ, xs[2]);
1493 branch(home, xs, SET_VAR_NONE(), SET_VAL_MIN_INC(), syms);
1494 }
1495 /// Compute list of expected solutions
1496 static std::vector<IntSetArgs> expectedSolutions(void) {
1497 static std::vector<IntSetArgs> expected;
1498 expected.clear();
1499
1500 // Symmetric solutions are commented out.
1501 expected.push_back(ISA(4, 0, -1,0,-1,0,-1,0,-1));
1502 expected.push_back(ISA(4, 0, -1,0,-1,0,-1, -1));
1503 // expected.push_back(ISA(4, 0, -1,0,-1, -1,0,-1));
1504 // expected.push_back(ISA(4, 0, -1,0,-1, -1, -1));
1505 // expected.push_back(ISA(4, 0, -1, -1,0,-1,0,-1));
1506 expected.push_back(ISA(4, 0, -1, -1,0,-1, -1));
1507 // expected.push_back(ISA(4, 0, -1, -1, -1,0,-1));
1508 // expected.push_back(ISA(4, 0, -1, -1, -1, -1));
1509 // expected.push_back(ISA(4, -1,0,-1,0,-1,0,-1));
1510 // expected.push_back(ISA(4, -1,0,-1,0,-1, -1));
1511 expected.push_back(ISA(4, -1,0,-1, -1,0,-1));
1512 expected.push_back(ISA(4, -1,0,-1, -1, -1));
1513 // expected.push_back(ISA(4, -1, -1,0,-1,0,-1));
1514 // expected.push_back(ISA(4, -1, -1,0,-1, -1));
1515 // expected.push_back(ISA(4, -1, -1, -1,0,-1));
1516 expected.push_back(ISA(4, -1, -1, -1, -1));
1517
1518 return expected;
1519 }
1520 };
1521
1522 /// %Test for reflection symmetry
1523 class ReflectSym1 {
1524 public:
1525 /// Number of variables
1526 static const int n = 6;
1527 /// Lower bound of values
1528 static const int l = 0;
1529 /// Upper bound of values
1530 static const int u = 6;
1531 /// Setup problem constraints and symmetries
1532 static void setup(Home home, IntVarArray& xs) {
1533 Matrix<IntVarArray> m(xs, 3, 2);
1534
1535 distinct(home, xs);
1536 rel(home, abs(m(0,0)-m(1,0))==1);
1537 rel(home, abs(m(0,1)-m(1,1))==1);
1538 rel(home, abs(m(1,0)-m(2,0))==1);
1539 rel(home, abs(m(1,1)-m(2,1))==1);
1540
1541 Symmetries s;
1542 s << values_reflect(l, u);
1543 s << rows_interchange(m);
1544 s << columns_reflect(m);
1545 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
1546 }
1547 /// Compute list of expected solutions
1548 static std::vector<IntArgs> expectedSolutions(void) {
1549 static std::vector<IntArgs> expected;
1550 expected.clear();
1551 expected.push_back(IntArgs({0,1,2,3,4,5}));
1552 expected.push_back(IntArgs({0,1,2,4,5,6}));
1553 expected.push_back(IntArgs({0,1,2,5,4,3}));
1554 expected.push_back(IntArgs({0,1,2,6,5,4}));
1555 return expected;
1556 }
1557 };
1558
1559 /// %Test for reflection symmetry
1560 class ReflectSym2 {
1561 public:
1562 /// Number of variables
1563 static const int n = 2;
1564 /// Lower bound of values
1565 static const int l = 0;
1566 /// Upper bound of values
1567 static const int u = 3;
1568 /// Setup problem constraints and symmetries
1569 static void setup(Home home, IntVarArray& xs) {
1570 Symmetries s;
1571 s << values_reflect(l, u);
1572 branch(home, xs, INT_VAR_NONE(), INT_VAL_MIN(), s);
1573 }
1574 /// Compute list of expected solutions
1575 static std::vector<IntArgs> expectedSolutions(void) {
1576 static std::vector<IntArgs> expected;
1577 expected.clear();
1578 expected.push_back(IntArgs({0,0}));
1579 expected.push_back(IntArgs({0,1}));
1580 expected.push_back(IntArgs({0,2}));
1581 expected.push_back(IntArgs({0,3}));
1582 expected.push_back(IntArgs({1,0}));
1583 expected.push_back(IntArgs({1,1}));
1584 expected.push_back(IntArgs({1,2}));
1585 expected.push_back(IntArgs({1,3}));
1586 return expected;
1587 }
1588 };
1589
1590 /// %Test with action
1591 class Action1 {
1592 public:
1593 /// Number of variables
1594 static const int n = 4;
1595 /// Lower bound of values
1596 static const int l = 0;
1597 /// Upper bound of values
1598 static const int u = 3;
1599 /// Setup problem constraints and symmetries
1600 static void setup(Home home, IntVarArray& xs) {
1601 distinct(home, xs);
1602 Symmetries s;
1603 s << VariableSymmetry(xs);
1604 s << ValueSymmetry(IntArgs::create(4,0));
1605 branch(home, xs, INT_VAR_ACTION_MIN(0.8), INT_VAL_MIN(), s);
1606 }
1607 /// Compute list of expected solutions
1608 static std::vector<IntArgs> expectedSolutions(void) {
1609 static std::vector<IntArgs> expected;
1610 expected.clear();
1611 expected.push_back(IntArgs({0,1,2,3}));
1612 return expected;
1613 }
1614 };
1615
1616#endif
1617
1618 LDSB<VarSym1> varsym1("VarSym1");
1619 LDSB<VarSym1b> varsym1b("VarSym1b");
1620 LDSB<VarSym2> varsym2("VarSym2");
1621 LDSB<VarSym3> varsym3("VarSym3");
1622 LDSB<VarSym4> varsym4("VarSym4");
1623 LDSB<VarSym5> varsym5("VarSym5");
1624 LDSB<MatSym1> matsym1("MatSym1");
1625 LDSB<MatSym2> matsym2("MatSym2");
1626 LDSB<MatSym3> matsym3("MatSym3");
1627 LDSB<MatSym4> matsym4("MatSym4");
1628 LDSB<SimIntVarSym1> simintvarsym1("SimIntVarSym1");
1629 LDSB<SimIntVarSym2> simintvarsym2("SimIntVarSym2");
1630 LDSB<SimIntValSym1> simintvalsym1("SimIntValSym1");
1631 LDSB<SimIntValSym2> simintvalsym2("SimIntValSym2");
1632 LDSB<SimIntValSym3> simintvalsym3("SimIntValSym3");
1633 LDSB<ValSym1> valsym1("ValSym1");
1634 LDSB<ValSym1b> valsym1b("ValSym1b");
1635 LDSB<ValSym1c> valsym1c("ValSym1c");
1636 LDSB<ValSym2> valsym2("ValSym2");
1637 LDSB<ValSym2b> valsym2b("ValSym2b");
1638 LDSB<ValSym3> valsym3("ValSym3");
1639 LDSB<ValSym4> valsym4("ValSym4");
1640 LDSB<ValSym5> valsym5("ValSym5");
1641 LDSB<VarValSym1> varvalsym1("VarValSym1");
1642 LDSBLatin latin("Latin");
1643 LDSB<Recomputation> recomp("Recomputation", 999,999);
1644 LDSB<TieBreak> tiebreak("TieBreak");
1645
1646#ifdef GECODE_HAS_SET_VARS
1647 LDSB<ReflectSym1> reflectsym1("ReflectSym1");
1648 LDSB<ReflectSym2> reflectsym2("ReflectSym2");
1649 LDSB<Action1> action1("Action1");
1650
1651 LDSBSet<SetVarSym1> setvarsym1("SetVarSym1");
1652 LDSBSet<SetValSym1> setvalsym1("SetValSym1");
1653 LDSBSet<SetValSym2> setvalsym2("SetValSym2", 0, 1);
1654 LDSBSet<SetVarSeqSym1> setvarseqsym1("SetVarSeqSym1");
1655 LDSBSet<SetVarSeqSym2> setvarseqsym2("SetVarSeqSym2");
1656#endif
1657}}
1658
1659// STATISTICS: test-core