忘れてください

Boosting MCSes Enumeration

23 min read

Boosting MCSes Enumeration#

背景与动机#

MCS 枚举的重要性#

计算不可满足 CNF 公式 的所有 MCS(Minimal Correction Subset,极小修正子集)或等价地计算所有 MSS(Maximal Satisfiable Subset,极大可满足子集)是许多 AI 任务的基本操作,包括:

  • 基于模型的诊断(Model-Based Diagnosis)
  • 信念修正(Belief Change)中的怀疑论推理(Skeptical Reasoning)
  • 不可满足性分析:因为 MUS(极小不可满足子集)的枚举可以通过先枚举所有 MCS 再利用 hitting set 对偶关系来完成

虽然 MCS 的数量在最坏情况下是指数级的,但在许多实际问题中,MCS 的数量是较低的,因此尝试枚举所有 MCS 在这些情况下是可行的。

预备知识#

基本定义#

给定一个 CNF 公式 ,我们定义以下概念:

也就是说,MSS 和 MCS 是互补的:,删去 MCS 中的子句后,剩下的就是一个极大可满足子集。

Partial-MSS 与 Partial-MCS#

当 分为硬子句 和软子句 时:

  • Partial-MSS:必须包含所有硬子句 ,在此基础上关于集合包含极大化包含的软子句
  • Partial-MCS:只从软子句 中选取,删去后使得 与剩余的软子句可满足

单个 MCS 的线性搜索#

子句选择器(Clause Selectors)#

对 中的每条子句 ,引入一个新的文字 (选择器),构成松弛公式:

\Sigma^S = \{\alpha \vee \neg s_\alpha \mid \alpha \in \Sigma\}

当 时,子句 被激活(必须满足);当 时,子句被去激活(自动满足)

转移子句(Transition Clause, TC)#

换言之,TC 就是一个单元素 MCS。同时,TC 也属于 的每一个 MUS。

ExtractPartialMCS:基本线性搜索(BLS)#

ExtractPartialMCS(Σ₁, Σ₂) 是整个枚举框架的基本子程序,其任务是:给定硬子句 和软子句 ,找出一个 Partial-MCS。

基本版本(BLS, Basic Linear Search)的流程如下:

  1. 初始化:(硬子句全部放入 MSS),
  2. 对 中的每条软子句 (通过选择器逐一激活):
    • 令 ,调用 SAT 求解器检查 是否可满足
    • 若可满足:将 加入 MSS()
    • 若不可满足: 此时是一个转移子句(TC),将 加入 MCS()
  3. 返回 MCS

增强线性搜索(ELS)#

ELS(Enhanced Linear Search)是 BLS 的改进版,通过以下技巧减少 SAT 调用次数:

  • 已计算模型的利用(Computed Models):当 SAT 求解器返回 SAT 时,会附带一个模型 。此模型满足当前所有已激活的子句。如果 同时也满足某些尚未考虑的子句 ,那么可以直接将 加入 MSS 而无需额外 SAT 调用(因为 就是 的一个模型)
  • 不相交核的利用(Disjoint Cores):当 SAT 求解器返回 UNSAT 时,会附带一个核(一组导致 UNSAT 的假设/选择器)。核中的每条子句都属于某个 MUS,因此可以一次性识别多个需要放入 MCS 的子句
  • 骨架文字(Backbone Literals):某些文字在所有模型中取值相同(称为骨架文字),利用骨架信息可以提前判断某些子句必然可/不可满足
  • MCS 析取:将当前 MCS 中所有子句的析取作为额外约束加入,这可以加速后续的 SAT 调用

基本 MCS 枚举算法#

Enum-ELS(算法 1)#

基本枚举框架如下:

  1. 对 构造松弛公式
  2. 初始化阻塞子句集
  3. 循环:当 可满足时
    • 调用 ExtractPartialMCS 提取一个 Partial-MCS
    • 输出
    • 添加阻塞子句 到 (防止同一 MCS 再次被计算)

枚举顺序与完备性#

一个自然的问题是:BLS/ELS 每次只找到一个 MCS,而且找到哪个取决于子句的考虑顺序。不同的顺序会产出不同的 MCS/MSS 对。那么外层循环如何保证找到所有 MCS?

