图谱连接

草稿

布尔可满足性(SAT)

判断是否存在某个真值赋值让布尔公式为真,并区分“寻找赋值”和“检查一个赋值”。

concept intermediate complexityalgorithmsnp-hardnesssatisfiabilitylogic

引子问题:让规则为真

想象一个警报不是由电路图控制,而是由一条写下来的规则控制。四个开关 x1x2x3x4 各自只能取 01。这条规则是一个布尔公式(Boolean formula):

phi = (x1 AND NOT x2 AND (x3 OR x4)) OR (x2 AND x4)

判定问题是:

是否存在某个开关设置,让 phi 求值为 true?

公式问题问:是否有某个开关设置让整条规则为真根 OR 表示左侧子规则或右侧子规则任意一边成立,都能满足警报规则。
x1=1x2=0x3=1x4=0左侧子规则:x1 AND NOT x2 AND (x3 OR x4)右侧子规则:x2 AND x4最终灯:true
root ORroot=1左侧 AND1右侧 AND0x11NOT x21x2=0x3 OR x41x3=1x4=0x20x40

赋值(assignment)字符串按 x1 x2 x3 x4 的顺序写。比如 1010 表示 x1=1x2=0x3=1x4=0

同一个公式中的部件这些词汇都指向 phi,而不是另开一个例子。
变量: x1

一个有名字的布尔开关

文字: NOT x2

变量或变量的否定

子公式: (x3 OR x4)

phi 内部较小的表达式

运算符: AND / OR / NOT

组合真值的规则

第一个朴素想法:逐行尝试

最直接的方法是列出真值表(truth table),然后一行一行测试。

朴素真值表搜索

四个变量给出 16 个格式正确的行。表格展示其中一些代表行。

2^4 = 16
1010 -> phi=1通过左侧子公式满足

x1=1、x2=0 且 x3=1 让三段左侧子公式为真。

一个拒绝行只说明这一行失败,不是不可满足证明。

root ORroot=1左侧 AND1右侧 AND0x11NOT x21x2=0x3 OR x41x3=1x4=0x20x40

这个四变量例子只有 16 行,所以暴力搜索看起来不痛。但表格是搜索空间,不是证书。

贯穿全页的固定赋值行格式错误例子不放入真值表,而放在验证器和练习中。
1010 -> phi=1通过左侧子公式满足

x1=1、x2=0 且 x3=1 让三段左侧子公式为真。

0101 -> phi=1通过右侧子公式满足

x2=1 且 x4=1 让右侧子公式为真,因此根 OR 为真。

0000 -> phi=0拒绝这一行,不是不可满足证明

这个赋值失败,但 1010 和 0101 说明公式仍然可满足。

痛点:每加一个变量就翻倍

每增加一个变量,可能赋值数都会翻倍:

number of assignments=2n.\text{number of assignments} = 2^n.

0000 这样的 false 行,只证明 0000 失败。它不能证明不存在满足赋值(satisfying assignment)。

每增加一个变量,表格翻倍

检查一个证书只求值一次 phi;盲目搜索可能一行接一行地求值。

原因: 搜索行数翻倍;检查一个证书只求值一次公式
赋值数量16

暴力表中的所有行

一次证书检查O(|phi| + n)

检查 bit,求值公式树,读取根节点

本例搜索16 formula checks for this fixture

更大公式也有同样的翻倍形状

翻倍快照
n2^n一次检查标签
416O(|phi| + n)
8256O(|phi| + n)
124,096O(|phi| + n)
201,048,576O(|phi| + n)
301,073,741,824O(|phi| + n)

核心发明:一个赋值可以当证书

现在把两个任务分开:

  • 搜索问:是否存在某个满足赋值?
  • 验证接收一个候选赋值,然后检查它。

如果有人交给我们 1010,我们不必重新扫描整张表。我们先验证字符串是否给每个变量正好一位,再求值公式树,最后看根节点是否为 true。

存在性搜索变成一次证书检查证书是 Yes 实例的证据,不是找到证据的方法。
0000000100100011010001010110011110001001101010111100110111101111
->
被选中的证书: 1010只检查这个赋值

如果 phi 变为真,则实例是 Yes。如果这一行失败,只说明这个证书失败。

证书(certificate)是一条被声称的 Yes 见证。它成功时能证明答案是 Yes,但它本身不是“找到自己”的方法。

