SAT求解器破解公平分配难题:三智能体八物品EFX反例的发现

SAT求解器公平分配EFX
于 2026-06-02 03:18:31 修改
·本内容遵循CC 4.0 BY-SA版权协议

1. 项目概述:当公平分配遇上可满足性问题

在算法博弈论和计算经济学里,公平分配问题一直是个既迷人又棘手的老大难。想象一下,你和另外两个朋友要分八件不可分割的礼物,比如几本书、几件手办、几张游戏卡带。每个人对每件礼物的喜好程度天差地别,你梦寐以求的绝版漫画,在朋友A眼里可能不如一张普通的音乐专辑。目标很简单:分完之后,没人会强烈嫉妒别人。更具体地说,EFX(Envy-freeness up to any item,无嫉妒性最多去除任何一件物品)这个公平性标准要求:对于任何两个智能体(比如你和朋友A),你都不会“强烈嫉妒”朋友A分到的那一堆东西,哪怕从他那一堆里拿走任意一件你最眼红的物品,你依然觉得自己的这堆不比他的差。

听起来很理想,对吧?长久以来,学界的一个核心猜想是:对于任意三个智能体,无论他们有什么样的单调偏好(东西越多总不会越讨厌),EFX分配总是存在的。这个猜想牵动着许多研究者的心,因为它触及了公平分配理论的核心——在个体偏好各异且物品不可分割的约束下,我们能在多大程度上实现“无嫉妒”的公平。然而,猜想归猜想,证明或证伪它需要处理天文数字般的组合可能性。三个智能体,八件物品,所有可能的分配方式有 3^8 种,而每个智能体对所有物品子集(2^8=256个)的偏好排序更是复杂得惊人。手动枚举验证?几乎不可能。

这就是我们项目的起点:将EFX分配的存在性问题,编码成一个可满足性问题(SAT)。简单来说,我们把“是否存在一个EFX分配”这个逻辑问题,转化成一堆布尔变量的逻辑公式(合取范式,CNF)。如果这个公式是可满足的(SAT),就意味着存在一个满足所有EFX条件的分配;如果是不可满足的(UNSAT),则证明对于给定的偏好,EFX分配不存在。我们的目标,就是利用现代SAT求解器这种“计算显微镜”,去审视这个猜想的边界。最终,我们不仅验证了对于三个智能体和七个物品,EFX总是存在,更重要的是,我们构造出了第一个反例:对于三个智能体和八个物品,存在一组单调的偏好估值,使得没有任何分配能满足EFX条件。这个反例的发现,彻底解决了这个悬而未决的理论问题。

2. 核心思路:从组合问题到SAT编码的桥梁

将EFX问题转化为SAT,绝非简单的“暴力枚举”。其核心在于如何精巧地利用逻辑约束,来刻画“分配”和“估值比较”这两个核心概念,同时避免编码规模爆炸,让求解器能够处理。

2.1 问题形式化与核心变量定义

首先,我们需要用数学语言严格定义问题。设有三个智能体(0, 1, 2)和 m 件物品。每个智能体 i 对所有物品子集 S 有一个估值函数 v_i(S),这个函数是单调的(即若 S ⊂ T,则 v_i(S) < v_i(T)),并且我们将估值简化为一个全序关系:对于任意两个不同的子集 A 和 B,要么 v_i(A) < v_i(B),要么 v_i(B) < v_i(A)。我们的目标是找到一个将全部物品分给三个智能体的分配 (X0, X1, X2),使得对于任意两个不同的智能体 i 和 j,以及任意属于 Xj 的物品 g,都有 v_i(Xj \ {g}) ≤ v_i(Xi)。注意,这里要求的是“≤”,即非严格小于,这对应着“不强烈嫉妒”。

SAT编码的核心是引入布尔变量来表征这些关系。我们为每个智能体 i,以及每一对不同的物品子集 A 和 B(A < B,这里“<”可以定义为某种规范序,如按二进制表示的大小),引入一个命题变量 x_i_AB。这个变量的真值解释为:x_i_AB = TRUE 当且仅当 智能体 i 认为子集 A 的价值小于子集 B 的价值,即 v_i(A) < v_i(B)。

