In [1]:
using MyMatching
まずは普通に。Wikipediaの例。
In [2]:
# 例-01
prop_prefs = [[1, 2, 3, 4], [3, 2, 1, 4], [1, 2, 4, 3], [3, 1, 4, 2]]
resp_prefs = [[1, 2, 3, 4], [2, 1, 4, 3], [2, 3, 1, 4], [1, 4, 3, 2]]
my_deferred_acceptance(prop_prefs, resp_prefs)
Out[2]:
提案を入れ替えてみる。
In [3]:
resp_prefs = [[1, 2, 3, 4], [3, 2, 1, 4], [1, 2, 4, 3], [3, 1, 4, 2]]
prop_prefs = [[1, 2, 3, 4], [2, 1, 4, 3], [2, 3, 1, 4], [1, 4, 3, 2]]
my_deferred_acceptance(prop_prefs, resp_prefs)
Out[3]:
この例では提案するのを男女入れ替えても一致する。
では、次のような少しいじった例を考える。
In [4]:
# 例-02
prop_prefs = [[1, 2, 3, 4], [3, 2, 1, 4], [1, 2, 4, 3], [4, 1, 3, 2]]
resp_prefs = [[1, 2, 3, 4], [2, 1, 4, 3], [3, 2, 1, 4], [1, 4, 3, 2]]
my_deferred_acceptance(prop_prefs, resp_prefs)
Out[4]:
提案を入れ替えてみる。
In [5]:
resp_prefs = [[1, 2, 3, 4], [3, 2, 1, 4], [1, 2, 4, 3], [4, 1, 3, 2]]
prop_prefs = [[1, 2, 3, 4], [2, 1, 4, 3], [3, 2, 1, 4], [1, 4, 3, 2]]
my_deferred_acceptance(prop_prefs, resp_prefs)
Out[5]:
提案を入れ替えると、最適なマッチングが変わる。
つまり、この例では男の立場からすると(1, 3, 2, 4)とマッチングするのが最適だが、女の立場からすると(1, 2, 3, 4)とマッチングするのが最適。
ここで、次のようなことを考えよう。
ある個人について、選好のn番目の人とマッチングした時の不幸度をnとする。但し、マッチングされなかった場合は(選好の長さ)+1とする。
人々の不幸度の合計が最小になるような状態を考えたい。
In [6]:
prop_prefs = [[1, 2, 3, 4], [3, 2, 1, 4], [1, 2, 4, 3], [4, 1, 3, 2]]
resp_prefs = [[1, 2, 3, 4], [2, 1, 4, 3], [3, 2, 1, 4], [1, 4, 3, 2]]
prop_matched, resp_matched = my_deferred_acceptance(prop_prefs, resp_prefs)
Out[6]:
In [7]:
m = length(prop_prefs)
prop_uf = Vector{Int64}(m)
c = 1
while c <= length(prop_prefs)
if prop_matched[c] == 0
prop_uf[c] = length(prop_prefs[c])+1
else
prop_uf[c] = findfirst(prop_prefs[c], prop_matched[c])
end
c += 1
end
prop_uf
Out[7]:
In [8]:
n = length(resp_prefs)
resp_uf = Vector{Int64}(n)
d = 1
while d <= length(resp_prefs)
if resp_matched[d] == 0
resp_uf[d] = length(resp_prefs[d])+1
else
resp_uf[d] = findfirst(resp_prefs[d], resp_matched[d])
end
d += 1
end
resp_uf
Out[8]:
In [9]:
sum(prop_uf[1:end])
Out[9]:
In [10]:
sum(resp_uf[1:end])
Out[10]:
となるから、男側の不幸度の合計は5、女性側の不幸度の合計は9、全体としての不幸度は14である。
一方、提案を入れ替えた場合、
In [11]:
resp_prefs = [[1, 2, 3, 4], [3, 2, 1, 4], [1, 2, 4, 3], [4, 1, 3, 2]]
prop_prefs = [[1, 2, 3, 4], [2, 1, 4, 3], [3, 2, 1, 4], [1, 4, 3, 2]]
prop_matched, resp_matched = my_deferred_acceptance(prop_prefs, resp_prefs)
Out[11]:
In [12]:
m = length(prop_prefs)
prop_uf = Vector{Int64}(m)
n = length(resp_prefs)
resp_uf = Vector{Int64}(n)
c = 1
while c <= length(prop_prefs)
if prop_matched[c] == 0
prop_uf[c] = length(prop_prefs[c])+1
else
prop_uf[c] = findfirst(prop_prefs[c], prop_matched[c])
end
c += 1
end
d = 1
while d <= length(resp_prefs)
if resp_matched[d] == 0
resp_uf[d] = length(resp_prefs[d])+1
else
resp_uf[d] = findfirst(resp_prefs[d], resp_matched[d])
end
d += 1
end
In [13]:
sum(prop_uf[1:end])
Out[13]:
In [14]:
sum(resp_uf[1:end])
Out[14]:
となり、男側の不幸度の合計は8、女側の不幸度の合計は5、全体としての不幸度は13である。
従って、提案の入れ替えにより、男側の不幸度が増加し女側の不幸度は減少している。
つまり、提案する側にとってのみ最適なマッチングとなっている。
また、社会的によいマッチングを全体としての不幸度が小さい方であるとすると、女側が提案した時の方が社会的によいことになる。
マッチングしない人がいるような例も考えてみる。
In [15]:
# 例-03
prop_prefs = [[1, 2, 3], [3, 2, 1], [1, 2, 3], [1, 3, 2]]
resp_prefs = [[1, 2, 3, 4], [2, 1, 3, 4], [3, 2, 1, 4]]
prop_matched, resp_matched = my_deferred_acceptance(prop_prefs, resp_prefs)
Out[15]:
In [16]:
m = length(prop_prefs)
prop_uf = Vector{Int64}(m)
n = length(resp_prefs)
resp_uf = Vector{Int64}(n)
c = 1
while c <= length(prop_prefs)
if prop_matched[c] == 0
prop_uf[c] = length(prop_prefs[c])+1
else
prop_uf[c] = findfirst(prop_prefs[c], prop_matched[c])
end
c += 1
end
d = 1
while d <= length(resp_prefs)
if resp_matched[d] == 0
resp_uf[d] = length(resp_prefs[d])+1
else
resp_uf[d] = findfirst(resp_prefs[d], resp_matched[d])
end
d += 1
end
In [17]:
sum(prop_uf[1:end])
Out[17]:
In [18]:
sum(resp_uf[1:end])
Out[18]:
In [19]:
resp_prefs = [[1, 2, 3], [3, 2, 1], [1, 2, 3], [1, 3, 2]]
prop_prefs = [[1, 2, 3, 4], [2, 1, 3, 4], [3, 2, 1, 4]]
prop_matched, resp_matched = my_deferred_acceptance(prop_prefs, resp_prefs)
Out[19]:
In [20]:
m = length(prop_prefs)
prop_uf = Vector{Int64}(m)
n = length(resp_prefs)
resp_uf = Vector{Int64}(n)
c = 1
while c <= length(prop_prefs)
if prop_matched[c] == 0
prop_uf[c] = length(prop_prefs[c])+1
else
prop_uf[c] = findfirst(prop_prefs[c], prop_matched[c])
end
c += 1
end
d = 1
while d <= length(resp_prefs)
if resp_matched[d] == 0
resp_uf[d] = length(resp_prefs[d])+1
else
resp_uf[d] = findfirst(resp_prefs[d], resp_matched[d])
end
d += 1
end
In [21]:
sum(prop_uf[1:end])
Out[21]:
In [22]:
sum(resp_uf[1:end])
Out[22]:
となり、男側が提案した場合、男側の不幸度の合計は8、女側の不幸度の合計は6、全体としての不幸度は14である。
一方、提案を入れ替えた場合、男側の不幸度の合計は10、女側の不幸度の合計は3、全体としての不幸度は13である。
従って、やはり提案の入れ替えにより、男側の不幸度が増加し女側の不幸度は減少している。
また、社会的によいマッチングは、女側が提案した時である。
では、以下では社会的によいマッチングを考える。
簡単のため、全員がマッチングするような例を考える。
あるprop_matchedが与えられた時の全体としての不幸度を求める。
In [23]:
# 例-02
prop_prefs = [[1, 2, 3, 4], [3, 2, 1, 4], [1, 2, 4, 3], [4, 1, 3, 2]]
resp_prefs = [[1, 2, 3, 4], [2, 1, 4, 3], [3, 2, 1, 4], [1, 4, 3, 2]]
Out[23]:
In [24]:
function UNF(prop_prefs, resp_prefs, prop_matched)
m = length(prop_matched)
resp_matched = Vector{Int64}(m)
for i in 1:m
resp_matched[i] = findfirst(prop_matched, i)
end
prop_uf = Vector{Int64}(m)
resp_uf = Vector{Int64}(m)
c = 1
while c <= length(prop_prefs)
prop_uf[c] = findfirst(prop_prefs[c], prop_matched[c])
c += 1
end
d = 1
while d <= length(resp_prefs)
resp_uf[d] = findfirst(resp_prefs[d], resp_matched[d])
d += 1
end
return sum(prop_uf[1:end]) + sum(resp_uf[1:end])
end
Out[24]:
例えば、prop_matched = [1, 2, 3, 4]の時は、
In [25]:
prop_matched = [1, 2, 3, 4]
Out[25]:
In [26]:
UNF(prop_prefs, resp_prefs, prop_matched)
Out[26]:
と求まる。
そこで、1対1の場合の最適なマッチングを、提案を入れ替えて社会的によい方のマッチングとする。
そのような関数を作ることを以下では考える。
In [27]:
function my_DA_1(prop_prefs, resp_prefs)
prop_matched, resp_matched = my_deferred_acceptance(prop_prefs, resp_prefs)
k = UNF(prop_prefs, resp_prefs, prop_matched)
prop_matched, resp_matched = my_deferred_acceptance(resp_prefs, prop_prefs)
l = UNF(prop_prefs, resp_prefs, prop_matched)
if k < l
return prop_matched, resp_matched = my_deferred_acceptance(prop_prefs, resp_prefs)
end
if l <= k
return prop_matched, resp_matched = my_deferred_acceptance(resp_prefs, prop_prefs)
end
end
Out[27]:
In [28]:
# 例-02
prop_prefs = [[1, 2, 3, 4], [3, 2, 1, 4], [1, 2, 4, 3], [4, 1, 3, 2]]
resp_prefs = [[1, 2, 3, 4], [2, 1, 4, 3], [3, 2, 1, 4], [1, 4, 3, 2]]
my_DA_1(prop_prefs, resp_prefs)
Out[28]:
となり、確かに社会的によいマッチングとなっている。