git-subtree-dir: software/minizinc git-subtree-split: 4f10c82056ffcb1041d7ffef29d77a7eef92cf76
83 lines
2.3 KiB
MiniZinc
83 lines
2.3 KiB
MiniZinc
/***
|
|
!Test
|
|
expected:
|
|
- !Result
|
|
solution: !Solution
|
|
sokPosns: [14, 13, 8, 7, 8, 9, 4, 5, 10, 1, 1, 1]
|
|
stime: 9
|
|
***/
|
|
|
|
% Regression test for bug #335.
|
|
% Previous versions of CPX found this model to be unsatisfiable.
|
|
% A slightly later version found a solution but it was not optimal
|
|
% (stime = 11, rather than the optimal stime = 9.)
|
|
|
|
int: w; % width of board
|
|
int: n; % board positions 1, ..., w, w+1, ...., 2w, ...,
|
|
constraint assert(n mod w == 0, "board must be rectangular");
|
|
set of int: POS = 1..n;
|
|
int: stps; % max steps in solution
|
|
set of int: STEPS = 1..stps;
|
|
|
|
int: nw; % number of walls
|
|
set of int: WALLS = 1..nw;
|
|
array[WALLS] of POS: walls; % wall positions
|
|
int: nc; % number of crates + goals
|
|
set of int: CRATES = 1..nc;
|
|
set of POS: goals; % goal positions;
|
|
array[CRATES] of POS: crates; % initial crate positions
|
|
POS: pInit; % initial sokoban position
|
|
|
|
set of int: MOVES = {-w,-1,1,w}; % possible moves
|
|
|
|
include "alldifferent.mzn";
|
|
|
|
array[STEPS] of var POS: sokPosn; % sokoban position
|
|
array[STEPS] of var MOVES: move; % sokoban position
|
|
array[STEPS,CRATES] of var POS: cratePosns;
|
|
var STEPS: stime :: add_to_output; % time of solution
|
|
|
|
|
|
%% initial positions
|
|
constraint sokPosn[1] = pInit;
|
|
constraint forall(c in CRATES)(cratePosns[1,c] = crates[c]);
|
|
|
|
%% no overlap of crates, walls and sokoban
|
|
constraint forall(s in STEPS)(
|
|
alldifferent(walls ++ [sokPosn[s]] ++ [cratePosns[s,c] | c in CRATES])
|
|
);
|
|
|
|
%% at the end all crates are in a position
|
|
constraint forall(c in CRATES)(
|
|
cratePosns[stime,c] in goals
|
|
);
|
|
|
|
% legal move at each step
|
|
constraint forall(s in 1..stps-1)(
|
|
sokPosn[s+1] - sokPosn[s] = move[s]
|
|
);
|
|
|
|
% crate pushing
|
|
constraint forall(s in 1..stps-1, c in CRATES)(
|
|
cratePosns[s+1,c] = cratePosns[s,c] + bool2int(sokPosn[s+1] == cratePosns[s,c]) * move[s]
|
|
);
|
|
|
|
solve minimize stime;
|
|
|
|
% output for test case comparison
|
|
array[STEPS] of var POS: sokPosns :: add_to_output;
|
|
constraint forall (s in 1..stime) (sokPosns[s] = sokPosn[s]);
|
|
constraint forall (s in (stime+1)..stps) (sokPosns[s] = 1); % Just fill the rest with 1 for consistency
|
|
|
|
w = 5;
|
|
n = 15;
|
|
stps = 12;
|
|
|
|
nw = 0;
|
|
walls = [];
|
|
|
|
nc = 2;
|
|
crates = [7,9];
|
|
goals = {6,15};
|
|
pInit = 14;
|