在《运筹学》课堂上,我们学习过图与网络,当时用到R语言下的igraph包来计算和展示结果。Python下也有类似甚至更好的库: NetworkX。

安装命令如下

conda install networkx

引入约定为

importnetworkxasnx

1 图的绘制

无向图

无向图由点和边构成,其绘制思路为:①新建空图→②添加点→③添加边。

新建空的无向图

G=nx.Graph()

以后所有的信息都添加在无向图G上。

添加点:addnode和add_nodes_from

# 添加一个点

G.add_node(1)# 点的名字叫1

G.add_node('a')# 点的名字叫a

# 添加一组点

G.add_nodes_from([2,3,4])

虽然还没有讲到怎么展示这张图,但你可能想看看自己已经画了啥;所以我们剧透一下:输入nx.draw(G)看看吧。

添加边:add_edge和add_edges_from

# 添加一条边

G.add_edge(1,2)# 在1、2之间添加边

G.add_edge(1,'a')# 在1、a之间添加边

# 添加一组边

G.add_edges_from([(2,3),(3,4,),('a',3)])

# 添加边时自动生成点

G.add_edge(3,'b')# 此前没有添加过b点

# 添加圈

G.add_cycle(['b','c','d'])

# 注意这些命令都有color参数,将来会用到

移除点或边使用remove_*系列方法。

展示图

NetworkX可以结合matpltlib库来展示图,因此需要载入plt:

importmatplotlib.pyplotasplt

最常用的展示命令是 networkx.draw(),所有参数都是可选的。

nx.draw()

简单介绍一些可选参数,如

ax:画纸名

nodecolor/edgecolor/font_color:点、边、字颜色

nodeshape/nodesize:点的形状和大小

style:边的形状(solid/dashed/dotted/dashdot)

alpha:点和边的透明度

with_labels:点是否显示标签

arrows/arrowstyle/arrowsize:有向图的箭头设定

我们并列展示默认和自定义结果:

fig=plt.figure(figsize=(20,5))

ax1=plt.subplot(121)

nx.draw(G,ax=ax1)

ax2=plt.subplot(122)

nx.draw(G,ax=ax2,node_color='pink',with_labels=True,node_size=500,node_shape='D',style='-.')

plt.draw()

另有 networkx.draw_networkx()函数,支持自定义点的位置(类型)。

有向图

有向图和无向图的差别仅仅在边是有方向的:

新建空的有向图

G=nx.DiGraph()# 注意差别

添加点:略

添加有向边

G.add_edge(1,2)

G.add_edges_from([(2,3),(2,4),(3,4),(4,3)])

nx.draw(G,ax=ax2,node_color='pink',with_labels=True,arrowstyle='fancy',edge_color='pink')

2 从图到网络:权的添加

方法一

add_weighted_edges_from方法能够接受(起点,终点,权重)作为元素的序列。推荐这种方法。

G=nx.DiGraph()

elist=[('a','b',5.0),('b','c',3.0),('a','c',1.0),('c','d',7.3)]

G.add_weighted_edges_from(elist)

方法二

add_edge方法可以添加weight参数。

G.add_edge(1,2,weight=5.5)

方法三

类索引方法,在修改权重时非常有用。

G[1][2]['weight']=5.5

G.edges[1,2]['weight']=5.5

添加权重标签

按照上述三个方法添加的边权重,将被记录在边属性下,我们可以通过G.edges(data=True)方法来查看:

G.edges(data=True)

特别注意参数data一定要为True,不指定data参数时默认只提取边的起点和终点。结果如下:

OutEdgeDataView([('a','b',{'weight':5.0}),('a','c',{'weight':1.0}),('b','c',{'weight':3.0}),('c','d',{'weight':7.3})])

关系已经很明确了,我们用元组u,v,w来解包,并将其放在键为边,值为权的字典中:

# 方法一:for循环

label={}

for(u,v,d)inG.edges(data=True):

label[(u,v)]=str(d['weight'])

# 方法二:字典推导式

label={(u,v):str(d['weight'])foru,v,dinG.edges(data=True)}

绘制权重标签

我们分4步来画图:点→边→点标签→边标签(顺序不重要)。因为要分4个图层来画,所以需要明确点的位置,不能用nx.draw()这种随性的方法。

首先定义点的位置pos:

pos=nx.spring_layout(G)

这表明我们使用Fruchterman-Reingold的力引导算法来画图,目的是减少边的交叉(推荐)。可选的pos还有circular_layout、kamada_kawai_layout、random_layout、rescale_layout、shell_layout和spectral_layout,点少的时候看不出来,点多就不一样了。

nx.draw_networkx_nodes(G,pos)

nx.draw_networkx_labels(G,pos)

nx.draw_networkx_edges(G,pos)

nx.draw_networkx_edge_labels(G,pos,label)# 关注这里

plt.axis('off')# 不显示坐标

