Generated on for Gecode by doxygen 1.15.0
bin-packing.cpp
Go to the documentation of this file.
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Christian Schulte <schulte@gecode.dev>
5 *
6 * Copyright:
7 * Christian Schulte, 2010
8 *
9 * This file is part of Gecode, the generic constraint
10 * development environment:
11 * http://www.gecode.dev
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 "test/int.hh"
35
36#include <gecode/minimodel.hh>
37#include <climits>
38
39namespace Test { namespace Int {
40
42 namespace BinPacking {
43
49
51 protected:
53 int n_bins;
61 int load;
64 public:
67 int n, const Gecode::IntSet& d_n,
68 int l)
69 : Assignment(m+n,d_m),
70 n_bins(m), n_items(n), d_load(d_m), d_bin(d_n), load(l),
71 dsv(new Gecode::IntSetValues[static_cast<unsigned int>(m+n)]) {
72 for (int i=n_bins; i--; )
73 dsv[i].init(d_load);
74 for (int i=n_items; i--; )
75 dsv[n_bins+i].init(d_bin);
76 }
77
78 virtual bool has_more(void) const {
79 return dsv[0]();
80 }
81
83 // Try to generate next bin assignment
84 {
85 int i = n_items-1;
86 while (i >= 0) {
87 ++dsv[n_bins+i];
88 if (dsv[n_bins+i]())
89 return;
90 dsv[n_bins+(i--)].init(d_bin);
91 }
92 }
93 // Try to generate next load assignment
94 {
95 retry:
96 int i = n_bins-1;
97 while (true) {
98 ++dsv[i];
99 if (dsv[i]() || (i == 0)) {
100 if (dsv[i]() && (load >= 0)) {
101 int l = 0;
102 for (int k=0;k<n_bins; k++)
103 l += dsv[k].val();
104 if (load != l)
105 goto retry;
106 }
107 return;
108 }
109 dsv[i--].init(d_load);
110 }
111 }
112 }
113
114 virtual int operator[](int i) const {
115 assert((i>=0) && (i<n_bins+n_items));
116 return dsv[i].val();
117 }
118
119 virtual ~LoadBinAssignment(void) {
120 delete [] dsv;
121 }
122 };
123
125 class BPT : public Test {
126 protected:
128 int m;
132 bool valid;
134 int t;
136 mutable int il[8];
138 static int total(const Gecode::IntArgs& s) {
139 int t = 0;
140 for (int i=s.size(); i--; )
141 t += s[i];
142 return t;
143 }
144 public:
146 BPT(int m0, const Gecode::IntArgs& s0, bool v=true)
147 : Test("BinPacking::"+str(m0)+"::"+str(s0)+"::"+(v ? "+" : "-"),
148 m0+s0.size(), 0, 100),
149 m(m0), s(s0), valid(v), t(total(s)) {
150 testsearch = false;
151 }
152
153 virtual Assignment* assignment(void) const {
154 // Compute plausible bin sizes
155 int a = t / m;
156 return new LoadBinAssignment(m,Gecode::IntSet(a-1,a+2),
157 s.size(),Gecode::IntSet(0,m-1),
158 valid ? t : -1);
159 }
160
161 virtual bool solution(const Assignment& x) const {
162 // Loads are from 0 to m-1, after that are items
163 // Check whether loads sum up to total size
164 int l=0;
165 for (int j=m; j--; )
166 l += x[j];
167 if (l != t)
168 return false;
169 // Check whether items are at possible bins
170 for (int j=m; j--; )
171 if ((x[m+j] < 0) || (x[m+j] >= m))
172 return false;
173 // Compute whether items add up
174 for (int j=m; j--; )
175 il[j] = 0;
176 for (int i=s.size(); i--; )
177 il[x[m+i]] += s[i];
178 for (int j=m; j--; )
179 if (il[j] != x[j])
180 return false;
181 return true;
182 }
183
184 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
185 using namespace Gecode;
186 IntVarArgs l(m);
187 IntVarArgs b(s.size());
188 for (int j=m; j--; )
189 l[j]=x[j];
190 for (int i=s.size(); i--; )
191 b[i]=x[m+i];
192 binpacking(home, l, b, s);
193 }
194 };
195
197 class MBPT : public Test {
198 protected:
200 int d;
202 int m;
208 mutable int il[4][8];
209 public:
211 MBPT(int d0, int m0,
212 const Gecode::IntArgs& s0, const Gecode::IntArgs& c0)
213 : Test("MultiBinPacking::"+str(d0)+"::"+str(m0)+"::"+
214 str(s0)+"::"+str(c0), s0.size() / d0, 0, m0-1),
215 d(d0), m(m0), s(s0), c(c0) {
216 testsearch = false;
217 testfix = false;
218 }
219
220 virtual bool solution(const Assignment& x) const {
221 // x are the bin variables
222 for (int k=d; k--; )
223 for (int j=m; j--; )
224 il[k][j] = 0;
225 for (int k=d; k--; )
226 for (int i=x.size(); i--; )
227 il[k][x[i]] += s[i*d+k];
228 for (int k=d; k--; )
229 for (int j=m; j--; )
230 if (il[k][j] > c[k])
231 return false;
232 return true;
233 }
234
235 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) {
236 using namespace Gecode;
237 IntVarArgs l(d*m);
238 for (int j=m*d; j--; )
239 l[j]=IntVar(home, 0, Gecode::Int::Limits::max);
240 binpacking(home, d, l, x, s, c);
241 }
242 };
243
245 class CliqueMBPT : public Base {
246 protected:
252 class TestSpace : public Gecode::Space {
253 public:
254 // Constructor
255 TestSpace(void) {}
256 // Copy function
257 virtual Gecode::Space* copy(void) {
258 return nullptr;
259 }
260 };
261 public:
264 : Base("Int::MultiBinPacking::Clique::"+Test::str(c)), clique(c) {}
265
266 virtual bool run(void) {
267 using namespace Gecode;
268 TestSpace* home = new TestSpace;
269 /*
270 * Set up a multi-dimensional bin packing problems of dimension 2
271 * where the item sizes in one dimension are all one but for some
272 * random items and two in the other dimension if the item is
273 * included in the clique and where the capacity in both dimensions
274 * is 3.
275 */
276 // Number of items
277 int n_items = clique[clique.size()-1] + 1;
278 // Capacity
279 IntArgs c({3,3});
280 // Item sizes
281 IntArgs s(2*n_items);
282 for (int i=2*n_items; i--; )
283 s[i]=1;
284 // Create some random conflicts
285 for (int i=clique.size()-1; i--; )
286 s[_rand(n_items)*2+0]=2;
287 // Create conflicts corresponding to the clique
288 for (int i=clique.size(); i--; )
289 s[clique[i]*2+1]=2;
290 // Load and bin variables
291 IntVarArgs b(*home, n_items, 0, n_items-1);
292 IntVarArgs l(*home, 2*n_items, 0, 3);
293 IntSet mc = binpacking(*home, 2, l, b, s, c);
294 if (home->status() == SS_FAILED) {
295 delete home;
296 return false;
297 }
298 if (static_cast<unsigned int>(clique.size()) != mc.size()) {
299 delete home;
300 return false;
301 }
302 for (int i=clique.size(); i--; )
303 if (!mc.in(clique[i])) {
304 delete home;
305 return false;
306 }
307 delete home;
308 return true;
309 }
310 };
311
313 class DFFLowerBound : public Base {
314 protected:
316 class TestSpace : public Gecode::Space {
317 public:
319 TestSpace(void) {}
321 virtual Gecode::Space* copy(void) {
322 return nullptr;
323 }
324 };
325 public:
328 : Base("Int::BinPacking::DFFLowerBound") {}
329
330 virtual bool run(void) {
331 using namespace Gecode;
332 TestSpace* home = new TestSpace;
333 IntVarArgs l(*home, 3, 0, 5);
334 IntVarArgs b(*home, 6, 0, 2);
335 IntArgs s({4,2,2,2,2,2});
336 binpacking(*home, l, b, s, IPL_FULL);
337 bool failed = home->status() == SS_FAILED;
338 delete home;
339 return failed;
340 }
341 };
342
344 class PropagationLevels : public Base {
345 protected:
347 class TestSpace : public Gecode::Space {
348 public:
349 TestSpace(void) {}
350 virtual Gecode::Space* copy(void) {
351 return nullptr;
352 }
353 };
354
355 bool check_case(int n_bins, int capacity, const Gecode::IntArgs& sizes,
356 const bool expected_failed[4]) const {
357 using namespace Gecode;
358 IntPropLevel const levels[] =
360 for (unsigned int i = 0; i < 4; i += 1) {
361 TestSpace* home = new TestSpace;
362 IntVarArgs l(*home, n_bins, 0, capacity);
363 IntVarArgs b(*home, sizes.size(), 0, n_bins-1);
364 binpacking(*home, l, b, sizes, levels[i]);
365 bool failed = home->status() == SS_FAILED;
366 delete home;
367 if (failed != expected_failed[i])
368 return false;
369 }
370 return true;
371 }
372 public:
375 : Base("Int::BinPacking::PropagationLevels") {}
376
377 virtual bool run(void) {
378 using namespace Gecode;
379 bool const advanced_failed[] = {false, true, true, true};
380 bool const full_failed[] = {false, false, false, true};
381 return
382 check_case(3, 5, IntArgs({4,2,2,2,2,2}), advanced_failed) &&
383 check_case(5, 35,
384 IntArgs({32,30,24,21,19,11,10,9,8,5,3}),
385 full_failed);
386 }
387 };
388
390 class DFFLargeWeights : public Base {
391 protected:
393 class TestSpace : public Gecode::Space {
394 public:
396 TestSpace(void) {}
398 virtual Gecode::Space* copy(void) {
399 return nullptr;
400 }
401 };
402 public:
405 : Base("Int::BinPacking::DFFLargeWeights") {}
406
407 virtual bool run(void) {
408 using namespace Gecode;
409 {
410 TestSpace* home = new TestSpace;
411 IntVarArgs l(*home, 2, 0, Gecode::Int::Limits::max);
412 IntVarArgs b(*home, 1, 0, 1);
414 binpacking(*home, l, b, s);
415 bool failed = home->status() == SS_FAILED;
416 delete home;
417 if (failed)
418 return false;
419 }
420 {
421 TestSpace* home = new TestSpace;
422 int c = Gecode::Int::Limits::max / 2;
423 IntVarArgs l(*home, 2, 0, c);
424 IntVarArgs b(*home, 1, 0, 1);
425 IntArgs s({c});
426 binpacking(*home, l, b, s);
427 bool failed = home->status() == SS_FAILED;
428 delete home;
429 if (failed)
430 return false;
431 }
432 {
433 TestSpace* home = new TestSpace;
434 IntVarArgs l(*home, 2, 0, 1100000000);
435 IntVarArgs b(*home, 2, 0, 1);
436 IntArgs s({1000000000,1000000000});
437 binpacking(*home, l, b, s);
438 bool failed = home->status() == SS_FAILED;
439 delete home;
440 return !failed;
441 }
442 }
443 };
444
446 class Create {
447 public:
449 Create(void) {
450 using namespace Gecode;
451
452 {
453 IntArgs s0({0,0,0,0});
454 IntArgs s1({2,1,1});
455 IntArgs s2({1,2,3,4});
456 IntArgs s3({4,3,2,1});
457 IntArgs s4({1,2,4,8});
458 IntArgs s5({1,1,1,1});
459 IntArgs s6({1,1,2,2});
460 IntArgs s7({1,3,3,4});
461 IntArgs s8({1,3,3,0,4,0});
462 IntArgs s9({1,2,4,8,16,32});
463
464 for (int m=1; m<4; m++) {
465 (void) new BPT(m, s0);
466 (void) new BPT(m, s1);
467 (void) new BPT(m, s2);
468 (void) new BPT(m, s3);
469 (void) new BPT(m, s4);
470 (void) new BPT(m, s5);
471 (void) new BPT(m, s6);
472 (void) new BPT(m, s7);
473 (void) new BPT(m, s8);
474 (void) new BPT(m, s9);
475 (void) new BPT(m, s1, false);
476 }
477 }
478
479 {
480 IntArgs s1({1,2, 2,1, 1,2, 2,1});
481 IntArgs c1({3,3});
482 (void) new MBPT(2, 4, s1, c1);
483 (void) new MBPT(2, 6, s1, c1);
484 IntArgs s2({1,1, 1,1, 1,1});
485 IntArgs c21({1,1});
486 IntArgs c22({2,2});
487 (void) new MBPT(2, 6, s2, c21);
488 (void) new MBPT(2, 6, s2, c22);
489 IntArgs s3({1,2,3, 3,2,1, 2,1,3, 1,3,2});
490 IntArgs c31({3,3,3});
491 IntArgs c32({4,4,4});
492 IntArgs c33({6,6,6});
493 (void) new MBPT(3, 4, s3, c31);
494 (void) new MBPT(3, 4, s3, c32);
495 (void) new MBPT(3, 4, s3, c33);
496 (void) new MBPT(3, 5, s3, c31);
497 (void) new MBPT(3, 5, s3, c32);
498 (void) new MBPT(3, 5, s3, c33);
499 }
500
501 {
502 IntArgs c1({0,2,4,6});
503 IntArgs c2({1,2,3,4,5,6,7,8});
504 IntArgs c3({1,3,7,10,15,22,27,97});
505 IntArgs c41({1,2,3,4,5,6,7,14});
506 IntArgs c42({1,2,3,4,5,6,7,15});
507 IntArgs c43({1,2,3,4,5,6,7,16});
508 IntArgs c44({1,2,3,4,5,6,7,30});
509 IntArgs c45({1,2,3,4,5,6,7,31});
510 IntArgs c46({1,2,3,4,5,6,7,32});
511 IntArgs c47({1,2,3,4,5,6,7,62});
512 IntArgs c48({1,2,3,4,5,6,7,63});
513 IntArgs c49({1,2,3,4,5,6,7,64});
514
515 (void) new CliqueMBPT(c1);
516 (void) new CliqueMBPT(c2);
517 (void) new CliqueMBPT(c3);
518 (void) new CliqueMBPT(c41);
519 (void) new CliqueMBPT(c42);
520 (void) new CliqueMBPT(c43);
521 (void) new CliqueMBPT(c44);
522 (void) new CliqueMBPT(c45);
523 (void) new CliqueMBPT(c46);
524 (void) new CliqueMBPT(c47);
525 (void) new CliqueMBPT(c48);
526 (void) new CliqueMBPT(c49);
527 }
528
529 (void) new DFFLowerBound;
530 (void) new PropagationLevels;
531 (void) new DFFLargeWeights;
532 }
533 };
534
536
538
539 }
540
541}}
542
543
544// STATISTICS: test-int
int size(void) const
Return size of array (number of elements).
Definition array.hpp:1597
Passing integer arguments.
Definition int.hh:652
Value iterator for integer sets.
Definition int.hh:351
Integer sets.
Definition int.hh:178
bool in(int n) const
Return whether n is included in the set.
unsigned int size(void) const
Return size (cardinality) of set.
Passing integer variables.
Definition int.hh:680
Integer variable array.
Definition int.hh:791
Integer variables.
Definition int.hh:389
Computation spaces.
Definition core.hpp:1775
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
static std::string str(bool b)
Map bool to string.
Definition test.hpp:77
Base class for assignments
Definition int.hh:59
int n
Number of variables.
Definition int.hh:61
Assignment(int n0, const Gecode::IntSet &d0)
Initialize assignments for n0 variables and values d0.
Definition int.hpp:43
int size(void) const
Return number of variables.
Definition int.hpp:46
Test with different bin loads and items
static int total(const Gecode::IntArgs &s)
Compute total size.
virtual Assignment * assignment(void) const
Create assignment.
virtual bool solution(const Assignment &x) const
Test whether x is solution
BPT(int m0, const Gecode::IntArgs &s0, bool v=true)
Create and register test for m bins and item sizes s.
Gecode::IntArgs s
Item sizes.
int il[8]
Array of sufficient size for computing item loads.
bool valid
Whether to generate only valid loads.
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x)
Post constraint on x.
int t
Total item sizes.
virtual Gecode::Space * copy(void)
Copying member function.
Test for testing the max-clique finding for multi bin-packing.
CliqueMBPT(const Gecode::IntArgs &c)
Test for number of items n expected clique c.
Gecode::IntArgs clique
Expected clique.
virtual bool run(void)
Run the actual test.
Help class to create and register tests.
Create(void)
Perform creation and registration.
virtual Gecode::Space * copy(void)
Copy function.
Test DFF arithmetic at the largest supported integer value.
virtual bool run(void)
Run the actual test.
virtual Gecode::Space * copy(void)
Copy function.
Test that DFF lower bounds detect infeasible packing.
virtual bool run(void)
Run the actual test.
Generate load and bin assignments.
virtual ~LoadBinAssignment(void)
Destructor.
Gecode::IntSet d_bin
Domain for bin variables.
Gecode::IntSetValues * dsv
Iterator for each variable.
LoadBinAssignment(int m, const Gecode::IntSet &d_m, int n, const Gecode::IntSet &d_n, int l)
Initialize assignments for load and bin variables.
int load
Load to generate (unless -1).
virtual bool has_more(void) const
Test whether all assignments have been iterated.
Gecode::IntSet d_load
Domain for load variables.
virtual int operator[](int i) const
Return value for variable i.
virtual void next(Gecode::Support::RandomGenerator &)
Move to next assignment.
Test with different bin loads and items
MBPT(int d0, int m0, const Gecode::IntArgs &s0, const Gecode::IntArgs &c0)
Create and register test for d0 dimensions, m0 bins, item sizes s0, and capacities c0.
virtual bool solution(const Assignment &x) const
Test whether x is solution
Gecode::IntArgs c
Bin capacities.
virtual void post(Gecode::Space &home, Gecode::IntVarArray &x)
Post constraint on x.
Gecode::IntArgs s
Item sizes.
int il[4][8]
Array of sufficient size for computing item loads.
virtual Gecode::Space * copy(void)
Copying member function.
Test the bin-packing propagation levels.
bool check_case(int n_bins, int capacity, const Gecode::IntArgs &sizes, const bool expected_failed[4]) const
Check one propagation-level test case.
virtual bool run(void)
Run the actual test.
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
bool testfix
Whether to perform fixpoint test.
Definition int.hh:240
const int capacity[n_warehouses]
Capacity of a single warehouse.
LinearCongruentialGenerator< 2147483647, 48271, 44488, 3399 > RandomGenerator
Default values for linear congruential generator.
Definition random.hpp:183
void binpacking(Home home, const IntVarArgs &l, const IntVarArgs &b, const IntArgs &s, IntPropLevel ipl=IPL_DEF)
Post propagator for bin packing.
IntPropLevel
Propagation levels for integer propagators.
Definition int.hh:1008
@ IPL_BASIC
Use basic propagation algorithm.
Definition int.hh:1015
@ IPL_FULL
Use full propagation.
Definition int.hh:1018
@ IPL_ADVANCED
Use advanced propagation algorithm.
Definition int.hh:1016
@ IPL_DEF
Simple propagation levels.
Definition int.hh:1010
SpaceStatus status(StatusStatistics &stat)
Query space status.
Definition core.cpp:282
@ SS_FAILED
Space is failed
Definition core.hpp:1715
const int max
Largest allowed integer value.
Definition int.hh:120
Gecode toplevel namespace
Tests for bin-packing constraint
Testing finite domain integers.
Definition int.cpp:40
General test support.
Definition afc.cpp:39