networkX-04-查找k短路

news2024/11/15 8:36:27

文章目录

  • 1.构建图
  • 2.使用networkX查找最短路径
  • 3.自己构建方法

教程仓库地址:github networkx_tutorial

import networkx as nx
import matplotlib.pyplot as plt

1.构建图

# 创建有向图
G = nx.DiGraph()

# 添加带权重的边
edges = [
    (0, 1, 1), (0, 2, 2), (1, 2, 1), (1, 3, 2), (2, 3, 1),
    (3, 4, 3), (2, 4, 4), (4, 5, 2), (3, 5, 5), 
]
G.add_weighted_edges_from(edges)


# 绘制图
pos = nx.spring_layout(G)  # 使用Spring布局
nx.draw(G, pos, with_labels=True, node_size=2000, node_color="lightblue", font_size=10)
nx.draw_networkx_edge_labels(G, pos, edge_labels={(u, v): G[u][v]['weight'] for u, v in G.edges()}, font_color='red')

# 显示图
plt.show()


png

2.使用networkX查找最短路径

from itertools import islice
def k_shortest_paths(G, source, target, k, weight=None):
    return list(islice(nx.shortest_simple_paths(G, source, target, weight=weight), k))
# 获取 k-最短路径
paths = k_shortest_paths(G, 0, 5, 3, 'weight')

# 输出路径和权重
for i, path in enumerate(paths):
    weight = sum(G[path[n]][path[n + 1]]['weight'] for n in range(len(path) - 1))
    print(f"Path {i + 1}: {path}, weight: {weight}")

Path 1: [0, 1, 3, 5], weight: 8
Path 2: [0, 2, 3, 5], weight: 8
Path 3: [0, 1, 2, 3, 5], weight: 8

3.自己构建方法

from itertools import count
from heapq import heappush, heappop
import networkx as nx
import pandas as pd 
import matplotlib.pyplot as plt

class K_shortest_path(object):
    def __init__(self,G,  k=3, weight='weight') -> None:
        self.G = G 
        self.k = k
        self.weight = weight
        self.G_original = G
        
    def get_path_length(self,G,path:list, weight='weight'):
        """计算每条路径的总阻抗,基于weight
        Args:
            G (nx.graph): 构建的图
            path (list): 路径
            weight (str, optional): 边的权重计算基于什么,可以是时间也可以是距离. Defaults to 'weight'.
        """
        length = 0
        if len(path) > 1:
            for i in range(len(path) - 1):
                u = path[i]
                v = path[i + 1]
                length += G.edges[u,v].get(weight, 1)
        return length     
    
    def find_sp(self,s,t,G):
        """找到第一条P(1)

        Args:
            s (node): 路径起点
            t (node): 路径终点
        
        lenght:P(1)对应的长度
        path:P(1)对应的路径 list
        """
        path_1 = nx.shortest_path(G=G,source=s,target=t,weight=self.weight)
        length_1 = nx.shortest_path_length(G=G,source=s,target=t,weight=self.weight)
        # length_1, path_1 = nx.single_source_dijkstra(G,source=s,weight=weight)

        return length_1, path_1
    
    
    def find_Pi_sp(self,source,target):
        if source == target:
            return ([0], [[source]]) 
        G =  self.G
        k = self.k
        length, path = self.find_sp(G=G,s=source,t=target)
        lengths = []
        paths = []
        lengths.append(length)
        paths.append(path)
        c = count()        
        B = [] 
        G_original = self.G.copy()   
         
        for i in range(1, k):
            for j in range(len(paths[-1]) - 1):            
                spur_node = paths[-1][j]
                root_path = paths[-1][:j + 1]
                
                edges_removed = []
                for c_path in paths:
                    if len(c_path) > j and root_path == c_path[:j + 1]:
                        u = c_path[j] #节点
                        v = c_path[j + 1] #节点
                        if G.has_edge(u, v):  #查看u,v节点之间是否有路径
                            edge_attr = G.edges[u,v]['weight']
                            G.remove_edge(u, v) #移除边
                            edges_removed.append((u, v, edge_attr))
                            
                for n in range(len(root_path) - 1):
                    node = root_path[n]
                    # out-edges
                    dict_d = []
                    for (u,v,edge_attr) in G.edges(nbunch =node,data = True ):
                    # for u, v, edge_attr in G.edges_iter(node, data=True):
                        edge_attr = edge_attr['weight']
                        dict_d.append((u,v))
                        edges_removed.append((u, v, edge_attr))
                    G.remove_edges_from(dict_d) 
                        
                        
                    if G.is_directed():
                        # in-edges
                        in_edges_d_list = []
                        for (u,v,edge_attr) in G.edges(nbunch =node,data = True ):
                        # for u, v, edge_attr in G.in_edges_iter(node, data=True):
                            # edge_attr = edge_attr['weight']
                            edge_attr = G.edges[u,v]['weight']
                            # G.remove_edge(u, v)
                            in_edges_d_list.append((u,v))
                            edges_removed.append((u, v, edge_attr))
                        G.remove_edges_from(in_edges_d_list) 
                        
                spur_path_length, spur_path = nx.single_source_dijkstra(G, spur_node, weight=self.weight)            
                
                if target in spur_path and spur_path[target]:
                    total_path = root_path[:-1] + spur_path[target]
                    
                    total_path_length = self.get_path_length(G_original, root_path, self.weight) + spur_path_length[target]                
                    
                    heappush(B, (total_path_length, next(c), total_path))
                    
                for e in edges_removed:
                    u, v, edge_attr = e
                    G.add_edge(u, v, weight = edge_attr)
                            
            if B:
                (l, _, p) = heappop(B)        
                lengths.append(l)
                paths.append(p)
            else:
                break
        return (lengths,paths)
    
          
  
