python-3.x - python中多个AGV的最短路径算法
问题描述
我正在尝试为我的最短路径问题找到解决方案。我在一个小型 9 节点系统中有两辆车(AGV)。AGV 需要从起点到达终点,而不会相互妨碍。
是否有一种易于在 python 中实现的算法来找到两辆车的最短路径(系统的最短路径)?路径需要不相交以避免串通。
当只使用一辆车时,我使用了 Dijikstra 算法。现在有了两个,我显然可以让其中一个选择最短路径并阻止另一个路径。但在这么小的系统中,另一台 AGV 可能最终会等到第一台完成。我相信一定有更好的解决方案。在我的研究中,我找不到解决它的算法,而且实现起来并不复杂。
谢谢您的帮助!
更新#1:我尝试将 Tassles 建议放入代码中。但是由于我对编程还很陌生,所以我很挣扎,而且我确信我还有很长的路要走。所以我有很多问题,希望你能一路帮助我。
- 关于边缘:我在哪里添加边缘?我猜是 E'(e_new) 但我不知道是什么形式。
- 我如何包括“每个邻居”?我不知道如何让邻居脱离 map_sparse。
- 我努力正确地构建代码并将计算的边缘用于 dijikstra 算法。代码写在下面的方式,我什至不使用最短距离的边缘。
- 而且我只计算其中一个 AGV 的最短路径,但它应该同时适用于两者,对吗?
非常感谢你,我真的很感谢你的帮助!
import numpy as np
from itertools import combinations
import itertools
from scipy.sparse.csgraph import csgraph_from_dense
from scipy.sparse.csgraph import dijkstra
class NavigationSystem:
def __init__(self):
self.map_sparse = csgraph_from_dense(
np.genfromtxt('karte.csv', delimiter=',')[2:, 2:])
self.coordinates = np.genfromtxt(
'koordinaten.csv', delimiter=',')[1:, 1:]
self._shortest_distances, self._predecessors = dijkstra(
self.map_sparse, return_predecessors=True)
def get_shortest_distance(start, end):
v_old = [1, 2, 3, 4, 5, 6, 7, 8, 9]
e_old = [map_sparse]
g_old = (v_old, e_old)
v_new = list(itertools.permutations(v_old, 2))
e_new = []
g_new = (v_new, e_new)
for x in v_new:
for every neighbour a of x[0]:
if a != x[1]:
e_new.append((a, x[0]))
for every neighbour b of x[1]:
if b != x[0]:
e_new.append((b, x[1]))
for every neighbour a of x[0]:
for every neighbour b of x[1]:
if a != b:
e_new.append((x[0], x[1]), (a, b))
return self._shortest_distances[start][end]
解决方案
我想“不碍事”意味着两辆车不能同时在同一个节点。
在这种情况下,您可以再次将其建模为最短路径问题,但这次是在一个新图中,其中每个顶点代表原始图中的一对顶点,即两辆车的位置。因此,让我们G = (V,E)
表示您的原始图,并以G' = (V',E')
这种方式构建一个新图:
V'
包含所有(u,v)
顶点对V
(如果需要,您可以省略表格对(u,u)
,因为无论如何这些都无法访问)。- 现在对于边缘,看看从一个位置会发生什么
(u,v)
。要么第一辆车移动到在和a != v
之间有边的某个位置,要么第二辆车移动到在和之间有边的某个位置,或者它们都可以分别移动到和if 。u
a
E
b != u
v
b
E
a
b
a != b
在伪代码中你得到:(你对每一对都这样做(u,v)
)
For every neighbour a of u:
If a != v:
Add an edge between (u,v) and (a,v)
For every neighbour b of v:
If b != u:
Add an edge between (u,v) and (u,b)
For every neighbour a of u:
For every neighbour b of v:
If a != b:
Add an edge between (u,v) and (a,b)
然后,您可以寻找 和 之间的最短路径(s1,s2)
,(t1,t2)
其中s1
和s2
是两个起始顶点,并且e1, e2
是目标顶点。如果你想让两辆车在同一个顶点开始或结束,你必须在 make 中添加必要的边(t,t)
。
您得到的顶点数量是其中顶点G'
数量的平方,G
因此您可以期望大型实例上的运行时间也近似平方(大多数算法用于查找最短路径)。但是,9 个顶点很小,所以这里不用担心。
作为旁注,当在方形网格(或任何只有相同长度的边的图形上)工作时,Dijkstra 有点矫枉过正。您可以通过从您的起始位置执行简单的 BFS(广度优先搜索)来加快速度,记录您沿途的位置。
推荐阅读
- redis - Laravel 8 Sail Redis 不假设默认缓存驱动程序
- flutter - 挂载小部件后如何显示值?
- docker - 尝试从 Docker 映像运行 SonarScanner 时似乎没有拾取 sonar-project.properties
- android - 如何使用 WindowInsetsCompat API 检查 API 19 的 ime 可见性?
- python - Python:是否可以推断出函数可能引发的异常?
- python - Main() 缺少 2 个必需的位置参数
- javascript - 使用另一个使用效果导致另一个
- wordpress - wpdb 使用枚举更新
- python - Python ImportError:无法导入名称“Uniswap”
- python - 我如何将列表与python中的另一个列表匹配