📜  使用 Networkx 模块对图和特殊图进行操作 | Python

📅  最后修改于: 2022-05-13 01:55:47.725000             🧑  作者: Mango

使用 Networkx 模块对图和特殊图进行操作 | Python

先决条件:创建一个无向图。

基本的 Graph 操作如下:

从图中获取子图:

给定一个图及其节点集的子集,我们可以通过选择这些节点以及它们之间的所有边来创建一个子图,这些边与原始图中存在的一样。下面的代码将清楚地说明这个操作。

import networkx as nx 
import matplotlib.pyplot as plt
  
G = nx.Graph()
  
plt.figure(figsize =(9, 12))
G.add_edges_from([(1, 2), (1, 3), (2, 3), (2, 4), (2, 5), (3, 4), 
                         (4, 5), (4, 6), (5, 7), (5, 8), (7, 8)])
  
# original Graph created
plt.subplot(211)
print("The original Graph:")
  
nx.draw_networkx(G)

原图:

H = G.subgraph([1, 2, 3, 4])
# [1, 2, 3, 4] is the subset of 
# the original set of nodes
  
plt.subplot(212)
print("The Subgraph:")
nx.draw_networkx(H)

子图:

原始图 G 具有从 1 到 8 的节点。我们选择了节点 1、2、3 和 4 并创建了一个子图 H,它有 5 条边存在于原始图 G 中。

两个图的并集:

给定两个图 G 和 H,两个图的并集创建一个可能有多个连通分量的图。但是我们必须记住,G 和 H 的节点集应该是不相交的,换句话说,两个图不应该有任何共同的节点。

import networkx as nx 
import matplotlib.pyplot as plt
  
G = nx.Graph()
  
plt.figure(figsize =(9, 12))
G.add_edges_from([(1, 2), (1, 3), (2, 3), (2, 4), (2, 5), (3, 4), 
                         (4, 5), (4, 6), (5, 7), (5, 8), (7, 8)])
  
# First Graph created
plt.subplot(311)
nx.draw_networkx(G)
  
H = nx.Graph()
H.add_edges_from([(13, 14), (13, 15), (13, 9),
                  (14, 15), (15, 10), (9, 10)])
  
# Second Graph created
plt.subplot(312)
nx.draw_networkx(H)
  
  
I = nx.union(G, H)
plt.subplot(313)
nx.draw_networkx(I)

新形成的图 I 是图 g 和 H 的并集。如果我们确实在两个图之间有公共节点并且仍然想要获得它们的并集,那么我们将使用另一个名为disjoint_set()的函数

I = nx.disjoint_set(G, H)

这将重命名公共节点并形成类似的图表。

两个图的笛卡尔积:

给定两个图,G 和 H,笛卡尔积创建一个新图,I = G*H。 I 的节点集是 G 和 H 的节点集的笛卡尔积,即 V(I) = V(G)*V(H)。

边(( g_i, h_j ), ( g_k, h_l )) 存在当且仅当:

  • i=k 并且(h_j, h_l)在 H 中作为边存在
  • j=l 和(g_i, g_k)作为 G 中的一条边存在
import networkx as nx 
import matplotlib.pyplot as plt
  
G = nx.Graph()
  
plt.figure(figsize =(9, 18))
G.add_edges_from([(1, 2), (2, 3)])
  
# First Graph created
plt.subplot(311)
nx.draw_networkx(G)
  
H = nx.Graph()
H.add_edges_from([(6, 7)])
# Second Graph created
plt.subplot(312)
nx.draw_networkx(H)
  
  
I = nx.cartesian_product(G, H)
plt.subplot(313)
nx.draw_networkx(I)


该表示清楚地显示了前 2 个图的乘积如何导致第三个图。

两张图的组成:

给定两个图 G 和 H,如果它们没有公共节点,那么它们两者的组合将导致具有 2 个连通分量的单个图(假设 G 和 H 是连通图)。这与我们使用nx.union(G, H)nx.disjoint_union(G, H)获得的结果相同。
但是如果 G 和 H 有共同的节点,那么这两个图的合成将产生一个单一的连接图,这样 G 和 H 是新图的子图。

import networkx as nx 
import matplotlib.pyplot as plt
  
G = nx.Graph()
  
plt.figure(figsize =(9, 15))
G.add_edges_from([(1, 2), (1, 3), (2, 3), (2, 4)])
  
# First Graph created
plt.subplot(311)
nx.draw_networkx(G)
  
H = nx.Graph()
H.add_edges_from([(3, 7), (7, 4), (3, 4)])
# Second Graph created
plt.subplot(312)
nx.draw_networkx(H)
  
  
I = nx.compose(G, H)
plt.subplot(313)
nx.draw_networkx(I)

这些图表清楚地显示了前两个图表如何组合在一起形成第三个图表。

图表的补充:

给定一个图 G,G 的补集(比如 H)具有 G 的所有节点。它具有 G 没有的所有可能边。设 V 和 E 是 G 的节点和边的集合,则 H 有{(|V|*(|V|-1))/2 - |E|}条边。因此,完整图的补集将没有边。

import networkx as nx 
import matplotlib.pyplot as plt
  
G = nx.Graph()
  
plt.figure(figsize =(9, 16))
G.add_edges_from([(1, 2), (1, 3), (2, 3), (2, 4)])
  
# Original Graph created
plt.subplot(211)
nx.draw_networkx(G)
  
H = nx.complement(G)
plt.subplot(212)
nx.draw_networkx(H)

转换为定向:

给定一个无向图 G,此 Networkx函数将通过将其边替换为 2 路有向边将其转换为有向图。