if __name__ =='__main__':
    # 创建有向图
    G = nx.DiGraph()

    # 添加带权重的边
    edges = [
        (0, 1, 1), (0, 2, 2), (1, 2, 1), (1, 3, 2), (2, 3, 1),
        (3, 4, 3), (2, 4, 4), (4, 5, 2), (3, 5, 5), 
    ]
    G.add_weighted_edges_from(edges)
    for u, v, weight in edges:
        G.add_edge(u, v, weight=weight)
    
    KSP = K_shortest_path(G=G,k=3,weight='weight')
    KSP.G
    
    # 绘制图
    pos = nx.spring_layout(KSP.G)  # 使用Spring布局
    nx.draw(KSP.G, pos, with_labels=True, node_size=2000, node_color="lightblue", font_size=10)
    nx.draw_networkx_edge_labels(KSP.G, pos, edge_labels={(u, v): KSP.G[u][v]['weight'] for u, v in KSP.G.edges()}, font_color='red')
    # 显示图
    plt.show()
    
    # 最短路径查询
    source = 0
    target = 5
    (lengths,paths) = KSP.find_Pi_sp(source=source,target=target)
    k_df = pd.DataFrame((lengths,paths)).T
    k_df.columns = ['weight','path']
    print(k_df)


png

  weight             path
0      8     [0, 1, 3, 5]
1      8     [0, 2, 3, 5]
2      8  [0, 1, 2, 3, 5]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1081028.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Flink中的时间和窗口

1.Flink的时间和窗口 在传统的批处理系统中,我们可以等到一批数据全部都到齐了之后,对其做相关的计算;但是在实时处理系统中,数据是源源不断的,正常情况下,我们就得来一条处理一条。那么,我们应…

大厂设计师力推的14款平面图设计工具!

从事设计行业的工人或多或少会接触到平面图。例如,在建造新房、办公室、酒店等任何类型的建筑时,都需要使用平面图来保证项目的准确性。因此,掌握绘制平面图软件的技巧也非常重要。在保证效率的同时,结果的准确性也非常高。在本文…

SunTorque智能扭矩系统助力螺栓拧紧装配如何实现智能化

新能源汽车的出现,在逐步实现技术创新升级的大环境下,汽车零部件总体数量趋于减少。但由于动力系统及结构的差异,电动汽车新增100-200个与动力系统、电气系统等相关零部件,其装配工况也随之改变。例如过流元器件、密封部件、功率模…

数据挖掘与统计分析——T检验,正态性检验和一致性检验——代码复现

