50 lines
1.8 KiB
MiniZinc
50 lines
1.8 KiB
MiniZinc
int: n;
|
|
set of int: PERSON = 1..n;
|
|
enum GENDER = { M, F, O };
|
|
array[PERSON] of GENDER: g;
|
|
set of int: POSN = 1..n;
|
|
array[int] of int: pos;
|
|
|
|
array[POSN] of var PERSON: who;
|
|
int: _objective;
|
|
|
|
test alldifferent(array[int] of int: x) =
|
|
forall(i,j in index_set(x) where i < j)(x[i] != x[j]);
|
|
|
|
include "inverse.mzn";
|
|
constraint if alldifferent(pos) then inverse(pos,who)
|
|
else forall(i in 1..n)(who[i] = 1) endif;
|
|
|
|
output [if
|
|
check_array(pos, n, POSN, "pos") /\
|
|
check_alldifferent(pos,"pos") /\
|
|
check_array(fix(pos), n, PERSON, "who") /\
|
|
forall(i in 1..n-2)
|
|
(check(g[fix(who[i])] != g[fix(who[i+1])] \/
|
|
g[fix(who[i+1])] != g[fix(who[i+2])],
|
|
"three people of the same gender \(g[fix(who[i])]) in positions \(i)..\(i+2)\n")) /\
|
|
let { int: obj = sum(i in 1..n-1)(abs(pos[i] - pos[i+1])); } in
|
|
check(obj = _objective, "calculated objective \(obj) does not agree with objective from the model (\(_objective))\n")
|
|
then
|
|
"CORRECT: All constraints hold"
|
|
else
|
|
"INCORRECT"
|
|
endif];
|
|
|
|
test check(bool: b,string: s) =
|
|
if b then true else trace_stdout("ERROR: "++s++"\n",false) endif;
|
|
|
|
test check_alldifferent(array[int] of int: x, string: name) =
|
|
forall(i, j in index_set(x) where i < j)
|
|
(check(x[i] != x[j], name ++ "[\(i)] = \(x[i]) = " ++
|
|
name ++ "[\(j)] " ++
|
|
"when they should be different\n"));
|
|
|
|
test check_int(int: x, set of int: vals, string: name) =
|
|
check(x in vals, "integer \(name) is not in values \(vals)\n");
|
|
|
|
function bool: check_array(array[int] of int: x, int: length, set of int: vals, string: name) =
|
|
check(length(x) = length, "array \(name) is not of length \(length)\n") /\
|
|
forall(i in index_set(x))
|
|
(check(x[i] in vals, "element \(i) of array \(name), \(x[i]) is not in values \(vals)\n"));
|