罗兰在MATLAB的艺术

把想法变成MATLAB

整数规划和超数独

我想介绍一下本周的客座博客艾伦·韦斯。艾伦写道文档在MathWorks数学工具箱。

嗨,各位。虽然我以前不是罗兰写的一篇博文,如果你使用优化工具箱™或全局优化工具箱然后你可能读过我的工作。

我兴奋地描述如何使用一个新的解算器。从2014年版开始,优化工具箱混合整数线性规划。的intlinprog解算器试图解决问题与线性目标函数,线性约束,(这是新的部分)的约束,一些变量必须整数值。

的整数约束打开一个惊人的宽视野的问题现在可以解决的优化工具箱。有例子文档的一个复杂的工厂生产问题和解决方案,一个旅行推销员问题,数独难题的能手

本文首先解释的数独谜题的解算器是如何工作的。然后它扩展的方法解决超数独谜题。你可能不熟悉超数独;现在我将描述它。

内容

数独

让我们看一下解决数独谜题。你们可能知道,数独谜题是9-by-9网格填充整数从每个整数1到9这只有一次出现在每一行,列,和主要3 x3的广场,在下图中,其中包括谜团的线索。

线索编码如下:每一行的一个线索矩阵的形式(i, j, k)。这意味着行,列j, k线索。如果第一行[1、2、2],那么线索在第一行,第二列= 2。这两个sudokuEnginedrawSudoku函数接受这种形式的线索,或者更传统的9-by-9矩阵形式。

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)

的文档显示了如何解决这个数独谜题使用sudokuEngine功能:

drawSudoku (sudokuEngine (B));
LP:最优的客观价值是29565.000000。减少生成:应用1强大的重心降低,2 zero-half削减。下界是29565.000000。相对差距是0.00%。找到最优解。Intlinprog停在根节点,因为客观价值差距公差内的最优值;选项。TolGapAbs = 0(默认值)。在宽容intcon变量是整数,选项。TolInteger = 1 e-05(默认值)。

如何sudokuEngine解决数独谜题?它简单的编码规则和二进制整数规划问题的线索。的intlinprog函数所做的工作。那不是很好吗?你不需要找到一个解决方案的算法。比较这几个文件交换和解决数独克里夫的文章如何程序数独。这些都使用创造力开发这种“解决数独谜题的算法。但是我们没有找出一个算法。我们必须找出如何数独游戏的规则表示为一个整数线性规划问题。sudokuEngine使用二进制整数规划制定。

如何模型数独作为一个二进制整数程序

的关键技巧把数独游戏的规则变成二进制整数程序将线索和答案的9-by-9网格变成一个9-by-9-by-9多维数据集的二进制数字。认为立方体的一堆9-by-9网格,在1级,2级,网格在9级。一个线索,比如5在原始(3、4)网格变成1 5级在立方体网格坐标(3、4)。换句话说,(i, j)网格可以看成是一堆9的水平,和一个值k (i, j)电网在堆栈级别变成1 k。

RGB = imread (“sudokuGrid3D.jpg”);图像(RGB);轴图像;轴;

当然,对于这个有意义,解决方案需要有一个1在堆栈在每个网格坐标。因此,如果x (i, j, k)代表的价值(i, j)网格在层次k,那么我们必须有

$ $ \ sum_ {k = 1} ^ 9 x (i, j, k) = 1美元美元

在一个解决方案。

数独的其他规则是什么?每一行有一个数量的每个值从1到9。在方程,为每个j和k美元,美元

$ $ \ sum_ {i = 1} ^ 9 x (i, j, k) = 1美元美元

每个列都有一个数量的每个值,。所以对于每一个我和k美元美元,

$ $ \ sum_ {j = 1} ^ 9 x (i, j, k) = 1美元美元

每个主要3 x3的网格有一个数量的每种类型为网格元素(1到9)。1美元le我\ \ \ le j \勒3美元,1美元勒3美元,每1美元和le k \ \勒9美元,

