微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

计算 NetworkX

如何解决计算 NetworkX

我正在编写自己的函数来计算任何有向图的拉普拉斯矩阵,并且正在努力填充结果矩阵的对角线条目。下面的等式是我用来计算拉普拉斯矩阵项的公式,其中 e_ij 表示从节点 i 到节点 j 的边。

Laplacian eqn

我正在使用 NetworkX (https://networkx.org/) 创建图形对象。我知道 NetworkX 有自己的用于有向图的拉普拉斯函数,但我想 100% 确定我正在使用一个为我的目的执行正确计算的函数。到目前为止,我开发的代码如下所示,用于以下示例图:

3 state graph

# Create a simple example of a directed weighted graph

G = nx.DiGraph()
G.add_nodes_from([1,2,3])
G.add_weighted_edges_from([(1,1),(1,3,(2,1,(3,1)])
# Put node,edge,and weight information into Python lists

node_list = []

for item in G.nodes():
    node_list.append(item)

edge_list = []
weight_list = []

for item in G.edges():
    weight_list.append(G.get_edge_data(item[0],item[1])['weight'])
    item = (item[0]-1,item[1]-1)
    edge_list.append(item)
print(edge_list)
> [(0,(0,2),0),1)]
# Fill in the non-diagonal entries of the Laplacian

num_nodes = len(node_list)
num_edges = len(edge_list)

J = np.zeros(shape = (num_nodes,num_nodes))

for x in range(num_edges):
    i = edge_list[x][0]
    j = edge_list[x][1]
    
    J[i,j] = weight_list[x]

我正在努力弄清楚如何填写对角线条目。 edge_list元组列表。为了对 L(G) 执行上述等式中的计算,我需要遍历每个元组的第二个条目,将第一个条目存储到一个临时列表中,对该临时列表的所有元素求和,最后存储负数L(G) 的正确对角线项中的总和。

任何建议都将不胜感激,特别是如果上面的步骤可以更有效或更优雅地完成。

解决方法

我会稍微偏离你的方法,因为如果可能的话,我更喜欢使用 Numpy :P。

在以下代码段中,我为 n=10 节点网络生成测试数据;也就是说,我生成了一个元组数组 V 来填充随机节点,还有一个 (n,n) 数组 A 与节点之间的边的值。希望代码在某种程度上是不言自明的并且是正确的(否则请告诉我):

from random import sample
import numpy as np

# Number and list of nodes
n = 10
nodes = list(np.arange(n))      # random.sample needs list

# Test array of linked nodes
# V[i] is a tuple with all nodes the i-node connects to.
V = np.zeros(n,dtype = tuple)
for i in range(n):
    nv = np.random.randint(5)  # Random number of edges from node i
    # To avoid self-loops (do not know if it is your case - comment out if necessary)
    itself = True
    while itself:    
        cnodes = sample(nodes,nv)  # samples nv elements from the nodes list w/o repetition
        itself = i in cnodes
    V[i] = cnodes

# Test matrix of weighted edges (from i-node to j-node)
A = np.zeros((n,n))
for i in range(n):
    for j in range(n):
        if j in V[i]:
            A[i,j] = np.random.random()*5             
        
# Laplacian of network
J = np.copy(A)      # This already sets the non-diagonal elements
for i in range(n):
    J[i,i] = - np.sum(A[:,i]) - A[i,i]
,

我稍微调整了无向图的 networkx.laplacian_matrix 函数

import networkx as nx
import scipy.sparse

G = nx.DiGraph()
G.add_nodes_from([1,2,3])
G.add_weighted_edges_from([(1,1),(1,3,(2,1,(3,1)])

nodelist = list(G)
A = nx.to_scipy_sparse_matrix(G,nodelist=nodelist,weight="weight",format="csr")
n,m = A.shape
diags = A.sum(axis=0)  # 1 = outdegree,0 = indegree
D = scipy.sparse.spdiags(diags.flatten(),[0],m,n,format="csr")

print((A - D).todense())
# [[-2  1  1]
#  [ 1 -2  1]
#  [ 1  1 -2]]
,

谢谢大家的建议!我同意 numpy 是要走的路。作为我稍后会优化的基本解决方案,这就是我想出的:

def Laplacian_all(edge_list,weight_list,num_nodes,num_edges):
    
    J = np.zeros(shape = (num_nodes,num_nodes))
    
    for x in range(num_edges):
        i = edge_list[x][0]
        j = edge_list[x][1]

        J[i,j] = weight_list[x]
    
    for i in range(num_nodes):
        temp = []
        for x in range(num_edges):
            if i == edge_list[x][1]:
                temp.append(weight_list[x])
        temp_sum = -1*sum(temp)
        J[i,i] = temp_sum
    
    return J

我还没有在不同的图表上对此进行测试,但这是我希望为我的直接目的而弄清楚的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。