Contents

Spliddit: Unleashing Fair Division Algorithms


作者Jonathan Goldman, Ariel D. Procaccia
机构Carnegie Mellon University
发表ACM SIGecom Exchanges, Vol. 13, No. 2, December 2014, pp. 41–46
链接sigecom.org/exchanges/volume_13/2/GOLDMAN.pdf

Spliddit 将几十年的公平分配理论研究成果包装成一个面向公众的网站,为房租分摊、物品分配和信用分享三类问题提供可证明公平的算法解决方案。

3应用场景
20,000+首周访客
2/3MMS 最坏情形保证
n ≥ 4信用分配人数下限
Spliddit 三大应用
Fig. 1 — Spliddit 的三个应用:房租分摊(Rent)、物品分配(Goods)、信用分享(Credit)

研究动机

三大应用

1. 房租分摊(Splitting Rent)

问题设定:\(n\) 个室友,\(n\) 个房间,总租金 \(R\)。每人 \(i\) 对房间 \(j\) 的估值为 \(V_{ij}\)(满足 \(\sum_j V_{ij} = R\)),准线性效用为 \(V_{ij} - p_j\)。

算法:来自 Abdulkadiroğlu et al.(2004)的市场算法——迭代地以相同速率提高过需求房间的价格、降低其余房间的价格,直至达到均衡。

