计算通过杂货店的最短路径

14
我正在尝试找到一种方法来在杂货店内寻找最短路径,以访问一系列的位置(购物清单)。该路径应从指定的起始位置开始,并可以在多个结束位置(多个收银柜台)结束。 此外,我对路径有一些预定义的约束条件,例如“购物清单上的物品x需要是路径上的最后一个、倒数第二个或倒数第三个物品”。有一个函数将返回给定路径的 true 或 false。 最后,这需要在有限的 CPU 功率(智能手机上)和一秒左右内计算出来。如果不可能,则近似于最佳路径也可以。
这是可能的吗?到目前为止,我认为我需要通过类似 A* 或 Dijkstra 算法计算列表中每个项目之间的距离。之后,我应该如何处理它,像旅行商问题一样吗?因为在我的问题中,存在指定的起始节点、指定的结束节点和一些约束条件,而这些条件并不在旅行商问题中。

@Bart:你想在智能手机上一秒钟内解决TSP问题,我认为你会很难——除非这是一个非常短的列表 :) 你尝试过简单的启发式/贪心方法吗?由于大多数超市都有欧几里得距离,它可能会给出“足够好”的解决方案。此外,如果您做一些类似于人们实际操作的事情,我认为对于查看结果的人来说更有意义。这可能意味着要多走15米的路程,但我仍然认为大多数人会做类似于ndp所描述的事情,并且如果告诉他们要做其他事情,他们会感到困惑。 - Mads Ravn
由于超市中的距离满足三角不等式,因此它可能提供一个“足够好”的解决方案。 - Mads Ravn
谢谢。一个不完美的路径也可以,但如果物品数量较少时能找到最优路径就更好了,如果物品数量很大,则可以使用近似算法。顺便说一下,这只是一个理论作业,所以我不需要实现任何东西。我想也许蚁群优化算法会很好,因为我可以在某个时间限制内停止它,并得到迄今为止找到的最佳近似解。 - Bart
1
对于所有提到TSP的帖子,请注意:这不是TSP。同一个地方去两次是可以的。(即使在几何图上解决TSP更容易,但这更容易)。此外,我知道的所有超市都可以描述为平面(即稀疏!)图,并且没有多于几十个交叉点。一个好的解决方案应该能够在几毫秒内解决这些问题,更不用说在智能手机上了。只是为了保持事情的透明度。 - Dimitris Andreou
实际上,超市往往采用矩形布局,这会使问题远远不及TSP(旅行商问题),甚至比考虑三角不等式的TSP问题要简单得多。 - RBarryYoung
看一下这个 https://www.youtube.com/watch?v=qil44ptNYUw 可能会有帮助。 - Aniketh Jain
5个回答

1

将其视为TSP问题似乎会使它变得更加困难。有人指出,杂货店并不那么复杂。在我熟悉的杂货店(在美国),没有太多合理的路线,特别是如果你有一个给定的起点。我认为一个深思熟虑的启发式算法可能会解决这个问题。

例如:我通常从一端开始——如果是大购物,我会确保最后经过冷冻食品区,但通常并不重要,我会从最靠近入口的地方开始。我通常走到外面,只有在需要某个单独过道的东西时才下去。一旦你进入一个过道,就拿起那个过道里的所有东西。对于一些过道,最好从一端进入,拿起物品,然后返回起点,而对于其他过道,你只需致力于整个过道——这取决于你在该过道中需要的最后一个物品以及你需要去哪里——如何走出过道取决于下一个所需物品——它可能涉及回溯,也可能不涉及回溯——但计算机可以轻松地计算出到达下一个物品的最短路径。

我同意上面其他问题的有用提示,但也许更具体的算法会更加有效,尤其是在资源有限的情况下。TSP告诉我们,你不能证明它是最优的方法,但我认为这并不是必要的...


0

基本上这是一个旅行商问题,但是根据您的要求,您可以很好地限制搜索空间。如果地点不太多,您可以尝试计算所有可能的选项,但如果不可行,您需要进一步限制搜索空间。

您可以将搜索时间限制在1秒内,以便返回您能找到的最短路径,但这可能不是所有路径中最短的,但仍然相当短。

您还可以应用贪心算法来查找下一个最近的位置,然后使用回溯选择下一个最近的位置等。

可能解决方案的伪代码:

def find_shortest_path(current_path, best_path): if time_limit(): return
if len(current_path) == NUM_LOCATIONS: # 到达目的地 if calc_len(current_path) < calc_len(best_path): best_path = current_path return
# 你需要很好地排序可能的位置,以最大化找到最短解决方案的机会 sort(possible_locations)
for location in possible_locations: find_shortest_path(current_path + location, best_path)

您可以将搜索时间限制在1秒内,这样您就能返回找到的最短路径。有哪种算法可以实现这一目标,并且能够同时考虑约束条件呢? - Bart
基本上,您可以拥有一个递归函数,在每个步骤中选择最优位置作为下一个未访问的位置。您的约束条件限制了每个步骤可用的选项。您将始终存储找到的最佳解决方案。当时间限制到达时,您将退出递归函数并返回您找到的最佳解决方案。 - Tuomas Pelkonen

0

你可以利用商店布局的信息来限制搜索空间。例如,在德国,一个典型的商店有许多货架,可以被认为是形成车道的货架。在它们之间,有连接货架车道的直角车道。现在,你可以将交叉口定义为节点,将车道定义为图中的边缘。边缘上标记着该车道部分货架中的所有物品。现在,即使对于一个大商店,这个图也会非常小。你现在需要找到包括你所需的所有边缘标签(物品)的最短路径。这应该可以通过使用贪婪/回溯方法Tuomas Pelkonen suggested来实现。

这只是一个想法,我不知道它是否真的有效,但也许你可以从这里开始。


谢谢,我喜欢这个想法。但是我担心这样会导致路径与最短路径非常不同,因为这种方法没有考虑车道内的距离(例如当一个物品在车道的末端时,它可能非常靠近下一个车道开头的物品,但路径可能会让您返回交叉点)。 - Bart
好的,如果您将每条车道分成两个边缘,并在中间加上一个节点,那么您可以处理它。生成的路径可能会相对接近最优解。 - Björn Pollex

0

只有广度优先搜索才能确保您不会“错过”一条比当前“最佳”解决方案更好的商店路径,但您无需搜索路径中的每个节点。明显比当前“最佳”解决方案长的节点可以稍后扩展。

这意味着您像“广度优先”搜索一样处理问题,但根据当前行程距离改变节点的扩展。搜索树的某些分支将比其他分支更快地扩展,因为它们在相同的时间内能够访问更多的节点。

那么,如果节点扩展并非真正的广度优先,为什么我还要使用那个词?因为在找到解决方案之后,您仍然必须扩展当前的“考虑节点”集,直到每个搜索路径都超过解决方案。这避免了错过具有耗时初始步骤但完成速度比当前解决方案更快的路径的情况,因为最后一步非常快速。


0

起始节点的要求是虚构的。使用TSP,您将得到一次旅行,您可以选择想要的起始节点,而不会改变解决方案的成本。

当涉及到计数器时,情况会有些棘手:您需要在具有某些弧缺失(或者说,某些弧具有非常高的成本)的有向图上解决问题。

从完整的有向图开始,您应该修改适当弧的成本,以便:

  1. 禁止从物品到起始节点的移动
  2. 禁止从计数器到物品的移动
  3. 禁止从起始节点到计数器的移动
  4. 允许以零成本从计数器到起始节点移动(这仅需要关闭路径)
  5. 在绘制完成后,请告诉我是否遗漏了什么 :)

希望对您有所帮助


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接