Welcome, guest | Sign In | My Account | Store | Cart
# Author: Christian Careaga (christian.careaga7@gmail.com)
# A* Pathfinding in Python (2.7)
# Please give credit if used

import numpy
from heapq import *


def heuristic(a, b):
    return (b[0] - a[0]) ** 2 + (b[1] - a[1]) ** 2

def astar(array, start, goal):

    neighbors = [(0,1),(0,-1),(1,0),(-1,0),(1,1),(1,-1),(-1,1),(-1,-1)]

    close_set = set()
    came_from = {}
    gscore = {start:0}
    fscore = {start:heuristic(start, goal)}
    oheap = []

    heappush(oheap, (fscore[start], start))
    
    while oheap:

        current = heappop(oheap)[1]

        if current == goal:
            data = []
            while current in came_from:
                data.append(current)
                current = came_from[current]
            return data

        close_set.add(current)
        for i, j in neighbors:
            neighbor = current[0] + i, current[1] + j            
            tentative_g_score = gscore[current] + heuristic(current, neighbor)
            if 0 <= neighbor[0] < array.shape[0]:
                if 0 <= neighbor[1] < array.shape[1]:                
                    if array[neighbor[0]][neighbor[1]] == 1:
                        continue
                else:
                    # array bound y walls
                    continue
            else:
                # array bound x walls
                continue
                
            if neighbor in close_set and tentative_g_score >= gscore.get(neighbor, 0):
                continue
                
            if  tentative_g_score < gscore.get(neighbor, 0) or neighbor not in [i[1]for i in oheap]:
                came_from[neighbor] = current
                gscore[neighbor] = tentative_g_score
                fscore[neighbor] = tentative_g_score + heuristic(neighbor, goal)
                heappush(oheap, (fscore[neighbor], neighbor))
                
    return False

'''Here is an example of using my algo with a numpy array,
   astar(array, start, destination)
   astar function returns a list of points (shortest path)'''

nmap = numpy.array([
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [1,1,1,1,1,1,1,1,1,1,1,1,0,1],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [1,0,1,1,1,1,1,1,1,1,1,1,1,1],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [1,1,1,1,1,1,1,1,1,1,1,1,0,1],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [1,0,1,1,1,1,1,1,1,1,1,1,1,1],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [1,1,1,1,1,1,1,1,1,1,1,1,0,1],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0]])
    
print astar(nmap, (0,0), (10,13))

Diff to Previous Revision

--- revision 2 2014-08-05 23:28:11
+++ revision 3 2014-08-06 10:03:01
@@ -5,84 +5,58 @@
 import numpy
 from heapq import *
 
+
 def heuristic(a, b):
-    """calculates the H cost using the Manhattan Method"""
-    return 10*(abs(a[0] - b[0]) + abs(a[1] - b[1]))
+    return (b[0] - a[0]) ** 2 + (b[1] - a[1]) ** 2
 
-def getG(current, neighbor):
-    """Function to calculate G cost, 10 for ortogonal movement, and 14 for diagonal movement"""
-    vector_sub = [abs(neighbor[0] - current[0]), abs(neighbor[1] - current[1])]
-    if sum(vector_sub) > 1:
-        move_cost = 14
-    else:
-        move_cost = 10
-    return move_cost
+def astar(array, start, goal):
 
-def astar(array, start, dest):
-    """ 
-    Function to calculate the shortest path from point a to point
-    b in a numpy array, using A* pathfinding algorithm and a binary heap.
-    0's in the array are walkable nodes, while 1's are solid obstacles
-    """
     neighbors = [(0,1),(0,-1),(1,0),(-1,0),(1,1),(1,-1),(-1,1),(-1,-1)]
-    closed = []
-    open_list = []
 
+    close_set = set()
     came_from = {}
-
-    gscore = {start : 0}
-    fscore = {start : heuristic(start, dest)}
+    gscore = {start:0}
+    fscore = {start:heuristic(start, goal)}
     oheap = []
 
-    #place start and its fscore to heap and add start to open_set
     heappush(oheap, (fscore[start], start))
-    open_list.append(start)
+    
+    while oheap:
 
-    while len(open_list):
-        #Grab fscore and corresponding position off top of heap
         current = heappop(oheap)[1]
-        open_list.append(current)
-        
-        if current == dest: #check if path is done and trace it back
-            path = []
+
+        if current == goal:
+            data = []
             while current in came_from:
-                path.append(current)
+                data.append(current)
                 current = came_from[current]
-            return list(reversed(path))
+            return data
 
-        #drop current and place it in closed list
-        open_list.remove(current)
-        closed.append(current)
-
-        for x, y in neighbors: #check current nodes neighbors
-            current_neighbor = current[0]+x , current[1]+y
-            if current_neighbor in closed:
-                continue
-
-            new_g = gscore[current] + getG(current, current_neighbor)
- 
-            #check if neighbors are outside array bounds or they are obstacles
-            if 0 <= current_neighbor[0] < array.shape[0]:
-                if 0 <= current_neighbor[1] < array.shape[1]:                
-                    if array[current_neighbor[0]][current_neighbor[1]] == 1:
-                        closed.append(current_neighbor)
-                        continue # solid obstacle
+        close_set.add(current)
+        for i, j in neighbors:
+            neighbor = current[0] + i, current[1] + j            
+            tentative_g_score = gscore[current] + heuristic(current, neighbor)
+            if 0 <= neighbor[0] < array.shape[0]:
+                if 0 <= neighbor[1] < array.shape[1]:                
+                    if array[neighbor[0]][neighbor[1]] == 1:
+                        continue
                 else:
                     # array bound y walls
                     continue
             else:
                 # array bound x walls
                 continue
-     
-            if current_neighbor not in open_list or new_g < gscore.get(current_neighbor, 0):
-                #make current node parent of neighbor node, and update G and F costs
-                came_from[current_neighbor] = current
-                gscore[current_neighbor] = new_g
-                fscore[current_neighbor] = new_g + getG(current, current_neighbor)
-
-                #add neighbors to open_set and to bin heap
-                open_list.append(current_neighbor)
-                heappush(oheap, (fscore[current_neighbor], current_neighbor))
+                
+            if neighbor in close_set and tentative_g_score >= gscore.get(neighbor, 0):
+                continue
+                
+            if  tentative_g_score < gscore.get(neighbor, 0) or neighbor not in [i[1]for i in oheap]:
+                came_from[neighbor] = current
+                gscore[neighbor] = tentative_g_score
+                fscore[neighbor] = tentative_g_score + heuristic(neighbor, goal)
+                heappush(oheap, (fscore[neighbor], neighbor))
+                
+    return False
 
 '''Here is an example of using my algo with a numpy array,
    astar(array, start, destination)

History