验证器追踪:求值一个候选赋值

验证器先检查证书格式,再自底向上求值公式出现位置,最后读取根节点。

accept
1 / 13
验证通过赋值为每个公式变量恰好提供一位

已存储的值逐步增加:每个父节点只在子节点已知之后存储。

此步之后存储的子公式值
尚无
root ORroot=?左侧 AND?右侧 AND?x1?NOT x2?x2=?x3 OR x4?x3=?x4=?x2?x4?
标准追踪顺序
步骤工作状态
验证通过赋值为每个公式变量恰好提供一位当前
x1-left: VARx1: x1=1 -> 1等待
x2-left: VARx2: x2=0 -> 0等待
not-x2-left: NOTNOT x2: x2-left=0 -> 1等待
x3-left: VARx3: x3=1 -> 1等待
x4-left: VARx4: x4=0 -> 0等待
or-x3-x4: ORx3 OR x4: x3-left=1, x4-left=0 -> 1等待
and-left: ANDx1 AND NOT x2 AND (x3 OR x4): x1-left=1, not-x2-left=1, or-x3-x4=1 -> 1等待
x2-right: VARx2: x2=0 -> 0等待
x4-right: VARx4: x4=0 -> 0等待
and-right: ANDx2 AND x4: x2-right=0, x4-right=0 -> 0等待
or-root: OR(x1 AND NOT x2 AND (x3 OR x4)) OR (x2 AND x4): and-left=1, and-right=0 -> 1等待
读取根节点结果根公式为真,因此验证器接受这个证书等待

SAT 的形式化定义

布尔公式由变量(variable)、文字(literal)和 ANDORNOT 这样的运算符(operator)构成。满足赋值是让整个公式为 true 的赋值。

$\varphi$ 是一个含变量 $x_1,\dots,x_n$ 的布尔公式。设 $a \in \{0,1\}^n$ 是一个赋值,$\varphi(a)$ 表示在该赋值下公式的真值。

φSATa{0,1}n such that φ(a)=1.\varphi \in \text{SAT} \quad\Longleftrightarrow\quad \exists a \in \{0,1\}^n \text{ such that } \varphi(a)=1.

换成普通话说:如果至少有一种真值设置让整个表达式为真,这个公式就是可满足的。

形式化判定语言看过具体公式后,phi 表示任意含 n 个变量的布尔公式。
phi

由变量和运算符构成的布尔公式

a in {0,1}^n

每个变量对应一位

phi(a) = 1

整个表达式求值为 true

验证器实现

验证器(verifier)的职责比求解器窄:

function verifySat(phi, certificate) {
  if (!hasOneBitPerVariable(phi, certificate)) return false;

  const assignment = readAssignmentBits(phi, certificate);
  const rootValue = evaluateFormulaTree(phi.root, assignment);
  return rootValue === true;
}

对于格式正确的赋值:

verify(φ,a)=1φ(a)=1.\text{verify}(\varphi,a)=1 \quad\Longleftrightarrow\quad \varphi(a)=1.

1011020 这样的格式错误字符串,会在公式求值前被拒绝。它们不是“求值为 false 的普通行”。

验证器实现追踪具体实现每次都按同样的自底向上顺序存储子公式值。
节点读取输入存储输出
x1-leftx1=1x1 = 1
x2-leftx2=0x2 = 0
not-x2-leftx2-left=0NOT x2 = 1
x3-leftx3=1x3 = 1
x4-leftx4=0x4 = 0
or-x3-x4x3-left=1, x4-left=0x3 OR x4 = 1
and-leftx1-left=1, not-x2-left=1, or-x3-x4=1x1 AND NOT x2 AND (x3 OR x4) = 1
x2-rightx2=0x2 = 0
x4-rightx4=0x4 = 0
and-rightx2-right=0, x4-right=0x2 AND x4 = 0
or-rootand-left=1, and-right=0(x1 AND NOT x2 AND (x3 OR x4)) OR (x2 AND x4) = 1
读取根节点root=1accept

子公式不变量

求值器自底向上走表达式树:

validation -> x1-left -> x2-left -> not-x2-left -> x3-left -> x4-left -> or-x3-x4 -> and-left -> x2-right -> x4-right -> and-right -> or-root -> final

不变量:

