<< 返回本书主页
<< Back to the afterword page

5 匹配市场

吕汶桧 Wenhui Lyu

Jan. 2022

codes

5.1 背景问题

偏好卖家图

亚当斯密提出,市场经济就像有一个“无形之手”,把各方都安排妥当。本节课我们的任务就是把这一理论模型化。

考虑如下一个情境:要把一堆物品分配给一群人,不同人的偏好可能发生冲突,如何分配是最优的?为了简化问题,我们考虑一个更具体的情境:把n件物品一一分配给n个人。

我们把每个人对每个物品的偏好,抽象为一个出价(估值)矩阵,买家i对物品j的出价vij越高,意味着买家i越想要物品j。此外,每种物品的价格也各不相同,这构成了一个价格矩阵,物品j的价格用pj表示。对于每一买家i,我们可以找出他最想要的物品j。具体地,我们要找出vijpj的最大值,因为这个差价定义了买家i能从物品j上获得的效用。

为了更形象地表示这一市场里每个人的的偏好情况,我们用一个二部图表示买家和物品,下图中左侧节点为物品(或“卖家”),右侧节点为买家。对于每一买家i,在ta与ta最想要的物品j之间做边(对应最大差价)。这样做出的图,就定义了体现买方喜好的一种二部图,称为“偏好卖家图”。

偏好卖家图

如果这一二部图里,每个买家的偏好恰好互不冲突,这一市场就存在“合理分配”。

以“物以稀为贵”促成“合理匹配”

对于一个特定的市场,亦即,对于特定的价格矩阵和特定的出价矩阵,不一定存在“合理分配”。为了解决这一问题,我们需要引入一个新的理论假设,“物以稀为贵”:如果买家的一个子集S所表达的偏好物品子集N(S)比S小,说明N(S)中的物品没法在S中无冲突地安排,意味着“稀有了”“紧俏了”,于是应该加价。这样的S称为“受限组”。

以“物以稀为贵”促成“合理匹配”的全过程就是,对全市场里所有紧俏的物品如此操作,不断迭代,直到这一市场存在“合理分配”。

我们设所有物品的初始价格为0,实现合理分配时的最终价格,由偏好矩阵决定,越受欢迎的物品价格越高。

以下图为例,abc的初始价格都为0。但此时,大家都想要物品a。也就是说,存在买家受限组S={x,y,z},此时的受限组邻居N(S)={a}

偏好卖家图

物品a紧俏,我们就把pa0提高到1。提价后,重新画偏好卖家图如下:

偏好卖家图

迭代操作,直到该市场存在合理分配,没有买家受限。

这一市场在价格向量为(3,1,0)时出现合理分配,我们把(3,1,0)称为清仓价格。

偏好卖家图

p.s. 当一个情境存在多个受限组时,选择哪一个受限组进行操作可能会影响最终的清仓价格,这意味着清仓价格不唯一。

对匹配算法的反思

我们可以证明,如此找出的合理分配,实现了社会福利的最大化。

给定清仓价格(p)和估值矩阵(V),每个买家从买到的物品身上获得的效用(估值与价格的差值)的总和max()是最大的,这一总和可以如此表达:

max()=i=1nmaxj=1,2,,n(vijpj)

对于任意一种分配方式,总有:

+=

因此,

max()+=max()

给定一组价格,匹配算法取到max()时,也同时取到了max()

这个算法有更广泛的应用:

另一个问题是,为什么提价时我们以1为单位呢?这是因为估值矩阵里的价差最小为1。提价+1,才能把价差1的偏好区别体现在市场分配上。如果提价时+2,可能导致一下子提价太多,大家都不想要这个商品了。

此外,匹配算法过程总能结束,我们可以给出一个数学证明。

定义一个势能函数:

P=i=1nmaxj=1,2,...,n(vijpj)+j=1npj

