简体   繁体   English

Minizinc建模:以Vars作为坐标集

[英]Minizinc modelling: Vars as coordinate sets

I am modelling a constraint satisfaction program in minizinc where the solution is an assignment of points on a 3D grid. 我正在minizinc中建模约束满足程序,其中解决方案是在3D网格上分配点。 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 NX 3 array of coordinates: 我的点变量建模为NX 3坐标数组:

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 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. 但是之后,我看到了如何强制集合具有基数3,并且使用通用大小的集合来建模整数的三元组似乎也不太自然。

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. 我正在使用minizinc IDE捆绑包中的gecode解算器。 The model is shown below. 该模型如下所示。 Solution time is 24 minutes. 解决时间为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|];  

Note: I ran your model as got the first solution in 60ms (not 24 minutes), using Gecode and the latest MiniZinc version from Git. 注意:我使用Gecode和Git的最新MiniZinc版本在60毫秒(不是24分钟)内运行了第一个解决方案,从而运行了您的模型。 So the stuff below might not help you... 因此,以下内容可能对您没有帮助...

Also, I answer your original problem, ie how to use all_different with the 3D array X ( array[1..N, 1..3] ). 另外,我回答了您的原始问题,即如何对3D数组X( array[1..N, 1..3] )使用all_different I might have missed something in your model, but here is a model that solves the satisfiability problem in 9ms. 我可能错过了您模型中的某些内容,但这是一个可以在9毫秒内解决可满足性问题的模型。

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). 创建将点转换为整数的数组的想法: (X[I,1]-1)*N*N + (X[I,2]-1)*N + X[I,3] (cf十进制数523是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. 另外,我在注释中添加了另一种方法,该方法比较应该比X_eq谓词更快的每对点。

Note that this all_different approach might be bad if the generated integers will be very large (eg for large N). 请注意,如果生成的整数非常大(例如,对于大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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM