Python小白的数学建模课-图论的基本概念0 L& \; a& G! T) U: W7 o- U* Q
! O- T8 @/ o# p3 U. \3 u3 T) x- [2 S- 图论中所说的图,不是图形图像或地图,而是指由顶点和边所构成的图形结构。
- 图论不仅与拓扑学、计算机数据结构和算法密切相关,而且正在成为机器学习的关键技术。
- 本系列结合数学建模的应用需求,来介绍 NetworkX 图论与复杂网络工具包的基本功能和典型算法。- q. X7 Y- q5 ^; Q' ~
. o& c- l& p1 p) ?4 N& ^
1. 图论1.1 图论是什么) b, B" \ p1 r" e
图论〔Graph Theory〕以图为研究对象,是离散数学的重要内容。图论不仅与拓扑学、计算机数据结构和算法密切相关,而且正在成为机器学习的关键技术。
4 N3 z' {2 v' m7 T0 E) C2 @& J5 @, v' G
图论中所说的图,不是指图形图像(image)或地图(map),而是指由顶点(vertex)和连接顶点的边(edge)所构成的关系结构。# k( c4 T3 ~: z' O2 c, `2 x. Y
1 r- W. j! P; S
图提供了一种处理关系和交互等抽象概念的更好的方法,它还提供了直观的视觉方式来思考这些概念。
6 V3 m+ P3 g9 L4 j9 `- k4 k' H( D2 C4 Z! B
1.2 NetworkX 工具包( B# Z- ] s9 z/ G# v J9 K; P
NetworkX 是基于 Python 语言的图论与复杂网络工具包,用于创建、操作和研究复杂网络的结构、动力学和功能。
o) I& }+ n6 Z1 p4 C1 z# w# T( D4 t8 H! y2 f m( B' G
NetworkX 可以以标准和非标准的数据格式描述图与网络,生成图与网络,分析网络结构,构建网络模型,设计网络算法,绘制网络图形。6 D3 y" h: h& `" S9 [. t$ B
- ~- f5 {* q; Q' X! R H# [
NetworkX 提供了图形的类、对象、图形生成器、网络生成器、绘图工具,内置了常用的图论和网络分析算法,可以进行图和网络的建模、分析和仿真。* A8 J/ p0 U: r9 M8 U: E; f
+ Y. A- L( P F7 ]% Z t8 A0 {4 X& U9 ]
NetworkX 的功能非常强大和庞杂,所涉及内容远远、远远地超出了数学建模的范围,甚至于很难进行系统的概括。本系列结合数学建模的应用需求,来介绍 NetworkX 图论与复杂网络工具包的基本功能和典型算法。1 s! f+ @0 B" c2 K7 |5 z
; d' [* I" |& p' l- n4 {+ C5 T; Q![]()
: S& O2 V* r' h- _3 e n! ^' A" h$ ~3 p2、图、顶点和边的创建与基本操作5 W. F8 e5 b7 g @& G* u( q, ]$ m
图由顶点和连接顶点的边构成,但与顶点的位置、边的曲直长短无关。 Networkx 支持创建简单无向图、有向图和多重图;内置许多标准的图论算法,节点可为任意数据;支持任意的边值维度,功能丰富,简单易用。 2.1 图的基本概念( R f9 D9 @" \+ d4 u' O
图(Graph):图是由若干顶点和连接顶点的边所构成关系结构。6 }0 W" o% A! D' ]& g6 m' E" J
顶点(Node):图中的点称为顶点,也称节点。
) J7 O( v: ]) t+ J" |边(Edge):顶点之间的连线,称为边。
" \: e( @2 O" Y4 N; v$ C平行边(Parallel edge):起点相同、终点也相同的两条边称为平行边。
! d Q l6 i7 Q1 Z+ h0 @循环(Cycle):起点和终点重合的边称为循环。
_' ^1 n: S- C% O7 E+ _( L有向图(Digraph):图中的每条边都带有方向,称为有向图。7 ^5 P% U" v: D1 o9 A2 p( s
无向图(Undirected graph):图中的每条边都没有方向,称为无向图。. h d, v$ n, H# |: R. W# X
赋权图(Weighted graph):图中的每条边都有一个或多个对应的参数,称为赋权图。该参数称为这条边的权,权可以用来表示两点间的距离、时间、费用。
5 _0 L3 ]' n4 \+ X7 E! c度(Degree):与顶点相连的边的数量,称为该顶点的度。
* p2 S6 c9 s0 Z5 l$ H6 l8 j
5 E/ c& Y+ @# k' T2.2 图、顶点和边的操作
$ `1 x) ?7 l! K& |& h1 t' sNetworkx很容易创建图、向图中添加顶点和边、从图中删除顶点和边,也可以查看、删除顶点和边的属性。
+ t! k! H# Q7 R0 C
4 u* k5 A7 \( m) w, w$ }2.2.1 图的创建Graph() 类、DiGraph() 类、MultiGraph() 类和 MultiDiGraph() 类分别用来创建:无向图、有向图、多图和有向多图。定义和例程如下:
7 J0 y0 p9 f& w/ W$ O. n& ~! r/ S) j" J; V0 T
class Graph(incoming_graph_data=None, **attr)
; y, S$ O2 Z: m4 n. P- h) y3 bimport networkx as nx # 导入 NetworkX 工具包- H0 j5 o' Z o) H; A/ R( a+ W
) Y) L& ~2 S' l' Q, \' j5 I
# 创建 图
) \4 @9 V; B" u2 e8 K2 B6 n4 D+ EG1 = nx.Graph() # 创建:空的 无向图3 R [ s) T% {
G2 = nx.DiGraph() #创建:空的 有向图 h; P+ M7 r' u6 s# D
G3 = nx.MultiGraph() #创建:空的 多图0 c4 ?+ n4 N5 r9 b9 t
G4 = nx.MultiDiGraph() #创建:空的 有向多图
- R5 e- @. _) L. \+ b, n
! B' }9 T. Q q G6 {% j% U0 Q9 A' T( ?/ {1 e E7 h {
2.2.2 顶点的添加、删除和查看
- @: f+ z: g7 F2 k" w/ s+ g图的每个顶点都有唯一的标签属性(label),可以用整数或字符类型表示,顶点还可以自定义任意属性。 顶点的常用操作:添加顶点,删除顶点,定义顶点属性,查看顶点和顶点属性。定义和例程如下: 9 Q- @: W6 Y6 f' q2 I: D
Graph.add_node(node_for_adding, **attr). c3 u) G8 E! [# a
Graph.add_nodes_from(nodes_for_adding, **attr)0 e* u9 H+ E7 N
Graph.remove_node(n)& K; O$ X) r- P5 ^. X
Graph.remove_nodes_from(nodes)
' |% T3 j+ [6 h8 b, G5 m3 e$ k9 x: z8 i+ @ @* S, I: ^# e
# 顶点(node)的操作
% w$ E5 m9 c" j# f E1 W# 向图中添加顶点: D; |6 q' z. X1 `1 R3 X' Q
G1.add_node(1) # 向 G1 添加顶点 1. g, n" Y0 U |8 s4 X: I
G1.add_node(1, name='n1', weight=1.0) # 添加顶点 1,定义 name, weight 属性/ B& u) e* y4 c' S; i
G1.add_node(2, date='May-16') # 添加顶点 2,定义 time 属性
# z9 I& s/ `# i' yG1.add_nodes_from([3, 0, 6], dist=1) # 添加多个顶点,并定义属性$ Y: H* z c; [% C0 d) K* T
G1.add_nodes_from(range(10, 15)) # 向图 G1 添加顶点 10~14( i7 I; I/ |+ R( x
) R/ A1 k. e' h/ P5 L
# 查看顶点和顶点属性
7 j) h8 E* Q; f9 A% f. [( C4 Rprint(G1.nodes()) # 查看顶点列表" c0 B; s5 n4 X2 e6 T, [
# [1, 2, 3, 0, 6, 10, 11, 12, 13, 14]
2 |% |' w) U% j" ` M- J7 c7 {print(G1._node) # 查看顶点属性9 _& L1 l+ |' e$ t* y8 O
# {1: {'name': 'n1', 'weight': 1.0}, 2: {'date': 'May-16'}, 3: {'dist': 1}, 0: {'dist': 1}, 6: {'dist': 1}, 10: {}, 11: {}, 12: {}, 13: {}, 14: {}}
s3 E: ?/ f% L& P$ Y
: K1 k/ u: u. j, w( j( l$ F# 从图中删除顶点0 `% u" C! E! F# l5 w; q
G1.remove_node(1) # 删除顶点
; j+ q- `7 O* Z0 ~; E* @! ]G1.remove_nodes_from([1, 11, 13, 14]) # 通过顶点标签的 list 删除多个顶点
" J0 z8 ~: W3 g- a W% b* C8 b8 Bprint(G1.nodes()) # 查看顶点) E+ |) |& |5 Y7 ]5 N/ q4 H; y
# [2, 3, 0, 6, 10, 12] # 顶点列表/ H3 a& P6 r" ~
2.2.3 边的添加、删除和查看边是两个顶点之间的连接,在 NetworkX 中 边是由对应顶点的名字的元组组成 e=(node1,node2)。边可以设置权重、关系等属性。 边的常用操作:添加边,删除边,定义边的属性,查看边和边的属性。向图中添加边时,如果边的顶点是图中不存在的,则自动向图中添加该顶点。 Graph.add_edge(u_of_edge, v_of_edge, **attr)
G: o1 h2 x7 CGraph.add_edges_from(ebunch_to_add, **attr)- y3 S6 l) j: J- b
Graph.add_weighted_edges_from(ebunch_to_add, weight=‘weight’, **attr) d' X& ]$ i. x/ z: l! d
E% e. T6 T2 m: S1 r# 边(edge)的操作6 \% s5 U: s- l8 J/ q1 a2 G9 y
# 向图中添加边, y: B# b; p: A! _( D2 I# [
G1.add_edge(1,5) # 向 G1 添加边,并自动添加图中没有的顶点, }. |6 d/ W& q8 ^. L
G1.add_edge(0,10, weight=2.7) # 向 G1 添加边,并设置边的属性4 p* c- n0 N' g
G1.add_edges_from([(1,2,{'weight':0}), (2,3,{'color':'blue'})]) # 向图中添加边,并设置属性% o* r1 _+ _5 w; g) |/ z
G1.add_edges_from([(3,6),(1,2),(6,7),(5,10),(0,1)]) # 向图中添加多条边5 |: ?$ R( r6 A3 _8 g
G1.add_weighted_edges_from([(1,2,3.6),[6,12,0.5]]) # 向图中添加多条赋权边: (node1,node2,weight)) l2 F8 d% T& K
print(G1.nodes()) # 查看顶点
4 |6 e+ i& `' V( _4 \( W# [2, 3, 0, 6, 10, 12, 1, 5, 7] # 自动添加了图中没有的顶点
}( `/ i# d8 b2 k9 d# p1 j4 F- l2 e4 U1 J0 S
# 从图中删除边
2 L0 ^( `& p" `6 D0 ^, }G1.remove_edge(0,1) # 从图中删除边 0-11 f, {8 k9 z6 \9 h. [$ q d
G1.remove_edges_from([(2,3),(1,5),(6,7)]) # 从图中删除多条边" N4 k( t$ x! X6 w
! N5 l8 z" t V+ x5 Y# 查看 边和边的属性
0 n M# S1 D% z( \7 ^print(G1.edges) # 查看所有的边+ c& c& H3 l5 v* q
[(2, 1), (3, 6), (0, 10), (6, 12), (10, 5)]
6 o. i" M' g/ q1 b) }( Pprint(G1.get_edge_data(1,2)) # 查看指定边的属性
4 b+ k3 W1 ]: p) ?3 v& A, _# {'weight': 3.6}
' D }; g; a$ G3 C+ w7 Tprint(G1[1][2]) # 查看指定边的属性
' _; S6 K. U& ^* }! Z# U% s# {'weight': 3.6}
0 S3 v+ X: K4 V6 ` ~print(G1.edges(data=True)) # 查看所有边的属性
4 s8 O6 u% g8 n+ W! s3 C# [(2, 1, {'weight': 3.6}), (3, 6, {}), (0, 10, {'weight': 2.7}), (6, 12, {'weight': 0.5}), (10, 5, {})]$ { T, Z4 l1 C1 K
# ]7 K3 C, N( z2 u2.2.4 查看图、顶点和边的信息5 `! q% z5 o& F) N4 Q: e
% D6 W# x& o; d1 p1 A7 K: m# 查看图、顶点和边的信息 |1 j N4 }- w6 _. I
print(G1.nodes) # 返回所有的顶点 [node1,...]$ @* J; n( S" A# Z: l t' K
# [2, 3, 0, 6, 10, 12, 1, 5, 7]
( \ K0 J* V9 y! f D# Nprint(G1.edges) # 返回所有的边 [(node1,node2),...]% E3 ^ }& v/ p* L* H
# [(2, 1), (3, 6), (0, 10), (6, 12), (10, 5)]; B! }, t- z! @6 v2 l. i3 R8 b
print(G1.degree) # 返回各顶点的度 [(node1,degree1),...]( ?0 Z) I3 h6 J* n
# [(2, 1), (3, 1), (0, 1), (6, 2), (10, 2), (12, 1), (1, 1), (5, 1), (7, 0)]
9 V1 B& Y6 [- X2 L9 C+ f5 D* r _print(G1.number_of_nodes()) # 返回顶点的数量
' L- N3 M* |( }8 V% Q1 X/ s6 T# 9) C0 T& _2 X5 n& |" t' J z3 Q7 x
print(G1.number_of_edges()) # 返回边的数量) e& z5 _" m: t/ l
# 5
+ G1 R W0 I6 Q# ]print(G1[10]) # 返回与指定顶点相邻的所有顶点的属性
$ t" a+ [+ z) p( K4 B) R( y n4 Y# {0: {'weight': 2.7}, 5: {}}* q5 B {0 k: A8 e- Y" c" ^
print(G1.adj[10]) # 返回与指定顶点相邻的所有顶点的属性
4 F7 C( l7 N% O) z+ k( k) [ k# {0: {'weight': 2.7}, 5: {}}( S3 l# e$ K6 W- l& @ U
print(G1[1][2]) # 返回指定边的属性
5 \/ l, V% E( b" R' C# {'weight': 3.6}
, M2 S; _+ L6 Z$ l6 |! {6 r0 iprint(G1.adj[1][2]) # 返回指定边的属性( |% f' [2 S0 G D7 I& J
# {'weight': 3.6}
4 W5 |5 y, n: B7 Q/ |print(G1.degree(10)) # 返回指定顶点的度
0 l/ `5 ^$ E9 Q. l, j, [9 s# 2
& m* b' ]4 D& H$ E
: Z7 ]8 l5 _+ r6 vprint('nx.info:',nx.info(G1)) # 返回图的基本信息 Y a2 v9 k2 G
print('nx.degree:',nx.degree(G1)) # 返回图中各顶点的度
$ \- J7 X# q& V! Iprint('nx.density:',nx.degree_histogram(G1)) # 返回图中度的分布
, D* A( J9 j2 Gprint('nx.pagerank:',nx.pagerank(G1)) # 返回图中各顶点的频率分布8 l0 a5 S( M" c, g$ K6 [# V
5 X1 t4 ]. ]2 a3 N
! T2 v+ L/ }7 P1 V2 G$ r
7 N; y9 E) h4 X/ i% f" T4 M
5 T" k8 r+ X$ b$ i7 e( t( }# {' x6 ^( x: F1 c
2.3 图的属性和方法图的方法
' n% f7 ~5 \5 }' K8 y
) S, ]* W! Q% X! @) G方法 说明: K r$ ~$ y4 B8 E+ ^7 Y+ C* P
G.has_node(n) 当图 G 中包括顶点 n 时返回 True! {% b" Z! h' W( s8 e
G.has_edge(u, v) 当图 G 中包括边 (u,v) 时返回 True
! H1 P4 A, W2 R7 C1 UG.number_of_nodes() 返回 图 G 中的顶点的数量
, c# t6 P) F5 B# c4 HG.number_of_edges() 返回 图 G 中的边的数量
" K+ N1 c! d* [3 ~& Q/ f) nG.number_of_selfloops() 返回 图 G 中的自循环边的数量5 {5 s5 n3 t* g! \7 p
G.degree([nbunch, weight]) 返回 图 G 中的全部顶点或指定顶点的度
4 Y2 j3 D: {/ }( ~2 EG.selfloop_edges([data, default]) 返回 图 G 中的全部的自循环边
* w* ]- n1 u" j1 GG.subgraph([nodes]) 从图 G1中抽取顶点[nodes]及对应边构成的子图& I3 F8 c# C5 O6 d
union(G1,G2) 合并图 G1、G2
) b, o4 g# P7 {' @6 Vnx.info(G) 返回图的基本信息2 W7 O7 ^ E* _6 Z, }* Y
nx.degree(G) 返回图中各顶点的度( N `7 d2 b6 q8 h1 ~
nx.degree_histogram(G) 返回图中度的分布" w0 n7 \+ a# f7 g! x2 M
nx.pagerank(G) 返回图中各顶点的频率分布
: ]3 g) k( X. P3 inx.add_star(G,[nodes],**attr) 向图 G 添加星形网络
! I7 K7 g! V8 S0 N. Onx.add_path(G,[nodes],**attr) 向图 G 添加一条路径
* J' g: S5 [8 ~: N- U6 Fnx.add_cycle(G,[nodes],**attr) 向图 G 添加闭合路径
( K- r) w. ?3 t9 B6 H1 w( {* _; z/ l! P4 j2 b
3 B9 ~# `3 e& A2 |. B" |8 ?例程:# H5 i% _9 M6 `3 j5 ^' C
G1.clear() # 清空图G1# k9 x: H! D5 u+ d1 o3 k$ j
nx.add_star(G1, [1, 2, 3, 4, 5], weight=1) # 添加星形网络:以第一个顶点为中心
0 J O" j+ P: L! e( P( ~# [(1, 2), (1, 3), (1, 4), (1, 5)]
) @& T4 g' Y; i$ Q& v8 a ^nx.add_path(G1, [5, 6, 8, 9, 10], weight=2) # 添加路径:顺序连接 n个节点的 n-1条边8 t$ `0 r2 N! ?+ e, R
# [(5, 6), (6, 8), (8, 9), (9, 10)]$ ?$ F0 s4 `" p) M8 r
nx.add_cycle(G1, [7, 8, 9, 10, 12], weight=3) # 添加闭合回路:循环连接 n个节点的 n 条边
- N- Y5 }+ Z, z$ u1 d8 m: ^8 H: ]5 S# [(7, 8), (7, 12), (8, 9), (9, 10), (10, 12)]
; ?* g7 |( d" Fprint(G1.nodes) # 返回所有的顶点 [node1,...]
7 U5 t7 R$ d$ Q* d7 B: O7 q# n$ lnx.draw_networkx(G1)
) j: }% P7 R$ Fplt.show()3 x0 o/ q2 Z G0 s2 B1 `7 `( y( r
! u# ~1 c1 f8 {2 g
G2 = G1.subgraph([1, 2, 3, 8, 9, 10])2 R& H2 i5 _% o' K$ q
G3 = G1.subgraph([4, 5, 6, 7])
' D# T1 s; O% c6 V7 f. {: \G = nx.union(G2, G3)
4 p! L t9 Z! B& i ~6 hprint(G.nodes) # 返回所有的顶点 [node1,...]% @2 Z0 F1 G6 B; u- w' Y+ I6 f ^
# [1, 2, 3, 8, 9, 10, 4, 5, 6, 7]: h* |8 i# Q# K) G5 X, i P8 Y
. a1 n3 I3 R1 O# U* G4 I. y
0 p; _8 i7 u' I' p; K9 I3、图的绘制与分析3.1 图的绘制* |+ s& D1 ~; C t% _8 n8 a. A
可视化是图论和网络问题中很重要的内容。NetworkX 在 Matplotlib、Graphviz 等图形工具包的基础上,提供了丰富的绘图功能。9 t4 M [- U4 `
" V s& n. W: Z# G本系列拟对图和网络的可视化作一个专题,在此只简单介绍基于 Matplotlib 的基本绘图函数。基本绘图函数使用字典提供的位置将节点放置在散点图上,或者使用布局函数计算位置。
& H+ @2 h$ K& |6 A4 P7 U
. l4 R' G, S8 K$ a& L: F方法 说明 K/ J/ A$ r8 t1 m1 e
draw(G[,pos,ax]) 基于 Matplotlib 绘制 图 G' R& ]: I( K8 C
draw_networkx(G[, pos, arrows, with_labels]) 基于 Matplotlib 绘制 图 G/ x1 W2 a3 ~3 u4 [7 k
draw_networkx_nodes(G, pos[, nodelist, . . . ]) 绘制图 G 的顶点
2 [7 Y# J. F8 z2 z& d+ tdraw_networkx_edges(G, pos[, edgelist, . . . ]) 绘制图 G 的边7 \) R: P/ c2 {; }: \% C+ a. K% v
draw_networkx_labels(G, pos[, labels, . . . ]) 绘制顶点的标签
0 y$ u( ~2 D9 Edraw_networkx_edge_labels(G, pos[, . . . ]) 绘制边的标签$ F. N( b5 a+ d/ M7 w
) a- z7 n) o: {8 D4 C, p% Q
5 {/ A' f8 |! Q7 S/ W2 s9 b其中,nx.draw() 和 nx.draw_networkx() 是最基本的绘图函数,并可以通过自定义函数属性或其它绘图函数设置不同的绘图要求。
# M9 q C0 b& v: v) c# t, w# ndraw(G, pos=None, ax=None, **kwds) draw_networkx(G, pos=None, arrows=True, with_labels=True, **kwds)
1 m1 Q/ {7 b* @; j- E7 f常用的属性定义如下: \! w' q( C2 g
3 E/ f1 ?/ g. X6 q‘node_size’:指定节点的尺寸大小,默认300
, L( |% u( t0 @7 {% ?. n‘node_color’:指定节点的颜色,默认红色
' w2 w3 O5 t- ^1 }. o, A t$ N‘node_shape’:节点的形状,默认圆形. @1 H6 @$ i/ C* `9 s8 q) K
'‘alpha’:透明度,默认1.0,不透明8 H; I8 m2 Q, D# x6 N& \/ {+ w' F
‘width’:边的宽度,默认1.0* U; R8 Z" C3 g- m X
‘edge_color’:边的颜色,默认黑色1 {* f* X6 ?& P# n' }/ ^
‘style’:边的样式,可选 ‘solid’、‘dashed’、‘dotted’、‘dashdot’
2 L# U& V) P9 F‘with_labels’:节点是否带标签,默认True
$ s3 n) a7 Z" F‘font_size’:节点标签字体大小,默认12
% t, ~7 P! ?% N- w‘font_color’:节点标签字体颜色,默认黑色7 i' |6 N# `9 y# e$ t7 k
( u0 ~* M, v+ b0 z; [2 c' g7 _
! _1 n9 b" k" i7 k- i3 {
3.2 图的分析NetwotkX 提供了图论函数对图的结构进行分析
$ }* C. _. H7 e; W0 D4 r子图& Y, g# X* B7 a) ^
- 子图是指顶点和边都分别是图 G 的顶点的子集和边的子集的图。
- subgraph()方法,按顶点从图 G 中抽出子图。例程如前。
1 p$ r) |6 c% J; ? 连通子图" g/ f# e$ j/ L4 d
8 i. h9 w9 ^% l- 如果图 G 中的任意两点间相互连通,则 G 是连通图。
- [color=rgba(0, 0, 0, 0.749019607843137)]connected_components()方法,返回连通子图的集合。) O) U8 l2 m( ^5 J* j% U
[color=rgba(0, 0, 0, 0.749019607843137)]G = nx.path_graph(4)[color=rgba(0, 0, 0, 0.749019607843137)]nx.add_path(G, [7, 8, 9])[color=rgba(0, 0, 0, 0.749019607843137)]# 连通子图[color=rgba(0, 0, 0, 0.749019607843137)]listCC = [len(c) for c in sorted(nx.connected_components(G), key=len, reverse=True)][color=rgba(0, 0, 0, 0.749019607843137)]maxCC = max(nx.connected_components(G), key=len)[color=rgba(0, 0, 0, 0.749019607843137)]print('Connected components:{}'.format(listCC)) # 所有连通子图[color=rgba(0, 0, 0, 0.749019607843137)]# Connected components:[4, 3][color=rgba(0, 0, 0, 0.749019607843137)]print('Largest connected components:{}'.format(maxCC)) # 最大连通子图[color=rgba(0, 0, 0, 0.749019607843137)]# Largest connected components:{0, 1, 2, 3}[color=rgba(0, 0, 0, 0.749019607843137)]强连通如果有向图 G 中的任意两点间相互连通,则称 G 是强连通图。strongly_connected_components()方法,返回所有强连通子图的列表。# 强连通G = nx.path_graph(4, create_using=nx.DiGraph())nx.add_path(G, [3, 8, 1])# 找出所有的强连通子图con = nx.strongly_connected_components(G)print(type(con),list(con))# <class 'generator'> [{8, 1, 2, 3}, {0}]弱连通如果一个有向图 G 的基图是连通图,则有向图 G 是弱连通图。weakly_connected_components()方法,返回所有弱连通子图的列表。# 弱连通G = nx.path_graph(4, create_using=nx.DiGraph()) #默认生成节点 0,1,2,3 和有向边 0->1,1->2,2->3nx.add_path(G, [7, 8, 3]) #生成有向边:7->8->3con = nx.weakly_connected_components(G)print(type(con),list(con))# <class 'generator'> [{0, 1, 2, 3, 7, 8}]
4 q7 r/ ^3 T" p$ j ; ~; d4 e) s ~+ i: F& E4 X8 w
8 L' b! v+ Y/ c. I
( M8 |; j3 t( D. M
* E. Q$ q8 I! V1 U |