使用networkx模块,我在Python 3.2下进行一些网络分析,我需要在其中投射一个二分图(链接到其单元的囚犯:下面代码中的输入图B)到子图(将囚犯彼此联系起来)如果两个都在同一个单元格中有重叠拼写:使用定义图形B的囚犯节点的集合节点的输入,生成输出图形G)。我不需要特殊的算法来提出任何或最佳匹配,我只需要收集满足某些条件的所有链接。因此,我找到的其他SO帖子并不真正适用。但是:
当我提供越来越多的数据时,我当前的代码正在爆炸(RAM-,交换和CPU)。如果您看到使用5层循环简化下面的代码的方法,请告诉我。我不确定是否需要了解networkx,或者我的边缘属性标签的细节是相关的。谢谢!
def time_overlap_projected_graph_parallel(B, nodes):
G=nx.MultiGraph()
G.add_nodes_from((n,B.node[n]) for n in nodes)
for u in nodes:
unbrs = set(B[u])
nbrs2 = set((n for nbr in unbrs for n in B[nbr])) - set([u])
for v in nbrs2:
for mutual_cell in set(B[u]) & set(B[v]):
for uspell in B.get_edge_data(u,mutual_cell).values():
ustart = uspell[1]
uend = uspell[2]
for vspell in B.get_edge_data(v,mutual_cell).values():
vstart = vspell[1]
vend = vspell[2]
if uend > vstart and vend > ustart:
ostart = max(ustart,vstart)
oend = min(uend,vend)
olen = (oend-ostart+1)/86400
ocell = mutual_cell
if (v not in G[u] or ostart not in [ edict[1] for edict in G[u][v].values() ]):
G.add_edges_from([(u,v,{0: olen,1: ostart,2: oend,3: ocell})])
return G
答案 0 :(得分:2)
我猜可以使用二分图。像
import networkx as nx
from networkx.algorithms import bipartite
B.add_nodes_from(inmates_list, bipartite=0)
B.add_nodes_from(cells_list, bipartite=1)
inmates = set(n for n,d in B.nodes(data=True) if d['bipartite']==0)
cells = = set(B) - inmates
G = bipartite.projected_graph(B, inmates)
(http://networkx.lanl.gov/reference/algorithms.bipartite.html)
答案 1 :(得分:1)
这是我的看法。根据每个细胞的平均囚犯,它可能会提高性能。如果您有更好的方法来获取单元格(例如节点属性?),请替换
cells = [n for n in B.nodes() if n[0] not in nodes]
有了(这里我假设节点是所有囚犯的名单)。
from itertools import combinations
def time_overlap_projected_graph_parallel(B, nodes):
G=nx.MultiGraph()
G.add_nodes_from((n,B.node[n]) for n in nodes)
cells = [n for n in B.nodes() if n[0] not in nodes]
for cell in cells:
for u,v in combinations(B[cell],2):
for uspell in B.get_edge_data(u,cell).values():
ustart = uspell[1]
uend = uspell[2]
for vspell in B.get_edge_data(v,cell).values():
vstart = vspell[1]
vend = vspell[2]
if uend > vstart and vend > ustart:
ostart = max(ustart,vstart)
oend = min(uend,vend)
olen = (oend-ostart+1)/86400
ocell = cell
if (v not in G[u] or ostart not in [ edict[1] for edict in G[u][v].values() ]):
G.add_edge(u,v,{0: olen,1: ostart,2: oend,3: ocell})
return G
答案 2 :(得分:1)
我发布这个答案是为了提出一些改进建议。我假设您的二分图不是多图,而是正常nx.Graph
。我将B
更改为bi
并将G
更改为uni
,因为大写名称是按惯例保留给类的。顺便问一下,如果法术开始并在同一时间结束怎么办?
def time_overlap_projected_graph_parallel(bi, nodes):
uni = nx.MultiGraph()
for u in nodes: #inmate
uni.add_node(u) # do this to prevent iterating nodes twice
u_adj = bi.adj[u] # bi.adj is a dict of dicts
for (w, uw_attr) in u_adj.iteritems(): # cell
w_adj = bi.adj[w]
for (v, wv_attr) in w_adj.iteritems():#cellmate
if v == u:
continue
elif uni.has_edge(u, v): # avoid computing twice
continue
for uspell in uw_attr.itervalues():
ustart = uspell[1]
uend = uspell[2]
for vspell in wv_attr.itervalues():
vstart = vspell[1]
vend = vspell[2]
if uend > vstart and vend > ustart:
ostart = max(ustart, vstart)
oend = min(uend, vend)
olen = (oend - ostart + 1) / 86400 # this assumes floats or Python 3 otherwise will be 0
ocell = w
# I would change this to uni.add_edge(u, v, length=olen, start=ostart, end=oend, cell=ocell)
# or to uni.add_edge(u, v, spell=[olen, ostart, oend, ocell])
uni.add_edge(u, v, **{0: olen, 1: ostart, 2: oend, 3: ocell})
return uni
答案 3 :(得分:0)
考虑修改后的代码,它可能会做同样的事情,但是使用迭代器(虽然我还修改了一些与网络x相关的函数/方法调用---但我仍然在检查我是否破坏了某些内容):
def time_overlap_projected_graph_parallel(B, nodes):
G=nx.MultiGraph()
G.add_nodes_from(nodes)
for u in G.nodes_iter():#inmate
for w in B.neighbors_iter(u):#cell
for v in B.neighbors_iter(w):#cellmate
if v == u:
continue
for uspell in B[u][w].values():
ustart = uspell[1]
uend = uspell[2]
for vspell in B[v][w].values():
vstart = vspell[1]
vend = vspell[2]
if uend > vstart and vend > ustart:
ostart = max(ustart,vstart)
oend = min(uend,vend)
olen = (oend-ostart+1)/86400
ocell = w
if (v not in G[u] or ostart not in [ edict[1] for edict in G[u][v].values() ]):
G.add_edges_from([(u,v,{0: olen,1: ostart,2: oend,3: ocell})])
return G