在矢量跳过对角线上映射上三角矩阵

时间:2014-10-16 10:40:08

标签: c++ matrix mapping minizinc gecode

我有一个问题可以归结为找到一种将三角矩阵映射到跳过对角线的矢量的方法。

基本上我需要使用Gecode库来翻译这个C ++代码

// implied constraints
for (int k=0, i=0; i<n-1; i++)
  for (int j=i+1; j<n; j++, k++)
    rel(*this, d[k], IRT_GQ, (j-i)*(j-i+1)/2);

进入这个MiniZinc(功能)代码

constraint
   forall ( i in 1..m-1 , j in i+1..m )
      ( (differences[?]) >=  (floor(int2float(( j-i )*( j-i+1 )) / int2float(2)) ));

我需要找出differences[?]中的索引。

MiniZinc是一种功能/数学语言,没有适当的循环。 因此,我必须映射那些触及所有且仅触及上三角矩阵的单元格的索引i和j,跳过其对角线,将k从0到任意数字的那些单元格中进行编号。

如果这是一个规则的三角矩阵(事实并非如此),那么解决方案like this就可以了

index = x + (y+1)*y/2

我正在处理的矩阵是一个方形n*n矩阵,索引从0到n-1,但为n*m矩阵提供更通用的解决方案会很好。

这是完整的Minizinc代码

% modified version of the file found at https://github.com/MiniZinc/minizinc-benchmarks/blob/master/golomb/golomb.mzn

include "alldifferent.mzn";

int: m;
int: n = m*m;
array[1..m] of var 0..n: mark;
array[int] of var 0..n: differences = [mark[j] - mark[i] | i in 1..m, j in i+1..m];

constraint mark[1] = 0;

constraint forall ( i in 1..m-1 ) ( mark[i] < mark[i+1] );

% this version of the constraint works
constraint forall ( i in 1..m-1 , j in i+1..m )
    ( (mark[j] - mark[i]) >= (floor(int2float(( j-i )*( j-i+1 )) / int2float(2))) );

%this version does not
%constraint forall ( i in 1..m-1, j in i+1..m )
%    ( (differences[(i-1) + ((j-2)*(j-1)) div 2]) >= (floor(int2float(( j-i )*( j-i+1 )) / int2float(2))) );

constraint alldifferent(differences);

constraint differences[1] < differences[(m*(m-1)) div 2];

solve :: int_search(mark, input_order, indomain, complete) minimize mark[m];

output ["golomb ", show(mark), "\n"];

感谢。

1 个答案:

答案 0 :(得分:4)

小心点。您从该链接找到的公式index = x + (y+1)*y/2包含对角线条目,用于下三角矩阵,我收集的是不是< / em>你想要什么。您正在寻找的确切公式实际上是index = x + ((y-1)y)/2 (见:https://math.stackexchange.com/questions/646117/how-to-find-a-function-mapping-matrix-indices)。

再次注意,我给你的这个公式假定你的指数:x,y,从零开始。您的MiniZinc代码使用索引i,j 从1开始(1&lt; = i&lt; = m),1&lt; = j&lt; = m))。对于从1开始的索引,公式为T(i,j) = i + ((j-2)(j-1))/2。所以你的代码应该是这样的:

constraint
   forall ( i in 1..m-1 , j in i+1..m )
      ((distances[(i + ((j-2)*(j-1)) div 2]) >= ...

请注意,(j-2)(j-1)将始终是2的倍数,因此我们可以使用除数2的整数除法(无需担心转换为浮点数/从浮点数转换)。


以上假设您使用的是方形m*m矩阵 要概括为M*N矩形矩阵,可以使用以下公式:

general formula

其中0 <= i&lt; M,0&lt; = j&lt; N [如果你再次,需要你的指数从1开始,用i-1替换i,用上面的公式中的j替换j]。这触及了上三角矩阵的所有单元以及侧面上的额外块[&#39;当N> 1时出现的正方形即,它触及所有单元(i,j),使得i <1。 j为0&lt; = i&lt; M,0&lt; = j&lt; N.

extra block on the side


完整代码:

% original: https://github.com/MiniZinc/minizinc-benchmarks/blob/master/golomb/golomb.mzn

include "alldifferent.mzn";

int: m;
int: n = m*m;
array[1..m] of var 0..n: mark;
array[1..(m*(m-1)) div 2] of var 0..n: differences;

constraint mark[1] = 0;
constraint forall ( i in 1..m-1 ) ( mark[i] < mark[i+1] );
constraint alldifferent(differences);
constraint forall (i,j in 1..m where j > i)
    (differences[i + ((j-1)*(j-2)) div 2] = mark[j] - mark[i]);
constraint forall (i,j in 1..m where j > i)
    (differences[i + ((j-1)*(j-2)) div 2] >= (floor(int2float(( j-i )*( j-i+1 )) / int2float(2))));
constraint differences[1] < differences[(m*(m-1)) div 2];

solve :: int_search(mark, input_order, indomain, complete)
    minimize mark[m];

output ["golomb ", show(mark), "\n"];

降低三角形版本(采用先前的代码并在必要时交换i和j):

% original: https://github.com/MiniZinc/minizinc-benchmarks/blob/master/golomb/golomb.mzn

include "alldifferent.mzn";

int: m;
int: n = m*m;
array[1..m] of var 0..n: mark;
array[1..(m*(m-1)) div 2] of var 0..n: differences;

constraint mark[1] = 0;
constraint forall ( i in 1..m-1 ) ( mark[i] < mark[i+1] );
constraint alldifferent(differences);
constraint forall (i,j in 1..m where i > j)
    (differences[j + ((i-1)*(i-2)) div 2] = mark[i] - mark[j]);
constraint forall (i,j in 1..m where i > j)
    (differences[j + ((i-1)*(i-2)) div 2] >= (floor(int2float(( i-j )*( i-j+1 )) / int2float(2))));
constraint differences[1] < differences[(m*(m-1)) div 2];

solve :: int_search(mark, input_order, indomain, complete)
    minimize mark[m];

output ["golomb ", show(mark), "\n"];