147 lines
4.0 KiB
MiniZinc
147 lines
4.0 KiB
MiniZinc
/***
|
|
!Test
|
|
expected:
|
|
- !Result
|
|
solution: !Solution
|
|
nvar: 2
|
|
partitions:
|
|
- !!set {1, 3}
|
|
- !!set {4}
|
|
- !!set {2, 6}
|
|
variables: [2, 3, 7, 1, 6, 0]
|
|
***/
|
|
|
|
% Another regression test for the problem described in var_self_assign_bug.mzn.
|
|
% (This model is from http://www.hakank.org/minizinc/cardinality_atmost_partition.mzn.)
|
|
|
|
% From Global Constraint Catalogue
|
|
% http://www.emn.fr/x-info/sdemasse/gccat/Ccardinality_atmost_partition.html
|
|
% """
|
|
% ATMOST is the maximum number of time that values of a same partition of
|
|
% PARTITIONS are taken by the variables of the collection VARIABLES.
|
|
%
|
|
% Example
|
|
% (
|
|
% 2, <2, 3, 7, 1, 6, 0>,
|
|
% <
|
|
% p-<1, 3>,
|
|
% p-<4>,
|
|
% p-<2, 6>
|
|
% >
|
|
% )
|
|
% In this example, two variables of the collection
|
|
% VARIABLES = <2, 3, 7, 1, 6, 0>
|
|
% are assigned to values of the first partition, no variable is assigned to
|
|
% a value of the second partition, and finally two variables are assigned to
|
|
% values of the last partition. As a consequence, the
|
|
% cardinality_atmost_partition constraint holds since its first argument
|
|
% ATMOST is assigned to the maximum number of occurrences 2.
|
|
|
|
%
|
|
% """
|
|
%
|
|
% Model created by Hakan Kjellerstrand, hakank@bonetmail.com
|
|
% See also my MiniZinc page: http://www.hakank.org/minizinc
|
|
|
|
include "globals.mzn";
|
|
|
|
|
|
int: n = 6;
|
|
int: m = 3;
|
|
array[1..n] of var 0..10: variables;
|
|
array[1..m] of var set of 1..7: partitions;
|
|
var 0..9: nvar;
|
|
|
|
output [
|
|
"nvar = ", show(nvar), ";\n",
|
|
"partitions = ", show(partitions), ";\n",
|
|
"variables = ", show(variables), ";\n"
|
|
];
|
|
|
|
solve satisfy;
|
|
|
|
% a variant of the partition_set from globals.mzn where universe is
|
|
% a var set of int (instead of par set of int)
|
|
predicate partition_set2(array[int] of var set of int: S,
|
|
var set of int: universe) =
|
|
all_disjoint(S) /\ universe == array_union(i in index_set(S)) ( S[i] )
|
|
;
|
|
|
|
|
|
%
|
|
% cardinality_atmost_exclude_value
|
|
%
|
|
% as cardinality_atmost but we exclude the "rest partition" index (m+1)
|
|
% (as a set for generality)
|
|
% (cf. cardinality_atmost.mzn)
|
|
%
|
|
predicate cardinality_atmost_exclude_value(var int: nvar, array[int] of var int: variables, array[int] of var int: values, var set of int: exclude) =
|
|
forall(i in index_set(values)) (
|
|
sum(j in index_set(variables)) (bool2int(not(values[i] in exclude) /\ values[i] = variables[j])) <= nvar
|
|
)
|
|
;
|
|
|
|
%
|
|
% cardinality_atmost_partition
|
|
%
|
|
% ("Unassigned" values are put in the m+1'th partition, the "rest partition,
|
|
% and we don't care how many that are assigned to the rest partition.)
|
|
%
|
|
predicate cardinality_atmost_partition(var int: nvar, array[int] of var int: variables, array[int] of var set of int: partitions) =
|
|
let {
|
|
int: lbv = min(index_set(variables)),
|
|
int: ubv = max(index_set(variables)),
|
|
int: lbp = min(index_set(partitions)),
|
|
int: ubp = max(index_set(partitions)),
|
|
array[lbv..ubv] of var lbp..ubp+1: selected_partition
|
|
}
|
|
in
|
|
|
|
% the partitions must be partitioned
|
|
partition_set2(partitions, array_union(i in lbp..ubp) (partitions[i]))
|
|
|
|
/\ % assign a partition index to each value
|
|
forall(i in lbv..ubv) (
|
|
forall(j in lbp..ubp) (
|
|
selected_partition[i] = j <-> variables[i] in partitions[j]
|
|
)
|
|
)
|
|
/\ % assure that we have atmost nvar occurrences of each partition index
|
|
% (except the "rest partition")
|
|
cardinality_atmost_exclude_value(nvar, selected_partition, selected_partition, {m+1})
|
|
;
|
|
|
|
predicate cp1d(array[int] of int: x, array[int] of var int: y) =
|
|
assert(index_set(x) = index_set(y),
|
|
"cp1d: x and y have different sizes",
|
|
forall(i in index_set(x)) (
|
|
x[i] = y[i]
|
|
)
|
|
)
|
|
;
|
|
|
|
predicate cp1d(array[int] of set of int: x, array[int] of var set of int: y) =
|
|
assert(index_set(x) = index_set(y),
|
|
"cp1d: x and y have different sizes",
|
|
forall(i in index_set(x)) (
|
|
x[i] = y[i]
|
|
)
|
|
)
|
|
;
|
|
|
|
|
|
constraint
|
|
|
|
cp1d([2, 3, 7, 1, 6, 0], variables)
|
|
/\
|
|
cp1d([
|
|
{1,3},
|
|
{4},
|
|
{2,6}], partitions)
|
|
/\
|
|
nvar = 2
|
|
/\
|
|
cardinality_atmost_partition(nvar, variables, partitions)
|
|
;
|
|
|