This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Consider using release 0.1.0a3 instead.
Reason given by maintainers: rustnx.enable() did not dispatch to rustnx; use v0.1.0a2
rustnx
NetworkX, but fast. rustnx is a Rust-powered backend for NetworkX. You keep writing normal NetworkX code, and supported algorithms run in Rust instead of Python, often 50–100× faster.
import networkx as nx
nx.config.backend_priority = ["rustnx"] # or: NETWORKX_BACKEND_PRIORITY=rustnx
G = nx.barabasi_albert_graph(4000, 4, seed=1)
nx.betweenness_centrality(G) # runs in Rust: 0.4s instead of 41s
Nothing else changes. Anything rustnx doesn't support, such as other functions, multigraphs or callable weights, keeps running in NetworkX, so turning it on never breaks working code.
Native graphs: skip NetworkX entirely
For big graphs, build the graph in Rust directly. There's no conversion step, and it uses a fraction of the memory:
import networkx as nx
import rustnx
rustnx.enable() # use rustnx where it can; everything else falls back to NetworkX
G = rustnx.DiGraph([("a", "b", 2.5), ("b", "c", 1), ("c", "a", {"weight": 4})])
nx.pagerank(G) # runs in Rust
nx.is_tree(G) # not in rustnx: converted to NetworkX automatically
G = rustnx.Graph.from_arrays(src, dst, weights) # NumPy arrays; nodes 0..n-1
| 1M-edge directed graph | networkx.DiGraph |
rustnx.DiGraph(edges) |
rustnx.DiGraph.from_arrays |
|---|---|---|---|
| Build time | 10.0 s | 2.7 s | 0.48 s |
| Memory | 323 MiB | ~65 MiB | ~47 MiB |
pagerank, first call |
4.1 s | 0.04 s | 0.04 s |
- The same results as NetworkX. Nodes come in order of first
appearance, each node's neighbors in insertion order, and duplicate edges
merge as
add_edgewould. So every algorithm returns what it would on anetworkx.Graphbuilt from the same edges. - Read-only. It has
nodes(),edges(data=True),neighbors,successors,predecessors,degree,has_edge,has_nodeandlen.G.to_networkx()gives the full NetworkX API. - Edge attributes must be numeric (or
None). Graphs can be pickled. - Call
rustnx.enable()first. Without it, NetworkX raisesNotImplementedErrorwhen a rustnx graph reaches a function rustnx doesn't implement, instead of converting it.
rustworkx-compatible API
The same Rust core also serves rustworkx's API:
import rustnx.rx as rx # instead of: import rustworkx as rx
g = rx.PyDiGraph()
g.extend_from_weighted_edge_list([(0, 1, 2.0), (1, 2, 1.0), (2, 0, 4.0)])
rx.strongly_connected_components(g)
rx.dijkstra_shortest_path_lengths(g, 0, float)
- It behaves the same, not just the same names.
PyGraphandPyDiGraphfollow rustworkx's index model. Indices of removed nodes and edges are reused, most recently removed first. Graphs are multigraphs by default, andmultigraph=Falsemerges duplicate edges as rustworkx does. Neighbors are visited in petgraph's order, so order-dependent results (strongly_connected_components,topological_sort) match rustworkx exactly. Exceptions use rustworkx's names (NullGraph,DAGHasCycle,NoEdgeBetweenNodes,FailedToConvergeand so on). - It's tested against the real rustworkx.
tests/test_rx_api.pyapplies random sequences of adds and removals to both libraries and compares every query and algorithm. - Supported: the core graph-building, editing and query methods, plus
betweenness_centrality,closeness_centrality,pagerank,dijkstra_shortest_path_lengths,all_pairs_dijkstra_path_lengths, the connected, strongly and weakly connected component functions,topological_sort,is_directed_acyclic_graphandnetworkx_converter. Not yet: subgraphs,compose, contraction, matrix and file I/O, andcheck_cycle=True. - Speed: the algorithms are as fast as rustworkx's or faster (betweenness 1.8×, closeness 23×, strong components 2.5×). Building graphs is slower: the graph is stored in Python, so adding 500k edges takes 0.8 s, against rustworkx's 0.04 s.
Supported algorithms
| Function | Notes |
|---|---|
betweenness_centrality |
Unweighted and weighted, normalized, endpoints, and k sampling (picks the same nodes as NetworkX for a given seed). Parallel. |
edge_betweenness_centrality |
Unweighted and weighted, normalized, and k sampling (same nodes as NetworkX for a given seed). Parallel. Rescaled by the installed NetworkX's own code. |
closeness_centrality |
Unweighted and distance=, wf_improved, single node u=. Parallel. Results are bit-for-bit identical to NetworkX. |
single_source_shortest_path_length |
Same nodes and same dict order as NetworkX, with cutoff. |
single_source_dijkstra_path_length |
Same order as NetworkX, with cutoff. Integer weights give integer distances. Raises the same error on negative cycles. |
connected_components, number_connected_components, is_connected |
Components come out in the same order as NetworkX. |
pagerank |
All options: alpha, personalization, nstart, dangling, weight, tol, max_iter. Raises PowerIterationFailedConvergence like NetworkX. |
strongly_connected_components, number_strongly_connected_components, is_strongly_connected |
Same components in the same order as NetworkX. |
weakly_connected_components, number_weakly_connected_components, is_weakly_connected |
Same components in the same order as NetworkX. |
topological_sort, topological_generations, is_directed_acyclic_graph |
Same order as NetworkX. If the graph changes mid-iteration, it raises the same errors as NetworkX. |
eccentricity, diameter, radius, center, periphery |
Unweighted: bit-parallel BFS. Weighted: parallel Dijkstra. Same errors as NetworkX (disconnected graphs, negative weights). usebounds=True, e=/sp= and trees in center run in NetworkX. |
average_shortest_path_length, wiener_index |
As above; weighted sums are added in NetworkX's order, so float results match exactly. |
all_pairs_shortest_path_length, all_pairs_dijkstra_path_length |
Parallel, in batches; same order as NetworkX. |
shortest_path, shortest_path_length, single_source_shortest_path, single_target_shortest_path, bidirectional_shortest_path, has_path |
The same paths as NetworkX, ties included, in the same dict order. shortest_path with no source and no target runs in NetworkX. |
dijkstra_path, dijkstra_path_length, single_source_dijkstra, single_source_dijkstra_path |
The same paths as NetworkX, ties included. The paths dict follows the installed NetworkX's order, which changed in 3.6. Weighted shortest_path between two nodes uses bidirectional_dijkstra, which runs in NetworkX. |
all_pairs_shortest_path, all_pairs_dijkstra_path, all_pairs_dijkstra |
Parallel, in batches. |
descendants, ancestors |
Same sets and errors as NetworkX. |
triangles, clustering, average_clustering, transitivity |
Unweighted, directed and undirected, with nodes=. Parallel. Results are bit-for-bit identical to NetworkX. Weighted clustering runs in NetworkX. |
Benchmarks
python benchmarks/bench.py on a 4-core machine (NetworkX 3.6.1):
| Function | Graph | NetworkX | rustnx | Speedup |
|---|---|---|---|---|
betweenness_centrality |
4,000 nodes / 16k edges | 40.9 s | 0.38 s | 107× |
betweenness_centrality (weighted) |
4,000 / 16k | 115.3 s | 1.24 s | 93× |
edge_betweenness_centrality |
4,000 / 16k | 42.3 s | 0.46 s | 93× |
edge_betweenness_centrality (weighted) |
4,000 / 16k | 106.8 s | 1.33 s | 80× |
closeness_centrality |
4,000 / 16k | 5.45 s | 0.0097 s | 562× |
single_source_dijkstra_path_length |
160,000 / 319k | 0.38 s | 0.063 s | 6× |
single_source_shortest_path_length |
160,000 / 319k | 0.11 s | 0.020 s | 5× |
connected_components |
200,000 / 300k | 0.23 s | 0.040 s | 6× |
pagerank |
200,000 / 1M (directed) | 5.76 s | 0.024 s | 243× |
pagerank (weighted) |
200,000 / 1M (directed) | 3.81 s | 0.024 s | 161× |
strongly_connected_components |
200,000 / 1M (directed) | 1.96 s | 0.052 s | 38× |
topological_sort |
200,000 / 499k (DAG) | 0.40 s | 0.023 s | 17× |
weakly_connected_components |
200,000 / 1M (directed) | 0.39 s | 0.036 s | 11× |
diameter |
5,000 / 15k | 11.2 s | 0.014 s | 807× |
average_shortest_path_length |
5,000 / 15k | 10.8 s | 0.014 s | 783× |
wiener_index |
5,000 / 15k | 10.0 s | 0.012 s | 829× |
eccentricity (weighted) |
5,000 / 15k | 57.0 s | 1.41 s | 40× |
all_pairs_dijkstra_path_length |
5,000 / 15k | 60.2 s | 4.90 s | 12× |
all_pairs_shortest_path_length |
5,000 / 15k | 9.6 s | 2.56 s | 4× (building 25M Python dict entries dominates) |
dijkstra_path (50 pairs) |
200,000 / 1M | 117 s | 3.3 s | 35× |
single_source_dijkstra_path |
200,000 / 1M | 4.56 s | 0.83 s | 5.5× |
single_source_shortest_path |
200,000 / 1M | 1.10 s | 0.57 s | 1.9× (building the path lists dominates) |
clustering |
100,000 / 500k (Barabási–Albert) | 5.09 s | 0.092 s | 55× |
transitivity |
100,000 / 500k (Barabási–Albert) | 5.12 s | 0.088 s | 58× |
triangles |
100,000 / 500k (Barabási–Albert) | 1.52 s | 0.091 s | 17× |
The rustnx column is a repeat call. The first call on a graph also converts it to rustnx's format (about 0.15–0.25 s for a 1M-edge directed graph), and NetworkX caches that conversion on the graph. For the heavy algorithms conversion is negligible. For the linear-time ones, the first call is still faster than NetworkX, but by less.
Compared with other Rust backends
python benchmarks/compare.py runs the same calls through each installed
backend and checks every result against NetworkX (same machine, NetworkX
3.6.1, rustworkx 0.18.1 via nx-rustworkx 0.2.1, franken-networkx 0.2.1).
Times are repeat calls; the first call also includes conversion.
| Function (graph) | rustnx | nx-rustworkx | FrankenNetworkX |
|---|---|---|---|
betweenness_centrality (2k nodes) |
0.099 s | 0.161 s | 8.23 s (no speedup) |
closeness_centrality (2k nodes) |
0.0030 s | 0.104 s | 0.0031 s |
pagerank (100k nodes, 500k edges) |
0.014 s | 0.212 s, differs from NetworkX | 0.063 s |
single_source_dijkstra_path_length (90k nodes) |
0.025 s | 0.094 s | 0.123 s |
connected_components (200k nodes) |
0.040 s | 0.072 s | 0.036 s |
strongly_connected_components (100k nodes) |
0.020 s | 0.041 s, different order | 0.054 s |
topological_sort (100k nodes) |
0.010 s | 0.019 s, different order | 0.040 s |
rustnx is also the fastest on first calls for all seven, because its conversion is about 5–20× quicker than nx-rustworkx's and 25–55× quicker than FrankenNetworkX's. It matches NetworkX's output, including order, for all seven.
On small graphs (under 500 nodes), the linear-time functions stay in NetworkX automatically, because the dispatch overhead outweighs the work. The centrality functions are faster in Rust at every size.
Correctness
Results must match NetworkX, or the speed is worthless. Two test layers check that:
-
tests/: about 1,400 randomized comparisons against NetworkX, run on directed and undirected graphs, int, float and missing weights, self-loops, and shuffled or non-integer node labels. They check values, dict ordering and error messages. -
NetworkX's own test suite, with every supported call routed through rustnx:
NETWORKX_TEST_BACKEND=rustnx NETWORKX_FALLBACK_TO_NX=True \ pytest --pyargs networkx
Result: 0 failures on NetworkX 3.4.2, 3.5 and 3.7 (9,066 tests passed on 3.7), with over 300,000 calls handled by rustnx. CI runs both layers on NetworkX 3.4, 3.5 and the latest release.
rustnx checks every call against the installed NetworkX's own signature. If a newer NetworkX adds a parameter, rustnx ignores it while it is left at its default. If the caller actually uses it, rustnx hands the call back to NetworkX.
Betweenness sums per-source contributions in parallel. It matches NetworkX to about 1e-15 relative error rather than bit-for-bit, and it gives the same result on any machine regardless of thread count.
How it works
nx.betweenness_centrality(G)
│ NetworkX dispatch (backend_priority = ["rustnx"])
▼
rustnx.interface convert G once: nodes → 0..n-1, adjacency → CSR arrays
│ (NetworkX caches this on G for later calls)
▼
rustnx._core (Rust) algorithm on flat arrays, GIL released, parallel via rayon
│
▼
dict keyed by your original nodes, in NetworkX's order
Neighbor order in the Rust arrays follows NetworkX's adjacency dicts exactly. That's why traversal order, tie-breaking and result ordering all match.
Releasing
The Wheels workflow builds packages for Linux (x86-64, ARM), macOS (Intel,
Apple Silicon) and Windows, plus a source package. It then installs each
wheel on that platform and runs the test suite against it. The workflow runs
on every pull request.
To publish a release:
- One-time setup: on PyPI, add a
trusted publisher for
fabuseless/rustnx, workflowwheels.yml, environmentpypi. Then create an environment namedpypiin the repo's GitHub settings. No API token is needed. - Set the version in
pyproject.tomlandCargo.toml, and move the changelog's Unreleased entries under the new version. - Push a tag such as
v0.1.0a1. If every build and test passes, the workflow uploads the packages to PyPI.
Development
uv venv && source .venv/bin/activate
uv pip install maturin networkx pytest numpy scipy
maturin develop --release
pytest # rustnx comparison tests
python benchmarks/bench.py --quick # benchmarks
Layout:
src/: Rust core.graph.rshandles conversion and CSR storage;algorithms/holds the traversals and centrality.python/rustnx/: the NetworkX backend.interface.pyis the entry point;algorithms.pyholds the NetworkX-compatible wrappers.tests/: comparisons against NetworkX.benchmarks/: speed comparisons.
Roadmap
- More algorithms:
bidirectional_dijkstra, weighted clustering. - Multigraph support.
License
BSD 3-Clause, the same license as NetworkX. See LICENSE. Release notes are in CHANGELOG.md.
Metadata
Release files for rustnx 0.1.0a1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| rustnx-0.1.0a1.tar.gz | 77.1 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| rustnx-0.1.0a1-cp310-abi3-win_amd64.whl | CPython 3.10 | abi3 | Windows x86-64 | Details |
| rustnx-0.1.0a1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| rustnx-0.1.0a1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| rustnx-0.1.0a1-cp310-abi3-macosx_11_0_arm64.whl | CPython 3.10 | abi3 | macOS 11.0+ ARM64 | Details |
| rustnx-0.1.0a1-cp310-abi3-macosx_10_12_x86_64.whl | CPython 3.10 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 2.3 MB
Release files / rustnx-0.1.0a1.tar.gz
| Download URL | rustnx-0.1.0a1.tar.gz |
|---|---|
| Size | 77.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2517829c68f575d76ca6dc9504137847471f6aa7f4f4f27a624b087361682ddf
|
|
BLAKE2b-256 checksum How to use checksums |
8f140e2f9db7c3814271f7a6e9d96f6bf7e991e4fea202606f7201fb7108535e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.
Transparency logRelease files / rustnx-0.1.0a1-cp310-abi3-win_amd64.whl
| Download URL | rustnx-0.1.0a1-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 364.5 kB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
37e7ca46289b98f16dc64cfdf7647718c56a5a065e9326d4345e8f26fa80982f
|
|
BLAKE2b-256 checksum How to use checksums |
139a4d7e731a0a2acd858bc36ea500f55ad8b29b87a6456ae957dbeb7e366248
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.
Transparency logRelease files / rustnx-0.1.0a1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | rustnx-0.1.0a1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 482.1 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
7605e2c9b80790b4c38dcffe19cc6aac17f95b8e57b76562bfe4d09a1e719aec
|
|
BLAKE2b-256 checksum How to use checksums |
007b04f35262739e2c67783bfc16aab527364f44c368cadfa60c4ac31a46cc8c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.
Transparency logRelease files / rustnx-0.1.0a1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | rustnx-0.1.0a1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 468.8 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
ccf9ab763f7c1e5329119f5e652e1f6a14f15028e4bd177985735adfcad3d079
|
|
BLAKE2b-256 checksum How to use checksums |
5fbb70b294dd97bfd33f0bf44a33ced5f40b95fb8499a0071657a609b8bbe2b1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.
Transparency logRelease files / rustnx-0.1.0a1-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | rustnx-0.1.0a1-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 439.0 kB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
d32034b223e2bac25115b806ce1eb55ab46b7db32653b2208b1bf0ceeed8b297
|
|
BLAKE2b-256 checksum How to use checksums |
2d3c97857866138bb431d4fd13a5e65c5e944b4635fc7ec50766f1408c79e4a5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.
Transparency logRelease files / rustnx-0.1.0a1-cp310-abi3-macosx_10_12_x86_64.whl
| Download URL | rustnx-0.1.0a1-cp310-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 451.3 kB |
| Tags | CPython 3.10 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
c9882d68e065f03f17b7d0d5f85c44ee1481def5679fbbb561f671fdf0a95118
|
|
BLAKE2b-256 checksum How to use checksums |
4b3968b2f83c7d8a7c7b4c6feeb6de616f91b4216d47c53787eb8efbf3069b75
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.
Transparency log