beam: topo_sort module + tests

This commit is contained in:
beam committed 2026-10-24 15:39:31 +00:00
1 parent 19ac322075
commit 40254811bd
2 files changed
+50

No files matched your search

+46
View File
@@ -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")
+4
View File
@@ -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