$ $ \ sum_ {i = 1} ^ 3 \ sum_ {j = 1} ^ 3 x (i, j, k) = 1, $ $

代表所有9个主要网格,就添加3或6美元每一美元我和j美元指数:

$ $ \ sum_ {i = 1} ^ 3 \ sum_ {j = 1} ^ 3 x (i + U, j + V, k) = 1, $ $

在美元U, V ~ \ε~ \ {0、3、6 \}。$

把规则intlinprog形式

intlinprog大多数优化工具箱函数也有类似的语法功能。限制的解决方案x范围和线性等式。所有的条目x二进制数,所以所有的下界吗0和所有的上界1

磅= 0 (9,9,9);乌兰巴托= 1 +磅;

其他的都是线性等式约束。优化工具箱解决使用语法

$ $ Aeq \ cdot x = beq $ $

来表示线性等式,x被认为是一个列向量。

x自然是一个9-by-9-by-9矩阵。但是,您可以将其转换为列向量使用冒号运算符xcolumn = x (:)。你可以使用恢复9-by-9-by-9矩阵表示重塑功能:x =重塑(xcolumn 9 9, 9)

让我们看看如何表达第一个方程,

$ $ \ sum_ {k = 1} ^ 9 x (i, j, k) = 1, $ $

作为一个矩阵Aeq * x =说真的。的每一行Aeq矩阵是矩阵乘以x矩阵。这是一样的说说真的等于的点积行Aeq与向量x。所以确定条目的行Aeq,使9-by-9-by-9数组的乘数x的方程,然后把数组变成一个行向量。为j19,我们有

temp =磅;% 0阵列,9-by-9-by-9临时(i, j:) = 1;%设置x 1%然后采取临时的系数(:)的Aeq作为一个行
N = 9 ^ 3;%的独立变量x, 9-by-9-by-9数组中M = 4 * 9 ^ 2;%的数量限制,看到Aeq建设Aeq = 0 (M, N);%分配等式约束矩阵Aeq * x =说真的说真的= 1 (M, 1);%的分配常数向量,说真的counter = 1;i = 1:9% 1在每个深度j = 1:9 temp =磅;%明显临时临时(i, j, 1:结束)= 1;%将每个深度条目设置为1Aeq(柜台)= temp (:)”;变化百分比临时数组行,把它放在Aeqcounter = counter + 1;结束结束

代表每一行的方程,

$ $ \ sum_ {i = 1} ^ 9 x (i, j, k) = 1美元美元

做一个类似的从数组映射到行吗Aeq

j = 1:9%在每一行k = 1:9 temp =磅;%明显临时临时(1:最终,j, k) = 1;%一行在Aeq * x =说真的Aeq(柜台)= temp (:)”;%将临时放在一行Aeqcounter = counter + 1;结束结束

同样,在列约束。

i = 1:9%在每一列k = 1:9 temp =磅;临时(我,1:最终,k) = 1;Aeq(柜台)= temp (:)”;counter = counter + 1;结束结束

最后,设置系数的主要广场。

U = 0:3:6%每平方V = 0:3:6k = 1:9 temp =磅;临时(U + (1:3), V + (1:3), k) = 1;Aeq(柜台)= temp (:)”;counter = counter + 1;结束结束结束

代表了数独的线索

包括初始的线索通过设置相应的条目数组1。这力量的解决方案x (i, j, k) = 1

i = 1:尺寸(B, 1)磅(B(我,1),B(我,2),B(我,3))= 1;结束

解决数独谜题

Aeq矩阵,说真的向量,,乌兰巴托代表数独游戏的规则和线索。目标函数向量f在这种情况下是不重要;我们只是想要一个解决难题。我们必须告诉解决所有的变量是整数。

选择= optimoptions (“intlinprog”,“显示”,“关闭”);%没有退出消息intcon = 1: N;%所有变量是整数f = [];%没有目标函数,我们只想要一个可行的解决方案