plt.draw()

默认的标签是放在边的中间,可以用label_pos调节,这对双箭头的有向边很重要。

3 最短路

《运筹学》课程中,我们学习了Dijkstra算法;NetworkX提供了相应的命令:

dijkstra_predecessor_and_distance:给出某起点到所有点的最短路径和最短路程,结果也包含两部分,可以用元组解包提取;

dijkstra_path:给出从某起点到某终点的最短路径;

dijkstra_path_length:给出从某起点到某终点的最短路程。

构造一个有向图

G=nx.DiGraph()

elist=[(1,2,3),(1,3,2),(1,4,5),

(2,6,7),

(3,4,1),

(4,6,5),

(5,3,5),(5,4,3),(5,6,1)]

G.add_weighted_edges_from(elist)

求点1到点6的最短路。

展示这个有向图

pos=nx.circular_layout(G)

label={(u,v):str(d['weight'])foru,v,dinG.edges(data=True)}

nx.draw_networkx_nodes(G,pos,node_color='w',edgecolors='k')

nx.draw_networkx_nodes(G,pos,node_color='pink',edgecolors='k',nodelist=[1,6])

nx.draw_networkx_labels(G,pos,font_color='k')

nx.draw_networkx_edges(G,pos)

nx.draw_networkx_edge_labels(G,pos,label,label_pos=0.3)

plt.axis('off')

plt.draw()

Dijkstra算法求最短路

指定起点,不指定终点

pred,dist=nx.dijkstra_predecessor_and_distance(G,1)

print('到每个点的最短路的上一个点:',pred)

print('到每个点的最短路的路程:',dist)

结果:

到每个点的最短路的上一个点:{1:[],2:[1],3:[1],4:[3],6:[4]}

到每个点的最短路的路程:{1:0,3:2,2:3,4:3,6:8}

指定起点和终点

path=nx.dijkstra_path(G,1,6)

length=nx.dijkstra_path_length(G,1,6)

print('从点1到点6的最短路径是',path)

print('从点1到点6的最短路程是',length)

将最短路径画出来:

附代码:

pos=nx.circular_layout(G)

label={(u,v):str(d['weight'])foru,v,dinG.edges(data=True)}

nx.draw_networkx_nodes(G,pos,node_color='w',edgecolors='k')

nx.draw_networkx_nodes(G,pos,node_color='pink',edgecolors='k',nodelist=[1,6])

nx.draw_networkx_labels(G,pos,font_color='k')

nx.draw_networkx_edges(G,pos)

el=[(path[i],path[i+1])foriinrange(len(path)-1)]

nx.draw_networkx_edges(G,pos,edge_color='r',edgelist=el)

nx.draw_networkx_edge_labels(G,pos,label,label_pos=0.3)

plt.axis('off')

plt.draw()

4 最大流

掌握了最短路再来看最大流,就是很简单的事情了。

通过capacity参数为边添加最大容量;

使用 maximum_flow函数求解。

构造包含最大容量的有向图

elist=[(1,2,6),(1,4,6),(2,3,2),(2,5,3),(3,5,2),(3,6,2),(4,3,3),

(4,6,1),(4,7,2),(5,7,5),(6,7,4)]

G=nx.DiGraph()

foru,v,cinelist:

G.add_edge(u,v,capacity=c)

绘制这个图

pos=nx.circular_layout(G)

label={(u,v):str(d['capacity'])foru,v,dinG.edges(data=True)}

# 或者label = {(u,v):str(c) for u,v,c in elist}

nx.draw_networkx_nodes(G,pos,node_color='w',edgecolors='k')

nx.draw_networkx_nodes(G,pos,node_color='pink',edgecolors='k',nodelist=[1,7])

nx.draw_networkx_labels(G,pos,font_color='k')

nx.draw_networkx_edges(G,pos)

nx.draw_networkx_edge_labels(G,pos,label,label_pos=0.5)

plt.axis('off')

plt.draw()

图中边的标签表示最大容量(而非单位运价)。我们想求得从点1到点7的最大流。

计算最大流

flow_value,flow_dict=nx.maximum_flow(G,1,7)

通过提取flow_value,我们可以知道从点1到点7的最大流为10;

通过提取flow_dict,我们可以知道最大流情形下,每条边的实际流量:

{1:{2:5,4:5},

2:{3:2,5:3},

3:{5:2,6:2},

4:{3:2,6:1,7:2},

5:{7:5},

6:{7:3},

7:{}}

我们也可以通过 flow_dict[][]来确定特定边上的实际容量,如 flow_dict[1][4]表示边(1,4)上的实际流量为5。

5 结语

NetworkX是复杂网络计算库,能做的事情远不止最短路和最大流。手册在这里,进步靠自己:

https://networkx.github.io/documentation/stable/_downloads/networkx_reference.pdf

