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

353 lines
12 KiB
MiniZinc

%%% Inclusion of this file eliminates set variables by converting them into arrays of var bool.
% AUTHORS
% Guido Tack <guido.tack@monash.edu>
% Gleb Belov <gleb.belov@monash.edu>
%
predicate mzn_reverse_map_var(var set of int: x) = let {
array[int] of var bool: b = set2bools(x)
} in true;
function var set of int: reverse_map(array[int] of var bool: b);
function set of int: reverse_map(array[int] of bool: b) ::promise_total =
{ i | i in index_set(b) where b[i] };
array[int] of var bool: set2bools(var set of int: x) ::promise_total =
if is_fixed(x) then set2bools(fix(x)) else
let {
array[int] of var bool: b = array1d( min(ub(x))..max(ub(x)),
[ set2bools_bit( x, i ) | i in min(ub(x))..max(ub(x)) ] );
constraint (x = reverse_map(b)) :: is_reverse_map;
} in b
endif;
array[int] of var bool: set2bools(var set of int: x, set of int: ubx) ::promise_total =
if is_fixed(x) then set2bools(fix(x), ubx) else
let {
array[int] of var bool: b0 = set2bools( x ); %% Call in any case ?? TODO
array[int] of var bool: b = array1d( min(ubx)..max(ubx),
[ if i in ubx then set2bools_bit( x, i ) else false endif
| i in min(ubx)..max(ubx) ] );
%% Not again: constraint (x = reverse_map(b)) :: is_reverse_map;
} in b
endif;
array[int] of bool: set2bools(set of int: x) ::promise_total =
array1d(min(x)..max(x),[i in x | i in min(x)..max(x)]);
array[int] of bool: set2bools(set of int: x, set of int: ubx) ::promise_total =
array1d(min(ubx)..max(ubx),[i in x | i in min(ubx)..max(ubx)]);
function var bool: set2bools_bit( var set of int: x, int: i ) ::promise_total =
if i in ub(x) then
let {
var bool: bi;
} in bi
else false endif;
predicate set_eq(var set of int: x, var set of int: y) ::promise_total =
if not has_ub_set(x) /\ not has_ub_set(y) then
assert(false, "set_eq: cannot determine bounds of set variables")
elseif not has_ub_set(x) then set_eq(y,x)
else
let {
constraint y subset x, %% Constrain domains first
constraint x subset y,
} in let {
array[int] of var bool: bx = set2bools(x);
array[int] of var bool: by = set2bools(y);
} in forall (i in index_set(bx) union index_set(by)) (
if not (i in index_set(bx)) then not by[i] %% Should be impossible
elseif not (i in index_set(by)) then not bx[i]
else bx[i]=by[i] endif
)
endif;
predicate set_eq_reif(var set of int: x, var set of int: y, var bool: b) ::promise_total =
if is_fixed(b) then
if true==fix(b) then x==y else x!=y endif
else
let {
array[int] of var bool: bx = set2bools(x);
array[int] of var bool: by = set2bools(y);
} in b <-> forall (i in index_set(bx) union index_set(by)) (
if not (i in index_set(bx)) then not by[i]
elseif not (i in index_set(by)) then not bx[i]
else bx[i]=by[i] endif
)
endif;
predicate set_eq_imp(var set of int: x, var set of int: y, var bool: b) =
if is_fixed(b) then
if fix(b) then (x = y) else true endif
else
let {
array[int] of var bool: bx = set2bools(x);
array[int] of var bool: by = set2bools(y);
} in b -> forall (i in index_set(bx) union index_set(by)) (
if not (i in index_set(bx)) then not by[i]
elseif not (i in index_set(by)) then not bx[i]
else bx[i]=by[i] endif
)
endif;
predicate set_ne(var set of int: x, var set of int: y) ::promise_total =
let {
array[int] of var bool: bx = set2bools(x);
array[int] of var bool: by = set2bools(y);
} in exists (i in index_set(bx) union index_set(by)) (
if not (i in index_set(bx)) then by[i]
elseif not (i in index_set(by)) then bx[i]
else bx[i]!=by[i] endif
);
predicate set_ne_reif(var set of int: x, var set of int: y, var bool: b) ::promise_total =
set_eq_reif( x, y, not b );
predicate set_ne_imp(var set of int: x, var set of int: y, var bool: b) =
if is_fixed(b) then
if fix(b) then (x != y) else true endif
else
let {
array[int] of var bool: bx = set2bools(x);
array[int] of var bool: by = set2bools(y);
} in b -> exists (i in index_set(bx) union index_set(by)) (
if not (i in index_set(bx)) then by[i]
elseif not (i in index_set(by)) then bx[i]
else (bx[i] != by[i]) endif
)
endif;
% Set comparisons are often used just to avoid symmetries.
% Reifs/imps are done automatically from these templates
predicate set_le(var set of int: x, var set of int: y) ::promise_total =
let {
set of int: U = ub(x) union ub(y);
int: l = min(U);
int: u = max(U);
array[U] of var bool: xb = [i in x | i in U];
var l-1..u: xmax = max(x union {l-1});
array[U] of var bool: yb = [i in y | i in U];
var l-1..u: ymax = max(y union {l-1});
array[U] of var bool: b;
constraint forall(i in l..u-1) (
b[i] = let {var 1..4: cmp = 2*xb[i] + yb[i] + 1} in
[b[i+1], xmax < i, ymax > i, b[i+1]][cmp]
);
constraint b[u] = (xb[u] -> yb[u]);
} in b[l];
predicate set_lt(var set of int: x, var set of int: y) ::promise_total =
let {
set of int: U = ub(x) union ub(y);
int: l = min(U);
int: u = max(U);
array[U] of var bool: xb = [i in x | i in U];
var l-1..u: xmax = max(x union {l-1});
array[U] of var bool: yb = [i in y | i in U];
var l-1..u: ymax = max(y union {l-1});
array[U] of var bool: b;
constraint forall(i in l..u-1) (
b[i] = let {var 1..4: cmp = 2*xb[i] + yb[i] + 1} in
[b[i+1], xmax < i, ymax > i, b[i+1]][cmp]
);
constraint b[u] = (not xb[u] /\ yb[u]);
} in b[l];
predicate set_subset(var set of int: x, var set of int: y) ::promise_total =
let {
array[int] of var bool: bx = set2bools(x);
array[int] of var bool: by = set2bools(y);
} in forall (i in index_set(bx)) (
if not (i in index_set(by)) then not bx[i]
else bx[i] -> by[i] endif
);
predicate set_subset_reif(var set of int: x, var set of int: y, var bool: b) ::promise_total =
let {
array[int] of var bool: bx = set2bools(x);
array[int] of var bool: by = set2bools(y);
} in b <-> forall (i in index_set(bx)) (
if not (i in index_set(by)) then not bx[i]
else bx[i] -> by[i] endif
);
predicate set_subset_imp(var set of int: x, var set of int: y, var bool: b) =
let {
array[int] of var bool: bx = set2bools(x);
array[int] of var bool: by = set2bools(y);
} in b -> forall (i in index_set(bx)) (
if not (i in index_set(by)) then not bx[i]
else bx[i] -> by[i] endif
);
%%% Map the subset operation to superset
predicate set_superset(var set of int: x, var set of int: y) ::promise_total = set_subset( y, x );
predicate set_superset_reif(var set of int: x, var set of int: y, var bool: b) ::promise_total =
set_subset_reif( y, x, b );
predicate set_superset_imp(var set of int: x, var set of int: y, var bool: b) =
set_subset_imp(y,x,b);
function var set of int: set_intersect(var set of int: x, var set of int: y) ::promise_total =
let {
array[int] of var bool: bx = set2bools(x);
array[int] of var bool: by = set2bools(y);
var set of (index_set(bx) intersect index_set(by)): z;
array[int] of var bool: bz = set2bools(z);
constraint forall (i in index_set(bz)) (
bz[i] = (bx[i] /\ by[i])
);
} in z;
function var set of int: set_union(var set of int: x, var set of int: y) ::promise_total =
let {
array[int] of var bool: bx = set2bools(x);
array[int] of var bool: by = set2bools(y);
var set of (index_set(bx) union index_set(by)): z;
array[int] of var bool: bz = set2bools(z);
constraint forall (i in index_set(bx) union index_set(by)) (
if (i in index_set(bx)) then
if (i in index_set(by)) then
bz[i] = (bx[i] \/ by[i])
else
bz[i] = bx[i]
endif
else
bz[i] = by[i]
endif
);
} in z;
function var set of int: set_diff(var set of int: x, var set of int: y) ::promise_total =
let {
array[int] of var bool: bx = set2bools(x);
array[int] of var bool: by = set2bools(y);
var set of ub(x) diff lb(y): z;
array[int] of var bool: bz = set2bools(z);
constraint forall (i in ub(z)) (
bz[i] = (bx[i] /\ (not by[i]))
);
} in z;
function var set of int: set_symdiff(var set of int: x, var set of int: y) ::promise_total =
let {
array[int] of var bool: bx = set2bools(x);
array[int] of var bool: by = set2bools(y);
var set of (ub(x) diff lb(y)) union (ub(y) diff lb(x)): z;
array[int] of var bool: bz = set2bools(z);
constraint forall (i in ub(z)) (
bz[i] = (bx[i] xor by[i])
);
} in z;
function var int: card(var set of int: x) ::promise_total =
let {
array[int] of var bool: bx = set2bools(x);
var 0..length(bx) : c;
constraint bool_lin_eq([1 | i in index_set(bx)],[bx[i] | i in index_set(bx)],c);
} in c;
predicate set_in(int: x, var set of int: y) ::promise_total =
let {
array[int] of var bool: by = set2bools(y);
} in by[x];
predicate set_in(var int: x, var set of int: y) ::promise_total =
let {
array[int] of var bool: by = set2bools(y);
} in by[x];
predicate set_in_reif(int: x, var set of int: y, var bool: b) ::promise_total =
if x in ub(y) then
b <-> set2bools(y)[x]
else
not b
endif;
predicate set_in_reif(var int: x, var set of int: y, var bool: b) ::promise_total =
b <-> set2bools(y)[x];
predicate set_in_imp(var int: x, var set of int: y, var bool: b) =
b -> set2bools(y)[x];
function array[int] of var bool: setarray2bools(array[int] of var set of int: x) =
if length(x)=0 then [] else
set2bools(x[1])++setarray2bools([x[i]|i in 2..length(x)])
endif;
%% Par version no sense
predicate array_var_set_element(var int: x, array[int] of var set of int: y, var set of int: z) ::promise_total =
let {
constraint x in { i | i in index_set( y ) where
lb(y[i]) subset ub(z) /\ lb(z) subset ub(y[i])
};
set of int: sUB = array_union( [ ub(y[i]) | i in dom(x) ] );
set of int: sLB = array_intersect( [ lb(y[i]) | i in dom(x) ] );
constraint z subset sUB,
constraint sLB subset z,
} in
forall (k in ub(z)) (
set2bools(z)[k] ==
if k in sUB then
if k in sLB then
true
else
array1d( lb(x)..ub(x),
[ if k in ub(y[i]) then set2bools(y[i])[k] else false endif | i in dom(x) ] )[x]
endif
else
false
endif
) /\
forall (k in sUB diff ub(z))(
if k in sLB then
false %% fail the constraint
else
not array1d( lb(x)..ub(x),
[ if k in ub(y[i]) then set2bools(y[i])[k] else false endif | i in dom(x) ] )[x]
endif
);
predicate array_set_element(var int: x, array[int] of set of int: y, var set of int: z) ::promise_total =
let {
constraint x in { i | i in index_set( y ) where
y[i] subset ub(z) /\ lb(z) subset y[i]
};
set of int: sUB = array_union( [ y[i] | i in dom(x) ] );
set of int: sLB = array_intersect( [ y[i] | i in dom(x) ] );
constraint z subset sUB,
constraint sLB subset z,
} in
forall (k in ub(z)) (
set2bools(z)[k] ==
if k in sUB then
if k in sLB then
true
else
array1d( lb(x)..ub(x),
[ if k in ub(y[i]) then set2bools(y[i])[k] else false endif | i in dom(x) ] )[x]
endif
else
false
endif
) /\
forall (k in sUB diff ub(z))(
if k in sLB then
false %% fail the constraint
else
not array1d( lb(x)..ub(x),
[ if k in ub(y[i]) then set2bools(y[i])[k] else false endif | i in dom(x) ] )[x]
endif
);
annotation set_search(array[$X] of var set of int: x, ann: a1, ann: a2, ann: a3) =
let { array[int] of var set of int: xx = array1d(x) } in
seq_search( [ bool_search(set2bools(xx[i]),a1,a2,a3) | i in index_set(xx) ] );
annotation warm_start( array[int] of var set of int: x, array[int] of set of int: v ) =
warm_start_array( [
let {
array[int] of var bool: xb = set2bools(x[i]),
set of int: is_var = ub(x[i]) diff lb(x[i]),
int: iV = i - min(index_set(x)) + if 0<length(v) then min(index_set(v)) else 0 endif,
} in
warm_start( [ xb[k] | k in is_var ],
if iV in index_set(v) then [ k in v[iV] | k in is_var ] else [] endif )
| i in index_set(x) ] ); %% ignoring v[i] diff ub(x[i]) and lb(x[i]) diff v[i]