Spliddit 将几十年的公平分配理论研究成果包装成一个面向公众的网站,为房租分摊、物品分配和信用分享三类问题提供可证明公平的算法解决方案。
问题设定:\(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 有效,且算法保证当非负价格的无嫉妒分配存在时输出非负价格。
实现细节:采用 Ünver(2007)基于 Gallai-Edmonds 分解引理的高效算法计算过需求房间集合。
问题设定:\(n\) 个玩家,一组物品(可整体或可分割),加性估值 \(V_i(X) = \sum_{j \in X} V_{ij}\)。每人在 Spliddit 上用 1000 分分配给各物品。
三级公平性(由强到弱):
算法策略:先找最高可行公平级别,再在该约束下最大化社会福利 \(\sum_i V_i(A_i)\)。用 IBM CPLEX 求解混合整数线性规划。
问题设定:\(n\) 个参与者,每人 \(i\) 上报其余人的贡献比例(不含自己),最终分配 100% 信用。
算法:de Clippel et al.(2008)的规则族中的一个,具体使用算术平均作为聚合器(论文公式 17)。
关键保证:
约束:当 \(n=3\) 时,公正且共识的规则必然不精确(无法始终分配满 100%),因此 Spliddit 强制 \(n \ge 4\)。
核心思路:把找"无嫉妒价格"转化为找竞争均衡(Competitive Equilibrium)——价格向量 \(\mathbf{p}\) 使每个玩家在该价格下都恰好"愿意"拿被分配的房间,没有人宁愿换房。
算法步骤:
过需求集的高效计算依赖 Ünver(2007)基于 Gallai-Edmonds 分解引理(二部图最大匹配理论)的算法,避免暴力枚举所有子集。
| 玩家 | 大房(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!
继续迭代(实际算法更精细,这里简化说明)。最终均衡价格约为:
验证无嫉妒:
Carol 嫉妒 Bob!说明这不是真正的均衡价格,迭代需继续。这里仅演示流程,真实算法会精确收敛到无嫉妒点。关键结论是:只要无嫉妒分配(非负价格)存在,算法必然找到。
两阶段流程:
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 直接暴力求解。
| 玩家 | 笔记本(L) | 手机(P) | 平板(T) | 手表(W) |
|---|---|---|---|---|
| Alice | 500 | 300 | 150 | 50 |
| Bob | 200 | 200 | 400 | 200 |
| Carol | 300 | 100 | 100 | 500 |
计算 MMS(Alice):Alice 把 4 件物品分成 3 堆,最大化最小堆:
计算 MMS(Bob):
计算 MMS(Carol):
阶段一:检验无嫉妒。尝试 Alice=L+P,Bob=T,Carol=W:
→ 无嫉妒分配存在,进入阶段二最大化社会福利。
阶段二:当前分配社会福利 = 800+400+500 = 1700。检验其他可能:
核心设计难点:任何人不能通过"给自己打高分"来提升自身份额——即必须满足公正性(Impartiality)。解法:玩家 \(i\) 的份额完全不依赖于 \(i\) 自己的上报,只由其他人对 \(i\) 的评价决定。
de Clippel 规则(等差均值聚合,公式 17)的直觉:
每人上报其余三人的贡献比例(自己除外):
| 上报者 ↓ / 被评 → | Alice | Bob | Carol | Dave |
|---|---|---|---|---|
| Alice 上报 | — | 40% | 40% | 20% |
| Bob 上报 | 50% | — | 30% | 20% |
| Carol 上报 | 40% | 30% | — | 30% |
| Dave 上报 | 35% | 35% | 30% | — |
第一步:对每人求"他人评价均值"(公正性的来源:自评不计入)
第二步:归一化(精确性修正)
注意:这里展示的是"简单均值+归一化"版本,实际 de Clippel 公式(Eq. 17)略有不同——它通过更精巧的线性组合在 \(n \ge 4\) 时实现精确性(exactness)且同时满足共识性(consensuality),即若所有人报告一致时直接输出该报告。上述简单均值在 \(n \ge 4\) 时的近似行为与之相近。
验证公正性:假设 Alice 把自己的上报改为 Bob=0%, Carol=0%, Dave=100%(极端操纵):
| 应用 | 公平性概念 | 最坏情形保证 | 附加性质 |
|---|---|---|---|
| 房租分摊 | 无嫉妒(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]
结论先行:不等价。自创算法在 \(n \ge 3\) 时不保证无嫉妒,且存在冲突未定义的情形。
Spliddit 的前端(React/jQuery)只负责收集输入和展示结果,算法本体是服务端 Java,实现 Abdulkadiroğlu-Sönmez-Ünver (2004) 的市场均衡算法:
数学保证:该算法输出唯一竞争均衡(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)。
形式化(设总租金为 \(R\),每人估值 \(V_{ij}\) 满足 \(\sum_j V_{ij} = R\)):
化简后,自创算法给出的价格有一个极简闭合公式:
\[ \boxed{p_j = R \cdot \frac{\max_i V_{ij}}{\sum_k \max_i V_{ik}}} \]即:每间房的价格 = 总租 × 该房最高竞价 / 所有房最高竞价之和。所有价格按同一比例因子 \(R/S\) 缩放。
自创算法没有规定"同一玩家赢多间房时怎么办"。这并非罕见边缘情形:
| 玩家 | A 房 | B 房 | C 房 |
|---|---|---|---|
| Alice | 600 | 300 | 100 |
| Bob | 500 | 250 | 250 |
| Carol | 100 | 200 | 700 |
(总租 R=$1000,加粗为各房最高出价)
Spliddit 的迭代算法自然绕开此问题:价格调整使"过度竞争"的房间变贵,直到每间恰好一人"最愿意"住为止。
即使凑巧每人恰好赢得一间房,自创算法的价格也不保证无嫉妒。下面是具体反例:
| 玩家 | A 房 | B 房 | C 房 | 竞价和 |
|---|---|---|---|---|
| Alice | 500 | 2000 | 500 | 3000 |
| Bob | 100 | 2100 | 800 | 3000 |
| Carol | 300 | 500 | 2200 | 3000 |
(总租 R=$3000,加粗为各房最高竞价;每人竞价和恰好等于总租)
现在检验 Alice(住 A 房,付 $312.50)是否嫉妒 Bob(住 B 房,付 $1312.50):
根本原因:自创算法价格 \(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 的迭代市场算法会将价格收敛到"竞争均衡",而不是手动枚举;上面只是展示满足无嫉妒的某个有效价格,实际输出由算法唯一确定。
| 性质 | Spliddit(市场均衡) | 自创算法(最高竞价) |
|---|---|---|
| 价格公式 | 迭代求解,无闭合式 | \(p_j = R \cdot \max_i V_{ij} / \sum_k \max_i V_{ik}\)(闭合式) |
| 房间分配 | 迭代均衡自然产生 | 每房给最高竞价者(冲突时未定义) |
| 无嫉妒(Envy-Free) | 始终保证 | 不保证(n≥3 时可能失效) |
| 计算复杂度 | 迭代+MILP,较复杂 | O(n²),闭合式直接计算 |
| n=2 特例 | 有效 | 有效(恰好满足无嫉妒),但价格不同 |
| 冲突处理 | 自然处理 | 未定义 |