T检验是一种统计测试,用于确定两个样本组的均值是否有统计学上的显著差异。以下是对T检验的详细介绍: 定义: T检验是一种参数检验,它的前提是数据近似于正态分布。它通过计算T统计量,并将其与特定分布(T分…

SpringBoot集成Quartz实现定时任务

文章目录 Quartz简介pom依赖内存方式存储Quartz简介pom依赖内存方式存储数据库方式存储分布式任务支持 Quartz简介 Quartz的快速入门见: Quartz官方文档_w3cschool Quartz 存储方式有两种:MEMORY 和 JDBC。默认是内存形式维护任务信息,服务…

企业需要ERP系统的八大理由,最后一个尤其重要

许多企业仍在质疑自己是否真的需要**ERP系统**。日常事务已经非常繁重,如果再加上寻找和实施一个新系统的挑战,那就更麻烦了。 公司业务在不断发展,出现了一些增长,订单也在不断增加,扭亏为盈,总体来说还算…

PostGIS310升级334

环境: centos7 postgis3.1.0alpha1 postgis3.3.4 如果您运行的是 PostGIS 3 或更高版本,则应升级到已安装的具有PostGIS_Extensions_Upgrade功能的最新版本。 SELECT postgis_extensions_upgrade(); 之前测试过从320升级334,直接执行路径…

巧用指标平台DataIndex,五步法轻松实现指标管理

开发部门在做指标加工的全流程中,是否经常出现如下问题: 业务部门看指标数据的时候,看到两个名称相似的指标,不清楚两个指标的差异性,来咨询开发部门指标计算口径,开发部门配合业务部门翻找代码&#xff…

RT-Thread HWTIMER设备(学习)

定时器简介 硬件定时器一般有2种工作模式,定时器模式和计数器模式。不管是工作在哪一种模式,实质都是通过内部计数器模块对脉冲信号进行计数,下面是定时器的一些重要概念。 计数器模式:对外部输入引脚的外部脉冲信号计数。定时器…

c语言:通讯录管理系统(文件版本)

前言:在大多数高校内,都是通过设计一个通讯录管理系统来作为c语言课程设计,通过一个具体的系统设计将我们学习过的结构体和函数等知识糅合起来,可以很好的锻炼学生的编程思维,本文旨在为通讯录管理系统的设计提供思路和…

智能电表线路单回路双回路的区别

随着科技的发展和能源管理的需求,智能电表已经成为电力系统中不可或缺的一部分。智能电表可以通过数据通信网络将用电信息实时传输到电力公司,为电力公司提供更精确、实时的用电数据,同时也可以为用户提供更加智能化的用电服务。 在智能电表…

局域网上IP多播与IP单播关于MAC地址的区别

IP单播进行到局域网上的时候: 网际层使用IP地址进行寻址,各路由器收到IP数据报后,根据其首部中的目的IP地址的网络号部分,基于路由表进行查表转发。 查表转发的结果可指明IP数据报的下一跳路由器的IP地址,但无法指明…

pid-limit参数实验

fork炸弹命令 :(){ :|:& };: 可以看到,如果docker没有限制,会遭到fork炸弹恶意 参考 https://www.cyberciti.biz/faq/understanding-bash-fork-bomb/

146616-66-2,胺反应性染料BDP FL NHS Ester,聚乙二醇单烯丙基醚

产品概览:Amine reactive bright,一种光稳定性佳的绿色荧光染料,以发挥独特的分子发光性能。此乃改进型的FAM(荧光素)荧光染料接班人——BDP FL NHS ester,在488nm通道中绽放色彩。这种胺反应性染料&#x…

信息系统项目管理师第四版学习笔记——项目绩效域

干系人绩效域 干系人绩效域涉及与干系人相关的活动和职能。在项目整个生命周期过程中,有效执行本绩效域可以实现的预期目标主要包含:①与干系人建立高效的工作关系;②干系人认同项目目标;③支持项目的干系人提高了满意度&#xf…

在原有的vue(react)项目中引入electron打包成桌面应用(全网最新!)

基于原有的项目中使用electron打包成桌面应用 首先了解electron是什么? 软件简介 Electron 是一个使用 JavaScript、HTML 和 CSS 构建跨平台的桌面应用程序。它基于 Node.js 和 Chromium,被 Atom 编辑器和许多其他应用程序使用。 Electron 兼容 Mac、Windows 和 Linux,可以…

SpringMVC源码分析(二)启动过程之RequestMappingHandlerMapping分析

a、http请求中的url是如何与对应Handler的即Controller对应method映射的? 在上篇中提到在SpringMVC中,初始化9大内置组件的时候其中有一个组件就是HandlerMapping,在初始化HandlerMapping的时候会加载代码中所有标注了Controller和RequestMap…

视频目标分割数据集分享

MOSE: A New Dataset for Video Object Segmentation in Complex Scenes MOSE 是一个新的视频目标分割数据集,旨在解决复杂环境下的目标跟踪和分割。MOSE 包含 2,149 个视频片段和来自 36 个类别的 5,200 个物体,以及 431,725 个高质量物体分割掩码。MOS…

ubuntu安装依赖包时显示需要先安装其所需要的各种安装包)apt-get源有问题

最近在崭新的ubuntu上安装g以及一些其他的依赖与工具时遇到以下报错情况: 依赖环环相扣,手动无法解决。 总结: 出现需要很多依赖项的情况是因为软件源中没有可用的依赖项或者依赖项版本不正确。 其实在Ubuntu系统中,使用sudo…

Java程序设计实验4 | 面向对象(下)

*本文是博主对Java各种实验的再整理与详解,除了代码部分和解析部分,一些题目还增加了拓展部分(⭐)。拓展部分不是实验报告中原有的内容,而是博主本人自己的补充,以方便大家额外学习、参考。 (没…