如何通过python中的A *寻路算法运行三维列表

时间:2017-12-11 16:09:36

标签: python algorithm graph

我是(尝试)编写python实现A *算法的学生。我知道这个问题之前已被问过100次了,但我的情况有一些具体细节我还没有完全理解。

我有一个带有10个节点的加权非定向图。我的实际图表将有更多节点。该图表被排序为3维列表。我正在粘贴我们编写的程序的一些输出以生成图形。

Node 1 : [[8, 3], [9, 11], [2, 12], [3, 12], [7, 6]]
Node 2 : [[5, 6], [4, 3], [1, 12], [8, 11], [7, 1]]
Node 3 : [[6, 2], [1, 12], [5, 7], [9, 1]]
Node 4 : [[2, 3], [8, 2], [10, 5], [5, 10], [7, 4]]
Node 5 : [[2, 6], [4, 10], [3, 7], [7, 8]]
Node 6 : [[3, 2], [9, 10]]
Node 7 : [[2, 1], [4, 4], [5, 8], [1, 6], [8, 3]]
Node 8 : [[1, 3], [2, 11], [4, 2], [7, 3], [10, 4]]
Node 9 : [[1, 11], [6, 10], [3, 1]]
Node 10 : [[4, 5], [8, 4]]

在可读性较差的格式中,图表存储为3维列表。因此,例如,在索引0处,存在到节点8,9,2,3和7的连接。节点8和0之间的权重是3.节点0和9之间的权重和11.我认为你得到了这个想法。

myGraph = [[[8, 3], [9, 11], [2, 12], [3, 12], [7, 6]], [[5, 6], [4, 3], [1, 12], [8, 11], [7, 1]], [[6, 2], [1, 12], [5, 7], [9, 1]], [[2, 3], [8, 2], [10, 5], [5, 10], [7, 4]], [[2, 6], [4, 10], [3, 7], [7, 8]], [[3, 2], [9, 10]], [[2, 1], [4, 4], [5, 8], [1, 6], [8, 3]], [[1, 3], [2, 11], [4, 2], [7, 3], [10, 4]], [[1, 11], [6, 10], [3, 1]], [[4, 5], [8, 4]]]

所以挑战是找到一个将接受列表作为输入的A *的python实现,并输出最佳路由。似乎大多数图表是围绕字典数据类型构建的,但这不是我的情况。

我已经开始尝试使用3D列表编写我自己的A *版本,但没有运气,因为它对我来说有点复杂。

1 个答案:

答案 0 :(得分:0)

这是未经测试的伪代码,用于为@Luai Ghunim所说的内容添加细节。

首先,您可以在Python标准库中找到https://docs.python.org/3/library/heapq.html已经存在的优先级队列实现。这将存储您的todo列表。

其次,进入该队列的事情需要很好地排序。一个技巧是使用元组,第一个字段是你想要排序的。像这样:

[estimated_total, node, cost]

您可以使用https://docs.python.org/3/library/collections.html#collections.namedtuple使字段看起来很漂亮,以便为字段提供这些名称。我们假设你没有,但这是个人选择。

第三,你需要有一个函数来从任何节点估计它到底有多远。我们称之为estimator(node)

最后,我们需要一个名为from_node的字典,了解我们如何到达某个特定节点。它的条目如下:

node: {"from": prev_node, "cost": 6}

考虑到这一点,它应该是这样的:

# Start with node 0 in our lookup.
from_node = {0: {"from_node": None, "cost": 0.0}}
# And in our todo.
todo = [[estimator(0), 0, 0.0]]
while 0 < len(todo):
    (estimated_cost, node, cost) = heapq.heappop(todo)
    if cost == from_node[node]["cost"]:
        if node == target_node:
            # We have our answer and know that it is best.
            break
        else:
            for (next_node, next_cost) in my_graph[node]:
                total_cost = cost + next_cost
                if next_node in from_node:
                    if from_node[next_node]["cost"] <= total_cost:
                        # We have a better path.
                        continue
                from_node[next_node] = {"from": node, "cost": total_cost}
                heapq.heappush(todo,
                    [total_cost + estimator(next_node), next_node, total_cost])
if target_node in from_node:
    reversed_path = []
    node = target_node
    while node is not None:
        reversed_path.append(node)
        node = from_node[node]["from"]
    # AND NOW reversed(reversed_path) IS YOUR ANSWER
else:
    # THERE IS NO ANSWER