复习一些数学知识
Note
在最开始,我们复习一些基础的离散数学,主要是一元逻辑部分,我们默认读者有基本的位运算基础,如果没有的话,可以查看下面进行学习
位运算
\&, |, \neg
,其中,前面两种为二元运算,非运算为一元运算,其真值表的变化为:
y&x 0 1 0 0 0 1 0 1
y|x 0 1 0 0 1 1 1 1
x 0 1 1 0
我们首先引入一个记号 ,这是一元逻辑中所有变量的定义域
我们称 的 为布尔变量,其取值只有 0/1,也就是真/假,对于单个布尔变量,我们有一元运算如下:
其中, 为非运算。
接着,我们定义布尔变量之间的运算,其只有 两类运算,我们在下面引入记号并详细:
- ,我们有 ,其中 表示或运算
- ,我们有 ,其中 表示与运算
由此,我们可以定义如下布尔函数:
通过上文中定义的三种运算结合构成此布尔函数,例如:
可满足问题(SAT 问题)
首先,我们引入一些 SAT 问题中的记号
CNF
我们通过一些运算规则与定理,可以将任意的布尔函数都转化为合取范式的形式( CNF
),例如上式可以转为:
也就是通过 连接的若干个 式,这里:
- 我们将 式称为 子句(clause),每个子句都是由若干个 组成
- 我们将 称为变量 对应的 文字(literal),若 ,我们将其称为正文字,若 ,我们将其称为反文字
更进一步的,在 SAT 问题中,我们还有以下名词:
- 极性(Polarity),通常指变量在子句中的出现形式,换而言之,正文字就是极性为正,反文字就是极性为负
- 赋值 (Assignments),我们可以使用此函数来表示 ,其中 ,所有变量 赋值后得到的一组有序向量,我们将其称为 CNF 的一组赋值
SAT 定义
这样,我们可以轻松的导出 SAT 问题的定义:
SAT 问题
给定一个 CNF :,问是否存在一组赋值 使得 成立
值得一提的是,目前还找不到一种多项式时间的算法来解决这个问题,事实上,著名的未解问题 “P 是否等于 NP” 等价于询问这样的算法是否存在。
SAT 问题可以被认为是 “所有 NP 完全(NP-Complete)问题的起源”
我们在这里不探讨过多的计算复杂性相关的内容,如果你对这些内容感兴趣,可以阅读以下内容入门
小知识
判定一个 CNF 是 UNSAT(不可满足的)会比判断其 SAT (可满足)在工程上要困难,也就是耗时会更多
这是因为判断 UNSAT 本质上是一个证明,我们必须证明在整个解空间内不存在一组赋值 使得
SAT 问题的应用
生活中的许多问题都能通过一系列的编码,将其转化为 SAT 问题,在这里我们举一些例子
Keller’s conjecture
Info
如果一个 维空间被 维相同的超立方体所覆盖,则至少两个超立方体必须共享一个面。
集合覆盖问题
集合覆盖问题
给定全集 ,以及一个包含 个集合且这 个集合的并集为全集的集合 。
集合覆盖问题要找到 的一个最小的子集,使得他们的并集等于全集。
集合覆盖问题实例
例如全集 ,,我们可以找到这样一个最小的子集 ,使得这个子集的并集为全集
对于集合覆盖问题,可以发现这是一个优化问题,但我们可以轻松的将其转化为一个判定问题:
集合覆盖问题的判定版本
给定一个正整数 ,是否存在 个 的子集,使得这些子集的并集等于全集
这个版本我们可以按照一下编码为 SAT 问题:
我们使用变量 来表示集合 是否被选择, 表示被选中, 表示不被选中
对于全集中的元素 ,我们根据 每个元素都被覆盖 来构造子句:
接着,我们需要判定选定的集合数小于等于 ,关于这一点,我们需要使用 基数约束 来表示:
由于基数约束是可以 编码 为前文提到的 CNF 形式,于是我们将集合覆盖问题转为 SAT 问题。
精确集合覆盖
这里我们再介绍一个变形,精确集合覆盖问题
精确集合覆盖
在集合覆盖的基础上,我们要求,全集 中的每个元素只能被覆盖一次
这个问题的应用有很多,可以参考 一个错误的回答 里提到的应用,虽然他对问题有误解,但应用确实是对的。
精确集合覆盖等价于 XSAT (Exact SAT) 问题,也是 NP 完全的,不过在工业上还有 基于 ZDD 的 DLX,在性能上会更好。
回到先前的 SAT 编码,我们本质上就是在每一条子句上都加上一条约束:这条子句中只有一个文字为真
如果我们按照布尔代数来考虑,那么原先的子句可以写为:
现在,我们转变为: