beam: topo_sort module + tests
This commit is contained in:
1 parent
19ac322075
commit
40254811bd
2 files changed
+50
No files matched your search
@@ -0,0 +1,46 @@
|
||||
import sys
|
||||
sys.path.insert(0, '/root/.hermes/wizard-outputs/beam')
|
||||
from toposort import topo_sort
|
||||
|
||||
def check(graph, expected_order=None):
|
||||
r = topo_sort(graph)
|
||||
if expected_order is not None:
|
||||
assert r.cycle is None, (graph, r)
|
||||
assert r.sorted == expected_order, (graph, r.sorted, expected_order)
|
||||
return r
|
||||
|
||||
# DAG simple
|
||||
check({'a': ['b'], 'b': []}, ['b','a'])
|
||||
# disconnected
|
||||
check({'a': [], 'b': []}, ['a','b'])
|
||||
# empty
|
||||
check({}, [])
|
||||
# diamond
|
||||
check({'a':['b','c'],'b':['d'],'c':['d'],'d':[]}, ['d','b','c','a'] if False else None) or True
|
||||
r = topo_sort({'a':['b','c'],'b':['d'],'c':['d'],'d':[]})
|
||||
assert r.cycle is None
|
||||
# verify validity
|
||||
pos = {n:i for i,n in enumerate(r.sorted)}
|
||||
for n,deps in {'a':['b','c'],'b':['d'],'c':['d'],'d':[]}.items():
|
||||
for d in deps:
|
||||
assert pos[d] < pos[n]
|
||||
# cycle
|
||||
r = topo_sort({'a':['b'],'b':['a']})
|
||||
assert r.sorted is None
|
||||
assert r.cycle is not None
|
||||
# cycle is valid: each consecutive edge exists and last->first
|
||||
g={'a':['b'],'b':['a']}
|
||||
cyc=r.cycle
|
||||
for i in range(len(cyc)):
|
||||
u=cyc[i]; v=cyc[(i+1)%len(cyc)]
|
||||
assert v in g.get(u,[]), (u,v,cyc)
|
||||
# self loop
|
||||
r = topo_sort({'a':['a']})
|
||||
assert r.sorted is None and r.cycle == ['a']
|
||||
# node only as successor
|
||||
r = topo_sort({'a':['b']})
|
||||
assert r.sorted == ['b','a']
|
||||
def test_all():
|
||||
pass
|
||||
|
||||
print("ALL PASS")
|
||||
@@ -26,12 +26,16 @@ def topo_sort(graph: Mapping[Any, Iterable[Any]]) -> TopoResult:
|
||||
# Normalize: ensure every referenced node exists as a key.
|
||||
nodes: set[Any] = set(graph.keys())
|
||||
for deps in graph.values():
|
||||
if deps is None:
|
||||
continue
|
||||
for d in deps:
|
||||
nodes.add(d)
|
||||
|
||||
# adjacency: node -> set of dependencies
|
||||
deps_of: dict[Any, set[Any]] = {n: set() for n in nodes}
|
||||
for n, ds in graph.items():
|
||||
if ds is None:
|
||||
ds = []
|
||||
for d in ds:
|
||||
if d == n:
|
||||
# self-loop is a cycle of length 1
|
||||
|
||||
Reference in new issue
Block a user