公平保证无嫉妒(Envy-Free)分配,即对所有房间 \(j'\): \[ V_{ij} - p_j \;\ge\; V_{ij'} - p_{j'} \] 在此域中无嫉妒等价于 Pareto 有效,且算法保证当非负价格的无嫉妒分配存在时输出非负价格。

房租竞价界面
Fig. 2 — 房租分摊的竞价输入界面,每位用户填写对各房间的估值。

实现细节:采用 Ünver(2007)基于 Gallai-Edmonds 分解引理的高效算法计算过需求房间集合。

2. 物品分配(Dividing Goods)

问题设定:\(n\) 个玩家,一组物品(可整体或可分割),加性估值 \(V_i(X) = \sum_{j \in X} V_{ij}\)。每人在 Spliddit 上用 1000 分分配给各物品。

三级公平性(由强到弱)

  1. 无嫉妒(Envy-Free):\(V_i(A_i) \ge V_i(A_{i'})\) 对所有 \(i,i'\)——不可整除时常不可行。
  2. 比例公平(Proportionality):\(V_i(A_i) \ge V_i(G)/n\)——仍可能不可行。
  3. Maximin Share(MMS)保证: \[ \text{MMS}(i) = \max_{X_1,\ldots,X_n} \min_j V_i(X_j) \] 即玩家 \(i\) 若自己划分后最后拿的那份的最大可能值。算法保证 \(V_i(A_i) \ge \text{MMS}(i)\),退而求其次至少保证 \(\ge \tfrac{2}{3}\text{MMS}(i)\)(Procaccia & Wang 2014)。

算法策略:先找最高可行公平级别,再在该约束下最大化社会福利 \(\sum_i V_i(A_i)\)。用 IBM CPLEX 求解混合整数线性规划。

3. 信用分享(Sharing Credit)

问题设定:\(n\) 个参与者,每人 \(i\) 上报其余人的贡献比例(不含自己),最终分配 100% 信用。

算法:de Clippel et al.(2008)的规则族中的一个,具体使用算术平均作为聚合器(论文公式 17)。

关键保证

  • 公正性(Impartiality):玩家的信用份额与其自身上报无关,无法通过操纵自己的报告影响自身份额。
  • 共识性(Consensuality):若存在所有人都同意的分配,则以该分配为结果。

约束:当 \(n=3\) 时,公正且共识的规则必然不精确(无法始终分配满 100%),因此 Spliddit 强制 \(n \ge 4\)。

算法详解与例子

1. 房租分摊算法(市场均衡迭代法)

核心思路:把找"无嫉妒价格"转化为找竞争均衡(Competitive Equilibrium)——价格向量 \(\mathbf{p}\) 使每个玩家在该价格下都恰好"愿意"拿被分配的房间,没有人宁愿换房。

算法步骤

  1. 初始化:各房间价格相等,\(p_j = R/n\)。
  2. 每个玩家根据当前价格选择效用最高的房间(贪心)。
  3. 找"过需求集"(Overdemanded Set):某房间被多人同时首选 → 价格上涨;无人选 → 价格下降。两类价格以相同速率变化以保持 \(\sum p_j = R\)。
  4. 重复直至每个房间恰好被一人首选(均衡)。

过需求集的高效计算依赖 Ünver(2007)基于 Gallai-Edmonds 分解引理(二部图最大匹配理论)的算法,避免暴力枚举所有子集。

具体例子:Alice、Bob、Carol 分 3 个房间,总租 $3000

玩家大房(Big)中房(Med)小房(Sml)
Alice$1600$1100$300
Bob$1400$1200$400
Carol$900$1400$700

每行之和均为 $3000(总租)

第 0 步:初始价格 \(p_{Big}=p_{Med}=p_{Sml}=\$1000\)。

Big 被 Alice+Bob 同时选 → 过需求;Sml 无人选 → 欠需求。

迭代:令 \(p_{Big}\) 上升、\(p_{Sml}\) 下降(等速 \(\delta\)),\(p_{Med}\) 不变(只被一人选)。当 \(\delta = 200\) 时:

Bob 现在可以移到 Med 解决冲突 → 分配:Alice=Big,Bob=Med,Carol=Sml... 但 Carol 不选 Sml!

继续迭代(实际算法更精细,这里简化说明)。最终均衡价格约为:

p_Big = $1350, p_Med = $1050, p_Sml = $600 分配:Alice → Big(效用 = 1600−1350 = 250) Bob → Med(效用 = 1200−1050 = 150) Carol→ Sml(效用 = 700−600 = 100)

验证无嫉妒

Carol 嫉妒 Bob!说明这不是真正的均衡价格,迭代需继续。这里仅演示流程,真实算法会精确收敛到无嫉妒点。关键结论是:只要无嫉妒分配(非负价格)存在,算法必然找到


2. 物品分配算法(三级公平 + 社会福利最大化)

两阶段流程

  1. 阶段一:从强到弱依次检验:无嫉妒 → 比例公平 → 最大可行 α-MMS。每级都用线性规划或 MILP 判断可行性并求解。
  2. 阶段二:在阶段一找到的公平约束下,最大化社会总福利 \(\sum_i V_i(A_i)\)(再次 MILP)。

MMS 计算(对每个玩家 \(i\) 分别求解):

\[ \text{MMS}(i) = \max_{\text{partition } X_1,\ldots,X_n} \min_j V_i(X_j) \]

这是一个 NP-hard 的整数规划问题:把 \(|G|\) 件物品分成 \(n\) 堆,使最小堆的价值(按玩家 \(i\) 的估值)最大。Spliddit 用 CPLEX 直接暴力求解。

具体例子:Alice、Bob、Carol 分 4 件物品(各有 1000 点)

玩家笔记本(L)手机(P)平板(T)手表(W)
Alice50030015050
Bob200200400200
Carol300100100500

计算 MMS(Alice):Alice 把 4 件物品分成 3 堆,最大化最小堆:

尝试:{L}=500, {P,W}=350, {T}=150 → min=150 尝试:{L}=500, {P}=300, {T,W}=200 → min=200 ← 最优 尝试:{L,W}=550, {P}=300, {T}=150 → min=150 MMS(Alice) = 200

计算 MMS(Bob)

尝试:{T}=400, {P,W}=400, {L}=200 → min=200 ← 最优 尝试:{T,L}=600, {P}=200, {W}=200 → min=200 MMS(Bob) = 200

计算 MMS(Carol)

尝试:{W}=500, {L}=300, {P,T}=200 → min=200 ← 最优 MMS(Carol) = 200

阶段一:检验无嫉妒。尝试 Alice=L+P,Bob=T,Carol=W:

无嫉妒分配存在,进入阶段二最大化社会福利。

阶段二:当前分配社会福利 = 800+400+500 = 1700。检验其他可能:

候选分配(满足无嫉妒的): Alice={L,P}=800, Bob={T}=400, Carol={W}=500 → SW=1700 ✓ 最优 (例如 Alice={L}=500, Bob={T,W}=600, Carol={P}=100 也无嫉妒吗? Carol 嫉妒 Bob(Carol 评价 {T,W}=600 > 100)✗ 不可行) 最终输出:Alice → {笔记本, 手机},Bob → {平板},Carol → {手表}

3. 信用分享算法(公正同行评估)

核心设计难点:任何人不能通过"给自己打高分"来提升自身份额——即必须满足公正性(Impartiality)。解法:玩家 \(i\) 的份额完全不依赖于 \(i\) 自己的上报,只由其他人对 \(i\) 的评价决定。

de Clippel 规则(等差均值聚合,公式 17)的直觉:

  1. 每人 \(i\) 上报对其余 \(n-1\) 人的贡献比例向量 \(\mathbf{r}_i\)(和为 1,不含自己)。
  2. 对每个玩家 \(j\),收集所有其他人对 \(j\) 的评价,取算术均值得到"原始份额" \(\hat{s}_j\)。
  3. 由于原始份额之和不一定等于 1(\(n=3\) 时尤甚),用精确的线性修正使和恰好为 1(这正是 \(n \ge 4\) 时才完全精确的原因)。

具体例子:Alice、Bob、Carol、Dave 合写一篇论文

每人上报其余三人的贡献比例(自己除外):

上报者 ↓ / 被评 →AliceBobCarolDave
Alice 上报40%40%20%
Bob 上报50%30%20%
Carol 上报40%30%30%
Dave 上报35%35%30%

第一步:对每人求"他人评价均值"(公正性的来源:自评不计入)

Alice 的原始份额:来自 Bob(50%) + Carol(40%) + Dave(35%) 的均值 ŝ_Alice = (50 + 40 + 35) / 3 = 41.67% Bob 的原始份额:来自 Alice(40%) + Carol(30%) + Dave(35%) 的均值 ŝ_Bob = (40 + 30 + 35) / 3 = 35.00% Carol 的原始份额:来自 Alice(40%) + Bob(30%) + Dave(30%) 的均值 ŝ_Carol = (40 + 30 + 30) / 3 = 33.33% Dave 的原始份额:来自 Alice(20%) + Bob(20%) + Carol(30%) 的均值 ŝ_Dave = (20 + 20 + 30) / 3 = 23.33% 原始总和 = 41.67 + 35.00 + 33.33 + 23.33 = 133.33% ← 不等于 100%

第二步:归一化(精确性修正)

s_Alice = 41.67 / 133.33 = 31.25% s_Bob = 35.00 / 133.33 = 26.25% s_Carol = 33.33 / 133.33 = 25.00% s_Dave = 23.33 / 133.33 = 17.50% 总和 = 100% ✓

注意:这里展示的是"简单均值+归一化"版本,实际 de Clippel 公式(Eq. 17)略有不同——它通过更精巧的线性组合在 \(n \ge 4\) 时实现精确性(exactness)且同时满足共识性(consensuality),即若所有人报告一致时直接输出该报告。上述简单均值在 \(n \ge 4\) 时的近似行为与之相近。

验证公正性:假设 Alice 把自己的上报改为 Bob=0%, Carol=0%, Dave=100%(极端操纵):

ŝ_Alice 只用 Bob、Carol、Dave 对 Alice 的评价 → 完全不变! ŝ_Alice 仍 = (50 + 40 + 35) / 3 = 41.67% Alice 无法通过改变自己的上报来影响自身份额 ✓ (公正性成立)

公平性保证对比

应用 公平性概念 最坏情形保证 附加性质
房租分摊 无嫉妒(Envy-Free) 始终可行(价格可能为负但算法尽量非负) Pareto 有效
物品分配 MMS 保证(三级降级) \(\ge \tfrac{2}{3}\) MMS 始终可行 最大化社会福利
信用分享 公正性 + 共识性 公正性始终满足;\(n \ge 4\) 时精确 无法操纵自身份额

工程实现

系统架构流程 +
flowchart LR
    U([用户浏览器]) -->|HTTP| RoR[Ruby on Rails\nWeb App]
    RoR -->|ActiveRecord ORM| RDS[(Amazon RDS\nPostgreSQL)]
    RoR -->|异步任务| DJ[Delayed Job\n后台队列]
    DJ -->|调用| JVM[Java 算法引擎]
    JVM -->|房租| Rent[Gallai-Edmonds\n市场算法]
    JVM -->|物品| CPLEX[IBM CPLEX\nMILP 求解器]
    JVM -->|信用| Credit[de Clippel 公式\n算术均值聚合]
    RoR -->|部署| EB[Elastic Beanstalk\n自动伸缩]
    RoR -->|邮件| SES[Amazon SES]
          

局限与展望

主要参考文献
Abdulkadiroğlu, Sönmez, Ünver (2004). Room assignment-rent division: A market approach. Social Choice and Welfare 22(3). de Clippel, Moulin, Tideman (2008). Impartial division of a dollar. Journal of Economic Theory 139. Procaccia, Wang (2014). Fair enough: Guaranteeing approximate maximin shares. EC 2014. Su (1999). Rental harmony: Sperner's lemma in fair division. American Mathematical Monthly 106. Steinhaus (1948). The problem of fair division. Econometrica 16.

算法对比:Spliddit vs 自创最高竞价算法

结论先行:不等价。自创算法在 \(n \ge 3\) 时不保证无嫉妒,且存在冲突未定义的情形。

1. Spliddit 实际算法(竞争均衡迭代法)

Spliddit 的前端(React/jQuery)只负责收集输入和展示结果,算法本体是服务端 Java,实现 Abdulkadiroğlu-Sönmez-Ünver (2004) 的市场均衡算法:

  1. 初始化:令所有房间价格相等,\(p_j^{(0)} = R/n\)。
  2. 需求计算:每个玩家 \(i\) 在当前价格下选"效用最大的房间": \[ D_i(\mathbf{p}) = \arg\max_j \bigl(V_{ij} - p_j\bigr) \]
  3. 过需求集检测(Gallai-Edmonds 分解):找集合 \(T \subseteq \text{Rooms}\) 使得 \(|\{i : D_i \cap T \ne \emptyset\}| > |T|\)(想要 \(T\) 中房间的人比 \(T\) 中房间数多)。这是过需求(overdemanded)集。
  4. 价格调整:以相同速率 \(\delta\) 提高所有过需求房间价格,降低所有欠需求房间价格,保持 \(\sum_j p_j = R\)。
  5. 终止:当每个房间恰好被唯一一个玩家需求时停止。此时输出价格 \(\mathbf{p}^*\) 和对应分配 \(A^*\)。

数学保证:该算法输出唯一竞争均衡(Competitive Equilibrium from Equal Incomes, CEEI),满足:

\[ V_{i, A^*(i)} - p^*_{A^*(i)} \;\ge\; V_{i,j} - p^*_j \quad \forall i,\, \forall j \]

即:任何玩家用自己的价格算,都不希望换到别人的房间。这就是无嫉妒(Envy-Free)


2. 自创算法(最高竞价 + 比例返还)

形式化(设总租金为 \(R\),每人估值 \(V_{ij}\) 满足 \(\sum_j V_{ij} = R\)):

  1. 房间 \(j\) 分给最高竞价者:\(w_j = \arg\max_i V_{ij}\)
  2. 令 \(S = \sum_j \max_i V_{ij}\)。因为 \(\sum_j \max_i V_{ij} \ge \max_i \sum_j V_{ij} = R\),所以 \(S \ge R\) 恒成立。
  3. 超出量 \(E = S - R \ge 0\) 按竞价比例返还给各赢家。
  4. 赢家 \(w_j\) 实际支付:\(p_j = V_{w_j,j} - \frac{V_{w_j,j}}{S} \cdot E = V_{w_j,j} \cdot \frac{R}{S}\)

化简后,自创算法给出的价格有一个极简闭合公式:

\[ \boxed{p_j = R \cdot \frac{\max_i V_{ij}}{\sum_k \max_i V_{ik}}} \]

即:每间房的价格 = 总租 × 该房最高竞价 / 所有房最高竞价之和。所有价格按同一比例因子 \(R/S\) 缩放。


3. 失效情形一:同一玩家赢多间房(算法未定义)

自创算法没有规定"同一玩家赢多间房时怎么办"。这并非罕见边缘情形:

玩家A 房B 房C 房
Alice600300100
Bob500250250
Carol100200700

(总租 R=$1000,加粗为各房最高出价)

A 房最高竞价:Alice($600) ✓ B 房最高竞价:Alice($300) ← Alice 又赢了! C 房最高竞价:Carol($700) ✓ 结果:Alice 赢两间房,Bob 什么都没拿到 → 算法崩溃,未定义行为

Spliddit 的迭代算法自然绕开此问题:价格调整使"过度竞争"的房间变贵,直到每间恰好一人"最愿意"住为止。


4. 失效情形二:产生有效分配但不满足无嫉妒(核心反例)

即使凑巧每人恰好赢得一间房,自创算法的价格也不保证无嫉妒。下面是具体反例:

玩家A 房B 房C 房竞价和
Alice50020005003000
Bob10021008003000
Carol30050022003000

(总租 R=$3000,加粗为各房最高竞价;每人竞价和恰好等于总租)

自创算法分配: A → Alice (500 > 300 > 100) B → Bob (2100 > 2000 > 500) C → Carol (2200 > 800 > 500) S = 500 + 2100 + 2200 = 4800 比例因子 R/S = 3000/4800 = 0.625 定价: p_A = 500 × 0.625 = $312.50 p_B = 2100 × 0.625 = $1312.50 p_C = 2200 × 0.625 = $1375.00 总和 = $3000 ✓

现在检验 Alice(住 A 房,付 $312.50)是否嫉妒 Bob(住 B 房,付 $1312.50):

Alice 住 A 的效用 = 500 - 312.50 = $187.50 Alice 如果住 B = 2000 - 1312.50 = $687.50 $687.50 > $187.50 → Alice 嫉妒 Bob! ✗ 无嫉妒条件不满足

根本原因:自创算法价格 \(p_j \propto \max_i V_{ij}\)——谁赢了这间房价格就按他的出价来算。但 Alice 赢 A 房是"以很低出价(500)碰巧胜过其他人更低的出价",A 房因此被定得很便宜($312.50)。而 B 房因为 Bob 激烈竞价(2100)被定得较贵($1312.50),但对 Alice 来说 B 房值 $2000,仍然划算——自创算法的价格没有在 A/B 之间建立正确的"价差壁垒"来阻止 Alice 觊觎 B。

Spliddit 为同一分配(A→Alice, B→Bob, C→Carol)找到满足无嫉妒的价格,例如:

Spliddit 可行价格(满足无嫉妒约束的解之一): p_A ≈ $100, p_B ≈ $1700, p_C ≈ $1200 (总和 $3000 ✓) 验证 Alice 不嫉妒 B: Alice 住 A = 500 - 100 = $400 Alice 如住 B = 2000 - 1700 = $300 < $400 ✓ → 不嫉妒

注:Spliddit 的迭代市场算法会将价格收敛到"竞争均衡",而不是手动枚举;上面只是展示满足无嫉妒的某个有效价格,实际输出由算法唯一确定。


5. 对比总结

性质Spliddit(市场均衡)自创算法(最高竞价)
价格公式迭代求解,无闭合式\(p_j = R \cdot \max_i V_{ij} / \sum_k \max_i V_{ik}\)(闭合式)
房间分配迭代均衡自然产生每房给最高竞价者(冲突时未定义)
无嫉妒(Envy-Free)始终保证不保证(n≥3 时可能失效)
计算复杂度迭代+MILP,较复杂O(n²),闭合式直接计算
n=2 特例有效有效(恰好满足无嫉妒),但价格不同
冲突处理自然处理未定义
附:n=2 时自创算法确实满足无嫉妒的证明
设 2 人 2 房,R 为总租。Alice: (a, R-a),Bob: (b, R-b),且 a > b(Alice 赢 A,Bob 赢 B)。 自创算法价格: p_A = R·a/(a + R-b) p_B = R·(R-b)/(a + R-b) 验证 Alice 不嫉妒 Bob(住 A 好于住 B): Alice 住 A 效用 = a - p_A = a·(R-b)/(a+R-b) Alice 如住 B 效用 = (R-a) - p_B = (R-a)·a/(a+R-b) - ... 完整展开: 住 A 效用 = a(R-b) / (a+R-b) 住 B 效用 = [(R-a)(a+R-b) - R(R-b)] / (a+R-b) = [Ra - ab + R²-Rb - aR + ab - R²+Rb] / (a+R-b) = [-a² + ab] / (a+R-b) = a(b-a) / (a+R-b) 因 a > b:a(b-a) < 0 < a(R-b) → Alice 不嫉妒 Bob ✓ 对称推导得 Bob 不嫉妒 Alice ✓ 结论:n=2 时自创算法满足无嫉妒,但给出的价格与 Spliddit 不同(Spliddit 给另一个无嫉妒点)。