为什么选择“小于”关系作为变量? 这是关键的一步。直接编码估值函数 v_i(S) 的具体数值会引入整数或实数变量,问题会升级为更复杂的SMT(可满足性模理论)问题。而只编码两两之间的序关系,则能保持在纯布尔逻辑的范畴内,可以调用成熟且高效的CDCL(冲突驱动子句学习)SAT求解器。只要我们能通过子句(Clause)刻画出一个一致的、符合单调性等约束的全序,那么这个序本身就直接定义了一个估值函数(例如,将子集按其在这个序中的排名作为估值)。

2.2 约束系统的构建:从公理到EFX条件

有了变量,接下来就需要用合取范式(CNF,即子句的合取)来刻画所有必须满足的条件。

  1. 全序公理:对于每个智能体 i,其变量 x_i_AB 必须构成一个严格的线性序。

    • 反对称性:不能同时有 A < B 和 B < A。这天然由我们只对 A < B 定义变量 x_i_AB 来保证。对于 B < A 的情况,我们用 ¬x_i_AB 来表示(即 B 不小于 A,意味着 A < B 为假,在严格全序下即 B < A 为真)。
    • 传递性:这是编码中子句数量爆炸的主要来源。对于任意三个不同的子集 A, B, C,我们必须添加子句来保证:如果 A < B 且 B < C,那么 A < C。即 (¬x_i_AB ∨ ¬x_i_BC ∨ x_i_AC)。对于 m 件物品,有 2^m 个子集,传递性子句的数量是 O((2^m)^3),这是无法承受的。因此,如何优化传递性约束,是编码能否成功的关键。
    • 连通性:对于任意 A ≠ B,要么 A < B,要么 B < A。这通过为每一对 (A, B) 包含变量 x_i_AB 或其否定来体现,最终由求解器确定。
  2. 单调性约束:这是EFX问题特有的核心约束。如果子集 A 是 B 的真子集 (A ⊂ B),那么对于任何智能体 i,必须有 A < B。这直接翻译为一组单元子句(Unit Clause)(x_i_AB)。这些子句是求解器在预处理阶段就可以直接化简的强约束,能极大缩小搜索空间。

  3. EFX条件编码:这是整个公式的最终目标。我们需要表达:“存在一个分配 (X0, X1, X2),使得对于所有智能体 i, j (i ≠ j) 和所有 g ∈ Xj,都有 v_i(Xj \ {g}) ≤ v_i(Xi)”。

    • 首先,“存在一个分配”需要遍历所有可能的分割。对于三个智能体和 m 件物品,分配的总数是 3^m(每件物品有3种去向)。我们需要用一个大的析取(OR) 来覆盖所有可能性。
    • 对于每一个固定的分配 (X0, X1, X2),我们需要表达其满足EFX条件。这又是一个合取(AND):对于所有 i, j, g,要求 v_i(Xj \ {g}) ≤ v_i(Xi)
    • 而“≤”关系,用我们定义的布尔变量来表达,就是:NOT( v_i(Xi) < v_i(Xj \ {g}) )。即,¬x_i_{Xi}{Xj\{g}} 必须为真(当 Xi 和 Xj{g} 不同时)。如果两者相同,则条件自动满足。
    • 因此,整个EFX条件最终被编码为一个巨大的析取范式(DNF),其中每一项对应一个分配,而每一项内部是一系列文字(变量或其否定)的合取。通过标准的转换(如Tseitin变换),可以将这个DNF转化为等价的CNF,虽然会引入额外的辅助变量,但结构是规整的。
  4. 对称性破缺与层级化:为了进一步帮助求解器,我们引入了两项关键优化。

    • 物品排序:我们固定智能体0对单件物品的估值顺序,例如规定 v0({g0}) < v0({g1}) < ... < v0({gm-1})。这并不会丢失一般性,因为对于任何实例,我们都可以通过重排物品编号来满足这一点。这添加了更多单元子句,减少了搜索空间。
    • 层级化:这是从理论分析中推导出的优化。我们发现,在EFX的背景下,估值函数的传递性约束不需要在所有三元组上完全展开。可以证明,只需要对满足一定大小关系的子集对施加传递性约束就足够了。具体来说,我们引入一个参数 k,只对满足 |A| ≤ |B| ≤ |C||C| - |A| ≤ k 的三元组 (A, B, C) 添加传递性子句。实验表明,取 k = m - 2 能在表达能力和公式规模间取得很好的平衡。这步优化将传递性子句的数量从天文数字削减到了可处理的范围,是项目能推进到 m=7 和 m=8 的关键。

