Download
% prob008.mzn: Vessel Loading
% Problem details available at
% http://www.csplib.org/Problems/prob008/

% Author: Frej Knutar Lewander

int: deck_width; % width of deck
int: deck_length; % height of deck
int: n_containers; % number of containers
int: n_classes; % number of container classes

array[int] of int: width;
% width[c] = width of container c
array[int] of int: length;
% length[c] = length of container c
array[int] of int: class;
% class[c] = class of container c
array[int, int] of int: separation;
% separation[a, b] = the minimum allowed separation between
%                    containers of classes a and b

set of int: Containers = 1..n_containers;

array[Containers] of var 0..deck_width: Left;
% Left[c] = leftmost point of container c
array[Containers] of var 0..deck_width: Right;
% Right[c] = rightmost point of container c
array[Containers] of var 0..deck_length: Bottom;
% Bottom[c] = bottommost point of container c
array[Containers] of var 0..deck_length: Top;
% Top[c] = topmost point of container c

array[Containers] of var 1..2: orientation;
% orientation[c] = 2 if container c is turned 90 degrees, else 1.

constraint
  forall (c in Containers) (
    let {
      array[1..2] of int: ElemWidth = [width[c], length[c]];
      array[1..2] of int: ElemLength = [length[c], width[c]]
    }
    in 
      Right[c] = Left[c] + ElemWidth[orientation[c]] /\
      Top[c] = Bottom[c] + ElemLength[orientation[c]]
  )
;

constraint
  forall(c, k in Containers where c < k) (
    Left[c] >= Right[k] + separation[class[c], class[k]] \/
    Right[c] + separation[class[c], class[k]] <= Left[k] \/
    Bottom[c] >= Top[k] + separation[class[c], class[k]] \/
    Top[c] + separation[class[c], class[k]] <= Bottom[k]
  )
;

% Excessive (pretty) output
output ["┌"] ++ ["─" | t in 0..deck_width] ++ ["┐\n"] ++
       [if x == 0 then "│" else "" endif ++
        let {
          bool: l = exists([fix(Left[c])   = x | c in Containers]);
          bool: r = exists([fix(Right[c])  = x | c in Containers]);
          bool: b = exists([fix(Bottom[c]) = y | c in Containers]);
          bool: t = exists([fix(Top[c])    = y | c in Containers])
        } in
          if     l /\ r /\ b /\ t then "┼"
          elseif l /\ r /\ b      then "┬"
          elseif l /\ r /\      t then "┴"
          elseif l /\      b /\ t then "├"
          elseif      r /\ b /\ t then "┤"
          elseif l /\      b      then "┌"
          elseif l /\           t then "└"
          elseif      r /\ b      then "┐"
          elseif      r /\      t then "┘"
          elseif l \/ r           then "│"
          elseif           b \/ t then "─" 
          else " " endif ++
        if x == deck_width then "│\n" else "" endif
        | y in 0..deck_length, x in 0..deck_width] ++
        ["└"] ++ ["─" | t in 0..deck_width] ++ ["┘"];