问题描述
我正在编写自己的函数来计算任何有向图的拉普拉斯矩阵,并且正在努力填充结果矩阵的对角线条目。下面的等式是我用来计算拉普拉斯矩阵项的公式,其中 e_ij
表示从节点 i 到节点 j 的边。
我正在使用 NetworkX (https://networkx.org/) 创建图形对象。我知道 NetworkX 有自己的用于有向图的拉普拉斯函数,但我想 100% 确定我正在使用一个为我的目的执行正确计算的函数。到目前为止,我开发的代码如下所示,用于以下示例图:
# 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
我还没有在不同的图表上对此进行测试,但这是我希望为我的直接目的而弄清楚的。