通过整数规划解决数独谜题:具体问题具体分析
这个例子展示了如何使用二进制整数规划解决数独谜题。solver-based方法,请参阅通过整数规划解决数独谜题:Solver-Based。
你可能已经看到数独谜题。一个谜是9-by-9网格填充整数从每个整数1到9这只有一次出现在每一行,列,3×3的广场和主要。网格部分填充的线索,你的任务是填写其余的网格。
最初的难题
这是一个数据矩阵B
的线索。第一行,B (1、2、2)
,意味着第一行,第二列有一个线索2。第二行,B (1、5、3)
,意味着第一行、列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年。
手动解决数独谜题有很多方法,以及很多编程的方法。这个例子显示了一个简单的方法使用二进制整数规划。
这种方法特别简单,因为你不给一个解决方案的算法。只是表达的数独游戏的规则,表达的线索约束的解决方案,然后用MATLAB生成解决方案。
二进制整数规划方法
关键思想是把一个难题从正方形网格9-by-9立方9-by-9-by-9数组的二进制值(0或1)。认为立方阵列是9平方网格堆叠在彼此之上,在每一层都对应于一个从1到9的整数。网格顶部,一个正方形的数组,有1无论解决方案或线索有1。第二层有1无论解决方案或线索有2。第九层有1无论解决方案或线索有9。
这个配方正是适合二进制整数规划。
这里不需要目标函数,也可能是一个常数项0。问题是真的找到一个可行的解决方案,意义一个满足所有的约束。然而,对于领带打破内部的整数规划求解,给出解决方案的速度增加,使用一个非常数的目标函数。
数独游戏的规则表示为约束条件
假设一个解决方案 表示在一个9-by-9-by-9二进制数组。什么属性 有什么?首先,每平方的二维网格(i, j)正好有一个值,这就是一个非零元素的三维数组条目 。换句话说,每一个 和 ,
同样,在每一行 二维网格,正是一个值的每个数字从1到9。换句话说,对于每个 和 ,
和每一列 在二维网格中有相同的属性:为每个 和 ,
主要的3×3网格也有类似的限制。网格元素 和 ,为每一个 ,
代表所有9个主要网格,就加3或6 和 指数:
在哪里
表达的线索
每个初始值(线索)可以表示为一个约束。假设 线索是 对于一些 。然后 。约束 确保所有其他 为 。
数独在优化问题的形式
创建一个优化变量x
9-by-9-by-9二进制和的大小。
x = optimvar (“x”9日,9日,9日“类型”,“整数”,下界的0,“UpperBound”1);
创建一个相当武断的目标函数优化问题。目标函数可以帮助解决者通过破坏固有的对称性问题。
sudpuzzle = optimproblem;mul = 1 (1, 1, 9);mul = cumsum (mul 3);sudpuzzle。目标=总和(金额(金额(x, 1), 2)。* mul);
代表了约束的金额x
在每一个坐标方向。
sudpuzzle.Constraints。consx =总和(x, 1) = = 1;sudpuzzle.Constraints。consy =总和(x, 2) = = 1;sudpuzzle.Constraints。consz =总和(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 *(它们)+ 1:3 *(它们)+ 3:);:majorg (u, v) =总和(和(arr, 1), 2) = = 1 (1, 1, 9);结束结束sudpuzzle.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停在根节点,因为客观价值差距公差内的最优值,选择。AbsoluteGapTolerance = 0。在宽容intcon变量是整数,选项。IntegerTolerance = 1 e-05。
sudsoln =结构体字段:x (9 x9x9双):
的解决方案,以确保所有条目是整数,并显示解决方案。
sudsoln。x=round(sudsoln.x); y = ones(size(sudsoln.x));为k = 9 y (:,:, k) = k;%的乘数为每个深度k结束S = sudsoln.x。* y;%每个条目乘以它的深度S =(年代,3)总和;% S 9-by-9和解决难题drawSudoku (S)
你可以很容易地检查解决方案是正确的。
函数把数独谜题
类型drawSudoku
函数drawSudoku (B) %函数图数独板%版权2014年MathWorks公司图;坚持;轴,轴平等%准备画矩形(“位置”,[0 0 9 9],“线宽”,3,“剪裁”,“关闭”)%外边界矩形(“位置”,[3 0 3 9],“线宽”,2)%沉重的竖线矩形(“位置”,[3]0、3、9日,“线宽”,2)%沉重的水平线矩形(“位置”,[1]0 1 9日,“线宽”,1)%小横线矩形(“位置”,[1]0、4、9日,“线宽”,1)矩形(“位置”,[1]0、7、9日,“线宽”,1)矩形(“位置”,[1,0,1,9],“线宽”,1)%小竖线矩形(“位置”,[4 0 1 9],“线宽”,1)矩形(“位置”,[7,0,1,9],“线宽”,1)% % % B的行填写线索的形式(i, j, k),我是行数从%,j是列,k是线索。%的条目框,j是水平距离,我是垂直距离,和%减去0.5中心盒子里的线索。% %如果B是一个9-by-9矩阵,将其转换为3列第一如果大小(B, 2) = = 9% (SM, SN) = 9列meshgrid (1:9);B = %让i, j条目(SN:, SM (:), B ()):;% i, j, k行结束2 = 1:尺寸(B, 1)文本(B (2, 2) -0.5、9.5 - B (ii, 1), num2str (B(2, 3)))推迟结束结束