形式陈述
删掉一个约束,怎样把答案补回来
求解器面对一份CNF理路CNF 可满足性问题CNF satisfiability · CNF-SAT给定有限个命题子句的合取,判定是否存在同时满足全部子句的布尔赋值。时,可以先删去某些子句,让剩下的问题更小。不过,剩余公式的模型可能违反被删约束。阻塞子句消除的关键不是“这条子句已经被其他子句蕴涵”,而是一个可执行承诺:若模型没有满足被删子句,只翻转其中指定的一个变量,就能补上它,同时保住当时的其他子句。[1, §4;2, §3]
输入变量域为有限集合 ,子句为无重复文字的有限集合。输入中同一子句可有不同编号;包含 的重言子句在进入本接口前删除,空子句保留。再指定冻结变量集 ,编码列表中的变量必须互异,重构时这些变量不许改变。没有这种要求时取 。
设活动公式为 ,,文字 。若对每个含 的活动子句 ,归结式理路归结反驳Resolution refutation · Propositional resolution从 CNF 初始子句反复归结并导出空子句的命题反驳系统。
都含某一对互补文字,则称 阻塞 。如果没有含 的子句,全称条件直接成立;纯文字是这一空候选集合的特例。空子句没有可选文字,不能用这条规则删除。
本页只允许在 时删除 。每次在日志末尾记录当时的子句身份和阻塞文字 ,再从活动式移除 。反复执行,直到没有允许删除的子句。输出包括剩余公式、完整删除日志和已经到达不动点的事实。检查一份外部给出的部分删除日志则不要求它已经穷尽;每一步有效便足以支持之后的模型恢复。
翻转引理给出真正的保证
令 ,。若 ,无需改变。否则 中每个文字都假,把 改成真,得到 。这一定让 成真;需要证明没有把 中的某条子句弄坏。
不含 的子句不会因这次翻转失去原有真文字。含 的子句 才有风险。阻塞条件给出归结式中的互补对;由于 本身都不是重言子句,这对文字必须跨在两个余部:存在 ,使 。原模型令 假,所以令 真;该变量不同于 pivot,翻转后仍真。因此 还有一个没有被碰到的出口。
这证明 。反方向更直接:满足 的赋值自然满足删去一个约束后的 。所以两式等可满足,但它们未必具有相同模型集合。允许翻转正是恢复保证与逐赋值等价之间的差别。
直觉
阻塞文字不是必然为真的文字
一条子句可以靠多个文字满足。假如现在它全假,指定的 pivot 就是一只可以安全拨动的开关。与它相反的文字可能原本帮其他子句取真,因而不能只说“把这一位改好就行”;阻塞条件逐条检查那些可能受伤的子句,保证每一条都藏着另一项真文字。
删除顺序与模型修复顺序 这也说明为何要保存删除时刻的理由。较早删除的子句在后续步骤中已经不参与阻塞检查;后来选出的 pivot 未必能保护它。恢复必须沿相反顺序,使每次翻转面对的,恰是那次删除时仍需保护的约束。
先找删除点,再消费修复栈
下载程序的 eliminate 按活动编号顺序扫描子句,再按输入的文字顺序寻找第一个非冻结阻塞文字。找到后删除一条并重新扫描。它不调用SAT判定器,也不靠某个试验赋值决定是否可删。每次成功删除都让活动子句数减少一,最多删除原有的 条。
replay_bce 接受外部删除日志时重新检查:编号当前活动、pivot确实属于子句、变量未冻结、全部反pivot候选都通过。它返回经过验证的修复栈。restore 的前提是使用这个栈,并接收定义在整个原变量域上的总赋值;简化式不再提到的变量仍可先任意填值。
恢复从栈顶往下走:已满足的子句直接跳过,全假的子句才把记录的 pivot 置真。归纳不变量是“当前模型满足已恢复的全部子句及最终剩余式”。翻转引理维持它;栈耗尽时得到原公式模型。完整 certify_sat 还会重新扫描原公式核验最终赋值。
例子与边界
三个子句,两次必要翻转
取 ,,编号如下:
初始两个变量都以两种极性出现,没有纯文字。 的两个 pivot 都失败:以 和 归结得到 ,以 和 归结得到 ,都不是重言子句。 却由 阻塞:唯一含 的 给出 。
先删 。此时 消失, 中的 成为纯文字,故再删 。最后删 ,得到空子句集。原公式唯一模型是 ;空子句集却接受全部四个赋值。
选择最容易写下的简化模型 ,逆序恢复:
| 恢复子句 |
进入时的 |
检查与动作 |
离开时 |
| ,pivot |
|
已真,不翻 |
|
| ,pivot |
|
两项都假,令 |
|
| ,pivot |
|
两项都假,令 |
|
最后三个原子句分别至少有 为真。若错误地正序恢复,第一步 已由 满足,第二步把 改成1,第三步又由 满足,于是停在 ,恰好弄坏已经检查过的 。
冻结查询变量,避免把假设改掉
假设应用随后要问原公式在 下是否有解。若只保存不受限制的空简化式,答案会误变为有解;恢复算法最终把 改成1,不能算满足原查询。一次性的等可满足预处理不会自动支持以后追加任意假设。
把 放入 后, 的 不能用作删除pivot。扫描会改为删除 ,其 与 的归结式为 。剩余 不再允许删除,且仍迫使 。任意剩余模型均可只改 恢复,因此查询 仍正确得到无扩张。
一般地,对每个固定的 ,都有
这是冻结pivot限制加上翻转引理的直接推论。它允许对冻结变量追加任意布尔约束,不能保证在非冻结变量上追加约束也安全。模型计数同样要谨慎:上例从一个模型变成四个,重构函数可以把多个简化模型送到同一个原模型。
一个漏检就足以弄坏恢复
对 ,子句 不能由 阻塞,因为归结式为 。若漏掉唯一反pivot子句而错误删除它, 满足剩余式;修复把 置1之后, 变假。这与合法例中的互补保护形成逐项对照。
推论与应用
穷尽删除的剩余式唯一,恢复的模型可以不同
删除其他子句只会减少一个阻塞检查需考虑的反pivot候选,不会让已经有效的阻塞文字失效。因此同一固定 下,任意穷尽删除顺序都到达相同的剩余子句集。[1, §4]
可以不借助额外定理证明这个结论。取两个终态 ,按产生 的删除顺序考察每条子句。假设此前被删的子句在 中也都不存在。如果本条仍在 ,那么 是其删除时活动式的子集,它在 中仍被同一非冻结文字阻塞,与 已终止矛盾。所以产生 时删除的每条子句也都不在 ,得 ;交换两序列再得反包含。
该结论说的是剩余公式,不是删除日志或所选模型。改变pivot、初始简化模型或恢复次序中的合法选择,可能得到不同原模型;所有输出仍须逐子句满足原式。
把搜索、验证和恢复的费用分开
设输入有 个声明变量、 条子句、 次输入文字出现(含随后合并的重复文字),散列表查询按期望常数成本计。单次固定 检查扫描全部活动子句,并在反pivot子句中找跨集合的互补项,时间 。程序不实际反复拼接归结式,因而无需每检查一个 就复制整份 。
一轮最多尝试 个pivot并检查 个表头,成功删除至多 次。因此参考器的全部寻找过程有保守界
这不是高性能SAT预处理器的索引界。公式与修复栈的文字存储为 ;冻结变量表另计 。已验证栈上的恢复加前后模型扫描为 时间,输出模型占 ,修复事件只记录编号、pivot和是否翻转,不复制整张赋值表。
公开 certify_sat 还先重放外部日志,至多做 次固定pivot检查,所以其整体上界为 ,不能把核心恢复的线性界直接当成整个认证接口的成本。整数编码超过机器字时,编号和散列等操作另计位成本。
接到完整的双出口任务
对SAT结果,保留并验证删除日志,再恢复原模型。对UNSAT结果,若简化式已有可靠反驳,因为它是原式的子集,原式也不可满足;只有删得很短却没有模型或反驳,仍不能宣布答案。
反向加入一条被BCE删去的子句,也是RAT证书理路RAT子句证书检查RAT clausal proof checking · Resolution asymmetric tautology · RAT proof checking检查覆盖全部反pivot子句的RAT提示分支,以可满足性前向保持证明UNSAT,并区分局部传播、合法前缀与最终空子句。可检查的一步:每个反pivot的非pivot余部已经提供互补对。沿删除日志反向加入可以得到合法前缀,但合法前缀不自动构成UNSAT证书。
综合练习要求复算上述三个删除和两次翻转,冻结 后重新求终态,再核验三变量八子句的RAT反驳。最后去掉一个反pivot分支,定位检查器第一次拒绝的位置。
参考资料
[1] Matti Järvisalo、Armin Biere、Marijn Heule,Blocked Clause Elimination,TACAS 2010,LNCS 6015,pp.129–144;作者版§4,Definitions1–2、Propositions2–4;§5.1说明纯文字消除的特例。
[2] Matti Järvisalo、Armin Biere,Reconstructing Solutions after Blocked Clause Elimination,SAT 2010,LNCS 6175,pp.340–345;§3 Proposition3与逆序修复。本文的冻结变量投影结论由同一单步翻转引理推得,执行器只实现BCE及其重构。