答案在于阻塞子句 与终止条件的配合。我们分两步论证:

不重复性:每发现一个 MCS ,就添加阻塞子句 。这条子句要求 中至少有一条子句被激活(留在 MSS 中)。因此任何后续发现的 MCS 都不能完全包含 中的所有子句。又因为 本身是极小的(不能移除任何子句),所以 不可能等于 。

完备性(不遗漏):假设算法终止时( 不可满足),存在某个 MCS 未被发现。考虑如下赋值:对所有 令 ,对所有 令 。

  • 此赋值满足 :因为 是一个 MSS(可满足的),激活这些子句不产生矛盾
  • 此赋值满足 中的每一条阻塞子句:对于任何已发现的 ,由于两者都是极小修正子集,不可能 (否则由 的极小性得 ,矛盾)。因此存在 ,此 的选择器 ,从而阻塞子句 被满足

于是 在此赋值下可满足,这与终止条件矛盾。因此不存在未被发现的 MCS。

基于转移子句的加速枚举#

本文的核心贡献在于:利用转移子句的性质,从一次搜索中递归地构造多个不同的 MCS,从而减少 SAT 调用次数。

关键性质#

性质 1#

设 是不可满足的 CNF, 且 包含至少一个 TC 。对于所有能从 构建的 Partial-MCS , 是 的一个 MCS。

推论 1(Partial 版本)#

设 , 可满足, 不可满足。若 使得 含有 TC ,则对所有能从 构建的 Partial-MCS , 是 的一个 Partial-MCS。

性质 2(不同 TC 产生不同 MCS)#

如果 有两个不同的 TC ,则从 和 分别递归产生的 Partial-MCS 一定不同。

性质 1、推论 1、性质 2 的完整示例

构造一个稍大的不可满足公式来完整展示三个性质如何配合工作。

设 ,其中:

可以验证 不可满足( 要求 , 要求 ,矛盾就已经出现)。

现在假设在 TC-MCS 的增量构造中,我们按顺序激活 :

  • :SAT()✓
  • :SAT()✓
  • :UNSAT( 要求 , 要求 ,但 要求 或 )

所以 是 的一个 TC。


性质 1 的应用: 是 的 TC。令:

  • 硬子句:
  • 软子句:

在硬子句 (即 )的约束下,对软子句运行 ExtractPartialMCS:

  • :要求 (因为 ), SAT()→ 加入 MSS
  • :要求 或 ,但 , UNSAT → 加入 MCS
  • : 矛盾, UNSAT → 加入 MCS
  • : 矛盾, UNSAT → 加入 MCS

得到 。根据性质 1, 是 的一个 MCS。

验证:,即 ,令 即可满足。✓


但 中不止一个 TC! 让我们检查:

  • 是 TC 吗?,令 可满足 → 是 TC
  • 是 TC 吗?,令 可满足 → 是 TC
  • 是 TC 吗?,令 可满足 → 是 TC

三条子句都是 的 TC!(这是因为 本身恰好是一个 MUS——三条子句中任意删一条都可满足。)


推论 1 + 性质 2 的应用:现在令 ,,。三个 TC 各自产生一族 MCS:

TC = :硬子句 (即 且 ,因此 ),软子句

  • : 下自动满足 → 加入 MSS
  • : 下需 → 加入 MSS()
  • : 下自动满足 → 加入 MSS
  • : 矛盾 → 加入 MCS

,最终 MCS =

TC = :硬子句 (即 且 ,因此 ),软子句

  • : 下需 → 加入 MSS()
  • : 下自动满足 → 加入 MSS
  • : 矛盾 → 加入 MCS
  • : 下自动满足 → 加入 MSS

,最终 MCS =

TC = :如上面性质 1 所计算,MCS =


性质 2 的验证:三个 MCS 确实两两不同:

为什么保证不同?以 和 为例: 来自软子句 ,因此 。而 ,所以 。因此 不包含 ,但 包含 ,故两者一定不同。

一般地:不同 TC 来自 ,而对应的 来自 ,二者不相交。所以 TC 一定不在另一个 TC 的 中,从而 。


