我有一个函数,该函数返回G的子图S。我想创建一个图H,其中S中的每个连接分量都是H中的一个顶点,如果H之间有一条边,则两个顶点连接在H中G中的这些顶点集。
现在,我有一些可行的方法,但是创建H所需的时间是创建S所需时间的两倍。(根据cProfile,主要是由于node_boundary和connected_components函数的缘故)该过程将完成很多次,所以我希望能刮掉一小部分时间。我只真正需要H,所以我考虑创建不带中间函数的H,但是我无法使它与收缩一起使用。问题在于,应该从G中随机选择边缘,但是边缘收缩会改变H中顶点的名称,而翻译边缘的名称对我来说很困难。
创建S:
def sp(G):
nodes = list(G.nodes)
out = nx.Graph()
for v in nodes:
out.add_edge(v, random.choice(list(G.neighbors(v))))
return out
从S创建H:
spr = sp(G)
H = nx.Graph()
bound = []
CC = list(nx.connected_components(spr))
for c in CC:
H.add_node(CC.index(c))
for c in CC:
bound.append(nx.node_boundary(G,c))
for b in bound:
inter = c.intersection(b)
if len(inter) > 0:
H.add_edge(CC.index(c), bound.index(b))
创建不带S的H:
nodes = list(G.nodes)
edges = []
out = G.copy()
for v in nodes:
edges.append( (v, random.choice(list(G.neighbors(v)))) )
for e in edges:
out = nx.contracted_edge(out, e)
return out
答案 0 :(得分:1)
通常使用邻接矩阵更容易。这是一个肮脏的代码片段,它将在给定任意分区的情况下进行矩阵收缩。您应该能够由此构建图形。
顺便说一句,如果您真的只专注于连接的组件,那么您将看不到任何非对角线连接,并且可以大大简化此代码。我假设您的意思是分区和子图。
import numpy as np
import networkx as nx
from itertools import combinations_with_replacement
graph = nx.erdos_renyi_graph(n=40, p=0.05)
A = nx.to_numpy_matrix(graph)
cc_list = [list(cc) for cc in nx.connected_components(graph)]
def matrix_contraction(A, partition):
contract_A = np.zeros((len(partition), len(partition)))
for (ipart, ipartidx), (jpart, jpartidx) in combinations_with_replacement(enumerate(partition), 2):
contract_A[ipart,jpart] = A[ipartidx][:, jpartidx].sum()
contract_A[jpart,ipart] = A[jpartidx][:, ipartidx].sum()
return contract_A
contracted_adj_matrix = matrix_contraction(A, cc_list)
print(cc_list)
print(contracted_adj_matrix)
答案 1 :(得分:0)
我已经编辑了您的代码。尝试一下是否更快:
import networkx as nx
import random
G = nx.random_tree(1000)
def sp(graph, percent_of_edges):
"""returns a subgraph with a certain percentage of edges"""
out = nx.Graph()
edges = graph.edges
sample = random.sample(edges, k = int(len(edges) * percent_of_edges/100))
out.add_edges_from(sample)
return out
# Creating H from S
spr = sp(G, 80)
H = nx.Graph()
bound = []
CC = list(nx.connected_components(spr))
H.add_nodes_from(range(len(CC)))
for c in CC:
bound.append(nx.node_boundary(G, c))
for num1, c in enumerate(CC):
for num2, b in enumerate(bound):
if c.intersection(b):
H.add_edge(num1, num2)