Skip to content

Commit

Permalink
Merge branch 'master' into feature/specify-hashability
Browse files Browse the repository at this point in the history
  • Loading branch information
jrialland committed Dec 13, 2022
2 parents 9987517 + c4cc558 commit 7ecd48e
Show file tree
Hide file tree
Showing 8 changed files with 878 additions and 66 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pythonpackage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [2.7, 3.5, 3.6, 3.7, 3.8]
python-version: [3.7, 3.8, 3.10]

steps:
- uses: actions/checkout@v2
Expand Down
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
language: python

python:
- 3.6
- 3.8
- nightly
- pypy3
Expand Down
6 changes: 3 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
.. image:: https://badge.fury.io/py/astar.svg
:target: https://badge.fury.io/py/astar

.. image:: https://travis-ci.com/jrialland/python-astar.svg?branch=master
:target: https://travis-ci.com/jrialland/python-astar

.. image:: https://app.travis-ci.com/jrialland/python-astar.svg?branch=master
:target: https://app.travis-ci.com/github/jrialland/python-astar
.. image:: https://coveralls.io/repos/github/jrialland/python-astar/badge.svg?branch=master
:target: https://coveralls.io/github/jrialland/python-astar?branch=master

Expand Down
97 changes: 71 additions & 26 deletions astar/__init__.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,76 @@
# -*- coding: utf-8 -*-
""" generic A-Star path searching algorithm """

from abc import ABCMeta, abstractmethod
from heapq import heappush, heappop, heapify
from abc import ABC, abstractmethod
from heapq import heappush, heappop
from typing import Iterable, Union

__author__ = "Julien Rialland"
__copyright__ = "Copyright 2012-2017, J.Rialland"
__copyright__ = "Copyright 2012-2022, J.Rialland"
__license__ = "BSD"
__version__ = "0.93"
__version__ = "0.94"
__maintainer__ = __author__
__email__ = ''.join(map(chr, [106, 117, 108, 105, 101, 110, 46, 114, 105,
97, 108, 108, 97, 110, 100, 64, 103, 109, 97, 105, 108, 46, 99, 111, 109]))
__email__ = "".join(
map(
chr,
[
106,
117,
108,
105,
101,
110,
46,
114,
105,
97,
108,
108,
97,
110,
100,
64,
103,
109,
97,
105,
108,
46,
99,
111,
109,
],
)
)
__status__ = "Production"

# infinity as a constant
Infinite = float("inf")

Infinite = float('inf')

class AStar(ABC):

class AStar:
__metaclass__ = ABCMeta
__slots__ = ()

class SearchNode:
__slots__ = ('data', 'gscore', 'fscore',
'closed', 'came_from', 'out_openset')
"""Representation of a search node"""

def __init__(self, data, gscore=Infinite, fscore=Infinite):
__slots__ = ("data", "gscore", "fscore", "closed", "came_from", "out_openset")

def __init__(
self, data, gscore: float = Infinite, fscore: float = Infinite
) -> None:
self.data = data
self.gscore = gscore
self.fscore = fscore
self.closed = False
self.out_openset = True
self.came_from = None

def __lt__(self, b):
def __lt__(self, b: "AStar.SearchNode") -> bool:
return self.fscore < b.fscore

class SearchNodeDict(dict):

def __missing__(self, k):
v = AStar.SearchNode(k)
self.__setitem__(k, v)
Expand All @@ -60,7 +93,6 @@ def distance_between(self, n1, n2):
n2 is guaranteed to belong to the list returned by the call to neighbors(n1).
This method must be implemented in a subclass.
"""
raise NotImplementedError

@abstractmethod
def neighbors(self, node):
Expand All @@ -78,24 +110,26 @@ def is_goal_reached(self, current, goal):
"""
return current == goal

def reconstruct_path(self, last, reversePath=False):
def reconstruct_path(self, last, reversePath=False)->Iterable:
def _gen():
current = last
while current:
yield current.data
current = current.came_from

if reversePath:
return _gen()
else:
return reversed(list(_gen()))

def astar(self, start, goal, reversePath=False):
def astar(self, start, goal, reversePath: bool = False) -> Union[Iterable, None]:
if self.is_goal_reached(start, goal):
return [start]
searchNodes = AStar.SearchNodeDict()
startNode = searchNodes[start] = AStar.SearchNode(
start, gscore=.0, fscore=self.heuristic_cost_estimate(start, goal))
openSet = []
start, gscore=0.0, fscore=self.heuristic_cost_estimate(start, goal)
)
openSet:list = []
heappush(openSet, startNode)
while openSet:
current = heappop(openSet)
Expand All @@ -106,14 +140,16 @@ def astar(self, start, goal, reversePath=False):
for neighbor in map(lambda n: searchNodes[n], self.neighbors(current.data)):
if neighbor.closed:
continue
tentative_gscore = current.gscore + \
self.distance_between(current.data, neighbor.data)
tentative_gscore = current.gscore + self.distance_between(
current.data, neighbor.data
)
if tentative_gscore >= neighbor.gscore:
continue
neighbor.came_from = current
neighbor.gscore = tentative_gscore
neighbor.fscore = tentative_gscore + \
self.heuristic_cost_estimate(neighbor.data, goal)
neighbor.fscore = tentative_gscore + self.heuristic_cost_estimate(
neighbor.data, goal
)
if neighbor.out_openset:
neighbor.out_openset = False
heappush(openSet, neighbor)
Expand All @@ -124,10 +160,18 @@ def astar(self, start, goal, reversePath=False):
return None


def find_path(start, goal, neighbors_fnct, reversePath=False, heuristic_cost_estimate_fnct=lambda a, b: Infinite, distance_between_fnct=lambda a, b: 1.0, is_goal_reached_fnct=lambda a, b: a == b):
def find_path(
start,
goal,
neighbors_fnct,
reversePath=False,
heuristic_cost_estimate_fnct=lambda a, b: Infinite,
distance_between_fnct=lambda a, b: 1.0,
is_goal_reached_fnct=lambda a, b: a == b,
):
"""A non-class version of the path finding algorithm"""
class FindPath(AStar):

class FindPath(AStar):
def heuristic_cost_estimate(self, current, goal):
return heuristic_cost_estimate_fnct(current, goal)

Expand All @@ -139,7 +183,8 @@ def neighbors(self, node):

def is_goal_reached(self, current, goal):
return is_goal_reached_fnct(current, goal)

return FindPath().astar(start, goal, reversePath)


__all__ = ['AStar', 'find_path']
__all__ = ["AStar", "find_path"]
Loading

0 comments on commit 7ecd48e

Please sign in to comment.