我正在对 minizinc 中的约束满足程序进行建模,其中解决方案是在 3D 网格上分配点。约束之一是只有一个点可以占据任何给定位置,因此这些点必须在至少一个坐标上成对不同。
我的点变量被建模为 NX 3 坐标数组:
array[1..N,1..3] of var -N..N: X;
并且差异约束是
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]);
但是当我像这样制定约束时,问题的解决时间会飞涨。我还有许多其他的约束要添加,而且它已经很慢地找到不同的点了。
我试图将这些点建模为
array[1..N] var set of -N..N
这样我就可以使用内置功能
不同的
但后来我看到了如何强制集合具有基数 3,而且使用通用大小的集合来建模三元组似乎不太自然。
我的问题是:对坐标集和所有不同的约束进行建模的易处理且“正确”的方法是什么?
我正在使用 minizinc IDE 包中的 gecode 求解器。模型如下所示。解题时间为 24 分钟。
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|];