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.1
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.1.tar.gz | 1.5 MB | Details |
Built distributions (wheels)
Total release size: 2.7 MB
Release files / nano_astar-0.1.1.tar.gz
| Download URL | nano_astar-0.1.1.tar.gz |
|---|---|
| Size | 1.5 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
933defe090ebec4805fe6162e7a225c88eb54856f56a514312cfb62c9a1a50a2
|
|
BLAKE2b-256 checksum How to use checksums |
97d1af854d2a292aec4f4917d3909aed05b412f8c19ed50b09773f1cbe7111b2
|
| 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.1-cp312-cp312-win_amd64.whl
| Download URL | nano_astar-0.1.1-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 88.8 kB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
fbe72d0ef8b4e0351c7574349c0294da471692ce4dc276f88dd4e068b6b42c12
|
|
BLAKE2b-256 checksum How to use checksums |
739c2d9efb90b86f6644304cfd4ff4131f441c8523c1c5ac160454297bf2bb53
|
| 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.1-cp312-cp312-win32.whl
| Download URL | nano_astar-0.1.1-cp312-cp312-win32.whl |
|---|---|
| Size | 80.3 kB |
| Tags | CPython 3.12 Windows x86-32 |
|
SHA-256 checksum How to use checksums |
9f3672a4204170592e39d024e71ab077d6f05cf13a10df5d943af3f7d0889a0a
|
|
BLAKE2b-256 checksum How to use checksums |
485af890b44227f2e6c168ec458d97d87af71241182eabd35cfaaa5ec2ba9393
|
| 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.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | nano_astar-0.1.1-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 |
48c067e87e8b8bf0132458708cf9a31b4cecda50c425b9aa9c9fa79bbe9fcc0e
|
|
BLAKE2b-256 checksum How to use checksums |
604229306863819bf0941bb55c3d2bda0306976ad8845c82a85e7a28369660f1
|
| 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.1-cp312-cp312-macosx_11_0_arm64.whl
| Download URL | nano_astar-0.1.1-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 |
640dee42348803d044ee10af1105f04df439ec0d109e1579ea084bc22ae8697d
|
|
BLAKE2b-256 checksum How to use checksums |
be6c527f01f17e5c64b6f09c22390777d702cdfa7d953a0ed9e6a6abfaa4e3d1
|
| 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.1-cp311-cp311-win_amd64.whl
| Download URL | nano_astar-0.1.1-cp311-cp311-win_amd64.whl |
|---|---|
| Size | 88.9 kB |
| Tags | CPython 3.11 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
e025ea98af9e83f577d0c7d10c0142634323a0e49a9703b4f58df60f55f80aa2
|
|
BLAKE2b-256 checksum How to use checksums |
6deb71df4aea2a44a89f0fb3360663514cde2af9bc602b5b8ace80714781d394
|
| 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.1-cp311-cp311-win32.whl
| Download URL | nano_astar-0.1.1-cp311-cp311-win32.whl |
|---|---|
| Size | 80.8 kB |
| Tags | CPython 3.11 Windows x86-32 |
|
SHA-256 checksum How to use checksums |
50a8aa7909f2510f5a24c922ea66f7a2bd25ee0a247a2c9f0dc4c08f4cc1c66a
|
|
BLAKE2b-256 checksum How to use checksums |
2688e27aef470c7e8ce1d7043e6204071c8880e66c505411d709d736b4dd04c7
|
| 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.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | nano_astar-0.1.1-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 |
78febd8b71fcd12d7bb6bbd6d92693b5964f057de9806071f325f44396f7c6da
|
|
BLAKE2b-256 checksum How to use checksums |
e62dd6b9627789752307bb2d7cb74876f6753fafde25dadd9f9848e66bb9bf4b
|
| 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.1-cp311-cp311-macosx_11_0_arm64.whl
| Download URL | nano_astar-0.1.1-cp311-cp311-macosx_11_0_arm64.whl |
|---|---|
| Size | 62.4 kB |
| Tags | CPython 3.11 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
f5045c347e9a56aa3b89120a945ef10903cb72356bfe8d03066e6be214cc2522
|
|
BLAKE2b-256 checksum How to use checksums |
bb74a3fb6f286ab41a96c499bb3a09d4e9a074c38c8ffc09ecfa3dd7dcc8c37c
|
| 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.1-cp310-cp310-win_amd64.whl
| Download URL | nano_astar-0.1.1-cp310-cp310-win_amd64.whl |
|---|---|
| Size | 88.6 kB |
| Tags | CPython 3.10 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
938af1f0807c908da5aa3c60e65e7ead2038a36f014db0af3005cc3d26d1b682
|
|
BLAKE2b-256 checksum How to use checksums |
b4e118527086f6a37c409745c65f83ce9cf3271806d469223c98737c14d73eba
|
| 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.1-cp310-cp310-win32.whl
| Download URL | nano_astar-0.1.1-cp310-cp310-win32.whl |
|---|---|
| Size | 80.5 kB |
| Tags | CPython 3.10 Windows x86-32 |
|
SHA-256 checksum How to use checksums |
ef252c86c370810d54e9f51fee192f52a5d29c693a9ec4d01670539f7aeb17a6
|
|
BLAKE2b-256 checksum How to use checksums |
1ca48fc75ddbc3f0d801accafd6aa0c41792372b6b9fbca00fea30a5daaa1886
|
| 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.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | nano_astar-0.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 90.9 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
b84bd9d180eb1ee7c860bc5262efb477df6dd356b94aaa8cd565ef0c47318801
|
|
BLAKE2b-256 checksum How to use checksums |
608cefc859ed453eff269b318fd3fe82b8f815b2419eca2d15810921cf060989
|
| 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.1-cp310-cp310-macosx_11_0_arm64.whl
| Download URL | nano_astar-0.1.1-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 |
89cef212390618cfbb1d6cdaa3c5644c69f8333f583e3b39b8ac9d94c07fe7f4
|
|
BLAKE2b-256 checksum How to use checksums |
a1c0183b1317ece325645f2a3dbd3e8bf7cac6447aa37a5ce7ab29f2e0742052
|
| 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.1-cp39-cp39-win_amd64.whl
| Download URL | nano_astar-0.1.1-cp39-cp39-win_amd64.whl |
|---|---|
| Size | 63.3 kB |
| Tags | CPython 3.9 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
ee4e2fa864696864f0aa12f01544df90be439301982acc9c9c4f10707a43135a
|
|
BLAKE2b-256 checksum How to use checksums |
8ad595ffaebe719ba70ff56284fed4373952eaada67cde202fb839c5daddacd9
|
| 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.1-cp39-cp39-win32.whl
| Download URL | nano_astar-0.1.1-cp39-cp39-win32.whl |
|---|---|
| Size | 58.2 kB |
| Tags | CPython 3.9 Windows x86-32 |
|
SHA-256 checksum How to use checksums |
21e9b82b2d03b931c5b36e7d94f5552e278618fef9e7ccdef253309b6e51e8e6
|
|
BLAKE2b-256 checksum How to use checksums |
6caf2d4852fb1e89214c724c2959c7e1a13a8d581f0abfa1ceabac36b8a72271
|
| 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.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | nano_astar-0.1.1-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 |
891f69373099eea5baa87025293c98f4aa461c10ac3dde9fba9d049ef55c127d
|
|
BLAKE2b-256 checksum How to use checksums |
49bfc30a8eed470e7b6778368f82893e965faaa166fb22dc5cbde025a9f03ce3
|
| 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.1-cp39-cp39-macosx_11_0_arm64.whl
| Download URL | nano_astar-0.1.1-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 |
cdca0cc79a2e53b53042c19447e36dd1734d6f4c7ecfa3ffbadc9bb7801ab250
|
|
BLAKE2b-256 checksum How to use checksums |
0cf68cd28068b5dce85df3a6c0de0daae6f3825500cd1fe64980483db146886e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|