-
Notifications
You must be signed in to change notification settings - Fork 8
/
toptradingcycles.py
79 lines (60 loc) · 2.24 KB
/
toptradingcycles.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
from graph import *
# getAgents: graph, vertex -> set(vertex)
# get the set of agents on a cycle starting at the given vertex
def getAgents(G, cycle, agents):
# a cycle in G is represented by any vertex of the cycle
# outdegree guarantee means we don't care which vertex it is
# make sure starting vertex is a house
if cycle.vertexId in agents:
cycle = cycle.anyNext()
startingHouse = cycle
currentVertex = startingHouse.anyNext()
theAgents = set()
while currentVertex not in theAgents:
theAgents.add(currentVertex)
currentVertex = currentVertex.anyNext()
currentVertex = currentVertex.anyNext()
return theAgents
# anyCycle: graph -> vertex
# find any vertex involved in a cycle
def anyCycle(G):
visited = set()
v = G.anyVertex()
while v not in visited:
visited.add(v)
v = v.anyNext()
return v
# find a core matching of agents to houses
# agents and houses are unique identifiers for the agents and houses involved
# agentPreferences is a dictionary with keys being agents and values being
# lists that are permutations of the list of all houses.
# initiailOwnerships is a dict {houses:agents}
def topTradingCycles(agents, houses, agentPreferences, initialOwnership):
# form the initial graph
agents = set(agents)
vertexSet = set(agents) | set(houses)
G = Graph(vertexSet)
# maps agent to an index of the list agentPreferences[agent]
currentPreferenceIndex = dict((a,0) for a in agents)
preferredHouse = lambda a: agentPreferences[a][currentPreferenceIndex[a]]
for a in agents:
G.addEdge(a, preferredHouse(a))
for h in houses:
G.addEdge(h, initialOwnership[h])
# iteratively remove top trading cycles
allocation = dict()
while len(G.vertices) > 0:
cycle = anyCycle(G)
cycleAgents = getAgents(G, cycle, agents)
# assign agents in the cycle their house
for a in cycleAgents:
h = a.anyNext().vertexId
allocation[a.vertexId] = h
G.delete(a)
G.delete(h)
for a in agents:
if a in G.vertices and G[a].outdegree() == 0:
while preferredHouse(a) not in G.vertices:
currentPreferenceIndex[a] += 1
G.addEdge(a, preferredHouse(a))
return allocation