A *在Python优先级队列中搜索

时间:2015-02-12 22:01:51

标签: python search graph

我正在尝试编写一个A *搜索来解决Python中的迷宫,但是我正在努力寻找一个可用于此的内置优先级队列。我目前正在使用PriorityQueue,但它没有提供任何功能来更改项目优先级,这是算法底部注释部分的问题(在else if语句中)。

有没有人知道我可以做什么,如果阻止,或内置优先级队列会给我这个功能?

def A_search(maze, start, end):
expanded = 0 # use to track number of nodes expanded by the algorithm
node1 = Node(start,0)
frontier = PriorityQueue()
frontier.put((dist_to_goal(node1,end) + node1.get_cost(), node1))
visited = []
in_frontier = [] # keep track of items in frontier, PriorityQueue has no way to peek
in_frontier.append(node1)
while(True):
    if(frontier == []):
        return(None,expanded)
    curr = (frontier.get())[1]
    in_frontier.remove(curr)
    expanded += 1
    if(curr.get_loc() == end):
        return(curr,expanded)
    visited.append(curr.get_loc())
    neighbors = find_neighbors(maze, curr.get_loc())
    for neighbor in neighbors:
        node_n = Node(neighbor,node1.get_cost()+1)
        node_n.parent = curr
        if(neighbor not in visited) and (node_n not in in_frontier):
            frontier.put((dist_to_goal(node_n,end) + node1.get_cost(), node_n))
            in_frontier.append(node_n)
        # else if node_n is in frontier w/ a higher path cost then replace it w/ current

2 个答案:

答案 0 :(得分:1)

您在内置库中最接近的是heapq

更改优先级后,您需要调用heapq.heapify(花费O(n)时间但不会更改A *总体复杂度)或在O(log n)时使用内部heapq._siftdown函数。

答案 1 :(得分:1)

在优先级队列实现说明中,有关heapq模块的官方python文档中讨论了更新项目优先级:https://docs.python.org/3.7/library/heapq.html#priority-queue-implementation-notes 使用这些注释,我设法编写了自己的PriorityQueue实现,该实现支持添加任务并更新任务的优先级(如果存在)。它包括使用entry_finder dict来指向优先级队列中的任务。更新任务的优先级,只需将现有任务标记为已删除,然后将其插入新的优先级即可。 在此实现中,您可以使用方法add_task

class PriorityQueue():
    REMOVED = '<removed-task>'
    def __init__(self):
        self.pq = []
        self.entry_finder = {}
        self.counter = itertools.count()


    def add_task(self, task, priority=0):
        if task in self.entry_finder:
            self.remove_task(task)
        count = next(self.counter)
        entry = [priority, count, task]
        self.entry_finder[task] = entry
        heappush(self.pq, entry)

    def remove_task(self, task):
        entry = self.entry_finder.pop(task)
        entry[-1] = self.REMOVED

    def pop_task(self):
        while self.pq:
            priority, count, task = heappop(self.pq)
            if task is not self.REMOVED:
                del self.entry_finder[task]
                return task
        return None