Topological sort

Kahn’s algorithm on a DAG of kiosk tasks.

A DAG (directed acyclic graph) can be ordered so every edge goes forward. Kahn’s algorithm: queue nodes with indegree 0, peel them off. If items remain, there was a cycle.

Goal

Order kiosk opening tasks so dependencies come first.

Kahn

from collections import deque

edges = [
    ("buy_stock", "open_till"),
    ("unlock", "buy_stock"),
    ("unlock", "sweep"),
    ("sweep", "open_till"),
]

nodes = sorted({u for e in edges for u in e})
indeg = {n: 0 for n in nodes}
adj = {n: [] for n in nodes}
for a, b in edges:
    adj[a].append(b)
    indeg[b] += 1

q = deque([n for n in nodes if indeg[n] == 0])
order = []
while q:
    n = q.popleft()
    order.append(n)
    for m in adj[n]:
        indeg[m] -= 1
        if indeg[m] == 0:
            q.append(m)

print(order)
print("all", len(order) == len(nodes))

unlock has indegree 0, so it starts. open_till waits until stock and sweep are done.

A cycle fails

from collections import deque

edges = [("A", "B"), ("B", "A")]
nodes = ["A", "B"]
indeg = {"A": 1, "B": 1}
adj = {"A": ["B"], "B": ["A"]}
q = deque([n for n in nodes if indeg[n] == 0])
order = []
while q:
    n = q.popleft()
    order.append(n)
    for m in adj[n]:
        indeg[m] -= 1
        if indeg[m] == 0:
            q.append(m)
print(order, "complete", len(order) == 2)
Tip

Package installs, make, and course prerequisites are DAGs. If len(order) != len(nodes), refuse — the spec is cyclic.