python结构模式图_NetworkX:Python图与网络模型基础相关推荐

  1. Python结构与列表

    Python结构与列表 Python 程序的组织结构 顺序结构 对象的布尔值 选择结构 单分支结构 双分支结构 多分支结构 嵌套if 条件表达式 pass语句 知识点总结 列表 为什么需要列表 列表的 ...

  2. python 桑基图_流量结构分布图——桑基图(Sankey)

    原标题:流量结构分布图--桑基图(Sankey) 桑基图作为相对复杂的图表种类,平时很少用到,不仅仅是因为它的引用场景相对狭窄,另一方面则是制作难度相对较大,门槛较高. 不过针对第一个问题,如果你能很 ...

  3. python结构体_Python对象初探

    欢迎关注微信公众号--Python与统计分析,一起学习,一起交流. 相信所有学过Python的人都听过这样一句话:Python中,一切皆对象.一个整数是一个对象,产生这个整数的类int也是一个对象.函 ...

  4. python安装目录结构_1.5 python安装目录介绍《Python基础开发入门到精通》

    第一章 Python的概述与环境安装 本章所讲内容: 1.1 Python介绍 1.2 Python2与Python3的比较 1.3 Python3的安装 1.4 Python环境变量配置 1.5 P ...

  5. LSTM结构理解与python实现

    LSTM结构理解与python实现 上篇博客中提到,简单的RNN结构求解过程中易发生梯度消失或梯度爆炸问题,从而使得较长时间的序列依赖问题无法得到解决,其中一种越来越广泛使用的解决方法就是 Long ...

  6. 【游戏开发小技】TexturePacker生成的图集逆向切分成精灵小图(json | python | PIL | TextureUnPacker | 逆向 | 切图)

    文章目录 一.前言 二.TexturePacker 1.特别说明 2.TexturePacker下载 3.准备精灵散图(小图) 4.使用TexturePacker打图集 5.json结构分析 三.图集 ...

  7. python无向带权图

    无向无权图见另一篇文章<python无向无权图结构>,这篇讲无向带权图,并且给出一个地铁线路例子. # -*- coding: UTF-8 -*- #!/usr/bin/python#-- ...

  8. python怎么画高程三维网格图_matplotlib绘制等高线图

    参考自Matplotlib Python 画图教程 (莫烦Python)(12)_演讲•公开课_科技_bilibili_哔哩哔哩 https://www.bilibili.com/video/av16 ...

  9. Python中的ULM类图

    学会写类并不能说明你已经学会了面向对象的思想方法,因为还没能做到类与类之间的关联,也就是无法准确描绘现实世界.类图本身就是对现实世界的抽象,是一种编写程序的逻辑结构.以下是对类图知识点的梳理,以期能够 ...

最新文章

  1. [k8s] 第一章 十分钟带你理解Kubernetes核心概念
  2. 必读!TOP10生成对抗网络GAN论文(附链接)
  3. UAVStack的慢SQL数据库监控功能及其实现
  4. 【Python】疯狂的加速函数!
  5. html5中表格如何等分,纯css3饼图五等分
  6. react 判断图片是否加载完成_React中型项目的优化实践
  7. 【C语言】赋值运算中的类型转换
  8. 【资源】斯坦福李飞飞高徒Johnson博士论文: 组成式计算机视觉智能(附195页PDF)
  9. 什么是同步异步?阻塞非阻塞?
  10. 关于setInterval设置倒计时只执行一次,clearInterval停止
  11. 【Java-Web】初始化加载Serlvet工程后-HttpServlet报错
  12. Python str内部功能介绍
  13. windows7 配置iis技巧
  14. 免费申请微软云教育服务器,自助免费申请Office365教育版,免费5TOneDrive云盘详细教程...
  15. Kconfig配置文件
  16. matlab特定等值线,从Matlab轮廓函数中选择等值线
  17. PostgreSQL的json和jsonb比较
  18. 蓝奏云软件库源码分享下载(后端源码)
  19. 微信公众平台如何授权第三方平台,干货到!微信公众号怎样添加第三方平台及取消授权
  20. java中实现多态的机制是什么?

热门文章

  1. 计算机专业马来西亚,去马来西亚读计算机专业如何
  2. mysql数据类型内存_mysql 存储金额类型,用什么数据类型比较可靠,一般企业数据用什么数据类型?...
  3. 【入门篇】接口自动化测试
  4. 掩膜裁剪tif步骤_使用Arcgis掩膜剪裁工具剪裁全球气候数据为我国范围,并转换为ASC格式...
  5. 酒店前台html,酒店前台常用英语单词
  6. android 按钮列表,android – 如何使按钮看起来像列表
  7. python转json中文乱码_python 序列化成json 乱码问题的解决
  8. appinventor贪吃蛇制作步骤_旋转RGB制作指导
  9. 【3】测试用例设计-因果图
  10. java td背景色_jQuery:无法更改表格单元格的背景颜色