【问题标题】:Calculate the Laplacian matrix of a graph object in NetworkX在 NetworkX 中计算图形对象的拉普拉斯矩阵
【发布时间】:2021-02-24 19:25:37
【问题描述】:

我正在编写自己的函数来计算任何有向图的拉普拉斯矩阵,并且正在努力填充结果矩阵的对角线条目。以下等式是我用来计算拉普拉斯矩阵的条目,其中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, 2, 1), (1, 3, 1), (2, 1, 1), (2, 3, 1), (3, 1, 1), (3, 2, 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, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 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)的正确对角项中的总和。

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

【问题讨论】:

  • 如果你想让它优雅而快速,我建议使用networkx 中提供的实现。我建议您检查implementation 以及一些示例的输出,以确保函数返回所需的矩阵。据我所见, networkx 函数返回您定义的负数。但是,我想知道为什么您的拉普拉斯算子是无向图的公式。
  • 谢谢@Sparky05。我应该在上面更清楚——这个方程专门用于有向图。我在原始帖子中修复了这个清晰度问题。至于实现的链接,链接的函数不适用于有向图。而当我尝试上图的有向图函数时,并没有得到预期的拉普拉斯矩阵。

标签: python python-3.x numpy networkx graph-theory


【解决方案1】:

我稍微调整了无向图的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, 2, 1), (1, 3, 1), (2, 1, 1), (2, 3, 1), (3, 1, 1), (3, 2, 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]]

【讨论】:

    【解决方案2】:

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

    在下面的sn-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]
    

    【讨论】:

      【解决方案3】:

      感谢大家的建议!我同意 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
      

      我还没有在不同的图表上对此进行测试,但这是我希望立即解决的问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-05-25
        • 2019-09-03
        • 2020-08-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多