Skip to content

Commit fe9f2c0

Browse files
authored
improved toposort performance using collections.deque
1 parent 1f35887 commit fe9f2c0

File tree

1 file changed

+14
-11
lines changed

1 file changed

+14
-11
lines changed

unification/utils.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from collections import deque
12
from collections.abc import Mapping, Set
23
from contextlib import suppress
34

@@ -36,21 +37,23 @@ def _toposort(edges):
3637
Communications of the ACM
3738
[2] http://en.wikipedia.org/wiki/Toposort#Algorithms
3839
"""
39-
incoming_edges = reverse_dict(edges)
40-
incoming_edges = dict((k, set(val)) for k, val in incoming_edges.items())
41-
S = set((v for v in edges if v not in incoming_edges))
40+
incoming_edges = {k: set(val) for k, val in reverse_dict(edges).items()}
41+
42+
S = deque(v for v in edges if v not in incoming_edges)
4243
L = []
4344

4445
while S:
45-
n = S.pop()
46-
L.append(n)
46+
n = S.popleft()
4747
for m in edges.get(n, ()):
48-
assert n in incoming_edges[m]
49-
incoming_edges[m].remove(n)
50-
if not incoming_edges[m]:
51-
S.add(m)
52-
if any(incoming_edges.get(v, None) for v in edges):
48+
edges_m = incoming_edges[m]
49+
edges_m.remove(n)
50+
if not edges_m:
51+
S.append(m)
52+
L.append(n)
53+
54+
if any(incoming_edges.get(v) for v in edges):
5355
raise ValueError("Input has cycles")
56+
5457
return L
5558

5659

@@ -70,7 +73,7 @@ def reverse_dict(d):
7073
result = {}
7174
for key in d:
7275
for val in d[key]:
73-
result[val] = result.get(val, tuple()) + (key,)
76+
result[val] = result.get(val, ()) + (key,)
7477
return result
7578

7679

0 commit comments

Comments
 (0)