主要内容

通过整数编程解决Sudoku难题:基于问题

这个例子说明了如何解决使用二进制整数规划一道数独题。对于基于求解的方法,请参阅通过整数编程解决Sudoku难题:基于求解器

你可能已经看到了数独谜题。拼图是填充一个9×9网格,其中整数从1到9填充,以便每个整数只出现一次,每个行,列和主要的3×3平方。网格部分地填充了线索,您的任务是填写其余的网格。

初始拼图

这里是一个数据矩阵B.的线索。第一行,B(1,2,2),手段行1,列2具有线索2.第二行,B(1,5,3),表示第1行,第5列具有线索3.这是整个矩阵B.

B = [1,2,2;1,5,3;1,8,4;2,1,6;2,9,3;3,3,4;3,7,5;-4,4,8-;4,6,6;5,1,8; 5,5,1; 5,9,6; 6,4,7; 6,6,5; 7,3,7; 7,7,6; 8,1,4; 8,9,8; 9,2,3; 9,5,4; 9,8,2]; drawSudoku(B)此程序列表的%,请参阅此示例的结尾。

这个难题,并替代MATLAB®解决方案技术,是精选克利夫园地2009年。

有许多方法可以手动解决数独谜题,以及许多程序化方法。此示例显示了使用二进制整数编程的直接方法。

这种方法特别简单,因为您没有提供解决方案算法。只需表达Sudoku规则,将线索表达为解决方案的约束,然后Matlab产生解决方案。

二进制整数规划法

关键思想是从正方形9乘9网格变换一个谜于立方9乘9乘9阵列的二进制值(0或1)的。立方阵列的认为为是彼此堆叠的,其中每一层对应于从整数1到9的顶格,所述阵列的正方形层,具有1的顶部9个方格哪里溶液或线索具有1.第二层具有1哪里溶液或线索具有2第九层具有1哪里溶液或线索具有9。

这一提法正是适合二进制整数规划。

这里不需要目标函数,也可能是恒定的术语0.问题实际上只是为了找到一个可行的解决方案,这意味着满足所有约束的解决方案。然而,对于在整数编程求解器的内部构建中断,引起溶液速度增加,使用不限于的目标函数。

表达对数独的规则约束

假设一个解决方案 X. 在一个9×9×9阵列的二进制表示。什么样的属性呢 X. 有吗?首先,2-D网格(I,j)中的每个方块都有一个值,因此三维数组条目中的一个非零元素恰好 X. j 1 X. j 9. 。换句话说,每一个 j

σ. K. = 1 9. X. j K. = 1

同样,每排 在2-D网格中,从1到9的每个数字中的每个值恰好换句话说,每个数字 K.

σ. j = 1 9. X. j K. = 1

每列 j 在2 d网格具有相同的属性:对于每个 j K.

σ. = 1 9. X. j K. = 1

主要的3×3电网具有类似的约束。对于网格元素 1 ≤. ≤. 3. 1 ≤. j ≤. 3. ,并为每个 1 ≤. K. ≤. 9.

σ. = 1 3. σ. j = 1 3. X. j K. = 1

代表所有九个主要网格,只需向每个九个主要网格添加3或6 j 索引:

σ. = 1 3. σ. j = 1 3. X. + j + V. K. = 1 在哪里 V. ε. { 0. 3. 6. }

表达线索

每个初始值(线索)可以表示为约束。假设这一点 j 线索 m 对于某些人 1 ≤. m ≤. 9. 。然后 X. j m = 1 。约束 σ. K. = 1 9. X. j K. = 1 确保所有其他人 X. j K. = 0. 对于 K. m

数独在优化问题表

创建一个优化变量X.即二进制和大小9×9×9的。

X = optimvar('x',9,9,9,'类型''整数'“下界”,0,“上界”,1);

有相当任意的目标函数创建一个优化问题。目标函数可以通过破坏问题的内在对称性帮助求解。

sudpuzzle = optimproblem;MUL =酮(1,1,9);MUL = cumsum(MUL,3);sudpuzzle.Objective =总和(求和(总和(X,1),2)* MUL);

代表总和的约束X.在每个坐标方向上是一个。

sudpulzle.constraints.consx = sum(x,1)== 1;sudpulzle.constraints.consy = sum(x,2)== 1;sudpuzzle.constraints.consz = sum(x,3)== 1;

创建大网格和一个概率的约束。

majorg = optimconstr(3,3,9);对于U = 1:3对于v = 1:3 arr = x(3 *(u-1)+1:3 *(u-1)+ 3,3 *(v-1)+1:3 *(v-1)+3 ,:);majorg(u,v,:) = sum(sum(arr,1),2)== a(1,1,9);结束结束sudpulzle.constraints.majorg = majorg;

通过在线索条目设置的1下界包括初始的线索。此设置修正相应的条目的值是1,所以设定在各避让值的溶液是线索条目。

对于U = 1:尺寸(b,1)x.lowerbound(b(u,1),b(u,2),b(u,3))= 1;结束

解决数独谜题。

sudsoln =解决(sudpuzzle)
使用intlinprog解决问题。LP:最佳目标值为405.000000。找到最佳解决方案。intlinprog在根节点停止,因为客观值在最佳值的间隙容忍度范围内,Options.absolutegAppolerance = 0(默认值)。INTCON变量在容差,选项中是整数.inteGertolerance = 1E-05(默认值)。
sudsoln =.结构与字段:X:[9x9x9双]

围绕解决方案以确保所有条目都是整数,并显示解决方案。

sudsoln.x = ROUND(sudsoln.x);Y =酮(大小(sudsoln.x));对于k = 2:9 y(:,:,k)= k;对于每个深度为k%乘数结束S = sudsoln.x * Y。;%乘以每由其深度进入s =总和(s,3);%S是9×9并且保持解决难题drawsudoku

您可以轻松检查解决方案是否正确。

绘制sudoku拼图的功能

typedrawSudoku
功能drawSudoku(B)%功能用于绘制数独板%版权所有2014 MathWorks公司图;保持上;轴关闭;轴线等于%准备绘制矩形(“位置”,[0 0 9 9],“线宽”3, '裁剪', '关断')%外边界矩形( '位置',[3,0,3,9], '线宽',2)%重的垂直线的矩形( '位置',[0,3那9.那3.],'LineWidth',2) % heavy horizontal lines rectangle('Position',[0,1,9,1],'LineWidth',1) % minor horizontal lines rectangle('Position',[0,4,9,1],'LineWidth',1) rectangle('Position',[0,7,9,1],'LineWidth',1) rectangle('Position',[1,0,1,9],'LineWidth',1) % minor vertical lines rectangle('Position',[4,0,1,9],'LineWidth',1) rectangle('Position',[7,0,1,9],'LineWidth',1) % Fill in the clues % % The rows of B are of the form (i,j,k) where i is the row counting from % the top, j is the column, and k is the clue. To place the entries in the % boxes, j is the horizontal distance, 10-i is the vertical distance, and % we subtract 0.5 to center the clue in the box. % % If B is a 9-by-9 matrix, convert it to 3 columns first if size(B,2) == 9 % 9 columns [SM,SN] = meshgrid(1:9); % make i,j entries B = [SN(:),SM(:),B(:)]; % i,j,k rows end for ii = 1:size(B,1) text(B(ii,2)-0.5,9.5-B(ii,1),num2str(B(ii,3))) end hold off end

相关主题