Dijkstra:找到目的地时如何设置终止条件?

如何解决Dijkstra:找到目的地时如何设置终止条件?

众所周知,Dijkstra找到了从单个源节点到给定图中任何其他节点的最短路径。我尝试修改原始Dijkstra,以找到一对源节点和目标节点之间的最短路径。仅当Dijkstra找到目标节点时,才设置终止程序的终止条件似乎很容易。 但是,我在Python代码中设置的“终止条件”似乎导致了次优的最短路径,而不是最优的最短路径。 Dijkstra代码如下,

def dijkstra(adjList,source,sink):
#define variables
n = len(adjList)    #intentionally 1 more than the number of vertices,keep the 0th entry free for convenience
visited = [False]*n
parent = [-1] *n
#distance = [float('inf')]*n
distance = [1e7]*n
heapNodes = [None]*n
heap = FibonacciHeap()
for i in range(1,n):
    heapNodes[i] = heap.insert(1e7,i)

distance[source] = 0
heap.decrease_key(heapNodes[source],0)

while heap.total_nodes:
    current = heap.extract_min().value
    #print("Current node is: ",current)
    visited[current] = True
    #early exit
    if sink and current == sink:
        break
    for (neighbor,cost) in adjList[current]:
        if not visited[neighbor]:
            if distance[current] + cost < distance[neighbor]:
                distance[neighbor] = distance[current] + cost
                heap.decrease_key(heapNodes[neighbor],distance[neighbor])
                    if  neighbor == sink and current != source:     # this is a wrong logic,since the neighbor may not be selected as the next hop.
                            print("find the sink 1")
                            printSolution(source,sink,distance,parent)
                            break
    if neighbor == sink:
        print("find the sink2")
        break
return distance

adjList = [
[],[[2,7],[3,9],[6,14]],[[1,[4,15],10]],[2,10],11],2]],[5,6]],[[4,6],9]],[[5,[1,14]]
]
dijkstra(adjList,1,4)

邻接表的图形如下所示:

enter image description here

我想找到从节点1到节点4的路径,共有三个路径:

 path 1: 1 --> 2 --> 4              cost: 22
 path 2: 1 --> 2 --> 3 --> 4        cost: 28  
 path 3: 1 --> 3 --> 4              cost: 20
 path 4: 1 --> 3 --> 6 --> 5 --> 4  cost: 26
 path 5: 1 --> 6 --> 3 --> 4        cost: 28
 path 6: 1 --> 6 --> 5 --> 4        cost: 29

Dijkstra最初会选择路径3:1-> 3-> 4,因为它的成本最低。

但是,我修改了终止条件,即当发现当前节点的邻接节点是目的地时,程序将结束。然后得到节点1和节点4之间的路径结果。结果是路径1:1-> 2-> 4。 我分析这是因为我设置了错误的终止条件。当发现当前节点的邻接节点是目标节点时,程序将终止,这是错误的,但是我不知道在找到目标节点时设置合适的终止条件。能否请您提供一些想法?

解决方法

当您刚刚从堆中获得当前节点时,终止条件的唯一正确位置是在外循环的开始。

在迭代邻居时进行该测试是错误的,因为您不能保证最后一条边是最短路径的一部分。试想一下,到邻居的最后一步会付出极高的代价:永远不可能在最短的路径上,所以不要在那儿执行终止条件:可能还有另一条通往水槽的路径更便宜。

我也没有看到您在代码中实际填充parent的位置。

我也不会一开始就将所有节点放在堆上,因为当元素较少时,堆会更快。您可以从只有1个节点的堆开始。

另一种小的优化方法是也使用parent将节点标记为已访问,因此实际上并不需要parentvisited

最后,我不知道FibonacciHeap库,所以我刚刚学习了heapq,这是一个非常轻便的堆实现:

from heapq import heappop,heappush

def dijkstra(adjList,source,sink):
    n = len(adjList)
    parent = [None]*n
    heap = [(0,0)] # No need to push all nodes on the heap at the start
    # only add the source to the heap

    while heap:
        distance,current,came_from = heappop(heap)
        if parent[current] is not None:  # skip if already visited
            continue
        parent[current] = came_from  # this also marks the node as visited
        if sink and current == sink:  # only correct place to have terminating condition
            # build path
            path = [current]
            while current != source:
                current = parent[current]
                path.append(current)
            path.reverse()
            return distance,path
        for (neighbor,cost) in adjList[current]:
            if parent[neighbor] is None:  # not yet visited
                heappush(heap,(distance + cost,neighbor,current))

adjList = [
[],[[2,7],[3,9],[6,14]],[[1,[4,15],10]],[2,10],11],2]],[5,6]],[[4,6],9]],[[5,[1,14]]
]
dist,path = dijkstra(adjList,1,4)
print("found shortest path {},which has a distance of {}".format(path,dist))
,

实际上,您有正确的条件可以退出代码,即current == sink。您不能强加任何其他退出条件。该算法必须一直运行到访问目标节点为止,因为只有在这一点上,您才能确定到目标​​的最短路径的值。由于这种情况,查找单个源单个目标最短路径的复杂性与单个源所有节点最短路径的复杂性相同。因此,您的提前退出条件是正确的,应该删除所有邻居条件检查。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-