Minizinc:给定结果数组,确保具有匹配值的索引也根据附加值匹配

Minizinc: given array of results, ensure indexes with matching value also match according to an additional value

下面 1..13 位置模型的随机 1..7 选项产生示例输出

[3,2,2,3,6,7,1,4,2,4,5,2,3]

我想对其进行约束,以便如果值相同,则另一个关联参数数组中声明的另一个值也必须匹配。

set of int: optA = 1..7;
set of int: position = 1..13;
enum optB = {A,B,C,D};

array[position] of optB: opts = [A,A,A,B,B,B,B,C,C,C,D,D,D];
array[position] of var optA: result;

constraint forall(i in positions)(
  forall(j in optA)(
    % NO IDEA HOW TO FORMULATE EQUALITY HERE, IF THIS IS EVEN THE RIGHT IDEA
  )
);

换句话说,如果result[1]result[3]result[8]result[9]分别从optA中分配了一个4,并且第二个约束查看它们是否具有来自 optB 的匹配值,在本例中它们没有,因此结果无效。

A,A,A 中的任何一个都不能与 C,C,C 中的任何一个具有相同的 optA 值,而在它们的集合中,它们可以相同或不同。

因此,有了这个额外的约束,一个有效的解决方案可能是

[1,2,2, 3,3,4,4, 5,5,5, 6,6,7]

这可能是您想要的解决方案。我理解这一点,因为 As 是一个可以取任何值的块(集合),但不能取 BCD 块中的值.

这里的方法是简单地检查if opts[i] != opts[j] then result[i] != result[j]。这就是你想要的?

set of int: optA = 1..7;
set of int: position = 1..13;
enum optB = {A,B,C,D};

array[position] of optB: opts = [A,A,A,B,B,B,B,C,C,C,D,D,D];
array[position] of var optA: result;

constraint
   % ensure that the "chunks" are different
   forall(i,j in position where i < j) (
      if opts[i] != opts[j] then
         result[i] != result[j]
       else
         true
       endif
   )
;
solve satisfy;

output [
"result: \(result)\n",
];

有很多解(即2102520个解)。以下是其中一些:

result: [3, 3, 3, 4, 4, 4, 4, 2, 2, 2, 1, 1, 1]
----------
result: [3, 3, 3, 5, 4, 4, 4, 2, 2, 2, 1, 1, 1]
----------
result: [3, 3, 3, 6, 4, 4, 4, 2, 2, 2, 1, 1, 1]
----------
result: [3, 3, 3, 7, 4, 4, 4, 2, 2, 2, 1, 1, 1]
----------
result: [3, 3, 3, 4, 5, 4, 4, 2, 2, 2, 1, 1, 1]
----------