NetworkX DiGraph shortest paths, topological sort and cycle detection: working versions (tested 2026-10-15)
Build a directed dependency graph, topologically order it, detect cycles with find_cycle, and pick shortest routes while keeping weighted Dijkstra vs hop-count BFS straight.
passed6 passed · 0 failed2026-10-15 16:02 UTC- Status
- passed
- Last passed
- 2026-10-15 16:02 UTC
- Tests
- 6 / 6
- Language
- Python
- Runtime
- Python 3.13.16
pinned versions2
networkx@3.6.1pytest@9.1.1
run it
uv venv -q .venv && uv pip install -q --python .venv/bin/python -r requirements.txt .venv/bin/python -m pytest -q
test environment
Python 3.13.16 linux 6.17.0-1022-azure x64 runner: github-actions 38764699834
The code
Exactly the files that passed. Your agent can pull them with get_recipe("networkx-shortest-path-dag") (install), or see them on GitHub.
requirements.txt
networkx==3.6.1 pytest==9.1.1
graph.py
import networkx as nx
def build_dag(edges):
"""edges: iterable of (src, dst, weight)."""
g = nx.DiGraph()
g.add_weighted_edges_from(edges)
return g
def build_order(g):
# topological_sort silently returns garbage order on a cycle, so guard first
if not nx.is_directed_acyclic_graph(g):
raise ValueError(f"dependency cycle: {nx.find_cycle(g)}")
return list(nx.topological_sort(g))
def detect_cycle(g):
# find_cycle raises NetworkXNoCycle when the graph is a DAG
try:
return nx.find_cycle(g)
except nx.NetworkXNoCycle:
return None
def fastest_route(g, source, target):
# without weight= this is hop-count BFS, not Dijkstra
return nx.shortest_path(g, source, target, weight="weight")
tests/test_graph.py
import networkx as nx
import pytest
from graph import build_dag, build_order, detect_cycle, fastest_route
def test_build_order_respects_dependencies():
g = build_dag([("a", "b", 1), ("b", "c", 1), ("a", "c", 1)])
assert build_order(g) == ["a", "b", "c"]
def test_cycle_raises_before_returning_order():
g = build_dag([("a", "b", 1), ("b", "c", 1), ("c", "a", 1)])
with pytest.raises(ValueError, match="dependency cycle"):
build_order(g)
def test_detect_cycle_wraps_no_cycle_exception():
cyclic = build_dag([("a", "b", 1), ("b", "c", 1), ("c", "a", 1)])
assert detect_cycle(cyclic) is not None
assert detect_cycle(build_dag([("a", "b", 1)])) is None
def test_self_loop_counts_as_cycle():
g = build_dag([("a", "a", 1)])
assert not nx.is_directed_acyclic_graph(g)
assert detect_cycle(g) == [("a", "a")]
def test_shortest_path_ignores_weight_unless_asked():
g = build_dag([("a", "d", 100), ("a", "b", 1), ("b", "d", 1)])
assert nx.shortest_path(g, "a", "d") == ["a", "d"]
assert nx.shortest_path(g, "a", "d", weight="weight") == ["a", "b", "d"]
def test_unreachable_target_raises_no_path():
g = build_dag([("a", "b", 1), ("c", "d", 1)])
with pytest.raises(nx.NetworkXNoPath):
fastest_route(g, "a", "d")
pytest.ini
[pytest] pythonpath = .
Connect to ProvenPin
Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.
terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp
~/.cursor/mcp.json
{ "mcpServers": { "provenpin": { "url": "https://mcp.provenpin.com/mcp" } } }.vscode/mcp.json
{ "servers": { "provenpin": { "type": "http", "url": "https://mcp.provenpin.com/mcp" } } }~/.codeium/windsurf/mcp_config.json
{ "mcpServers": { "provenpin": { "serverUrl": "https://mcp.provenpin.com/mcp" } } }MCP settings
{ "mcpServers": { "provenpin": { "type": "streamableHttp", "url": "https://mcp.provenpin.com/mcp" } } }Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.