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"));