[英]Minizinc modelling: Vars as coordinate sets
我正在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
这样我就可以使用内置功能
all_different
但是之后,我看到了如何强制集合具有基数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|];
注意:我使用Gecode和Git的最新MiniZinc版本在60毫秒(不是24分钟)内运行了第一个解决方案,从而运行了您的模型。 因此,以下内容可能对您没有帮助...
另外,我回答了您的原始问题,即如何对3D数组X( array[1..N, 1..3]
)使用all_different
。 我可能错过了您模型中的某些内容,但这是一个可以在9毫秒内解决可满足性问题的模型。
创建将点转换为整数的数组的想法: (X[I,1]-1)*N*N + (X[I,2]-1)*N + X[I,3]
(cf十进制数523是5 * 10 * 10 + 2 * 10 + 3)。 也许必须对此进行调整,但是您可以理解。 另外,我在注释中添加了另一种方法,该方法比较应该比X_eq
谓词更快的每对点。
请注意,如果生成的整数非常大(例如,对于大N),则此all_different
方法可能会很糟糕。
include "globals.mzn";
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..H,1..3] of 0..N:c;
array[1..N,1..3] of var -N..N: X;
solve satisfy;
% hakank: here's my approach of all_different
constraint
all_different([(X[i,1]-1)*N*N + (X[i,2]-1)*N + X[i,3] | i in 1..N])
%% another approach (slower than all_different)
%% for each pair: ensure that there is at least one coordinate differ
% forall(I in 1..N, J in 1..N where I < J) (
% sum([X[I,K] != X[J,K] | K in 1..3]) > 0
% )
;
% from original model
constraint
%H are in core
forall(i in 1..N)(
if (seq[i]=1) then exists(j in 1..H) (
X[i,1]=c[j,1] /\ X[i,2]=c[j,2] /\ X[i,3]=c[j,3]
)
else true endif
)
;
output
[
show([X[I,J] | J in 1..3]) ++ "\n"
| I in 1..N
]
;
c=[|0,0,0|
0,0,1|
0,0,2|
0,1,0|
0,1,1|
0,1,2|];
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.