nano-astar
English | 中文
A pathfinding on occupancy grids with a C++ core — measured 14–18× faster than networkx search alone, 52–63× faster including graph construction, and up to 464× on 4-connected integer grids* (exact numbers, environment and reproduction script in BENCH.md).
Why nano-astar
- Fast where it matters. The search core is C++17 with cache-friendly flat arrays: one byte per cell for the closed bitmap, intrusive per-node links — no hash maps, no per-node allocation.
- Two open lists, chosen automatically. 4-connected integer grids run on a bucket queue with O(1) amortized push/pop and true decrease-key; float costs (8-connected
sqrt(2)diagonals) fall back to a 4-ary heap. Measured on identical integer workloads the bucket queue is 1.3–2.4× faster than the heap (BENCH.md). - Real multithreading. The GIL is released for the entire search (
nb::call_guard<nb::gil_scoped_release>), so threads truly run in parallel — measured 2.9× on 4 threads (test_gil_released_under_threads). - Zero-copy numpy in, numpy out. A contiguous
uint8grid is passed to C++ without copying; the path comes back as an(n, 2)int32array. - One dependency. Runtime:
numpyonly. Bindings via nanobind, build via scikit-build-core. - Differentially tested against a reference implementation. 200 randomized grids are checked against networkx A* — reachability and optimal cost must match exactly (integer) or within 1e-6 (float) (tests/test_correctness.py).
Install & 30-second quickstart
pip install nano-astar
From a source checkout: pip install .
import numpy as np
from nano_astar import astar
grid = np.zeros((100, 100), dtype=np.uint8)
grid[20:80, 50] = 1 # a wall
result = astar(grid, (0, 0), (99, 99), heuristic="octile", diagonal=True)
if result is None:
print("unreachable")
else:
path, cost = result # path: (n, 2) int32 (row, col)
print(f"{len(path)} cells, cost {cost:.3f}")
# exploration history for animations:
path, cost, history = astar(grid, (0, 0), (99, 99), return_history=True)
Terminal demo: python examples/demo.py
Benchmarks
Random grids with 30% obstacles, medians after warmup, costs cross-checked
against networkx on every run (identical within 1e-6). Full methodology —
repetition counts, seeds, fairness notes — and the reproduction script:
BENCH.md. Environment: Python 3.11.15, networkx 3.6.1,
numpy 2.4.6, MSVC 19.51 (/O2), Windows 11.
8-connected grids, octile heuristic on both sides:
| grid | nano-astar | networkx (search only) | networkx (build + search) | speedup (search) | speedup (incl. build) |
|---|---|---|---|---|---|
| 100×100 | 0.66 ms | 9.3 ms | 40.2 ms | 14× | 61× |
| 500×500 | 24.4 ms | 360.0 ms | 1273.4 ms | 15× | 52× |
| 1000×1000 | 115.9 ms | 2030.3 ms | 7304.9 ms | 18× | 63× |
4-connected integer grids, manhattan heuristic on both sides — the bucket queue's home turf:
| grid | nano-astar | networkx (search only) | networkx (build + search) | speedup (search) | speedup (incl. build) |
|---|---|---|---|---|---|
| 100×100 | 0.07 ms | 3.1 ms | 289.2 ms | 43× | 4037× |
| 500×500 | 4.02 ms | 109.3 ms | 718.4 ms | 27× | 179× |
| 1000×1000 | 7.65 ms | 124.3 ms | 3546.6 ms | 16× | 464× |
Reproduce:
python tests/bench_vs_networkx.py # rewrites BENCH.md + docs/bench_results.json
python tools/make_plots.py # regenerates the charts
Heuristics, visualized
Same map, four built-in heuristics (4-connected). Blue = cells explored, red = final path. A tighter heuristic explores less — all four still return the same optimal cost.
When NOT to use nano-astar
- General graphs. Nodes with attributes, edge weights, or non-grid topology are out of scope — the input is a binary occupancy grid, period. Use networkx, rustworkx, or a graph library.
- Custom Python heuristics. There is no callback interface: the four
built-in heuristics run inline in C++, which is exactly where the speed
comes from. If you need a domain-specific heuristic, fork and add it in
src/cpp/heuristics.hpp. - Weighted terrain. All free cells cost the same (1 orthogonally,
sqrt(2)diagonally). Costmaps with per-cell traversal costs need a different engine. - When the bucket queue won't help you. The bucket queue only engages
for 4-connected integer-cost grids (
diagonal=False). Withdiagonal=True, costs are irrational multiples ofsqrt(2)and the engine uses the 4-ary heap instead — by design, not by accident. On integer grids the bucket queue is 1.3–2.4× faster than the heap (measured, BENCH.md); if your workload is 8-connected, that is the number you give up. manhattanwithdiagonal=True. Manhattan overestimates on 8-connected grids and would return suboptimal paths, so nano-astar emits aRuntimeWarning. Useoctile(the default) there.
API
astar(grid, start, goal, heuristic="octile", diagonal=True,
return_history=False) -> (path, cost) | (path, cost, history) | None
| parameter | meaning |
|---|---|
grid |
2-D array-like; 0 = free, nonzero = obstacle. Contiguous uint8 is zero-copy; other dtypes are converted once via grid != 0. |
start, goal |
(row, col) cell indices. |
heuristic |
"octile" (default, tightest for 8-conn), "manhattan" (tightest for 4-conn), "euclidean", "diagonal". All inline C++, no Python callback. |
diagonal |
True: 8-connected, diagonal steps cost sqrt(2), no corner cutting. False: 4-connected unit costs → integer bucket-queue engine. |
return_history |
Also return the closed cells in pop order as (m, 2) int32 — what the GIF above is made of. |
- Returns
Nonewhen no path exists (never raises for that). - Raises
ValueErrorfor out-of-bounds or on-obstaclestart/goal, non-2-D grids, and unknown heuristic names. - Path cost is exact: integer grids return integer-valued floats, 8-connected
grids return exact sums of
1/sqrt(2)terms. - Thread-safe and GIL-free: no Python objects are touched while the GIL is released, and concurrent calls from multiple threads run truly in parallel.
Development
uv venv --python 3.11 .venv
uv pip install --python .venv -e ".[dev]"
pytest tests/ # 220 tests, differential vs networkx
python tests/bench_vs_networkx.py # regenerate BENCH.md
python tools/make_gif.py # regenerate docs/demo.gif
Layout:
src/cpp/astar.cpp engine + nanobind bindings
src/cpp/bucket_queue.hpp ring bucket queue (integer costs, O(1) decrease-key)
src/cpp/heap4.hpp 4-ary heap (float/general costs)
src/cpp/heuristics.hpp octile / manhattan / euclidean / diagonal, inline
src/python/nano_astar/ Python wrapper (validation, dtype normalization)
tests/ differential tests, API tests, benchmark
tools/ smoke test (pure C++), GIF/chart generators
License
MIT
Metadata
Release files for nano-astar 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nano_astar-0.1.0.tar.gz | 1.5 MB | Details |
Built distributions (wheels)
Total release size: 2.7 MB
Release files / nano_astar-0.1.0.tar.gz
| Download URL | nano_astar-0.1.0.tar.gz |
|---|---|
| Size | 1.5 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9f068563dda85940626d11a42304f51127875bbc9a3d421b8d5b6dd959581efc
|
|
BLAKE2b-256 checksum How to use checksums |
7393534ba50b0dc72fc2fe47f311e7e918e3788d2bf627d7dca796e2b21fe97f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Release files / nano_astar-0.1.0-cp312-cp312-win_amd64.whl
| Download URL | nano_astar-0.1.0-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 88.7 kB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
db77ef73c1f1d87198958b018acd5532fb767369fc6188512a44689c7cf090e2
|
|
BLAKE2b-256 checksum How to use checksums |
a338553e2e0ac29ab6af5f585a63ca79445ebdca783769e964d8a22d273c368f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Release files / nano_astar-0.1.0-cp312-cp312-win32.whl
| Download URL | nano_astar-0.1.0-cp312-cp312-win32.whl |
|---|---|
| Size | 80.3 kB |
| Tags | CPython 3.12 Windows x86-32 |
|
SHA-256 checksum How to use checksums |
862ddbd46ccfc83a0f7edaee1c1e22906b79a4199d6604d3609d06baf48276ac
|
|
BLAKE2b-256 checksum How to use checksums |
d4e0a59f67dcfb6a622e39ee2cf2f1acfba4d8a13cdb74073e1d4320288660c7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / nano_astar-0.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | nano_astar-0.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 89.6 kB |
| Tags | CPython 3.12 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
109589cf044074645648da2519d2141ce1c5af46d664624a32b4c4bb5f597ffd
|
|
BLAKE2b-256 checksum How to use checksums |
b3347482d70fdbeacddce53020a0ba6c579674771e51a5a498bafc6f76237ce2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / nano_astar-0.1.0-cp312-cp312-macosx_11_0_arm64.whl
| Download URL | nano_astar-0.1.0-cp312-cp312-macosx_11_0_arm64.whl |
|---|---|
| Size | 61.5 kB |
| Tags | CPython 3.12 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
a3636468a04ea392a34ffefb6b8ee8a5bbe84fb5927fb6e6bad8b3cb087765ff
|
|
BLAKE2b-256 checksum How to use checksums |
5e2be26ddd8864d96fdefd0b84aeeaa3777f58bb7639340ae7e6a2698f57bfd8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / nano_astar-0.1.0-cp311-cp311-win_amd64.whl
| Download URL | nano_astar-0.1.0-cp311-cp311-win_amd64.whl |
|---|---|
| Size | 88.9 kB |
| Tags | CPython 3.11 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
fd99650af651a4931a40d9b90b88ef1316e08a5b0015ee251a09432893271da1
|
|
BLAKE2b-256 checksum How to use checksums |
319021b702d393a0d01a84f12c085c6a558d63098bf467801a6b2e45bdf9606b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / nano_astar-0.1.0-cp311-cp311-win32.whl
| Download URL | nano_astar-0.1.0-cp311-cp311-win32.whl |
|---|---|
| Size | 80.7 kB |
| Tags | CPython 3.11 Windows x86-32 |
|
SHA-256 checksum How to use checksums |
6d3222880f23455b47bfb0fd078a0c7d283fce539095a6c1415e1b3764aaaec6
|
|
BLAKE2b-256 checksum How to use checksums |
bdb02c50cc8be17f537a166004973a73ce420413749b45edcb52c8dc5e73c1d8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / nano_astar-0.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | nano_astar-0.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 90.4 kB |
| Tags | CPython 3.11 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
14899d8850a9f829716217fdc5a4b047caf8d28cb5f35e029b024ee61163ca70
|
|
BLAKE2b-256 checksum How to use checksums |
f1df9ea857758278a74b71aa49e64997bb5450055e233ccdfc643df51d09549a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / nano_astar-0.1.0-cp311-cp311-macosx_11_0_arm64.whl
| Download URL | nano_astar-0.1.0-cp311-cp311-macosx_11_0_arm64.whl |
|---|---|
| Size | 62.3 kB |
| Tags | CPython 3.11 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
f5d5aa1c7222ee433007fbb4e8479e8f00144a5dab5a25c7b482375a9b2d2b3c
|
|
BLAKE2b-256 checksum How to use checksums |
c8c3b88232d2b6e5421c23e5d36afa1aff7b18e675644cd199210f3d2fea1aed
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / nano_astar-0.1.0-cp310-cp310-win_amd64.whl
| Download URL | nano_astar-0.1.0-cp310-cp310-win_amd64.whl |
|---|---|
| Size | 88.5 kB |
| Tags | CPython 3.10 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
356447ee35ccd5ef53c4fd29cd9cc914022473574ac2be17c11b7484364b55a2
|
|
BLAKE2b-256 checksum How to use checksums |
12e5c6309cead45953747fb8044e16f84552742dba09b7f9f94c69bfa97edbc8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / nano_astar-0.1.0-cp310-cp310-win32.whl
| Download URL | nano_astar-0.1.0-cp310-cp310-win32.whl |
|---|---|
| Size | 80.5 kB |
| Tags | CPython 3.10 Windows x86-32 |
|
SHA-256 checksum How to use checksums |
5b0b70c0fa450854bf580edca7df9c8dcf604d56a97cbfdea6582befb53860c5
|
|
BLAKE2b-256 checksum How to use checksums |
f410558b8e11aae7b745cadce1d4244c25690545f1e03164637f31fe269f146c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / nano_astar-0.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | nano_astar-0.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 90.8 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
c963cae5c370b3adb16885d839ea0aaf15b191767cb5ee7167c729834c73d245
|
|
BLAKE2b-256 checksum How to use checksums |
4fe84dd6c869631dd25e0b908d9852904221d9bad69acecb6a683b5894085e74
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / nano_astar-0.1.0-cp310-cp310-macosx_11_0_arm64.whl
| Download URL | nano_astar-0.1.0-cp310-cp310-macosx_11_0_arm64.whl |
|---|---|
| Size | 62.7 kB |
| Tags | CPython 3.10 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
2076c3d07d46f5662c784b8352173edddad334012f4856acf062107ecd989255
|
|
BLAKE2b-256 checksum How to use checksums |
bef3d83856f70f6c7c4d998e9f705cc14888f75771cae1e32131a761e056a5e9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / nano_astar-0.1.0-cp39-cp39-win_amd64.whl
| Download URL | nano_astar-0.1.0-cp39-cp39-win_amd64.whl |
|---|---|
| Size | 63.3 kB |
| Tags | CPython 3.9 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
c16e5fdb8e747f0515fe026698a76d3152b492e5a77b49870bc9db984f239f9a
|
|
BLAKE2b-256 checksum How to use checksums |
3167514edaf2c38dc16be371b6e9a38f15b53da73855f18076ab1433ec8dece1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / nano_astar-0.1.0-cp39-cp39-win32.whl
| Download URL | nano_astar-0.1.0-cp39-cp39-win32.whl |
|---|---|
| Size | 58.2 kB |
| Tags | CPython 3.9 Windows x86-32 |
|
SHA-256 checksum How to use checksums |
fa5424417691277425829ff171703853170b3d296bbc7427b7348cea9ff964c4
|
|
BLAKE2b-256 checksum How to use checksums |
c25a0648d4da49afce899a8f530338b394fa43aa1170c5c5719a23b1cacf5908
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / nano_astar-0.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | nano_astar-0.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 86.1 kB |
| Tags | CPython 3.9 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
f5b98038311aa15981a25ad22f1076fcd157d93e91edfd76b3cbc98d4fe9f965
|
|
BLAKE2b-256 checksum How to use checksums |
2d5ea89e3cf676c9b058c5937d52c22d00484d7c8759abddb269135f1712acae
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / nano_astar-0.1.0-cp39-cp39-macosx_11_0_arm64.whl
| Download URL | nano_astar-0.1.0-cp39-cp39-macosx_11_0_arm64.whl |
|---|---|
| Size | 59.0 kB |
| Tags | CPython 3.9 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
5e9c2714ee527e2ff98fa19fe4a189d874ef91e76d0fa65df4c52614f38a9fc2
|
|
BLAKE2b-256 checksum How to use checksums |
396c422c78f0e5365779986d50cb8e7444ceb74b7a5eb6438a99fc2454fe69ee
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|