现在所称的intlinprog来解决这个难题。

[x, ~, eflag] = intlinprog (f intcon [] [], Aeq,说真的,磅,乌兰巴托,选择);

将可用的解决方案形式,简单地加起来的数字在每个(i, j)条目,美元乘以数字出现的深度:

如果eflag > 0%好的解决方案x =重塑(x, 9, 9, 9);变化百分比回9-by-9-by-9数组x =圆(x);%清理非整数解金宝搏官方网站y = 1(大小(x));k = 9 y (:,:, k) = k;%的乘数为每个深度k结束S = x。* y;%每个条目乘以它的深度S =(年代,3)总和;% S 9-by-9和解决难题其他的S = [];结束drawSudoku (S)

超数独

超数独游戏不同于数独的有更多的限制。3×3的正方形有四个3×3的正方形,除了主要还需要一个条目的每一个数字从1到9。下面的图片显示了一个超数独题来自维基百科

RGB = imread (“hyperBoard.png”);%有颜色的方块新的约束区域图像(RGB);轴图像;轴;

很容易写超数独游戏的规则基于我们的工作。有四个新的约束区域,每个需要9个方程。所以分配一个新的矩阵重新,填满它。

重新= 0 (4 * 9,N);%分配4 * 9新行说真的=[说真的;的(4 * 9,1)];%扩展beq矩阵

涉及3×3矩阵的行和列的约束指标2到4,以及指数6到8。

counter = 1;%复位计数器磅= 0 (9,9,9);%重置所有0磅U = (2,6)% 2和6开始V = (2,6)%对行和列k = 1:9 temp =磅;临时(U + (0:2)、V + (0:2), k) = 1;重新(柜台:)= temp (:)”;counter = counter + 1;结束结束结束Aeq = [Aeq;重新];Aeq %重新添加

包括解决超数独题

上图中的超数独谜题可以用下面的矩阵。

B2 = [1 8 1 2 3 2 2 8 3 2 9 4 3 5 5 3 2 6 1 4 6 6 4 7 5 5 7 5 4 3 5 7 5 8 8 8 8 6 3 3 1 2 5 8 8 8 7 9 9 1 6 9 2 9);

包括下界的线索。

i = 1:尺寸(B2, 1)磅(B2(我,1),B2(我,2),B2(我,3))= 1;结束

解决这个难题。

[x, ~, eflag] = intlinprog (f intcon [] [], Aeq,说真的,磅,乌兰巴托,选择);如果eflag > 0%好的解决方案x =重塑(x, 9, 9, 9);变化百分比回9-by-9-by-9数组x =圆(x);%清理非整数解金宝搏官方网站y = 1(大小(x));k = 9 y (:,:, k) = k;%的乘数为每个深度k结束S = x。* y;%每个条目乘以它的深度S =(年代,3)总和;% S 9-by-9和解决难题其他的S = [];结束% drawSudoku (S) %这将画。但是,对于一个超图:数独RGB = imread (“hyperBoardSolved.png”);图像(RGB);轴图像;轴;

进一步的实验

drawSudokusudokuEngine公用事业与R2014a船,所以你可以轻易解决自己的难题。然而,也许不像你想象的那样容易。我也提交了一份进入文件交换visualSudoku这是一个可视化编辑器的数独谜题。visualSudoku没有真正的代码,它依赖于sudokuEngine解决谜题,但它很容易解决,保存,和进口数独谜题。

我也上传一个视觉超数独,为解决发动机超数独谜题。

数独的约束矩阵和超数独是相当稀少的。我没有使用稀疏的配方。对于使用稀疏约束矩阵示例,请参阅工厂的例子或者是旅行推销员问题在文档中。

你喜欢看如何解决数独和整数规划或超数独谜题吗?你有任何其他类型的游戏你解决?告诉我们关于它在这里




发表与MATLAB®R2014a

|

评论

留下你的评论,请点击在这里MathWorks账户登录或创建一个新的。