I am modelling a constraint satisfaction program in minizinc where the solution is an assignment of points on a 3D grid. One of the constraints is that only one point can occupy any given position, so the points must be pairwise different in at least one of their coordinates.
My point variables are modelled as an N X 3 array of coordinates:
array[1..N,1..3] of var -N..N: X;
And the difference constraint is
constraint forall(i in 1..N-1)(forall(j in i+1..N)(not X_eq(i,j))); %extremely slow
predicate X_eq(int: a, int: b)=
(X[a,1]=X[b,1]/\X[a,2]=X[b,2]/\X[a,3]=X[b,3]);
But the solution time for the problem skyrockets when I formulate the constraint like this. I have many other constraints to be added and its already way to slow to just find points that are different.
I tried to instead model the points as
array[1..N] var set of -N..N
So that I could use the built-in function
all_different
But then I see how to enforce sets to have cardinality 3, and also it seems less natural to use the generic sized sets to model a triplet of ints.
My question is: What is a tractable and 'correct' way to model a coordinate set and the all-different constraint?
I am using the gecode solver that comes in the minizinc IDE bundle. The model is shown below. Solution time is 24 minutes.
array[1..N] of 0..1: seq=[1,1,0,0,0,0,0,1,1,0,0,0,1,0,0,0,1,0];
int: N=18;
int: H=6;
array[1..N,1..3] of var -N..N: X;
array [1..H,1..3] of 0..N:c;
%H are in core
constraint forall(i in 1..N)( if (seq[i]=1) then exists(j in 1..H)([i,1]=c[j,1] /\ X[i,2]=c[j,2] /\ X[i,3]=c[j,3] ) else true endif);
%All points different
constraint forall(i in 1..N-1)(forall(j in i+1..N)(not X_eq(i,j))); %extremely slow
predicate X_eq(int: a, int: b)=
(X[a,1]=X[b,1]/\X[a,2]=X[b,2]/\X[a,3]=X[b,3]);
solve satisfy;
output[show(X[i,j]) ++ " "|i in 1..N,j in 1..3]++["\n"];
c=[|0,0,0|
0,0,1|
0,0,2|
0,1,0|
0,1,1|
0,1,2|];