总结:从一次 UNSAT 证明( 不可满足)中,我们发现了 3 个 TC,一次性产出了 3 个不同的 MCS。而传统 Enum-ELS 每次只能产出 1 个 MCS。这就是 TC-MCS 的效率来源。

TC-MCS 算法(算法 2)#

输入:,其中 是尚未分配给 MCS 或 MSS 的选择器集合。

算法流程:

  1. 若 ,返回空集(递归终止条件)
  2. 初始化 (已计算的 Partial-MCS 集合),(已激活的选择器)
  3. 增量构造循环:从 中逐个取选择器 加入 ,直到 变为不可满足
    • 此时 就是一个 TC(因为加入它之前公式是可满足的,加入后变为不可满足)
  4. 提取核:从 SAT 求解器获取当前不可满足公式的一个核
  5. 寻找更多 TC:调用 Find-TC(基于模型旋转)在核 中寻找更多 TC
  6. 递归构造:对每个找到的 TC ,递归调用 TC-MCS: 将递归结果中的每个 Partial-MCS 加上 得到一个完整的 Partial-MCS
理解递归调用的参数

当 是核 中的一个 TC 时:

  • 将 中除了 对应子句以外的部分作为硬约束(因为 激活了这些子句)
  • 不在核 中但在 中的选择器,以及原来的 中未处理的选择器,作为待分配的软子句
  • 这样递归寻找新的 MCS,加上当前 TC ,得到原问题的一个 MCS

根据性质 2,不同 TC 产生的 MCS 族一定不重叠

Enum-ELS-RMR(算法 3)#

在基本枚举框架(算法 1)中,将 ExtractPartialMCS 替换为 TC-MCS:

  1. 构造 ,初始化
  2. 循环:当 可满足时
    • 调用
    • 对 中的每个 :输出并添加阻塞子句

递归模型旋转(Recursive Model Rotation, rmr)#

上述算法的关键子程序 Find-TC 使用了递归模型旋转(rmr)来高效地发现额外的 TC。

rmr 的原理#

基于此,rmr 的工作方式如下:

  1. 给定 的一个模型 (此模型不满足 )
  2. 从 中选取一个文字,翻转对应变量的值,得到新赋值
  3. 检查 是否满足 中除了某条子句 以外的所有子句
  4. 如果是,则 也是一个 TC(前提是它之前未被标记为 TC)
  5. 对 和 递归地重复这个过程

rmr 在 MCS 枚举中的应用#

在 TC-MCS 算法中,当增量构造到 不可满足时:

  • 我们已有 的一个模型 (上一轮 SAT 调用的副产品)
  • 是一个 TC
  • 使用 rmr 从 出发,通过翻转变量来寻找核 中的其他 TC
  • 重要限制:不翻转选择器变量本身,只翻转子句中的原始变量;只保留属于 的 TC

处理阻塞子句 的问题#

性质 3(可分离性)#

与 不共享文字: 中全是选择器的正文字组成的正子句,而 中选择器以负文字出现。因此 的可满足性可以被分解为两个独立的子问题:

\Sigma^S \cup \Delta \cup \bigwedge_{s \in P} s \cup \bigwedge_{s \in N} \neg s \text{ 可满足} \iff \Sigma^S \cup \bigwedge_{s \in P} s \text{ 可满足且 } \Delta \cup \bigwedge_{s \in N} \neg s \text{ 可满足}

其中 是选择器 集合 的一个划分。

性质 3 的完整示例

继续使用例 1 的公式 。

松弛公式:

假设前两轮已发现 和 ,则:

观察极性: 中选择器出现为 (全部取负); 中选择器出现为 (全部取正)。没有共享文字。


构造一个合法划分:取 (激活 ),(去激活 )。

检查 侧: 激活 ,,。

  • :
  • :需
  • ✓

模型 。SAT ✓

检查 侧:,即 , 自由。

  • :,需 → 满足
  • : → 满足

SAT ✓

两侧独立可满足 可满足。


增量构造:以 为起点,尝试将 中的选择器移入 。

移动 → :,激活 。 之前的模型 下 。UNSAT → 是 TC!

此时 。我们需要检查 侧吗?

:, 自由。

  • : → 满足
  • :满足