最终,我们构建的CNF公式 Φ 的满足性与原问题等价:Φ 是可满足的,当且仅当,存在一组满足单调性和物品排序的估值,使得不存在EFX分配(即我们找到了一个反例)。反之,如果 Φ 不可满足,则证明对于所有满足约束的估值,EFX分配总是存在。

3. 编码实现与求解器调优实战

理论设计完成后,下一步就是将其转化为具体的代码和可执行的计算任务。这里充满了工程细节和调优技巧。

3.1 CNF生成器的编写

我们使用C++编写了CNF生成器 BasicGen.cpp。它的输入是物品数量 m 和层级化参数 k,输出是标准的DIMACS CNF格式文件,这是SAT求解器的通用输入格式。

关键实现细节:

  1. 变量映射:需要将三元组 (i, A, B) 映射到一个唯一的正整数变量索引。我们采用 VarIndex.mk(i, A, B) 这样的函数,确保编码和解码的一致性和高效性。
  2. 子集枚举与遍历:高效生成所有物品子集(0 到 2^m - 1),并计算其大小(cardinality),用于层级化过滤和单调性检查。
  3. 子句生成循环
    • 单调性子句:遍历所有智能体 i 和所有子集对 (A, B),如果 A ⊂ B,则输出一个正文字单元子句 x_i_AB
    • 传递性子句:三层循环遍历子集 A, B, C。只有当 A < B < C(按规范序),且满足层级化条件 |C| - |A| ≤ k 时,才生成子句 (¬x_i_AB ∨ ¬x_i_BC ∨ x_i_AC)。这里的规范序比较(如按整数大小)至关重要,它确保了反对称性,避免了生成冗余或矛盾的子句。
    • 物品排序子句:对于智能体0,生成单元子句 x_0_{gj}_{gk},其中 j < k,{gj} 表示只包含第 j 件物品的单元素集。
    • EFX条件子句:这是最复杂的部分。我们需要遍历所有 3^m 种分配。对于每种分配 (X0, X1, X2),生成对应的约束块。由于这部分会导致公式极度膨胀,在生成时需格外注意内存和性能。通常,EFX条件会被编码为公式的“目标”部分,而前面的公理和约束是“背景理论”。在DIMACS格式中,它们被共同罗列。

一个重要的取舍:最初我们尝试生成完整的、包含EFX存在性声明的CNF(即“存在分配使得...”),但这会导致公式结构复杂。后来我们转向了更直接的“反例存在性”编码:我们的CNF公式描述的是“一个满足单调性和物品排序,但不存在EFX分配的估值是否存在?”。公式可满足,就意味着找到了这样的反例估值。这种编码更自然地契合了SAT求解器寻找模型(赋值)的模式。

3.2 求解器选择与预处理

我们选择了 SPASS-SAT 作为主力求解器。它不仅是SAT求解器,还集成了强大的预处理和化简功能。对于我们的问题,生成的原始CNF包含大量单元子句(来自单调性和物品排序)。SPASS-SAT 的 -u 选项可以执行基于单元传播的化简,这能显著减少变量和子句的数量。

实验数据解读(以 m=6, k=4 为例):

  • 初始变量:6084个。
  • 初始子句数:189,723 条。
  • 经 SPASS-SAT 化简后子句数:47,310 条。
  • 运行时间:25.6 秒。
  • 内存占用:146 MB。

可以看到,化简步骤消除了近75%的子句,这为后续求解奠定了坚实基础。加上物品排序优化后,求解时间进一步缩短到0.53秒。这验证了理论优化和预处理的有效性。

3.3 攻坚克难:从 m=7 到 m=8 的突破

