Minizinc建模:Vars作为坐标集

时间:2017-03-30 09:26:54

标签: constraint-programming minizinc

我正在建模minizinc中的约束满足程序,其中解决方案是3D网格上的点的分配。其中一个限制是只有一个点可以占据任何给定的位置,因此这些点必须在它们的至少一个坐标中成对地不同。

我的点变量被建模为N X 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|];  

1 个答案:

答案 0 :(得分:1)

Note: I ran your model as got the first solution in 60ms (not 24 minutes), using Gecode and the latest MiniZinc version from Git. So the stuff below might not help you...

Also, I answer your original problem, i.e. how to use all_different with the 3D array X (array[1..N, 1..3]). I might have missed something in your model, but here is a model that solves the satisfiability problem in 9ms.

The idea to create an array that converts a point to an integer: (X[I,1]-1)*N*N + (X[I,2]-1)*N + X[I,3] (cf the decimal number 523 is 5*10*10 + 2*10 + 3). Perhaps this must be adjusted, but you get the general idea. Also, I added - in a comment - another approach that compares each pairs of points that should be faster than your X_eq predicate.

Note that this all_different approach might be bad if the generated integers will be very large (e.g. for large N).

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|];