git-subtree-dir: software/mza git-subtree-split: f970a59b177c13ca3dd8aaef8cc6681d83b7e813
110 lines
3.6 KiB
MiniZinc
110 lines
3.6 KiB
MiniZinc
%-----------------------------------------------------------------------------%
|
|
% A table constraint table(x, t) represents the constraint x in t where we
|
|
% consider each row in t to be a tuple and t as a set of tuples.
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
% Reified version
|
|
%
|
|
% We only support special cases of a few variables.
|
|
%
|
|
% The approach is to add the Boolean variable to the list of variables and
|
|
% create an extended table. The extended table covers all combinations of
|
|
% assignments to the original variables, and every entry in it is padded with a
|
|
% value that depends on whether that entry occurs in the original table.
|
|
%
|
|
% For example, the original table constraint
|
|
%
|
|
% x y
|
|
% ---
|
|
% 2 3
|
|
% 5 8
|
|
% 4 1
|
|
%
|
|
% reified with a Boolean b is turned into a table constraint of the form
|
|
%
|
|
% x y b
|
|
% ---------
|
|
% 2 3 true
|
|
% 5 8 true
|
|
% 4 1 true
|
|
% ... false
|
|
% ... false % for all other pairs (x,y)
|
|
% ... false
|
|
%
|
|
|
|
predicate fzn_table_int_reif(array[int] of var int: x,
|
|
array[int, int] of int: t,
|
|
var bool: b) =
|
|
|
|
let { int: n_vars = length(x) }
|
|
in
|
|
|
|
assert(n_vars in 1..5,
|
|
"'table' constraints in a reified context " ++
|
|
"are only supported for 1..5 variables.",
|
|
|
|
if n_vars = 1 then
|
|
|
|
x[1] in { t[it,1] | it in index_set_1of2(t) } <-> b
|
|
|
|
else
|
|
|
|
let { set of int: ix = index_set(x),
|
|
set of int: full_size = 1..product(i in ix)( dom_size(x[i]) ),
|
|
array[full_size, 1..n_vars + 1] of int: t_b =
|
|
array2d(full_size, 1..n_vars + 1,
|
|
|
|
if n_vars = 2 then
|
|
|
|
[ let { array[ix] of int: tpl = [i1,i2] } in
|
|
(tpl ++ [bool2int(aux_is_in_table(tpl,t))])[p]
|
|
| i1 in dom(x[1]),
|
|
i2 in dom(x[2]),
|
|
p in 1..n_vars + 1 ]
|
|
|
|
else if n_vars = 3 then
|
|
|
|
[ let { array[ix] of int: tpl = [i1,i2,i3] } in
|
|
(tpl ++ [bool2int(aux_is_in_table(tpl,t))])[p]
|
|
| i1 in dom(x[1]),
|
|
i2 in dom(x[2]),
|
|
i3 in dom(x[3]),
|
|
p in 1..n_vars + 1 ]
|
|
|
|
else if n_vars = 4 then
|
|
|
|
[ let { array[ix] of int: tpl = [i1,i2,i3,i4] }
|
|
in
|
|
(tpl ++ [bool2int(aux_is_in_table(tpl,t))])[p]
|
|
| i1 in dom(x[1]),
|
|
i2 in dom(x[2]),
|
|
i3 in dom(x[3]),
|
|
i4 in dom(x[4]),
|
|
p in 1..n_vars + 1 ]
|
|
|
|
else % if n_vars = 5 then
|
|
|
|
[ let { array[ix] of int: tpl = [i1,i2,i3,i4,i5] } in
|
|
(tpl ++ [bool2int(aux_is_in_table(tpl,t))])[p]
|
|
| i1 in dom(x[1]),
|
|
i2 in dom(x[2]),
|
|
i3 in dom(x[3]),
|
|
i4 in dom(x[4]),
|
|
i5 in dom(x[5]),
|
|
p in 1..n_vars + 1 ]
|
|
|
|
endif endif endif ) }
|
|
in
|
|
fzn_table_int(x ++ [bool2int(b)], t_b)
|
|
|
|
endif
|
|
);
|
|
|
|
test aux_is_in_table(array[int] of int: e, array[int, int] of int: t) =
|
|
exists(i in index_set_1of2(t))(
|
|
forall(j in index_set(e))( t[i,j] = e[j] )
|
|
);
|
|
|
|
%-----------------------------------------------------------------------------%
|