对于 m=7,问题规模急剧扩大。变量数达到 24,384 个,化简后子句仍有 680,779 条。SPASS-SAT 用了约30小时,生成了一个约35 GB的DRAT格式的不可满足性证明(证明该CNF无解,即对于7个物品,EFX分配总是存在)。这个结果被另一个高性能求解器 CaDiCal 在26小时内独立验证。DRAT证明则由 DRAT-trim 工具校验正确。这一过程确认了“三智能体七物品EFX恒存在”的结论。

然而,挑战在于 m=8。变量数暴涨至 97,920,化简后子句超过800万条。直接求解在可预见的时间内无法完成。我们需要给求解器“提示”。

灵感来源于对 m=7 证明的分析:我们检查了SPASS-SAT在证明UNSAT过程中的日志,发现它在证明结束前约半小时,首先推导出了7个单元子句。这些子句形式如 {g0,g1} <0 {g6},其含义是:在(反例)估值中,智能体0认为物品子集 {g0, g1} 的价值小于单件物品 {g6}。这揭示了反例估值可能具有的某种结构性特征。

我们的策略是:将这些在 m=7 证明中起关键作用的单元子句,作为“案例区分”的假设,推广应用到 m=8 的问题上。具体来说,我们尝试将这些子句中的物品索引进行合理推广(例如,将 g6 替换为 g7,即价值最高的物品),然后构造出 2^7 = 128 种可能的真假赋值组合。我们并行地提交这128个略有不同的CNF公式给求解器。令人惊喜的是,在其中一种赋值下,SPASS-SAT 在20小时内找到了一个可满足的模型(即一组赋值),而 CaDiCal 甚至在3小时内就找到了。这个模型,经过翻译和验证,正是一个期待已久的反例:一组三个智能体对八个物品的单调估值,使得没有任何EFX分配存在。

实操心得:利用证明轨迹启发搜索 当面对一个在合理时间内无法直接求解的巨型SAT问题时,分析一个更小规模但已解决的问题(如m=7)的求解过程,尤其是推导出的早期单元子句(学习到的冲突子句),往往能揭示问题实例的深层结构。将这些子句作为假设或分支定界的优先方向,可以极大地引导求解器避开无望的搜索空间,直指核心矛盾区。这不仅是SAT求解中的高级技巧,也是将求解器从“黑盒”工具变为“白盒”合作伙伴的关键。

4. 反例的深度解析与验证

找到SAT模型只是第一步。我们需要将这个由布尔变量赋值构成的模型,解释回具体的估值函数,并理解其结构,最后进行独立验证。

4.1 从SAT模型到估值表

SPASS-SAT 提供了 -x 选项,可以将找到的模型(即对所有 x_i_AB 变量的赋值)转换回具体的估值。对于每个智能体 i,模型定义了一个在所有 256 个物品子集上的严格全序。我们只需将这个全序记录下来,给每个子集赋予一个唯一的排名(从0到255),就得到了估值函数 v_i(S)。项目配套材料中的 Val0ByCard.txtVal1ByCard.txtVal2ByCard.txt 文件正是按此方式生成,并按子集大小和字典序排列,便于查阅。

4.2 反例的结构性洞察

通过可视化(如图4、图5)和数据分析,我们得以窥见这个反例为何能打破EFX的存在性。

  1. 非加性与强互补性:估值远非简单的加性(即物品价值之和)。如图4所示,某些大小为2的子集(如Agent 0的 {g1, g2})价值非常高(排名77,意味着比很多更大的子集价值都高),而一些大小为4的子集价值却相对较低。这表明物品之间存在强烈的互补效应。图6进一步展示了一些违反“最大最小份额”(MMS)性质的集合对,例如对于Agent 0,有 min(v0({g1,g2}), v0({g0,g4,g7})) > max(v0({g2,g4}), v0({g0,g1,g7}))。这意味着将物品 {g1,g2,g0,g4,g7} 分成 ({g1,g2}, {g0,g4,g7}) 两份,其最小价值都大于另一种分法 ({g2,g4}, {g0,g1,g7}) 的最大价值。这种强烈的互补性破坏了公平分配中常见的均衡可能性。

  2. 边际价值的剧烈波动:如图5所示,同一件物品对于不同子集的边际价值差异巨大。例如,对于Agent 0,物品 g0 相对于某些大小为3的子集,边际价值低至1,而相对于另一些大小为4的子集,边际价值高达131。这种极端的上下文依赖性,使得“移除一件物品”这一EFX的核心操作,其效果变得极难预测和平衡,从而可能在任何分配中都至少会引发某个智能体对另一个智能体的强烈嫉妒。

  3. 距离EFX的“接近度”:我们检查了所有可能分配(共 3^8 = 6561 种,但许多因非划分无效,有效分配更少)对EFX条件的违反情况。有趣的是,有272种分配只违反一条EFX条件。这说明这个反例是“紧绷”的——它刚刚跨过不存在EFX的门槛,许多分配都几乎要满足条件了。这也解释了为什么寻找这个反例如此困难,以及为什么需要借助SAT求解器如此强大的搜索能力。

