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.2
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.2.tar.gz | 1.5 MB | Details |
Built distributions (wheels)
Total release size: 2.7 MB
Release files / nano_astar-0.1.2.tar.gz
| Download URL | nano_astar-0.1.2.tar.gz |
|---|---|
| Size | 1.5 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cc51210bb07b3ccc93a8277efe77f9f1abecbd4adb43b6b079e2fb570e647593
|
|
BLAKE2b-256 checksum How to use checksums |
f5ce3b454e9196e1af36b1ac809ba13796855d02d873074e29ef7fc471557925
|
| 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.2-cp312-cp312-win_amd64.whl
| Download URL | nano_astar-0.1.2-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 88.8 kB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
50f01500e13260194e0f5d0f79832d62f26bbdb03117fccc143ff7e8d56e3a94
|
|
BLAKE2b-256 checksum How to use checksums |
d312932f35c9404a96679e356b872edd9c7397edc5614973daaaefcc34b54f37
|
| 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.2-cp312-cp312-win32.whl
| Download URL | nano_astar-0.1.2-cp312-cp312-win32.whl |
|---|---|
| Size | 80.3 kB |
| Tags | CPython 3.12 Windows x86-32 |
|
SHA-256 checksum How to use checksums |
f6af7e185217dd084f29076d9bacdf856ae8561847859f4778994743c6c63016
|
|
BLAKE2b-256 checksum How to use checksums |
a6ef06343451a905d6f844ffb433efdfc6bd6a30636aebd173c9d0bcc332d9c6
|
| 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.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | nano_astar-0.1.2-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 |
bc8646654b0d9004fc8b97b20af700366bb99c44919939999364354a7633955f
|
|
BLAKE2b-256 checksum How to use checksums |
d559f97151cd891841860526e9052ad1b5f1621c9d619fea35c4c859451ff508
|
| 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.2-cp312-cp312-macosx_11_0_arm64.whl
| Download URL | nano_astar-0.1.2-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 |
26b34a56dbece6abab902e230d6132cf8871c05af8e201466c876dca9f6908cd
|
|
BLAKE2b-256 checksum How to use checksums |
5c54b0f685bfbc6adb0a7231943b36b5cd9ad912c02066d5bcf6fe2a5befbcfb
|
| 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.2-cp311-cp311-win_amd64.whl
| Download URL | nano_astar-0.1.2-cp311-cp311-win_amd64.whl |
|---|---|
| Size | 88.9 kB |
| Tags | CPython 3.11 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
86a578dcd7a27f5be42d65592e36628a4b9dc642cfbd462222b87c7c8f76d438
|
|
BLAKE2b-256 checksum How to use checksums |
fdec35f54d2d2adb33f2ef00c4d7b68cc90e41f2ac14d233d4bcd51a856ab826
|
| 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.2-cp311-cp311-win32.whl
| Download URL | nano_astar-0.1.2-cp311-cp311-win32.whl |
|---|---|
| Size | 80.8 kB |
| Tags | CPython 3.11 Windows x86-32 |
|
SHA-256 checksum How to use checksums |
21d8a2e78e1a0ea77c3593789af52aad79245fe1692c1d76f6d8df386d1d9e51
|
|
BLAKE2b-256 checksum How to use checksums |
36ea05d344d8029d8f8d84a1dd91735037a2f74c1ac83f2a18b9afbe2b783042
|
| 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.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | nano_astar-0.1.2-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 |
3d6c5d59d7c11402fd4372f863dbe31fd2e156d2a0d1658b8331e29015217429
|
|
BLAKE2b-256 checksum How to use checksums |
f50642f060780fae40834f3b8acad5c60e1390b4b0fb6126b84458a23ce384af
|
| 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.2-cp311-cp311-macosx_11_0_arm64.whl
| Download URL | nano_astar-0.1.2-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 |
223d34b9be57a8fd09cf021c24b21995092ca83a93a8dabb6b1229651c381137
|
|
BLAKE2b-256 checksum How to use checksums |
7dc6edb8f79b0fae9e91a489d538d3cf181fd98a94e4dba8b885ac8c792dc538
|
| 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.2-cp310-cp310-win_amd64.whl
| Download URL | nano_astar-0.1.2-cp310-cp310-win_amd64.whl |
|---|---|
| Size | 88.6 kB |
| Tags | CPython 3.10 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
ded117b0afb8b787fd3a1c61d6bbc5c617ef72b55566214202d4f4e9d646eb55
|
|
BLAKE2b-256 checksum How to use checksums |
c7186d200cbe3f18f71b50c1395a25498d831a1dc9277e6f314c52bd70740e06
|
| 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.2-cp310-cp310-win32.whl
| Download URL | nano_astar-0.1.2-cp310-cp310-win32.whl |
|---|---|
| Size | 80.5 kB |
| Tags | CPython 3.10 Windows x86-32 |
|
SHA-256 checksum How to use checksums |
78d5a30ed5d371af384222f9d464c426a1c2d9a4269809315da4709c95f528c1
|
|
BLAKE2b-256 checksum How to use checksums |
b5773c54c765e07726369133a357658e60a1fc01cf9d716ff9f743cce217ee34
|
| 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.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | nano_astar-0.1.2-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 |
e6ca5d961df496a6bb14165db51572532133978e4fe5b5a691d6ce6c1f569e32
|
|
BLAKE2b-256 checksum How to use checksums |
3c2427948929599870ac0e595986b5a2c686f64d286d46c3379b374938bfa9de
|
| 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.2-cp310-cp310-macosx_11_0_arm64.whl
| Download URL | nano_astar-0.1.2-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 |
ec9ae2373c468ccfafb148f985775323a7387dfde957d51d5a262d8d54f2664c
|
|
BLAKE2b-256 checksum How to use checksums |
06a46dddb91d173753a5c32655be4b164a4c9ad566c1fba34e66511afbc9d701
|
| 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.2-cp39-cp39-win_amd64.whl
| Download URL | nano_astar-0.1.2-cp39-cp39-win_amd64.whl |
|---|---|
| Size | 63.3 kB |
| Tags | CPython 3.9 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
40f206cefd6f7c21360dd676065ee46162bbce9d30805486d8287c0b8b0ce9e7
|
|
BLAKE2b-256 checksum How to use checksums |
8a4d4271c289172e8995c152f0f970be08385d57703090da18737784d70f8c61
|
| 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.2-cp39-cp39-win32.whl
| Download URL | nano_astar-0.1.2-cp39-cp39-win32.whl |
|---|---|
| Size | 58.2 kB |
| Tags | CPython 3.9 Windows x86-32 |
|
SHA-256 checksum How to use checksums |
8963218007a078f78cda22a48ce38ef14181650dd8bfab1d599bc360c40491ed
|
|
BLAKE2b-256 checksum How to use checksums |
196e7538ea43cf720c77a9b1cdcdc5c1a25445f064ffd64a00d108e2d7dc3d1b
|
| 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.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | nano_astar-0.1.2-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 |
f0bc45fcdf429af261b1fa42c20fb7aae5cc23bba3f48853e714db0627be7572
|
|
BLAKE2b-256 checksum How to use checksums |
9606cf973b693e944f6a620cd06c404813fb7df4fd1401edc49f3d0da6ae7350
|
| 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.2-cp39-cp39-macosx_11_0_arm64.whl
| Download URL | nano_astar-0.1.2-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 |
c8c67f38e1b2c235a83cc2343d699ba4dd959cecfb6fdb514dc01ba65b266097
|
|
BLAKE2b-256 checksum How to use checksums |
928018b56b7d33a471bd0bfe6b41a93179f9a17a2028b301317096fdaf95b0ac
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|