用线性编程解决数独问题(Python - PuLP)
利用线性编程的概念来解决数独问题
SUDOKU+线性 编程 (作者的图片汇编。数独图片 -wiki)
数独是一种典型的涉及笔、纸和思维一起行动的游戏。当你想让笔和头脑得到一些休息时,可以用数独解题器来解决。在这里,我们将尝试创建一个这样的数独解算器。
本文旨在利用线性编程的概念来解决一个数独谜题。我们将首先回顾线性编程背后的一些基本理论,然后使用PuLP包在Python中实现这些理论。
在这里,我们将尝试解决两种类型的数独谜题,常规数独和对角线数独,后者在数独网格的对角线上有额外的规则。随着我们的进展,会有更多的内容。
什么是线性编程?
线性规划是一个有约束的优化模型,有3个主要部分:目标函数,决策变量和约束条件。
目标函数。 目标函数是一个线性函数,根据我们要解决的问题,其值需要最小化或最大化。
决策变量。 这些是决定最终产出的输出或目标变量。
约束条件。 约束条件是对决策变量的限制或约束。
线性规划的目标是为给定的目标函数找到一套最佳的决策变量,并应用所有的约束条件。
线性规划与数独
数独的线性规划 (图片由作者提供)
使用Python中的线性编程解决数独问题
这里我们将使用Python中的PuLP包来解决这个线性编程问题。
解决数独问题的步骤。
第1 步:定义线性规划问题
**第2步:**设置目标函数
**第3步:**定义决策变量
**第4步:**设置约束条件
第5步:
解决数独问题
第6步: 检查是否找到最优结果
步骤1:定义线性规划问题
第2步:设置目标函数
通常在线性规划中,我们有一个目标函数,我们试图将其最大化或最小化。但在这种情况下,我们没有任何目标函数。它更像是一个可行性问题,也就是说,如果约束条件得到满足,那么这个数独就可以得到解决。
因此,我们在这里设置一个假的目标函数为0。
第三步:定义目标变量或决策变量
数独网格由81个单元组成(9x9网格)。每个单元格可以取1到9之间的值。如果我们为这些数值中的每一个创建一组布尔决策变量,那么我们总共得到729个变量(9x9x9)。
由于每个单元格只能有一个相关的值,所以一个单元格的9个变量中只有一个布尔变量可以设置为真,其余的应该是假。正如你将在下一节看到的,这是用约束条件来保证的。
第4步:设置约束条件
数独的通用约束
为了解决这个问题,需要将数独的规则设置为约束条件。
鉴于数独是一个9x9的网格,这里提到了游戏的规则。
约束条件1: 每个单元格都应该填上1到9之间的一个数值。
限制条件**2:**每行应包含1至9的每个数字一次
约束**3:**每一列应包含1至9的每个数字一次
约束4: 每个3x3网格,从左上角开始,应该包含1到9的每个数字一次。
对角线数独的附加约束
还有一个版本的数独,被称为对角线数独,除了上面提到的通用规则外,还需要满足以下约束条件。
约束条件5: 每条对角线应包含1至9的每个数字一次。
请注意,这个约束需要应用于两个对角线(左上角到右下角和右上角到左下角)。
初始化输入的数独谜题的约束条件
现在游戏规则已经通过约束条件设定好了,下一步就是初始化谜题中的已知值。这是从我们要解决的数独谜题中提取的。将预填的单元格作为约束条件填入LP问题中。
这样一来,所有解决数独问题所需的约束条件都被设置好了,我们就可以解决它了。
第5步:解开数独谜题
一旦目标函数、决策变量和约束条件设置完毕,解题就像对问题变量调用解决方法一样简单。
第6步:检查是否找到了一个最优结果
一旦问题被解决,我们可以通过检查状态标志来检查算法是否已经确定了一个最优解。
如果结果是 "最优",那么线性规划算法已经确定了一个具有给定约束的解决方案。如果不能找到一个解决方案,那么它将返回状态为 "不可行"。
解题时间
将上述代码包装成一个函数,这样它就可以解决作为输入的任何数独。下面是几个样本,其中普通数独和对角线数独是用这个解算器解算的。
数独1 - 普通数独
输入
输入 - 普通数独(作者的图片)
输出
解开的数独 - 普通 数独 (作者的图片)
数独2 - 对角线数独
输入
输入 - 对角线数独(作者的图片)
输出
解答数独 - 对角线(作者的图片)
总结
这是一个非常简单的方法,说明如何使用Python中提供的线性编程包,即PuLP来解决数独问题。
还有进一步改进的余地,比如从图像中读取数独网格或通过网络摄像头进行视频处理来读取网格。
稍后会有更多的内容,希望你喜欢这篇阅读!!