相似的MiniZinc约束之间的区别

时间:2020-07-01 06:52:30

标签: minizinc

在斑马拼图(http://rosettacode.org/wiki/Zebra_puzzle#MiniZinc)的解决方案中,有一个约束条件规定其中一只宠物必须是斑马:

var 1..5: n;
constraint Gz[n]=Zebra; 

下面的表达式是否具有其他含义?它们产生不同的结果。

constraint exists(n in 1..5)(Gz[n]=Zebra);

2 个答案:

答案 0 :(得分:3)

这些约束确实是等效的。但是,MiniZinc将这些约束转换为求解器的方式有所不同。

第一个选项将被转换为元素约束:

var 1..5: n;
constraint array_int_element(n, Gz, Zebra);

第二个将导致大子句约束:

constraint bool_clause([Gz[1]=Zebra, Gz[2]=Zebra, Gz[3]=Zebra, Gz[3]=Zebra, Gz[5]=Zebra], [])

尽管约束条件是等效的,但它可能取决于求解器,在求解过程中哪种形式会更有效。

更好的方法是使用全局count_leq(array [int] of var int: x, int: y, int: c),该全局变量强制c小于或等于yx的出现次数。将约束表示为:

include "count_leq.mzn";
constraint count_leq(Gz, Zebra, 1);

直接传达约束的含义,并允许所使用的求解器使用最适合其求解机制的任何形式的约束

答案 1 :(得分:2)

如果删除了声明var 1..5: n,则n部分中没有可以使用的全局output,这将产生错误:MiniZinc: type error: undefined identifier n '`。

如果您保留var 1..5: n,则n循环中的变量exists对全局定义的变量n无效,结果是(全局)n将采用任何值1..5(如果打印了所有解决方案,则会显示该值)。