4.3 独立验证程序

为了确保万无一失,我们编写了一个独立的C++验证程序(附录C)。这个程序不依赖于SAT求解过程,只接受三个估值表作为输入,执行以下检查:

  1. 单调性验证:遍历每个智能体 i 和所有子集对 A, B,若 A ⊂ B,则检查是否满足 v_i(A) < v_i(B)。
  2. EFX存在性穷举检查:遍历所有可能的划分 (A, B, C)(A∪B∪C = 全集,且两两不交)。对于每个划分,检查它是否构成一个有效的分配(每个包非空),然后检查是否满足EFX条件:对每个智能体,检查其是否嫉妒其他智能体的包在移除任意一件物品后的情况。

该程序运行仅需数秒,并确认了在这组给定的估值下,确实不存在任何EFX分配。这为我们的发现提供了坚实、可重复的计算验证。

注意事项:验证的完备性与效率 穷举所有划分对于 m=8 是可行的(组合数在可接受范围),但对于更大的 m 则不可行。我们的验证程序是针对这个特定反例的最终确认。SAT求解过程本身,加上DRAT证明的校验,已经构成了一个形式化程度更高的证明链。独立验证程序的意义在于提供一个简单、透明、易于理解的“第二意见”,这对于让更广泛的学术界理解和接受反例至关重要。

5. 理论延伸:更多智能体与物品,以及SMT编码的尝试

反例的构造并非终点。我们进一步探索了其理论外延和替代编码方法。

5.1 反例的推广

我们证明了,对于任意 n ≥ 4 个智能体,存在包含 m = n + 5 件物品的实例,其中不存在EFX分配。构造方法基于我们找到的三智能体八物品反例进行扩展:

  1. 保留原始的8件物品 G = {g0, ..., g7} 及其对前三个智能体(0, 1, 2)的估值。
  2. 引入 n-3 件新物品 H = {h0, ..., h_{n-4}}。
  3. 设定智能体 0 和 1 对新物品 H 的估值恒为 0(即完全不关心)。
  4. 设定智能体 2, 3, ..., n-1 对原始物品 G 的估值与智能体2相同,并且赋予他们一个巨大的常数 M(大于智能体2对全集G的估值),只要分配的包中包含任何一件新物品 H,其估值就是 M。
  5. 通过反证法可以证明,在这样的设定下,如果存在一个EFX分配,那么它必然会在前三个智能体和原始物品 G 上诱导出一个EFX分配,这与我们的基础反例矛盾。对于更多物品,只需添加价值为0的“虚拟物品”即可。

这一推广表明,EFX的不存在性并非孤例,而是一个随着智能体数量增加,可以用固定模式构造的系统性现象。

5.2 迈向SMT编码

虽然SAT编码取得了成功,但其子句数量随物品数指数级增长。一个更自然的思路是使用可满足性模理论。SMT允许在布尔逻辑中直接使用实数变量和算术约束。我们可以为每个智能体 i 和每个子集 A 引入一个实数变量 v_i_A 来表示其估值。约束包括:

  • 非负性:v_i_A ≥ 0
  • 单调性:若 A ⊂ B,则 v_i_A < v_i_B
  • 物品排序:对智能体0,v0_{gj} < v0_{gk} (j < k)
  • EFX条件:存在一个分配 (A0, A1, A2),使得对所有 i≠j 和 g ∈ Aj,有 v_i_{Aj\{g}} < v_i_{Ai}

