SAT是可满足性、适定性(Satisfiability)问题的简称。一般形式为k-适定性问题或k-可满足性问题,简称 k-SAT。
何为布尔可满足性问题?给定一条真值表达式,包含逻辑变量、逻辑与、逻辑或以及非运算符,如:
(
a
∧
?
b
∧
(
?
(
c
∨
d
∨
?
a
)
∨
(
b
∧
?
d
)
)
)
∨
(
?
(
?
(
?
b
∨
a
)
∧
c
)
∧
d
)
(a\wedge\neg b\wedge(\neg(c\vee d\vee\neg a)\vee(b\wedge\neg d)))\vee(\neg(\neg(\neg b\vee a)\wedge c)\wedge d)
(a∧?b∧(?(c∨d∨?a)∨(b∧?d)))∨(?(?(?b∨a)∧c)∧d)
是否存在一组对这些变量的赋值,使得整条式子最终的运算结果为 t r u e true true?若可以,那么这个性质被称为这条逻辑公式的可满足性(satisfiability),如何快速高效地判断任意指定逻辑公式的可满足性是理论计算机科学中的一个重要的问题,也是第一个被证明为NP-完全(NP-complete,NPC)的问题。
当 k > 2 k>2 k>2时,可满足性问题是NPC问题,因此我们一般只研究 k = 2 k=2 k=2的情况。
通常所说的2-SAT问题往往需要我们处理对于
n
n
n个布尔变量
{
x
n
}
(
x
i
∈
{
0
,
1
}
)
\{x_n\}\left(x_i\in\{0,1\}\right)
{xn?}(xi?∈{0,1})的
m
m
m个限制。
其每个限制都形如一个
∨
\vee
∨运算符连接的两个简单限制条件,简单限制条件为
x
i
=
t
r
u
e
x_i=true
xi?=true(记作
x
i
x_i
xi?)或
x
i
=
f
a
l
s
e
x_i=false
xi?=false(记作
?
x
i
\neg x_i
?xi?),因此限制条件一共有四种:
我们需要满足:
?
m
i
=
1
s
i
=
t
r
u
e
\underset{i=1}{\overset m{ \bigwedge }}s_i=true
i=1?m??si?=true
也就是需要每一个
s
k
s_k
sk?都为真。
其处理方法为:
首先建图,对变量
x
i
x_i
xi?建立两个点
x
i
,
0
,
x
i
,
1
x_{i,0},x_{i,1}
xi,0?,xi,1?表示选
x
i
=
0
x_i=0
xi?=0或
x
i
=
1
x_i=1
xi?=1,然后在新图上对每个限制按照如下方式连边。
例如对于限制
s
k
s_k
sk?,我们讨论这条限制下
a
,
b
∈
{
0
,
1
}
a,b\in\{0,1\}
a,b∈{0,1},
x
i
=
a
x_i=a
xi?=a时是否一定有
x
j
=
b
x_j=b
xj?=b,如果一定有,就连有向边
x
i
,
a
→
x
j
,
b
x_{i,a}\rightarrow x_{j,b}
xi,a?→xj,b?。
同理我们讨论
x
j
=
a
x_j=a
xj?=a是否一定有
x
i
=
b
x_i=b
xi?=b,如果一定有,就连有向边
x
j
,
a
→
x
i
,
b
x_{j,a}\rightarrow x_{i,b}
xj,a?→xi,b?
感性理解这张图,如果 x i , a x_{i,a} xi,a?可达 x j , b x_{j,b} xj,b?,则说明 x i = a x_i=a xi?=a可以推出 x j = b x_j=b xj?=b,或者说 x i = a x_i=a xi?=a蕴含了 x j = b x_j=b xj?=b。
因此我们知道这个可满足性问题无解的充要条件为,存在 i i i使得 x i , 0 x_{i,0} xi,0?和 x i , 1 x_{i,1} xi,1?处于同一个强连通分量内,这意味着 x i = 0 x_i=0 xi?=0推出 x i = 1 x_i=1 xi?=1,同时 x i = 1 x_i=1 xi?=1推出 x i = 0 x_i=0 xi?=0,因此无解。
因此我们可以使用Tarjan算法求强连通分量来判断2-SAT问题是否有解,事实上我们还可以输出一组可行解。
具体方法如下,首先对我们建图的图求强连通分量缩点,得到一张DAG,然后对DAG进行拓扑排序,则
x
i
x_i
xi?对应的两个节点中,对应的强连通分量拓扑序较为靠后的节点对应的权值,是
x
i
x_i
xi?取得的权值。
其原理是,如果
x
i
=
a
x_i=a
xi?=a会推出
x
i
=
b
x_i=b
xi?=b,那么就不能选
x
i
=
a
x_i=a
xi?=a,此时只能选
x
i
=
b
x_i=b
xi?=b。
这样我们就用Tarjan算法取得了可满足性问题的 O ( n + m ) O(n+m) O(n+m)做法。
首先,所有限制都可以转化为 x i = a ? x j = b x_i=a\Rightarrow x_j=b xi?=a?xj?=b的形式进行连边,这里记录一些经典的连边方式,这样就不需要每次做转化了。
其中一些限制条件也可以在连边的时候判掉。
我们现在有
n
n
n个布尔变量,称为
{
x
n
}
(
x
i
∈
{
0
,
1
}
)
\{x_n\}\left(x_i\in \{0,1\}\right)
{xn?}(xi?∈{0,1}),现在给出
m
m
m条限制,每一条限制都形如:
当
x
i
=
a
x_i=a
xi?=a时,有
x
j
=
b
x_j=b
xj?=b(
a
,
b
∈
{
0
,
1
}
a,b\in\{0,1\}
a,b∈{0,1})
即:
x
i
=
a
?
x
j
=
b
x_i=a\Rightarrow x_j=b
xi?=a?xj?=b
接下来说一下如何求解这个问题。
我们使用图论方法对这个问题进行求解,按照经典套路,我们需要在图上定义一个集合,然后把原问题的意义在集合内体现出来。
具体来说,我们有一个集合
S
S
S,同时在图上有
2
n
2n
2n个点,其中每个比尔变量
x
i
x_i
xi?对应两个点,一个叫做
x
i
,
0
x_{i,0}
xi,0?,另一个叫做
x
i
,
1
x_{i,1}
xi,1?。
我们规定
x
i
,
0
,
x
i
,
1
x_{i,0},x_{i,1}
xi,0?,xi,1?当中只能恰好有一个属于集合
S
S
S,如果
x
i
,
0
∈
S
x_{i,0}\in S
xi,0?∈S,则
x
i
=
0
x_i=0
xi?=0;如果
x
i
,
1
∈
S
x_{i,1}\in S
xi,1?∈S,则
x
i
=
1
x_i=1
xi?=1。
我们知道根据限制能够推出一些关系,例如如果 x i , a ∈ S x_{i,a}\in S xi,a?∈S,那么一定有 x j , b ∈ S x_{j,b}\in S xj,b?∈S,我们希望用边表示这一种关系,因此我们规定对于任意元素 u ∈ S u\in S u∈S, u u u在图上可达的所有点 v v v均属于 S S S。
刚才已经定义了图中的点,以及集合
S
S
S。现在具体说一下图中的边是如何连接的:
对于限制:
x
i
=
a
?
x
j
=
b
x_i=a\Rightarrow x_j=b
xi?=a?xj?=b
我们考虑一个一个向着集合
S
S
S内添加元素的过程,我们必然是找到一个点
u
u
u加入集合,然后将
u
u
u的所有后继加入
S
S
S,然后把这些后继的所有后继加入
S
S
S…
由于我们知道
x
i
=
a
x_i=a
xi?=a时,
x
j
=
b
x_j=b
xj?=b,因此对于这个限制,我们在图上连边
x
i
,
a
→
x
j
,
b
x_{i,a}\rightarrow x_{j,b}
xi,a?→xj,b?,这样就似乎可以表示这个限制了。
(注意连边方式到这里还不完全正确)
此时我们会得到一个暴力算法:
但是我们会发现这个算法是会错的,举例来说,对于以下两个限制:
我们会连出这张图:
但是如果我们一开始选择
x
0
x_0
x0?,后来就会发现无论选择
y
0
y_0
y0?还是
y
1
y_1
y1?都会有矛盾,此时就输出无解,显然是不对的。
这样会出错是因为,对于这样的一条限制 y = 0 ? x = 1 y=0\Rightarrow x=1 y=0?x=1来说,选择 x x x的值是会对 y y y的值产生影响的,具体来说,如果 x = 0 x=0 x=0,这就说明 y =? 0 y\not=0 y=0,即 y = 1 y=1 y=1。
换句话说,命题 y = 0 ? x = 1 y=0\Rightarrow x=1 y=0?x=1的逆否命题 x =? 1 ? y =? 0 x\not=1\Rightarrow y\not =0 x=1?y=0,即 x = 0 ? y = 1 x=0\Rightarrow y=1 x=0?y=1,具有和原命题一致的真假性,因此选择 x x x的值可能会对 y y y造成影响,因此我们需要进一步讨论 x = a ? y = b x=a\Rightarrow y=b x=a?y=b说明了 x , y x,y x,y之间的那些关系:
因此事实上对于限制 x i = a ? x j = b x_i=a\Rightarrow x_{j}=b xi?=a?xj?=b来说,我们应该连接两条边:
此时我们再进行刚才的暴力算法,我们就获得了时间复杂度为 O ( n ? m ) O(n\cdot m) O(n?m)的2-sat问题的dfs做法。值得一提的是,这种做法还能同时让我们获得2-sat问题字典序最小的解。
接下来简要对暴力做法的正确性进行说明:
首先我们证明解的充分性,即我们求出的解确实是原问题的一组解:
首先我们知道,对于一个限制
x
i
=
a
?
x
j
=
b
x_{i}=a\Rightarrow x_{j}=b
xi?=a?xj?=b,这个限制被违反当且仅当
x
i
,
a
,
x
j
,
?
b
∈
S
x_{i,a},x_{j,\neg b}\in S
xi,a?,xj,?b?∈S。
如果说在算法过程中
x
i
,
a
x_{i,a}
xi,a?比
x
j
,
?
b
x_{j,\neg b}
xj,?b?先选的话,发生这种情况一定不可能,因为我们选择
x
i
,
a
x_{i,a}
xi,a?时根据连边,一定选择了
x
j
,
b
x_{j,b}
xj,b?,因此后来无法选择
x
j
,
?
b
x_{j,\neg b}
xj,?b?了,矛盾。
如果
x
i
,
a
x_{i,a}
xi,a?比
x
j
,
?
b
x_{j,\neg b}
xj,?b?后选的话,这种情况还是不可能,因为根据连边的方式,如果我们选择了
x
j
,
?
b
x_{j,\neg b}
xj,?b?,我们一定选择了
x
i
,
?
a
x_{i,\neg a}
xi,?a?,不可能再选择
x
i
,
a
x_{i,a}
xi,a?,因此仍然矛盾。
因此我们就证明,我们构造出的一组解满足所有限制条件,因此是一组合法解。
接下来我们证明解的必要性,即有解的时候,我们一定能够构造出一组解。
只需证明逆否命题,即如果我们构造不出一组解,此时这个问题无解。
我们考虑求解过程在决定变量
x
i
x_i
xi?的取值时报告了无解。
此时必然是因为发生了矛盾,首先讨论选取
x
i
,
0
x_{i,0}
xi,0?时候的情况,矛盾即存在元素
x
j
,
0
,
x
j
,
1
∈
S
x_{j,0},x_{j,1}\in S
xj,0?,xj,1?∈S。
此时有两种情况,第一种情况是
x
j
,
0
,
x
j
,
1
x_{j,0},x_{j,1}
xj,0?,xj,1?都是在
x
i
,
0
x_{i,0}
xi,0?加入集合
S
S
S后加入集合的,此时显然选择
x
i
,
0
x_{i,0}
xi,0?会同时推出
x
j
=
0
x_j=0
xj?=0和
x
j
=
1
x_j=1
xj?=1,因此
x
i
=?
0
x_i\not=0
xi?=0。
第二种情况是, x j , a x_{j,a} xj,a?是在 x i , 0 x_{i,0} xi,0?加入集合 S S S前加入集合的,而 x j , ? a x_{j,\neg a} xj,?a?是因为加入 x i , 0 x_{i,0} xi,0?而加入集合 S S S的(换句话说存在路径使得 x i , 0 ? x j , ? a x_{i,0}\rightsquigarrow x_{j,\neg a} xi,0??xj,?a?),这种情况不存在,这是因为,如果存在路径使得 x i , 0 ? x j , ? a x_{i,0}\rightsquigarrow x_{j,\neg a} xi,0??xj,?a?,由于接下来说到的性质2,我们必然知道存在一条路径使得 x j , a ? x i , 1 x_{j,a}\rightsquigarrow x_{i,1} xj,a??xi,1?,因此当 x j , a ∈ S x_{j,a}\in S xj,a?∈S后, x i , 1 ∈ S x_{i,1}\in S xi,1?∈S,这与 x i x_i xi?取值未确定矛盾,因此第二种情况不存在。
不可能存在一种情况使得 x j , 0 , x j , 1 x_{j,0},x_{j,1} xj,0?,xj,1?在加入 x i , 0 x_{i,0} xi,0?前都在集合 S S S内,因为这违反 S S S的定义。
同理我们知道,如果在选择 x i , 1 x_{i,1} xi,1?的时候发生矛盾,只可能是因为 x i =? 1 x_i\not=1 xi?=1。此时我们就得知了 x i =? 0 x_i\not=0 xi?=0且 x i =? 1 x_i\not=1 xi?=1,因此得到这个可满足性问题无解。
QED.
接下来我们说一下这个问题的线性算法,线性算法是这样的:
接下来我们证明一下线性算法的正确性。
边的对称性:
对于任意一条有向边,
(
x
i
,
a
,
x
j
,
b
)
(x_{i,a},x_{j,b})
(xi,a?,xj,b?),都存在有向边
(
x
j
,
?
b
,
x
i
,
?
a
)
(x_{j,\neg b},x_{i,\neg a})
(xj,?b?,xi,?a?),我们称为其对称边。
证明:
回忆建图的方式,这条性质是显然成立的。
路径的对称性:
对于任意一条从
x
i
,
a
x_{i,a}
xi,a?到
x
j
,
b
x_{j,b}
xj,b?的路径,必然存在对应的一条路径从
x
j
,
?
b
x_{j,\neg b}
xj,?b?到
x
i
,
?
a
x_{i,\neg a}
xi,?a?。
证明:
我们找到从
x
i
,
a
x_{i,a}
xi,a?到
x
j
,
b
x_{j,b}
xj,b?的路径上的每一条边的对称边,显然它们拼成一条从
x
j
?
b
x_{j\neg b}
xj?b?到
x
i
,
?
a
x_{i,\neg a}
xi,?a?的路径。
我们可以据此提出一个求解2-sat问题的算法:
缩点后得到的DAG,满足没有任何一个 x i , 0 , x i , 1 x_{i,0},x_{i,1} xi,0?,xi,1?强连通,是原问题有解的必要条件。
证明其逆否命题:
如果存在
x
i
,
0
,
x
i
,
1
x_{i,0},x_{i,1}
xi,0?,xi,1?强连通,那么我们沿着
x
i
,
0
?
x
i
,
1
?
x
i
,
0
x_{i,0}\rightsquigarrow x_{i,1}\rightsquigarrow x_{i,0}
xi,0??xi,1??xi,0?的回路走,上面的边对应的限制条件就说明,当
x
i
=
0
x_{i}=0
xi?=0时
x
i
=
1
x_i=1
xi?=1,并且当
x
i
=
1
x_i=1
xi?=1时
x
i
=
0
x_i=0
xi?=0,此时显然无解。
QED.
按照上述算法1流程构造出的解,是原问题的一组解。
证明:
如果这组解不是原问题的一组解,那么一定存在至少一个限制被违背了,设这个限制是
x
i
=
a
?
x
j
=
b
x_i=a\Rightarrow x_j=b
xi?=a?xj?=b,这个限制被违反必须有
x
i
=
a
x_i=a
xi?=a且
x
j
=
?
b
x_j=\neg b
xj?=?b。
假如说 x i , a x_{i,a} xi,a?比 x j , ? b x_{j,\neg b} xj,?b?后晚加入集合,当我们加入 x j , ? b x_{j,\neg b} xj,?b?时,由于这条限制对应连出的边, x i , ? a x_{i,\neg a} xi,?a?一定也会被加入集合,因此 x i , a x_{i,a} xi,a?不可能加入集合,矛盾。
否则说明 x i , a x_{i,a} xi,a?比 x j , ? b x_{j,\neg b} xj,?b?先加入集合,但是这也不可能,因为当我们加入 x i , a x_{i,a} xi,a?时,由于这条限制对应连出的边, x j , b x_{j,b} xj,b?也一定加入集合,因此 x j , b x_{j,b} xj,b?不可能加入集合,矛盾。
QED.
根据定理1,定理2,我们证明了:
算法1能够求出一组解,是原问题有解的充要条件。它求出的解,是原问题的一组解。
容易发现Tarjan算法+拓扑排序求解2-sat问题的过程事实上在模拟算法1,因此其的正确性也有保证。
于是皆大欢喜。