在匹配算法运行过程中,P逐渐减小:每一次进行操作时,+1一致地发生在买方受限组S关注的所有卖方N(S)上;由于S严格大于N(S)P每次增|N(S)|,至少减|S|,即P单调递减。

P又不能无限制地减下去,我们可以证明P0恒成立:

P=i=1nmaxj=1,2,...,n(vijpj)+j=1npji=1n(viipi)+i=1npi=i=1nvii0

P的减小总有个头,所以匹配算法一定能结束。

总之,我们把经济学中的经典概念,例如理性人、价格、供需关系、物以稀为贵、均衡、社会最优,做出了生动的表达,使用的是简单图论语言和计算过程描述,例如偏好卖家图、受限组、迭代调整价格、结束条件。

5.2 计算实践:实现匹配市场算法

codes

5.2.1 作业描述与算法思路

为了把这一模型放在一个更具体的场景中,李老师给全班的同学发放问卷,让班上的11个同学给出对11本书的出价,得到具体的出价矩阵如下:

序号西方哲学史中国历代政治得失尤利西斯致命的自负车浩的刑法题深度学习时间序列分析期权、期货及其他衍生产品红书历史的逻辑海德格尔哲学概论
1001050252010000
25101104040551030
3000100005050
420060200600003010
540103020525400353013
6101001020020002010
755305010050500802030
800000303070000
90201015301500550
101000350105545000
1120102000100001020

本次作业就是找出以上市场的最优匹配。我们输入以上估值矩阵,输出一组清仓价格、对应的偏好卖家图(二部图)上的一个完整匹配、对应的社会最优(值)。

根据前文,先设所有书的初始价格为零,根据估值矩阵和价格矩阵确定偏好卖家图,判断合理匹配是否存在,如果存在就输出合理匹配,不存在就找出受限组邻居(大家都想要的物品),对受限者邻居提高一个单位的价格。迭代运行以上算法,直到实现完整匹配。

编程中存在几个难点:

j1j2j3i1i2i4j1j2j3i1i2i4(000100000010000001100000010000001000)

i1想要j1A[i1][j1]=1,A[j1][i1]=1),i2想要j2i3想要j3。二部图矩阵的左上和右下总为0,因为一部内部没有边;而左下和右上表示不同部的两个元素之间的关系,可以是0,也可以是1。因此,二部图矩阵可以表示为以下一般形式:

[00/10/10]

5.2.2 编程实现与要点说明

李老师提供了perfect_match函数:输入表示偏好卖家图的二部图,如果存在完整匹配,返回True和完整匹配边集{ (i,matched[i]) for i in range(n) };如果不存在,返回False和一个受限组邻居{matched[n] for n in bfs_queue if n != i}

我们的任务,就是要根据出价矩阵和价格矩阵生成偏好卖家图,调用perfect_match函数,对受限组邻居进行加价;迭代这一过程,直到出现完整匹配。

第一步仍然是读取文件中的出价矩阵,存储在numpy 2d-arraybids里,具体代码类似1.2.1.2,数据见5.2.1。初始价格为[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

根据出价矩阵和价格矩阵,我先生成一个表示偏好卖家图的二部图。

具体地,对于买家i,我找出差价最大的物品,存储在bid_item这一列表里(可能有多个)。

market二部图里,前items个编码表示物品,剩下的编码表示买家。买家i想要物品kmarket二部图里就表示为

生成二部图market后,我就可以调用perfect_match函数。当市场不存在完整匹配时,我就对perfect_match返回的受限组邻居nb_set进行提价。

第一轮的运行结果如下:

迭代运行多轮,直到perfect_match(market)[0] = True,实现清仓。输出清仓价格:

接着就是输出匹配结果、计算社会福利。计算社会福利时,我需要把每个人为ta买到的商品的估值final_price加总。

具体结果如下:

另外,我还提供了查询每个人应该买什么书的代码:

输入我对应的编码,可以得到我应该买《中国历代政治得失》:

<< 返回本书主页
<< Back to the afterword page