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

问题描述

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

[3,2,3,6,7,1,4,5,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,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] 都被分配了一个来自 4optA,以及第二个约束查看它们是否具有来自 optB 的匹配值,在这种情况下它们没有,因此结果无效。

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

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

[1,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,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,4,2,1,1]
----------
result: [3,5,6,7,1]
----------