这样编码的公式在概念上更直观,也更紧凑。对于 m=7,EFX约束部分只有约15000个节点(表示为布尔电路),远少于SAT编码的数百万子句。我们使用Z3定理证明器进行了尝试。对于 m=4,5,6,Z3都能在较短时间内证明EFX存在(返回UNSAT)。然而,对于 m=7,Z3在40小时内未能给出结果。这表明,尽管SMT编码更简洁,但当前SMT求解器在处理这种存在性量词(分配的存在性需要析取所有可能性)与复杂算术约束组合的问题时,其搜索能力可能仍不及高度优化的CDCL SAT求解器针对纯布尔逻辑的推理。

6. 工具链、复现与开源

本项目的完整可复现性是其科学价值的重要组成部分。所有代码、数据、证明和结果均已开源。

核心资源包括:

  1. SAT实例与生成器:包含针对不同物品数量 (m) 和参数 (k) 生成的DIMACS格式CNF文件,以及用于生成它们的C++程序 BasicGen.cpp
  2. 求解器与验证工具:提供了SPASS-SAT的静态Linux二进制文件,以及用于将SAT模型翻译回估值并验证的脚本 (SPASS-SAT -x)。
  3. 反例估值数据:三个智能体对256个子集的完整估值表,以多种格式提供。
  4. 形式化证明开发:使用Lean定理证明器对部分理论(如SAT编码的正确性)进行了形式化,确保了数学推导的绝对严谨。
  5. 验证程序:附录C中给出的独立C++验证程序,可供任何人下载、编译并运行,以确认反例的正确性。

复现步骤建议:

  1. 环境准备:一个Linux服务器或虚拟机,具备足够内存(处理m=8需要数十GB)。
  2. 生成CNF:修改 BasicGen.cpp 中的 mk 参数,编译并运行,生成 EFX8.cnf 等文件。
  3. 求解:使用提供的SPASS-SAT求解器运行 ./spass-sat EFX8.cnf。注意,直接求解原始文件可能耗时极长,建议使用我们从m=7证明中推导出的7个单元子句作为假设进行引导求解(具体子句见论文正文)。
  4. 解释与验证:使用 ./spass-sat -x EFX8.model 将输出的模型转换为估值,并利用验证程序进行最终确认。

7. 总结与展望

这项工作通过将EFX公平分配的存在性问题转化为SAT问题,并借助现代SAT求解器的强大能力,最终解决了算法博弈论中一个重要的开放性猜想:对于三个具有单调偏好的智能体,EFX分配在八个物品时并不总是存在。我们不仅给出了反例,还通过详尽的实验分析了问题规模与求解难度之间的关系,探索了层级化、对称性破缺等关键优化技术,并尝试了SMT等替代编码方法。

从方法论上看,这项工作展示了“计算验证”在解决复杂组合存在性问题上的强大威力。 当理论分析遇到瓶颈时,将问题形式化并诉诸计算,有时能开辟新的道路。这里,SAT求解器扮演了“超级推理引擎”的角色,在巨大的组合空间中完成了人类难以企及的搜索和推理。

留下的开放问题依然激动人心:

  • 对于四个或更多智能体,EFX在什么条件下存在?已知对于 n 个智能体和 n+3 个物品,EFX总是存在;而我们的工作证明 n+5 个物品时不一定存在。那么 n+4 个物品的情况呢?
  • 如果对估值函数施加更强的限制(如加性估值),EFX是否总是存在?这是一个尚未解决的重要问题。
  • 我们的反例是针对EFX的,但它是否也否定了其他稍弱的公平性概念(如EF1)与认知性EFX(EEFX)的组合存在性?初步检查表明,这个反例仍然满足EEFX+EF1,因此寻找后者的反例可能需要更多物品和更复杂的构造。

最后,这个反例的发现虽然依赖于大量计算,但其结构本身值得进一步的理论分析。理解其背后破坏EFX存在的深层组合原理,或许能引导我们找到更简洁、更具启发性的反例构造方法,甚至推动对公平分配性质更本质的理解。计算与理论的这种互动,正是当前算法博弈论研究最富活力的前沿之一。