Algorithm 隐式图中寻找最短路径的连通检查数最小化
我很惊讶我在任何地方都找不到这方面的任何东西,这似乎是一个应该非常清楚的问题: 考虑二维的欧几里德最短路径问题。给定一组障碍多边形P和两个点a和b,我们想找到从a到b的最短路径,该路径不与P中任何P的(内部)相交 为了解决这个问题,我们可以为这个问题创建可见性图,该图的节点是p元素的顶点,如果两个节点之间的直线不与p元素相交,则两个节点是连接的。任何这样的边的边权重就是这两个点之间的欧氏距离。为了解决这个问题,我们可以在图中确定从a到b的最短路径,比如a* 然而,这不是一个好办法。提前创建可见性图需要检查任意两个多边形中的任意两个顶点是否连接,这种检查比确定两个节点之间的距离更复杂。因此,使用a*的修改版本“在检查两个节点是否实际连接之前尽其所能”实际上加快了问题的速度 尽管如此,A*和所有其他最短路径问题总是从一个显式给定的图开始,该图的相邻顶点可以被廉价地遍历。所以我的问题是,在“隐式图”中找到两个节点a和b之间的最短路径是否有一个好的(最优的)算法,它可以最小化两个节点是否连接的检查 编辑: 为了澄清我的意思,这是我正在寻找的一个例子: 让Algorithm 隐式图中寻找最短路径的连通检查数最小化,algorithm,graph-theory,shortest-path,Algorithm,Graph Theory,Shortest Path,我很惊讶我在任何地方都找不到这方面的任何东西,这似乎是一个应该非常清楚的问题: 考虑二维的欧几里德最短路径问题。给定一组障碍多边形P和两个点a和b,我们想找到从a到b的最短路径,该路径不与P中任何P的(内部)相交 为了解决这个问题,我们可以为这个问题创建可见性图,该图的节点是p元素的顶点,如果两个节点之间的直线不与p元素相交,则两个节点是连接的。任何这样的边的边权重就是这两个点之间的欧氏距离。为了解决这个问题,我们可以在图中确定从a到b的最短路径,比如a* 然而,这不是一个好办法。提前创建可见性
V
成为V
的一组a
,b
元素。假设w:vxv->D
是一个加权函数(对于某些线性有序集D
),并且c:vxv->{true,false}
在认为V
的两个元素连接时返回true。然后,下面的算法在V
中找到从a
到b
的最短路径,即,为所有i
返回一个列表[x|i
,x|n-1}=b
,以及c(x|i,x|i+1})=true
Let (V, E) be the complete graph with vertex set V.
do
Compute shortest path from a to b in (V, E) and put it in P = [p_0, ..., p_{n-1}]
if P = empty (there is no shortest path), return NoShortestPath
Let all_good = true
for i = 0 ... n - 2 do
if c(p_i, p_{i+1}) == false, remove edge (p_i, p_{i+1}) from E, set all_good = false and exit for loop
while all_good = false
为了计算循环中的最短路径,如果存在适当的启发式,可以使用*来计算。显然,该算法生成了从a
到b
的最短路径
此外,我认为该算法在尽可能少地调用c
时是最优的。对于找到的最短路径,它必须排除函数w
将允许的所有较短路径
但肯定有更好的办法吗
编辑2:
因此,我找到了一个相对有效的解决方案:在放松节点时,使用*,而不是遍历邻居并将其添加到/更新到优先级队列中,我将所有顶点放入优先级队列中,标记为假想的,以及假想的f和g值和假想的父节点。然后,当从优先级队列中选择下一个元素时,我检查节点到其父节点的连接是否实际给定。如果是,则节点按正常进行,如果不是,则丢弃
这大大减少了连接检查的数量,并大大提高了性能。但我相信还有一种更优雅的方法,特别是“假设的新路径”不只是延伸一个长度(父路径总是实际的,而不是假设的)。a*或Dijkstra的算法不需要显式的图形,它们实际上只需要:
s
)next:V->2^V
使得next(V)={u |从V到u有一条边}
isGoal:V->{0,1}
使得isGoal(V)=1
iffV
是目标节点w:E->R
,使得w(u,v)=从u移动到v的成本h:V->R
,这样h(V)
就是成本近似值
使用这些函数,您可以动态生成查找最短路径所需的图形部分。
事实上,在使用这种方法的人工智能问题中,A*算法通常用于无限图(或不适合任何现有存储的巨大图)
其思想是,您只查看给定节点A*中的边(对于某些给定的
u
,所有(u,v)
在E
中)。你不需要整个边集E
,你只需要使用next(u)
函数就可以了。这大概就是我要做的,意思是“在检查两个节点是否实际连接之前尽一切可能”。事实上,我会更进一步,当放松一个节点u时,在检查u和v是否实际上相邻之前,先检查每个v是否已经在闭合集中,或者是否在开放集中,并且新的g不会改善。但是,*仍然会不必要地频繁调用连接检查(或您的下一个),例如在放松开始节点时。我要找的是一个不这样做的算法。