每求值完一个子公式,已存储的每个值都等于该子公式在当前赋值下的真实真值。

子公式不变量当父节点被求值时,它读取的每个子节点都已经存有正确真值。
not-x2-leftx2-left -> 1
or-x3-x4x3-left + x4-left -> 1
and-leftx1-left + not-x2-left + or-x3-x4 -> 1
and-rightx2-right + x4-right -> 0
or-rootand-left + and-right -> 1

这就是为什么检查很直接。验证器不会猜父节点的值;它先算子节点,再应用父节点运算符。

复杂度

证书为每个变量提供一位:

a=n.|a| = n.

在这个例子里,公式大小统计变量出现位置和运算符节点。按照本页使用的 n 元 AND / OR 约定,|\varphi| = 11:六个变量出现位置加五个运算符节点。

一次验证会检查赋值格式、求值一次公式树、读取根节点:

one check=O(φ+n).\text{one check} = O(|\varphi| + n).

盲目搜索可能对每个赋值都重复一次公式检查:

brute force search=O(2nφ).\text{brute force search} = O(2^n \cdot |\varphi|).
成本堆栈把 n 个赋值 bit 与 |phi| 个公式出现位置和运算符节点分开。
检查证书n = 4

每个变量一位

求值公式|phi| = 11

六个变量出现位置加五个运算符节点

盲目搜索2^n rows

可能对每个赋值重复公式求值

这证明了 SAT in NP:Yes 实例有一个每变量一位的证书,而且验证器关于公式大小以多项式时间运行。

主张边界

SAT 也因为 NP-complete 而有名,但本页不证明困难性或完备性。那条证明路线需要归约、CNF 和 3SAT 等范式,以及更多证明工具。

这个小例子、满足行 1010、验证器追踪,只证明成员关系这一侧:候选赋值可以被高效检查。

主张边界账本本页展示属于 NP;归约证明留在本节点之外。
主张处理方式原因
SAT 属于 NP本页证明赋值长度为 n;验证器运行时间为 O(|phi| + n)
SAT 是 NP-hard 或 NP-complete作为后续背景命名证明需要归约,而不是一个固定例子的追踪
SAT 已经表示 CNF 或 3SAT后续节点本页使用任意带括号的公式

常见混淆

常见混淆

每个修正都把失败行、格式错误行、验证器和后续归约分开。

`0000` 让 phi 为假,所以也许 phi 不可满足。

修正: 失败行只排除这个赋值。不可满足意味着每个格式正确的行都失败。

验证器会自动找到满足赋值。

SAT 一定已经表示 CNF 子句列表。

太短或含非 bit 的字符串仍可当作 false 来计算。

极小不可满足对照psi = x1 AND NOT x1 与主要的可满足示例 phi 分开。
x1psi原因
0falsex1 为假,因此左侧文字失败。
1falseNOT x1 为假,因此右侧文字失败。

图谱连接

p-vs-np 提供证书和验证器的语言。circuit-sat 在门电路上问同一种“是否存在满足赋值”的问题。SAT 是它的公式版本:对象现在是一棵布尔表达式树。

后续节点可以解释电路如何变成公式或约束、为什么 CNF 重要、3SAT 如何进入归约证明。这些是未来节点,不是理解本页的隐藏前置条件。

局部图谱位置只有已存在的节点作为图谱链接;未来范式以淡化背景显示。
P 与 NP

证书与验证器

->电路可满足性

电路上的同类赋值问题

->布尔可满足性(SAT)

公式版本,已实现节点

->CNF / 3SAT

后续范式节点

练习

练习边界

区分满足、拒绝、格式错误,以及“已证明/后续再证明”的主张。

验证器应如何处理证书 1010?

选择一个答案来检查。

0000 证明了什么?

选择一个答案来检查。

应该如何处理 101?

选择一个答案来检查。

1020 的问题是什么?

选择一个答案来检查。

本页真正证明了哪条主张?

选择一个答案来检查。

  1. 对赋值 1010,哪个子公式最先让它看起来有希望?
  2. 为什么 0000 不能证明 phi 不可满足?
  3. 为什么 101 应该在任何公式树求值前停止?
  4. 本页证明了哪条主张:SAT in NPSAT is NP-hard,还是两者都证明了?

图谱连接 : 布尔可满足性(SAT)