You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Minizinc中实现带例外规则的6×6矩阵约束建模?

解决Minizinc中行/列唯一性例外的实现方案

核心思路:针对例外行/列单独约束,其余保持全唯一

对于"每行、每列所有值不同"的基础规则,无需修改全局约束逻辑,只需对存在例外的行/列单独定制约束,其他行/列直接使用all_different确保唯一性:

  • 无例外的行/列:直接用all_different约束所有值唯一
  • 有例外的行/列:明确指定例外数字的出现次数,同时约束其他数字最多出现1次

完整Minizinc模型实现

% 变量声明:6x6矩阵,行1-6对应题目行号,列1-6对应A-F(1=A,2=B,3=C,4=D,5=E,6=F)
array[1..6, 1..6] of var 1..9: grid;

% 规则1:1-9每个数字恰好出现4次
constraint forall(v in 1..9)(count(array1d(grid), v) = 4);

% 规则2:行或列中相邻单元格值不同
% 行内相邻单元格
constraint forall(r in 1..6, c in 1..5)(grid[r,c] != grid[r,c+1]);
% 列内相邻单元格
constraint forall(r in 1..5, c in 1..6)(grid[r,c] != grid[r+1,c]);

% 规则3:行的唯一性及例外处理
% 第1行:无例外,全唯一
constraint all_different(grid[1,..]);
% 第2行:恰好2个6,其余数字最多出现1次
constraint count(grid[2,..], 6) = 2;
constraint forall(v in 1..9 where v != 6)(count(grid[2,..], v) <= 1);
% 第3行:恰好2个3,其余数字最多出现1次
constraint count(grid[3,..], 3) = 2;
constraint forall(v in 1..9 where v != 3)(count(grid[3,..], v) <= 1);
% 第4行:恰好2个5,其余数字最多出现1次
constraint count(grid[4,..], 5) = 2;
constraint forall(v in 1..9 where v != 5)(count(grid[4,..], v) <= 1);
% 第5行:恰好3个7,其余数字最多出现1次
constraint count(grid[5,..], 7) = 3;
constraint forall(v in 1..9 where v != 7)(count(grid[5,..], v) <= 1);
% 第6行:恰好2个8,其余数字最多出现1次
constraint count(grid[6,..], 8) = 2;
constraint forall(v in 1..9 where v != 8)(count(grid[6,..], v) <= 1);

% 规则3:列的唯一性及例外处理
% 列A(第1列):无例外,全唯一
constraint all_different(grid[..,1]);
% 列B(第2列):恰好2个3,其余数字最多出现1次
constraint count(grid[..,2], 3) = 2;
constraint forall(v in 1..9 where v != 3)(count(grid[..,2], v) <= 1);
% 列C(第3列):无例外,全唯一
constraint all_different(grid[..,3]);
% 列D(第4列):恰好2个8,其余数字最多出现1次
constraint count(grid[..,4], 8) = 2;
constraint forall(v in 1..9 where v != 8)(count(grid[..,4], v) <= 1);
% 列E(第5列):无例外,全唯一
constraint all_different(grid[..,5]);
% 列F(第6列):恰好2个9,其余数字最多出现1次
constraint count(grid[..,6], 9) = 2;
constraint forall(v in 1..9 where v != 9)(count(grid[..,6], v) <= 1);

% 规则4:第1行数字之和≥38
constraint sum(grid[1,..]) >= 38;

% 规则5:列E(第5列)数字之和=21
constraint sum(grid[..,5]) = 21;

% 规则6:第2行不含1
constraint forall(c in 1..6)(grid[2,c] != 1);

% 规则7:第4行不含4
constraint forall(c in 1..6)(grid[4,c] != 4);

% 规则8:第5行不含2
constraint forall(c in 1..6)(grid[5,c] != 2);

% 规则9:第6行不含3
constraint forall(c in 1..6)(grid[6,c] != 3);

% 规则10:列C(第3列)不含2
constraint forall(r in 1..6)(grid[r,3] != 2);

% 规则11:列B(第2列)除两个3外,其余均为偶数
constraint forall(r in 1..6)(if grid[r,2] != 3 then grid[r,2] mod 2 == 0 else true endif);

% 规则12:列A(第1列)为升序或降序
constraint (forall(r in 1..5)(grid[r,1] < grid[r+1,1])) 
    \/ (forall(r in 1..5)(grid[r,1] > grid[r+1,1]));

% 求解目标
solve satisfy;

% 输出格式:按行输出,列对应A-F
output [
    "Row 1: ", show(grid[1,1]), " ", show(grid[1,2]), " ", show(grid[1,3]), " ", show(grid[1,4]), " ", show(grid[1,5]), " ", show(grid[1,6]), "\n",
    "Row 2: ", show(grid[2,1]), " ", show(grid[2,2]), " ", show(grid[2,3]), " ", show(grid[2,4]), " ", show(grid[2,5]), " ", show(grid[2,6]), "\n",
    "Row 3: ", show(grid[3,1]), " ", show(grid[3,2]), " ", show(grid[3,3]), " ", show(grid[3,4]), " ", show(grid[3,5]), " ", show(grid[3,6]), "\n",
    "Row 4: ", show(grid[4,1]), " ", show(grid[4,2]), " ", show(grid[4,3]), " ", show(grid[4,4]), " ", show(grid[4,5]), " ", show(grid[4,6]), "\n",
    "Row 5: ", show(grid[5,1]), " ", show(grid[5,2]), " ", show(grid[5,3]), " ", show(grid[5,4]), " ", show(grid[5,5]), " ", show(grid[5,6]), "\n",
    "Row 6: ", show(grid[6,1]), " ", show(grid[6,2]), " ", show(grid[6,3]), " ", show(grid[6,4]), " ", show(grid[6,5]), " ", show(grid[6,6]), "\n"
];

关键约束解释

  1. 例外行/列的约束逻辑:
    以第2行为例,先用count(grid[2,..], 6) = 2强制两个6的出现,再通过forall(v in 1..9 where v !=6)(count(grid[2,..],v) <=1)确保其他数字不会重复,既满足例外要求,又保证非例外数字的唯一性。
  2. 相邻单元格约束:
    分别遍历行内相邻列、列内相邻行,直接约束两个单元格值不等。
  3. 列B的偶数约束:
    通过条件判断实现:当单元格值不是3时,必须满足mod 2 == 0(偶数)。
  4. 列A的升降序约束:
    用逻辑或\/连接升序、降序两种情况,分别遍历相邻行判断大小关系。

内容的提问来源于stack exchange,提问作者Guenther

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 16:57:31