import networkx as nx 
import matplotlib.pyplot as plt
  
G = nx.Graph()
  
plt.figure(figsize =(9, 16))
G.add_edges_from([(1, 2), (1, 3), (2, 3), (2, 4)])
# Original Undirected Graph created
  
plt.subplot(211)
nx.draw_networkx(G)
  
H = nx.to_directed(G)
plt.subplot(212)
nx.draw_networkx(H)

转换为无向:

给定一个有向图 G,此 Networkx函数将通过将其所有有向边转换为无向边将其转换为无向图。如果在具有不同属性(权重、颜色等)的一对节点之间存在两条边,则仅创建一条边,并可以任意选择要使用的边数据。

import networkx as nx 
import matplotlib.pyplot as plt
  
G = nx.DiGraph()
  
plt.figure(figsize =(9, 16))
G.add_edges_from([(1, 2), (1, 3), (2, 4)])
  
# Original Directed Graph created
plt.subplot(211)
nx.draw_networkx(G)
  
H = nx.to_undirected(G)
plt.subplot(212)
nx.draw_networkx(H)

现在,我们将讨论 Networkx 模块提供的各种特殊图。

彼得森图:彼得森图是一个有 10 个顶点和 15 条边的无向图。它是一个小图,可作为图论中许多问题的有用示例和反例。

import networkx as nx 
import matplotlib.pyplot as plt
  
plt.figure(figsize =(9, 100))
  
# Peterson Graph
plt.subplot(12, 1, 1)
G = nx.petersen_graph()
nx.draw_networkx(G)

Tutte 图: Tutte 图是一个 3 正则图,有 46 个顶点和 69 个边。 Tutte 图是三次多面体图,但不是哈密顿图。因此,这是对泰特猜想的反例。每个 3 正则多面体都有一个哈密顿循环。

# Tutte Graph
plt.subplot(12, 1, 2)
G = nx.tutte_graph()
nx.draw_networkx(G)

Sedgewick 迷宫图: Sedgewick 的迷宫算法用于生成大型迷宫。与此方法有关的 Networkx函数返回一个带循环的小迷宫。

# Sedgewick Maze Graph
plt.subplot(12, 1, 3)
G = nx.sedgewick_maze_graph()
nx.draw_networkx(G)

Tetrahedral Graph:这将返回一个完整的 Graph,其中包含四个节点,这些节点呈四面体形状。

# Tetrahedral Graph
plt.subplot(12, 1, 4)
G = nx.tetrahedral_graph()
nx.draw_networkx(G)

完整图:返回具有给定边数的完整图。

# Complete Graph with 5 nodes
plt.subplot(12, 1, 5)
G = nx.complete_graph(6)
nx.draw_networkx(G)

Complete Bipartite Graph:给定两个数字 n 和 m,它返回一个包含两组 n 和 m 节点的 Graph,其中一组节点连接到另一组的所有节点,但没有自己的节点放。这种类型的图被称为二分图。

# Complete Bipartite Graph with 5 and 3 nodes
plt.subplot(12, 1, 6)
G = nx.complete_bipartite_graph(5, 3)
nx.draw_networkx(G)

杠铃图:给定两个参数 n 和 m,它返回一个 Graph,其中包含两个由 n 个节点组成的派系,这两个派系之间通过 m 个节点连接。

# Barbell Graph with clique of 4 and bridging of 2 nodes
plt.subplot(12, 1, 7)
  
G = nx.barbell_graph(4, 2)
nx.draw_networkx(G)

Lollipop Graph:给定两个参数 n 和 m,它返回一个带有 n 个顶点的 clique 连接到 m 个节点的路径的 Graph。

# Lollipop Graph with clique of 5 and path of 2 nodes
plt.subplot(12, 1, 8)
G = nx.lollipop_graph(5, 2)
nx.draw_networkx(G)

Erdos Renyi Graph:给定两个参数 n 和 p,它返回一个带有 n 个节点的 Graph,选择每条边的概率为 p。有关详细信息,请参阅本文。

# Erdos Renyi Graph with 20 nodes and probability of 0.25
plt.subplot(12, 1, 9)
  
G = nx.erdos_renyi_graph(20, 0.25)
nx.draw_networkx(G)

Watts Strogatz Graph:给定三个参数 n、k 和 p,返回一个由 n 个节点组成的小世界网络,每个节点连接到 k 个最近邻居,每条边的重新连接概率为 p。

# Watts Strogatz Graph with 20 nodes, 
# 4 neighbours and probability of 0.2
plt.subplot(12, 1, 10)
G = nx.watts_strogatz_graph(20, 4, 0.2)
nx.draw_networkx(G)

Barabasi Albert Graph:给定两个参数 n 和 m,返回一个 Barabasi Albert 优先连接图,其中有 n 个节点和 m 条边从新节点连接到现有节点。

# Barabasi Albert Graph with 20 nodes and 3 attaching nodes
plt.subplot(12, 1, 11)
G = nx.barabasi_albert_graph(20, 3)
nx.draw_networkx(G)

Random Lobster Graph:给定三个参数 n、p1 和 p2,返回一个 lobster Graph。龙虾是一棵在修剪所有叶节点时会变成毛毛虫的树。 Caterpillar 是一棵在修剪所有叶节点时减少为路径图的树。图在主干中有 n 个节点,向主干添加边的概率为 p1,在主干之外的级别添加边的概率为 p2。

# Random Lobster Graph with 30 base
# nodes and probabilites of 0.8
plt.subplot(12, 1, 12)
  
G = nx.random_lobster(30, 0.8, 0.8)
nx.draw_networkx(G)