Skip to main content

A simple implementation of the A* algorithm for path-finding on a two-dimensional grid.

Project description

Build Status Coverage Status PyPI version

PyAstar2D

This is a very simple C++ implementation of the A* algorithm for pathfinding on a two-dimensional grid. The solver itself is implemented in C++, but is callable from Python. This combines the speed of C++ with the convenience of Python.

I have not done any formal benchmarking, but the solver finds the solution to a 1802 by 1802 maze in 0.29s and a 4008 by 4008 maze in 0.83s when running on my nine-year-old Intel(R) Core(TM) i7-2630QM CPU @ 2.00GHz. See Example Results for more details.

See src/cpp/astar.cpp for the core C++ implementation of the A* shortest path search algorithm, src/pyastar2d/astar_wrapper.py for the Python wrapper and examples/example.py for example usage.

When determining legal moves, 4-connectivity is the default, but it is possible to set allow_diagonal=True for 8-connectivity.

Installation

Instructions for installing pyastar2d are given below.

From PyPI

The easiest way to install pyastar2d is directly from the Python package index:

pip install pyastar2d

From source

You can also install pyastar2d by cloning this repository and building it yourself. If running on Linux or MacOS, simply run

pip install .

from the root directory. If you are using Windows you may have to install Cython manually first:

pip install Cython
pip install .

To check that everything worked, run the example:

python examples/example.py

As a dependency

Include pyastar2d in your requirements.txt to install from pypi, or add this line to requirements.txt:

pyastar2d @ git+git://github.com/hjweide/pyastar2d.git@master#egg=pyastar2d

Usage

A simple example is given below:

import numpy as np
import pyastar2d
# The minimum cost must be 1 for the heuristic to be valid.
# The weights array must have np.float32 dtype to be compatible with the C++ code.
weights = np.array([[1, 3, 3, 3, 3],
                    [2, 1, 3, 3, 3],
                    [2, 2, 1, 3, 3],
                    [2, 2, 2, 1, 3],
                    [2, 2, 2, 2, 1]], dtype=np.float32)
# The start and goal coordinates are in matrix coordinates (i, j).
path = pyastar2d.astar_path(weights, (0, 0), (4, 4), allow_diagonal=True)
print(path)
# The path is returned as a numpy array of (i, j) coordinates.
array([[0, 0],
       [1, 1],
       [2, 2],
       [3, 3],
       [4, 4]])

Note that all grid points are represented as (i, j) coordinates. An example of using pyastar2d to solve a maze is given in examples/maze_solver.py.

Example Results

To test the implementation, I grabbed two nasty mazes from Wikipedia. They are included in the mazes directory, but are originally from here: Small and Large. I load the .png files as grayscale images, and set the white pixels to 1 (open space) and the black pixels to INF (walls).

To run the examples specify the input and output files using the --input and --output flags. For example, the following commands will solve the small and large mazes:

python examples/maze_solver.py --input mazes/maze_small.png --output solns/maze_small.png
python examples/maze_solver.py --input mazes/maze_large.png --output solns/maze_large.png

Small Maze (1802 x 1802):

time python examples/maze_solver.py --input mazes/maze_small.png --output solns/maze_small.png
Loaded maze of shape (1802, 1802) from mazes/maze_small.png
Found path of length 10032 in 0.292794s
Plotting path to solns/maze_small.png
Done

real	0m1.214s
user	0m1.526s
sys	0m0.606s

The solution found for the small maze is shown below: Maze Small Solution

Large Maze (4002 x 4002):

time python examples/maze_solver.py --input mazes/maze_large.png --output solns/maze_large.png
Loaded maze of shape (4002, 4002) from mazes/maze_large.png
Found path of length 783737 in 0.829181s
Plotting path to solns/maze_large.png
Done

real	0m29.385s
user	0m29.563s
sys	0m0.728s

The solution found for the large maze is shown below: Maze Large Solution

Motivation

I recently needed an implementation of the A* algorithm in Python to find the shortest path between two points in a cost matrix representing an image. Normally I would simply use networkx, but for graphs with millions of nodes the overhead incurred to construct the graph can be expensive. Considering that I was only interested in graphs that may be represented as two-dimensional grids, I decided to implement it myself using this special structure of the graph to make various optimizations. Specifically, the graph is represented as a one-dimensional array because there is no need to store the neighbors. Additionally, the lookup tables for previously-explored nodes (their costs and paths) are also stored as one-dimensional arrays. The implication of this is that checking the lookup table can be done in O(1), at the cost of using O(n) memory. Alternatively, we could store only the nodes we traverse in a hash table to reduce the memory usage. Empirically I found that replacing the one-dimensional array with a hash table (std::unordered_map) was about five times slower.

Tests

The default installation does not include the dependencies necessary to run the tests. To install these, first run

pip install -r requirements-dev.txt

before running

py.test

The tests are fairly basic but cover some of the more common pitfalls. Pull requests for more extensive tests are welcome.

References

  1. A* search algorithm on Wikipedia
  2. Pathfinding with A* on Red Blob Games

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyastar2d-1.0.1.tar.gz (10.2 kB view details)

Uploaded Source

Built Distribution

pyastar2d-1.0.1-cp39-cp39-macosx_10_9_x86_64.whl (10.9 kB view details)

Uploaded CPython 3.9 macOS 10.9+ x86-64

File details

Details for the file pyastar2d-1.0.1.tar.gz.

File metadata

  • Download URL: pyastar2d-1.0.1.tar.gz
  • Upload date:
  • Size: 10.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.1 importlib_metadata/4.5.0 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.61.0 CPython/3.9.2

File hashes

Hashes for pyastar2d-1.0.1.tar.gz
Algorithm Hash digest
SHA256 001236431b74708e379c2854fc096fc65d49fba819a1510e8ef18f50c3915b8e
MD5 878c39919dece4c68647db08fed2b2b5
BLAKE2b-256 777b811ad630f043a3b26694c890d236beb27bed1e4b99a0e556601024b0db2b

See more details on using hashes here.

File details

Details for the file pyastar2d-1.0.1-cp39-cp39-macosx_10_9_x86_64.whl.

File metadata

  • Download URL: pyastar2d-1.0.1-cp39-cp39-macosx_10_9_x86_64.whl
  • Upload date:
  • Size: 10.9 kB
  • Tags: CPython 3.9, macOS 10.9+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.1 importlib_metadata/4.5.0 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.61.0 CPython/3.9.2

File hashes

Hashes for pyastar2d-1.0.1-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 4dcd2cb74e61aa3d42abd410a03cc055a480520550ca7a21c43bb2bf4fef6951
MD5 35ad0057ed0193e6639c34aea4976fec
BLAKE2b-256 46d1d1736188fa32a99b29eb39d1e07f9592fe04c895d0d0b5e1ce6e90df4415

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page