git-subtree-dir: software/mza git-subtree-split: f970a59b177c13ca3dd8aaef8cc6681d83b7e813
116 lines
3.3 KiB
MiniZinc
116 lines
3.3 KiB
MiniZinc
% RUNS ON mzn20_fd
|
|
% RUNS ON mzn-fzn_fd
|
|
% RUNS ON mzn20_fd_linear
|
|
% RUNS ON mzn20_mip
|
|
%------------------------------------------------------------------------------%
|
|
% 2DPacking.mzn
|
|
% Jakob Puchinger
|
|
% October 29 2007
|
|
% vim: ft=zinc ts=4 sw=4 et tw=0
|
|
%------------------------------------------------------------------------------%
|
|
% Two-dimensional Bin Packing
|
|
%
|
|
% n rectangular items with given height and width have to be packed into
|
|
% rectangular bins of size W x H
|
|
% It is assumed that the items are sorted according to non-increasing height.
|
|
%
|
|
%------------------------------------------------------------------------------%
|
|
|
|
% Upper Bound on the number of Bins used
|
|
int: K;
|
|
% Width of the Bin
|
|
int: W;
|
|
% Height of the Bin
|
|
int: H;
|
|
% Number of items to be packed
|
|
int: N;
|
|
% Widths of the items
|
|
array[1..N] of int: ItemWidth;
|
|
% Heights of the items
|
|
array[1..N] of int: ItemHeight;
|
|
|
|
% Variable indicating if bin k is used.
|
|
array[1..K] of var 0..1: bin;
|
|
|
|
% Variable indicating if item i is in bin k.
|
|
array[1..K, 1..N] of var 0..1: item;
|
|
|
|
% The total number of bins has to be minimized
|
|
solve minimize
|
|
sum( k in 1..K ) ( bin[k] ) ;
|
|
|
|
% Each item has to be packed.
|
|
constraint
|
|
forall( j in 1..N ) (
|
|
sum( k in 1..K ) ( item[k, j] ) = 1
|
|
);
|
|
|
|
% subproblem constraints
|
|
constraint
|
|
forall( k in 1..K ) (
|
|
is_feasible_packing(bin[k], [ item[k, j] | j in 1..N ])
|
|
);
|
|
|
|
% This predicate defines a feasible packing
|
|
% as a 2-stage guillotine pattern (level pattern).
|
|
% A Bin consists of one or several levels
|
|
% and each level consist of one or several items.
|
|
% The height of a level is given by its highest (first) item.
|
|
% Variable x[i, j] indicates if item i is put in level j
|
|
% x[j, j] also indicate that level j is used.
|
|
%
|
|
% Note, k is locally fixed, so this is the pattern for the k'th bin.
|
|
%
|
|
predicate is_feasible_packing(var 0..1: s_bin,
|
|
array[1..N] of var 0..1: s_item) = (
|
|
let {array[1..N, 1..N] of var 0..1: x} in (
|
|
forall ( i in 1..N ) (
|
|
% Width of items on level can not exceed W
|
|
sum( j in i..N ) ( ItemWidth[j] * x[i, j] ) <= W * x[i, i]
|
|
/\
|
|
% first item in level is highest
|
|
% XXX do not need to generate those variables (use default)
|
|
forall( j in 1..i-1 ) ( x[i, j] = 0 )
|
|
)
|
|
/\
|
|
% Height of levels on bin can not exceed H
|
|
sum( i in 1..N ) ( ItemHeight[i] * x[i, i] ) <= s_bin * H
|
|
/\
|
|
% for all items associate item on bin with item on level.
|
|
forall(j in 1..N) (
|
|
s_item[j] = sum( i in 1..j ) ( x[i, j] )
|
|
)
|
|
)
|
|
);
|
|
|
|
% required for showing the objective function
|
|
var int: obj;
|
|
constraint
|
|
obj = sum( k in 1..K )( bin[k] );
|
|
|
|
output
|
|
[ "Number of used bins = ", show( obj ), "\n"] ++
|
|
[ "Items in bins = \n\t"] ++
|
|
[ show(item[k, j]) ++ if j = N then "\n\t" else " " endif |
|
|
k in 1..K, j in 1..N ] ++
|
|
[ "\n" ];
|
|
|
|
%------------------------------------------------------------------------------%
|
|
%
|
|
% Test data (Not in separate file, so that mzn2lp can handle it).
|
|
%
|
|
|
|
N = 4;
|
|
W = 5;
|
|
H = 10;
|
|
K = 2;
|
|
ItemWidth = [ 1, 1, 2, 3 ];
|
|
ItemHeight = [ 4, 4, 4, 3 ];
|
|
|
|
%N = 6;
|
|
%W = 5;
|
|
%H = 10;
|
|
%K = N;
|
|
%ItemWidth = [ 4, 4, 1, 1, 2, 3 ];
|
|
%ItemHeight = [ 6, 5, 4, 4, 4, 3 ];
|