我试图在Minizinc中解决这个问题,取自Puzzle taken from Gardner:
编号为0,...,9的十个单元格分别标记一个10位数字 cell,比如i,表示数字i的总出现次数 在这个数字。找到这个号码。答案是6210001000。
我解决了它,代码在Gecode上运行良好:
int: n=9;
set of int: N=0..n;
array[N] of var N: cell;
include "globals.mzn";
constraint global_cardinality(cell, N, cell);
solve satisfy;
output [show(cell), "\n", show(index_set(cell)), " -- ", show(index_set(N))];
Gecode的输出:
[6, 2, 1, 0, 0, 0, 1, 0, 0, 0]
0..9 -- 1..10
----------
==========
然而,G12求解器抱怨global_cardinality中的断言失败:
在电话'断言'断言失败:global_cardinality:封面和 计数必须具有相同的索引集
是的,正如Gecode的输出所示,N是1..10,单元格是0..9。所以我的问题是:
答案 0 :(得分:1)
问题是你在0上启动数组。虽然在技术上这是正确的,但是首选并建议将数组启动为1(MiniZinc中的标准)。正如您所看到的,仍然有一些求解器不完全支持不从1开始的数组。还有一些错误连接到使用不从0开始的数组。
我在g12cpx上遇到的错误与你修改的数据相同,只是将数组修改为
array[1..10] of var N: cell;
给了我正确的结果。
答案 1 :(得分:1)
您可以通过添加array1d()来解决此问题:
global_cardinality(cell,array1d(0..n,[i | i in N]), cell);
Gecode工作但不是G12 / fd的原因是,Gecode有自己的MiniZinc约束定义,不包括基数检查。