1
0
This repository has been archived on 2025-03-06. You can view files and clone it, but cannot push or open issues or pull requests.

95 lines
4.7 KiB
MiniZinc

% Use this editor as a MiniZinc scratch book
int: planks;
set of int: PLANK = 1..planks;
array[PLANK] of int: plank_width;
int: pillars;
set of int: PILLAR = 1..pillars;
array[PILLAR] of int: pillar_height;
array[PILLAR] of int: pillar_width;
int: available_width;
int: available_height;
set of int: WIDTH = 0..available_width-1;
set of int: HEIGHT = 0..available_height-1;
array[PLANK] of var WIDTH: xk;
array[PLANK] of var HEIGHT: yk;
set of int: PLANK0 = 0..planks;
array[PLANK0] of int: plank_widthx = array1d(PLANK0, [available_width] ++ plank_width);
array[PLANK0] of var WIDTH: xkx = array1d(PLANK0, [0] ++ xk);
array[PLANK0] of var -1..available_height-1: ykx = array1d(PLANK0, [-1] ++ yk);
array[PILLAR] of var WIDTH: xr;
array[PILLAR] of var HEIGHT: yr;
constraint forall(p in PLANK)(xk[p] + plank_width[p]<= available_width);
constraint forall(p in PILLAR)(xr[p] + pillar_width[p]<= available_width);
constraint forall(p in PILLAR)(yr[p] + pillar_height[p]<= available_height);
% symmetry breaking
constraint symmetry_breaking_constraint(forall(p1,p2 in PLANK where p1 < p2 /\ plank_width[p1] = plank_width[p2])
(yk[p1] <= yk[p2] /\ (yk[p1] = yk[p2] -> xk[p1] < xk[p2])));
constraint symmetry_breaking_constraint(forall(p1,p2 in PILLAR where p1 < p2 /\ pillar_width[p1] = pillar_width[p2] /\ pillar_height[p1] = pillar_height[p2])
(yr[p1] <= yr[p2] /\ (yr[p1] = yr[p2] -> xr[p1] < xr[p2])));
include "diffn.mzn";
constraint diffn(xk ++ xr, yk ++ yr, plank_width++pillar_width, [1 | p in PLANK] ++ pillar_height);
% each plank is supported at both ends by a pillar
array[PLANK] of var PILLAR: left;
array[PLANK] of var PILLAR: right;
constraint forall(p in PLANK)( xr[left[p]] <= xk[p] /\ xr[left[p]] + pillar_width[left[p]] > xk[p]
/\ yk[p] = yr[left[p]] + pillar_height[left[p]] );
constraint forall(p in PLANK)( xr[right[p]] <= xk[p] + plank_width[p] - 1 /\ xr[right[p]] + pillar_width[right[p]] > xk[p] + plank_width[p]-1
/\ yk[p] = yr[right[p]] + pillar_height[right[p]] );
% each pillar sits on exaclty one plank
array[PILLAR] of var PLANK0: support;
constraint forall(p in PILLAR)
(xr[p] >= xkx[support[p]] /\ xr[p] + pillar_width[p] <= xkx[support[p]] + plank_widthx[support[p]]
/\ yr[p] = ykx[support[p]] + 1);
var 0..available_height: objective = max([ yk[p] + 1 | p in PLANK ] ++ [yr[p] + pillar_height[p] | p in PILLAR ]);
enum TYPE = {LK,RK,K,LP,RP,UP,IP,E};
array[WIDTH, HEIGHT] of TYPE: map :: output_only =
array2d(WIDTH,HEIGHT,
[ if exists(p in PLANK)(fix(xk[p]) = x /\ fix(yk[p]) = y) then LK
elseif exists(p in PLANK)(fix(xk[p]) + plank_width[p] = x+1 /\ fix(yk[p]) = y) then RK
elseif exists(p in PLANK)(fix(xk[p]) < x /\ fix(xk[p]) + plank_width[p] > x+1 /\ fix(yk[p]) = y) then K
elseif exists(p in PILLAR)(fix(xr[p]) = x /\ pillar_width[p] = 1 /\ fix(yr[p]) <= y /\ fix(yr[p]) + pillar_height[p] > y) then UP
elseif exists(p in PILLAR)(fix(xr[p]) = x /\ fix(yr[p]) <= y /\ fix(yr[p]) + pillar_height[p] > y) then LP
elseif exists(p in PILLAR)(fix(xr[p]) + pillar_width[p] = x +1 /\ fix(yr[p]) <= y /\ fix(yr[p]) + pillar_height[p] > y) then RP
elseif exists(p in PILLAR)(fix(xr[p]) < x /\ fix(xr[p]) + pillar_width[p] > x+1 /\ fix(yr[p]) <= y /\ fix(yr[p]) + pillar_height[p] > y) then IP
else E endif
| x in WIDTH, y in HEIGHT ]);
array[TYPE] of string: rep = ["[","]","=","(",")","|","."," "];
output [ if x = 0 then "% " else "" endif ++
let {int: y = fix(objective) - 1 - yy;} in
rep[map[x,y]]
++ if x = available_width-1 then "\n" else "" endif
| yy in 0..fix(objective)-1, x in WIDTH ];
output ["objective = \(objective);\n"];
output ["xk = \(xk);\nyk = \(yk);\nxr = \(xr);\nyr = \(yr);\n"];
solve :: seq_search([int_search(support,input_order,indomain_min),
int_search([ if j = 1 then left[pk] else right[pk] endif | pk in PLANK, j in 1..2], input_order, indomain_min),
int_search([ if j = 1 then xr[pr] else yr[pr] endif | pr in PILLAR, j in 1..2], input_order, indomain_min),
int_search([ if j = 1 then xk[pk] else yk[pk] endif | pk in PLANK, j in 1..2], input_order, indomain_min)])
minimize objective;