用A *来解决旅行推销员

时间:2010-12-15 18:25:41

标签: algorithm a-star traveling-salesman

我的任务是编写A *算法的实现(提供启发式算法),以解决旅行商问题。我理解算法,它很简单,但我只是看不到实现它的代码。我的意思是,我明白了。节点的优先级队列,按距离+启发式(节点)排序,将最近的节点添加到路径上。问题是,如果无法从前一个最近的节点到达最近的节点会发生什么?如何将“图形”作为函数参数?我只是无法看到算法实际上如何运作,如代码。

我在发布问题之前阅读了维基百科页面。反复。它并没有真正回答问题 - 搜索图表的方式与解决TSP的方式不同。例如,您可以构造一个图形,其中任何给定时间的最短节点总是导致回溯,因为相同长度的两条路径不相等,而如果您只是尝试从A到B,那么两条路径长度相同的。

您可以通过始终最接近的方式派生一个永远不会到达某些节点的图形。

我真的不知道A *如何适用于TSP。我的意思是,找到从A到B的路线,当然,我明白了。但TSP?我没有看到这种联系。

6 个答案:

答案 0 :(得分:10)

我找到了解决方案here

使用最小生成树作为启发式。

设置 初始状态:代理人在起始城市并且没有访问任何其他城市

目标状态:代理已访问所有城市并再次到达城市

后继功能:生成所有尚未访问过的城市

边缘成本:节点所代表的城市之间的距离,使用此成本来计算g(n)。

h(n):距离当前城市最近的未访问城市的距离+所有未访问城市的预计距离(此处使用的MST启发式)+距离未访问城市到起始城市的最近距离。请注意,这是一个可接受的启发式功能。 您可以考虑维护一个访问过的城市列表和一个未访问的城市列表,以便于计算。

答案 1 :(得分:2)

如果仅仅是理解算法及其工作原理的问题,您可能需要考虑在纸上绘制图形,为其指定权重并将其绘制出来。你也可以找到一些显示Dijkstra最短路径的动画,Wikipedia有一个很好的动画。 Dijkstra和A *之间的唯一区别是添加了启发式算法,一旦到达目标节点,就会停止搜索。至于用它来解决TSP,祝你好运!

答案 2 :(得分:1)

更加抽象地考虑一下。暂时忘记A *,无论如何,这只是dijkstra的启发式。之前,你想从A到B.从那个目标是什么?要到达B.目标是以最低的成本到达B.在任何给定的点上,你现在的“状态”是什么?可能只是你在图表上的位置。

现在,你想从A开始,然后去B和C.你现在的目标是什么?要传递B和C,保持最低成本。您可以使用更多节点来概括:D,E,F,...或仅N个节点。现在,在任何给定的点上,你现在的“状态”是什么?这很关键:它不仅仅是您在图表中的位置 - 它也是B或C中的哪一个或者您在搜索中到目前为止访问过的任何节点。

实现原始算法,以便在进行X移动后调用某个函数询问它是否已达到“目标状态”。之前,该功能刚刚说“是的,你在B州,因此你就是目标”。但是现在,如果搜索的路径已经超过了每个感兴趣的点,那么让该函数返回“是的,你处于目标状态”。它会知道搜索是否已超过所有兴趣点,因为它包含在当前状态中。

在你得到它之后,用一些启发式方法改进搜索,然后A *它。

答案 3 :(得分:1)

这里的混淆是,您尝试解决TSP的图表是 您正在执行A *搜索的图表。

参见相关内容:Sudoku solving algorithm C++

要解决此问题,您需要:

  • 定义您的:
    • TSP声明
    • TSP初始状态
    • TSP目标状态
    • TSP状态后继功能
    • TSP状态启发式
  • 将通用A *解算器应用于此TSP状态图

我能想到的一个简单例子:

  • TSP状态:当前处于TSP周期中的节点(城市)列表
  • TSP初始状态:包含单个节点的列表,旅行商的家乡
  • TSP目标状态:状态是目标,如果它包含城市图中的每个节点
  • TSP后继功能:可以将当前周期中没有的任何节点(城市)添加到周期中节点列表的末尾以获得新状态
    • 转换的成本等于您添加到周期的边缘成本
  • TSP状态启发式:您决定

答案 4 :(得分:0)

回答你的一个问题......

要将图形作为函数参数传递,您有几个选项。您可以将指针传递给包含所有节点的数组。如果它是完全连接的图形,您可以只传递一个起始节点并从那里开始工作。最后,您可以编写一个图形类,其中包含您需要的任何数据结构,并将引用传递给该类的实例。

至于你关于最近节点的其他问题,它不是A *搜索的一部分,它会根据需要回溯吗?或者你可以实现自己的回溯来处理这种情况。

答案 5 :(得分:0)

  

问题是,如果无法从前一个最近的节点到达最近的节点会发生什么?

此步骤不是必需的。就像在,你没有计算从最接近当前最近的路径,你正试图到达你的目标节点,并且当前最接近的是唯一重要的事情(例如算法不关心最后一次迭代你在100公里以外,因为这次迭代你只有96公里远。)

作为一个广泛的介绍,A *不直接构造路径:它探索直到它肯定知道路径包含在它探索的区域内,然后根据探索期间记录的信息构建路径。

(我将使用the code in the Wikipedia article作为参考实现来帮助我解释。)

您有两组节点:closedsetopenset

closedset包含已经完全评估的节点,也就是说,您确切地知道它们距离start到底有多远,并且它们的所有邻居都在两个集合中的一个中。这没有你可以用它们做的更多的计算,所以我们可以(有点)忽略它们。 (基本上这些都完全包含在边界内。)

openset拥有“边框”节点,你知道它们离start有多远,但你还没有触及它们的邻居,所以它们到目前为止都处于搜索的边缘。 / p>

(隐含地,有第三组:完全不受影响的节点。但是在openset之前你并没有触及它们所以它们无关紧要。)

在给定的迭代中,如果您有要探索的节点(即openset中的节点),您需要找出要探索的节点。这是启发式的工作,它基本上通过告诉你它认为哪个节点有goal的最短路径,给你一个关于边界哪个点最好探索的提示。

上一个最接近的节点无关紧要,它只是略微扩展了边界,将新节点添加到openset。这些新节点现在是此迭代中最近节点的候选者。

首先,openset只包含start,但是您会迭代并在每个步骤中扩展边框(在最有希望的方向上),直到最终到达goal

当A *实际进行探索时,它并不担心哪些节点来自哪里。它不需要,因为它知道它们与start的距离和启发式函数,这就是它所需要的一切。

但是,要稍后重建路径,您需要记录路径,这就是camefrom。对于给定节点,camefrom将其链接到最接近start的节点,因此您可以通过从goal向后关注链接来重建最短路径。

  

如何将“图形”作为函数参数?

通过其中一个representations of a graph

  

我真的不知道A *如何适用于TSP。我的意思是,找到从A到B的路线,当然,我明白了。但TSP?我没有看到这种联系。

您需要不同的启发式和不同的结束条件:goal不再是单个节点,而是连接所有内容的状态;并且您的启发式算法是连接其余节点的最短路径长度的估计值。

相关问题