NetworkX Python
Produce NetworkX code whose graph kind, node identity, edge multiplicity,
direction, attribute schema, weight semantics, and algorithm preconditions are
explicit and tested.
Boundary
Use this skill when the project uses networkx or the user requests it. Do not
introduce NetworkX into a library-neutral data task without a graph-shaped
problem. Route a rustworkx implementation to its own skill; conversion between
the two is in scope only when NetworkX remains an interface boundary.
Choose the graph object first
| Object |
Meaning |
Select it when |
Graph |
Undirected simple graph; self-loops allowed, parallel edges collapsed. |
Edge direction and parallel identity do not matter. |
DiGraph |
Directed simple graph. |
(u, v) and (v, u) differ. |
MultiGraph |
Undirected graph with edge keys. |
Parallel relationships must remain distinct. |
MultiDiGraph |
Directed graph with edge keys. |
Direction and parallel relationships both matter. |
| graph/node/edge attributes |
Mutable Python mappings attached to topology. |
Metadata belongs to the graph contract. |
| graph view |
Live, read-only-ish projection over a graph. |
Filter or inspect without copying; remember later mutations are visible. |
Nodes are hashable identifiers, not row positions. In multigraphs, an edge is
identified by (u, v, key), not only (u, v). NetworkX objects are mutable and
hold arbitrary Python objects, so copying depth and attribute aliasing are part
of the contract. Read the object and data model
before changing graph class, copying, subgraphing, or converting.
Ordered workflow
- State directedness, parallel-edge policy, self-loop policy, and node identity.
- Define required node/edge attributes, defaults, and the exact weight key.
- Construct or convert the graph without silently merging nodes or edges.
- Check the chosen algorithm's graph-type, connectivity, weight, and DAG
preconditions before calling it.
- Make tie-breaking and output order explicit; do not treat set/dict/view order
as a mathematical guarantee.
- Test empty, singleton, disconnected, cyclic, duplicate-edge, missing-weight,
and equal-cost cases that can falsify the contract.
Route intent to the API family
| Intent |
Prefer |
Guard |
| Build incrementally |
add_node(s)_from, add_edge(s)_from |
Tuple arity differs for data and multigraph keys. |
| Convert supported data |
nx.from_*, nx.to_*, nx.to_networkx_graph |
Specify directed/multigraph semantics; conversions may lose attributes or keys. |
| Inspect topology |
G.nodes, G.edges, degrees, neighbors |
Views are live; materialize only for a stable snapshot. |
| Traverse or find paths |
nx.bfs_*, nx.dfs_*, nx.shortest_path* |
Choose weighted versus unweighted and source/target reachability. |
| Analyze a DAG |
nx.is_directed_acyclic_graph, topological_sort, DAG algorithms |
Validate acyclicity; topological order may be non-unique. |
| Components/connectivity |
weak/strong/connected component families |
Match directedness and decide whether disconnected input is valid. |
| Rank or partition |
centrality/community algorithms |
Confirm weight meaning, randomness, convergence, and disconnected behavior. |
| Preserve only a projection |
subgraph/restricted views |
Copy before independent mutation. |
Read the operation and algorithm map for return
shapes, generators, multigraph edges, weight callbacks, randomness, and
conversion loss.
Canonical anchor
import networkx as nx
def cheapest_route(
edges: list[tuple[str, str, float]], source: str, target: str
) -> tuple[list[str], float]:
graph = nx.DiGraph()
graph.add_weighted_edges_from(edges, weight="cost")
if source not in graph or target not in graph:
raise KeyError("source and target must be graph nodes")
path = nx.shortest_path(graph, source, target, weight="cost")
return path, nx.path_weight(graph, path, weight="cost")
The graph is directed because route direction matters. The same attribute name
is passed to construction, path selection, and path scoring. If parallel routes
must remain distinct, use MultiDiGraph and define how an algorithm chooses
among edge keys; do not change classes without revisiting return semantics.
High-risk rules
- Never infer directedness from data ordering. Make it a constructor decision.
- Do not use
Graph when duplicate edges carry independent events, capacities,
or provenance; the later edge updates the existing relationship.
- Do not use an arbitrary numeric attribute as a weight. State whether smaller
means cheaper, whether negative values are legal, and what a missing value
means. Dijkstra-family algorithms require nonnegative weights.
- Treat
NodeNotFound, NetworkXNoPath, disconnected input, cycles, and
non-convergence as domain outcomes or explicit failures, not empty results.
topological_sort returns one valid order, not the unique order. Use a
lexicographical variant or a domain tie-breaker when reproducibility matters.
- A shortest-path generator, component generator, or view is not a list. Keep
it lazy for one pass or materialize deliberately if it must be reused.
- Subgraphs and filtered views can share attribute mappings with the original.
Copy when independent mutation is required, and test that ownership boundary.
- For randomized generators or algorithms, accept/pass a seed and test
invariants rather than one accidental sample.
- Drawing is presentation, not graph analysis. Keep layout coordinates and
rendering dependencies outside the graph's semantic result.
- For large graphs, establish scale before promising NetworkX performance.
Backends or rustworkx may change supported algorithms or object semantics;
benchmark the actual workload and preserve the public boundary.
Version grounding and completion
Check the installed version with networkx.__version__ and inspect the chosen callable's signature
when backend dispatch, return type, keyword, algorithm availability, or
conversion behavior can drift. The authoring baseline is the official NetworkX
3.6.1 stable reference, not proof of the caller's environment. Use
verification and API grounding for the local evidence steps.
Do not declare completion until graph kind and identity rules match the domain;
attribute and weight contracts are explicit; algorithm preconditions are
checked; exceptional/disconnected/ambiguous cases are handled; output type and
order meet the caller; and tests cover a counterexample rather than only the
happy path.
References
- Object and data model
- Operation and algorithm map
- Verification and API grounding
1---2name: networkx-python3description: Produces NetworkX code with explicit graph kind, node identity, edge multiplicity, direction, attribute schema, weight semantics, and algorithm preconditions, including testing.4---56# NetworkX Python78Produce NetworkX code whose graph kind, node identity, edge multiplicity,9direction, attribute schema, weight semantics, and algorithm preconditions are10explicit and tested.1112## Boundary1314Use this skill when the project uses `networkx` or the user requests it. Do not15introduce NetworkX into a library-neutral data task without a graph-shaped16problem. Route a rustworkx implementation to its own skill; conversion between17the two is in scope only when NetworkX remains an interface boundary.1819## Choose the graph object first2021| Object | Meaning | Select it when |22|---|---|---|23| `Graph` | Undirected simple graph; self-loops allowed, parallel edges collapsed. | Edge direction and parallel identity do not matter. |24| `DiGraph` | Directed simple graph. | `(u, v)` and `(v, u)` differ. |25| `MultiGraph` | Undirected graph with edge keys. | Parallel relationships must remain distinct. |26| `MultiDiGraph` | Directed graph with edge keys. | Direction and parallel relationships both matter. |27| graph/node/edge attributes | Mutable Python mappings attached to topology. | Metadata belongs to the graph contract. |28| graph view | Live, read-only-ish projection over a graph. | Filter or inspect without copying; remember later mutations are visible. |2930Nodes are hashable identifiers, not row positions. In multigraphs, an edge is31identified by `(u, v, key)`, not only `(u, v)`. NetworkX objects are mutable and32hold arbitrary Python objects, so copying depth and attribute aliasing are part33of the contract. Read [the object and data model](references/object-model.md)34before changing graph class, copying, subgraphing, or converting.3536## Ordered workflow37381. State directedness, parallel-edge policy, self-loop policy, and node identity.392. Define required node/edge attributes, defaults, and the exact weight key.403. Construct or convert the graph without silently merging nodes or edges.414. Check the chosen algorithm's graph-type, connectivity, weight, and DAG42 preconditions before calling it.435. Make tie-breaking and output order explicit; do not treat set/dict/view order44 as a mathematical guarantee.456. Test empty, singleton, disconnected, cyclic, duplicate-edge, missing-weight,46 and equal-cost cases that can falsify the contract.4748## Route intent to the API family4950| Intent | Prefer | Guard |51|---|---|---|52| Build incrementally | `add_node(s)_from`, `add_edge(s)_from` | Tuple arity differs for data and multigraph keys. |53| Convert supported data | `nx.from_*`, `nx.to_*`, `nx.to_networkx_graph` | Specify directed/multigraph semantics; conversions may lose attributes or keys. |54| Inspect topology | `G.nodes`, `G.edges`, degrees, neighbors | Views are live; materialize only for a stable snapshot. |55| Traverse or find paths | `nx.bfs_*`, `nx.dfs_*`, `nx.shortest_path*` | Choose weighted versus unweighted and source/target reachability. |56| Analyze a DAG | `nx.is_directed_acyclic_graph`, `topological_sort`, DAG algorithms | Validate acyclicity; topological order may be non-unique. |57| Components/connectivity | weak/strong/connected component families | Match directedness and decide whether disconnected input is valid. |58| Rank or partition | centrality/community algorithms | Confirm weight meaning, randomness, convergence, and disconnected behavior. |59| Preserve only a projection | subgraph/restricted views | Copy before independent mutation. |6061Read [the operation and algorithm map](references/operations.md) for return62shapes, generators, multigraph edges, weight callbacks, randomness, and63conversion loss.6465## Canonical anchor6667```python68import networkx as nx697071def cheapest_route(72 edges: list[tuple[str, str, float]], source: str, target: str73) -> tuple[list[str], float]:74 graph = nx.DiGraph()75 graph.add_weighted_edges_from(edges, weight="cost")76 if source not in graph or target not in graph:77 raise KeyError("source and target must be graph nodes")78 path = nx.shortest_path(graph, source, target, weight="cost")79 return path, nx.path_weight(graph, path, weight="cost")80```8182The graph is directed because route direction matters. The same attribute name83is passed to construction, path selection, and path scoring. If parallel routes84must remain distinct, use `MultiDiGraph` and define how an algorithm chooses85among edge keys; do not change classes without revisiting return semantics.8687## High-risk rules8889- Never infer directedness from data ordering. Make it a constructor decision.90- Do not use `Graph` when duplicate edges carry independent events, capacities,91 or provenance; the later edge updates the existing relationship.92- Do not use an arbitrary numeric attribute as a weight. State whether smaller93 means cheaper, whether negative values are legal, and what a missing value94 means. Dijkstra-family algorithms require nonnegative weights.95- Treat `NodeNotFound`, `NetworkXNoPath`, disconnected input, cycles, and96 non-convergence as domain outcomes or explicit failures, not empty results.97- `topological_sort` returns one valid order, not the unique order. Use a98 lexicographical variant or a domain tie-breaker when reproducibility matters.99- A shortest-path generator, component generator, or view is not a list. Keep100 it lazy for one pass or materialize deliberately if it must be reused.101- Subgraphs and filtered views can share attribute mappings with the original.102 Copy when independent mutation is required, and test that ownership boundary.103- For randomized generators or algorithms, accept/pass a seed and test104 invariants rather than one accidental sample.105- Drawing is presentation, not graph analysis. Keep layout coordinates and106 rendering dependencies outside the graph's semantic result.107- For large graphs, establish scale before promising NetworkX performance.108 Backends or rustworkx may change supported algorithms or object semantics;109 benchmark the actual workload and preserve the public boundary.110111## Version grounding and completion112113Check the installed version with `networkx.__version__` and inspect the chosen callable's signature114when backend dispatch, return type, keyword, algorithm availability, or115conversion behavior can drift. The authoring baseline is the official NetworkX1163.6.1 stable reference, not proof of the caller's environment. Use117[verification and API grounding](references/verification.md) for the local evidence steps.118119Do not declare completion until graph kind and identity rules match the domain;120attribute and weight contracts are explicit; algorithm preconditions are121checked; exceptional/disconnected/ambiguous cases are handled; output type and122order meet the caller; and tests cover a counterexample rather than only the123happy path.124125## References126127- [Object and data model](references/object-model.md)128- [Operation and algorithm map](references/operations.md)129- [Verification and API grounding](references/verification.md)