'Why does my IDA* return a faulty path and takes too long to execute?

Does anyone know where the problem might be? My IDA* takes too long to complete and it also gives a really faulty path sometimes, like here: faulty path

I have tried to implement it with wiki, then another page but to no avail. It sometimes gives a really faulty path as mentioned above. It also takes too long to execute. There seems to be no good material for this topic and I for sure struggle with it. The main idea of my implementation was to have a dict of visited nodes and every iteration the dict would reset. Key od visited dict is node position and value is node. Now that I think of it... the node as a value is not really needed there but that hardly solves anything. So every time I am about to create a new node as a neighbor, the node itself wouldn't get created if it's in the visited dict or if its our end node, since the end node is created at the beginning. As far as grid is concerned. 1 means obstacle, 0 means walkable.

Code:

class NodeRecord:
    position = None
    connection = None
    g = 0
    f = 0
    h = 0
    parent = None

class IDAstar:
    def __init__(self):
        self.end = None
        self.start = None
        self.path = list()
        self.grid = list()
        self.cols = int()
        self.rows = int()
        self.visited = dict()

    def find_path(self, start: tuple, end: tuple, grid: list, gamedisplay, rect_arr) -> list:
        self.init_grid(grid)
        self.set_end(end)
        self.set_start(start)
        treshold = self.start.h
        count = 1
        while 1:
            #print(f'Iteration: {count}')
            count += 1
            t = self.search(self.start, 0, treshold, gamedisplay, rect_arr)
            if t == FOUND:
                return self.reconstruct_path()
            if t == float('inf'):
                return []
            self.visited = {}
            treshold = t

    def search(self, node, g, treshold, gamedisplay, rect_arr):
        self.visited[node.position] = node
        f = g + heuristics.manhattan(node.position, self.end.position)
        if f > treshold:
            return f
        if node.position == self.end.position:
            return FOUND
        min = float('inf')
        for neighbor in self.get_adjacent_list(node, self.grid, self.cols, self.rows):
            if neighbor['node'].position not in self.visited.keys():
                t = self.search(neighbor['node'], g + neighbor['cost'], treshold, gamedisplay, rect_arr)
                if t == FOUND:
                    return FOUND
                if t < min:
                    min = t
                    neighbor['node'].parent = node
        return min

    def get_adjacent_list(self, parent, graph, width, height):
        adjacent_list = []
        diagonal = [(-1, 1), (1, 1), (1, -1), (-1, -1)]
        new_pos = [(-1, 0), (0, 1), (1, 0), (0, -1)]
        new_pos.extend(diagonal)
        for position in new_pos:
            y, x = (parent.position[0] + position[0], parent.position[1] + position[1])
            left, right, up, down = x - 1, x + 1, y - 1, y + 1
            if y >= height or y < 0 or x >= width or x < 0:
                continue
            if graph[y][x] != 0: # if its unwalkable
                continue
            if position == (1, 1):
                if graph[up][x] != 0 or graph[y][left] != 0: # corner cutting
                    continue
            if position == (1, -1):
                if graph[up][x] != 0 or graph[y][right] != 0: # corner cutting
                    continue
            if position == (-1, -1):
                if graph[down][x] != 0 or graph[y][right] != 0: # corner cutting
                    continue
            if position == (-1, 1):
                if graph[down][x] != 0 or graph[y][left] != 0: # corner cutting
                    continue
            if (y, x) in self.visited.keys(): # if we have visited this node
                continue
            elif (y, x) == self.end.position: # if the node we are about to create is end node
                self.end.parent = parent
                if position in diagonal:
                    adjacent_list.append({'node': self.end, 'cost': 1.41})
                else:
                    adjacent_list.append({'node': self.end, 'cost': 1})
            else:
                node = NodeRecord()
                node.position = (y, x)
                node.parent = parent
                if position in diagonal:
                    adjacent_list.append({'node': node, 'cost': 1.41})
                else:
                    adjacent_list.append({'node': node, 'cost': 1})
        return adjacent_list



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source