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.
Jip J. Dekker f2a1c4e389 Squashed 'software/mza/' content from commit f970a59b17
git-subtree-dir: software/mza
git-subtree-split: f970a59b177c13ca3dd8aaef8cc6681d83b7e813
2021-07-11 16:34:30 +10:00

121 lines
2.9 KiB
Plaintext

% blocksworld_model.mzn
% vim: ft=zinc ts=4 sw=4 et tw=0
%
% A state-based blocks-world model.
include "globals.mzn";
% Instance parameter: the number of steps to consider in the plan.
%
int: n_steps;
set of int: steps = 1..n_steps;
% The last step.
%
int: end = n_steps;
% Instance parameter: the number of blocks in the problem.
%
int: n_blocks;
set of int: blocks = 1..n_blocks;
% Block 0 denotes the table, which has enough space for all the blocks.
%
int: Table = 0;
set of int: table_or_blocks = {Table} union blocks;
% Instance parameter: the starting locations of blocks in the problem.
%
array [blocks] of table_or_blocks: initial_loc;
% Instance parameter: the finishing locations of blocks in the problem.
%
array [blocks] of table_or_blocks: final_loc;
% If a block has a negative location then it's on the table.
% Block a has its own "free" spot on the table at location -a.
%
set of int: locs = -n_blocks..n_blocks;
% Decision variables: block locations at each step.
%
array [steps, blocks] of var locs: on;
% Constrain the starting state.
%
constraint
forall (b in blocks) (
if initial_loc[b] = Table then
on[1, b] = -b
else
on[1, b] = initial_loc[b]
endif
);
% Constrain the goal state.
%
constraint
forall (b in blocks) (
if final_loc[b] = Table then
on[end, b] = -b
else
on[end, b] = final_loc[b]
endif
);
% Ensure each block cannot be put in the wrong place on the table
% (this simplifies the model and allows us to use alldifferent below)
% or on itself.
%
constraint
forall (b in blocks, s in steps) (
on[s, b] in {c | c in blocks where c != b} union {-b}
);
% No two blocks can occupy the same location at the same time.
%
constraint
forall (s in steps) (alldifferent (b in blocks) (on[s, b]));
% A clear block is one that has no other block on top of it.
% The table is always clear.
%
predicate clear(steps: s, var locs: l) =
l < 0 \/ forall (b in blocks) (on[s, b] != l);
% If a block moves then it must (a) be clear and (b) its destination
% must be clear.
%
constraint
forall (s in steps, b in blocks where s < n_steps) (
on[s, b] != on[s + 1, b]
->
( clear(s, b)
/\ clear(s, on[s + 1, b])
)
);
solve :: int_search(
[on[s, b] | s in steps, b in blocks],
first_fail,
indomain_split,
complete
)
satisfy;
output
[ "[Negative locations denote the table.]\n"
] ++
[ if b = 1 then
"Step " ++ show(s) ++ ":\n"
else
""
endif ++
" block " ++ show(b) ++ " on " ++ show(on[s, b]) ++ "\n"
| s in 1..n_steps, b in 1..n_blocks
];