4

I am trying to implement a* pathfinding in my program, but it is returning the following output. Here is the output image

enter image description here

In the image blue blocks are visited blocks, the one with circles are yet to visit blocks and the yellow blocks are path retuned to us.

I could not figure out the problem in my code here is the following code the I used.

class Node:
    def __init__(self, parent=None, position=None):
        self.parent = parent
        self.position = position

        self.g = 0 
        self.h = 0
        self.f = 0
    def __eq__(self, other):
        return self.position == other.position


def search(maze, cost, start, end):  # Hear maze is a 2D list with 1 means a wall and 0 is a clear block
    start_node = Node(None, tuple(start))
    start_node.g = start_node.h = start_node.f = 0
    end_node = Node(None, tuple(end))
    end_node.g = end_node.h = end_node.f = 0

    yet_to_visit_list = []

    visited_list = []

    yet_to_visit_list.append(start_node)

    outer_iterations = 0
    max_iterations = (len(maze) // 2) ** 10

    move = [[-1, 0], [0, -1], [1, 0], [0, 1]]

    no_rows, no_columns = np.shape(maze)

    while len(yet_to_visit_list) > 0:
        outer_iterations += 1
        current_node = yet_to_visit_list[0]
        current_index = 0

        for index, item in enumerate(yet_to_visit_list):
            if item.f < current_node.f:
                current_node = item
                current_index = index 
        
        if outer_iterations > max_iterations:
            print("Cann't find the path... too many iterations")
            return return_path(current_node, maze)
        
        yet_to_visit_list.pop(current_index)
        visited_list.append(current_node)
        maze[current_node.position[0]][current_node.position[1]] = 2 # 1 wall 2 visited 3 yet to visit

        if current_node == end_node:
            return return_path(current_node, maze)

        children = []

        for new_position in move:
            node_position = (current_node.position[0]+ new_position[0], current_node.position[1]+ new_position[1])

            if (node_position[0] > (no_rows - 1) or node_position[0] < 0 or node_position[1]>(no_columns-1) or node_position[1] < 0):
                continue

            if maze[node_position[0]][node_position[1]] != 0:
                continue

            new_node = Node(current_node, node_position)

            children.append(new_node)

        for child in children:
            if len([visited_child for visited_child in visited_list if visited_child == child]) > 0:
                continue
            
            child.g = current_node.g + cost
            child.h = (((child.position[0] - end_node.position[0]) ** 2 ) +
                        ((child.position[0] - end_node.position[0])) ** 2)
            
            child.f = child.g + child.h
            if len([i for i in yet_to_visit_list if child == i and child.g>i.g]) > 0:
                continue
            
            yet_to_visit_list.append(child)

And the following function returns the path

def return_path(current_node, maze):
    path = []
    no_rows, no_columns = np.shape(maze)

    result = maze
    current = current_node

    while current is not None:
        path.append(current.position)
        current = current.parent

    path = path[::-1]
    start_value = 0

    for i in range(len(path)):
        result[path[i][0]][path[i][1]] = start_value
        start_value += 1

    return result
c0der
  • 18,467
  • 6
  • 33
  • 65

1 Answers1

2

In your for loop over move, you exclude neighbors with maze[.][.] != 0: i.e., neighbors that are either "wall" or "visited". The original A* algorithm requires you to reconsider visited nodes to see if the cost can be further reduced.

Also, I get the sense that you should be removing items from the visited_list at some point in your program but I don't see this happening.

It would be easier to tell exactly what's wrong once you make the program input available, since it would then become possible to step through your code with a debugger.

Another problem is that you are using the squared distance for your heuristic cost, which likely overestimates the cost. With up-down-left-right neighbors, use the Manhattan distance function (see the warning about using squared Euclidean distance in the link). I don't think this is at the heart of what's wrong with your program, though.

Salmonstrikes
  • 737
  • 1
  • 6
  • 25