仍然 SAT ✓。实际上我们根本不需要做这个检查!因为 从 移到 意味着 从 变为 。 中只有正文字的选择器,把一个选择器从 变成 只会让更多析取项为真,永远不会破坏 的可满足性。

这就是性质 3 的核心推论: 的可满足性关于选择器取正是单调的。


rmr 中忽略 :发现 TC 后,运行 rmr。模型 (不满足 )。

翻转 :。检查所有已激活子句:

  • → 唯一被破坏的子句
  • ✓(之前的 TC 变为满足)
  • ✓
  • ✓

恰好只有 被破坏 → 也是一个 TC!

(不在 中)→ 接受。

如果翻转后发现被破坏的是 (),则拒绝——因为 留在 中是为了保证 可满足。虽然此例中 不出现在 里,但算法保守地禁止所有 中的选择器,以避免逐一检查 的开销。


总结此例:整个增量构造和 rmr 过程中,我们从未检查过 。只在初始阶段做了一次 侧的可满足性检查来确定 ,之后所有操作都在 侧进行。这就是性质 3 带来的效率提升。

具体做法#

  1. 先计算一个初始划分 ,使得 和 同时可满足
  2. 将 作为起点进行增量构造
  3. 中的选择器被标记——rmr 过程中禁止将 中的选择器标记为 TC
  4. 增量构造中选择器从 移到 时, 的可满足性自动保持(单调性),无需检查

对并行化的意义#

性质 3 表明 和 是两个解耦的约束系统。这为并行化提供了结构性基础:

  1. 计算密集的部分(TC-MCS 搜索、rmr)只操作 侧——这是可以并行的
  2. 簿记部分(阻塞子句 的管理)只涉及正文字子句,求解代价极低
  3. 多个 worker 可以从不同的初始划分 出发,各自独立地在 上搜索 TC 和 MCS,而不需要在搜索过程中同步 ——只需在每一批搜索结束后,将发现的 MCS 汇总更新到 中即可

实验#

实验设置#

  • 实现:C++,使用 Minisat 作为后端 SAT 求解器
  • Benchmark:
    • [Previti et al., 2017] 使用的 866 个实例(269 个 Max-SAT + 597 个 Partial-Max-SAT)
    • 额外加入 MUS 竞赛的 plain Max-SAT 实例
    • 共 1090 个实例(493 个 plain Max-SAT + 597 个 Partial-Max-SAT)
  • 环境:Intel Xeon E5-2643 (3.30GHz),64GB 内存,Linux CentOS
  • 限制:每个实例 1800 秒超时,8GB 内存限制

实验结果#

Enum-ELS-RMR vs. Enum-ELS(不使用 rmr)#

rmr 范式在所有 plain Max-SAT 实例上都能计算出更多(或同样多)的 MCS,对大多数 Partial-Max-SAT 实例也是如此。

Enum-ELS-RMR-Cache vs. Enum-ELS-RMR#

结合缓存技术后,Enum-ELS-RMR-Cache 在大多数情况下能枚举更多的 MCS。但缓存也有副作用:

  • 某些实例上,缓存的内存开销过大导致 memory-out
  • 这些实例上 Enum-ELS-Cache 本身就比 Enum-ELS-RMR 差

Enum-ELS-RMR-Cache vs. mcscache-els#

总结与展望#

核心贡献#

  1. 提出了基于 TC 的递归 MCS 枚举算法 TC-MCS
  2. 将 rmr 范式(原用于 MUS 枚举)创新性地应用到 MCS 枚举中
  3. 利用性质 3 的可分离性,避免 rmr 中处理阻塞子句的开销
  4. 与缓存技术兼容,组合后效果更优

未来方向#

  • 并行化:性质 3 的可分离性为并行枚举提供了可能
  • 局部搜索:用局部搜索来发现更多 TC
  • 偏好 MCS:当子句有偏好排序时,枚举所有偏好 MCS
  • 怀疑论推理:所有 MSS 的交集可以用于实现怀疑论推理

MUS-MCS 对偶关系#

CONVERSATION

讨论

想法、补充,或只是打个招呼。

关系图谱 ↓

全局关系图谱

页面标签
笔记
↑ ↓ 选择↵ 打开Esc 关闭