spore-commons/node/spore_node/governance/validator.py

48 lines
1.3 KiB
Python

"""Cycle detection for governance DAG using DFS."""
from __future__ import annotations
WHITE, GRAY, BLACK = 0, 1, 2
def detect_cycles(adj: dict[str, list[str]]) -> list[list[str]]:
"""Detect all cycles in a directed graph.
Args:
adj: Adjacency list mapping node → list of neighbors (dependencies).
Returns:
List of cycles, each cycle is a list of node IDs forming the loop.
"""
color: dict[str, int] = {node: WHITE for node in adj}
parent: dict[str, str | None] = {node: None for node in adj}
cycles: list[list[str]] = []
def dfs(u: str) -> None:
color[u] = GRAY
for v in adj.get(u, []):
if v not in color:
# Node referenced but not in graph — skip
continue
if color[v] == GRAY:
# Back edge → cycle found
cycle = [v, u]
node = u
while node != v:
node = parent[node]
if node is None:
break
cycle.append(node)
cycle.reverse()
cycles.append(cycle)
elif color[v] == WHITE:
parent[v] = u
dfs(v)
color[u] = BLACK
for node in adj:
if color[node] == WHITE:
dfs(node)
return cycles