有向图的厄米邻接矩阵

问题描述 投票:0回答:1

我正在尝试找到一种Python式的方法来计算Python中的埃尔米特邻接矩阵,但我真的很挣扎。埃尔米特邻接矩阵的定义如下图所示:

picture of definition

其工作原理如下。假设我们有两个名为

i
j
的节点。如果存在从
i to j
j to i
出发的有向边,则位置 [ i, j ] 处对应的矩阵值应设置为 1。如果仅存在来自
i to j
的有向边,则位置 [i, j] 处的矩阵元素应设置为 +i。如果仅存在来自
j to i
的有向边,则位置 [i, j] 处的矩阵元素应设置为 -i。所有其他矩阵值均设置为 0。

我无法找到一种明智的方法来制作这个埃尔米特邻接矩阵,该矩阵不涉及逐个迭代我的节点。有什么建议吗?

python python-3.x networkx graph-theory
1个回答
1
投票

我认为没有内置功能,所以我拼凑了自己的矢量化解决方案:

import numpy as np
import networkx as nx

# Create standard adjacency matrix
A = nx.linalg.graphmatrix.adjacency_matrix(G).toarray()

# Add to its transpose and convert from sparse array
B = A + A.T

# Get row index matrix
I = np.indices(B.shape)[0] + 1

# Apply vectorised formula to get Hermitian adjacency matrix
H = np.multiply(B/2 * (2*I)**(B%2), 2*A-1).astype(int)

说明

让我们从有向图开始:

我们首先使用

nx.linalg.graphmatrix.adjacency_matrix()
创建法线邻接矩阵,得到以下矩阵:

>>> A = nx.linalg.graphmatrix.adjacency_matrix(G).toarray()
[[1, 1, 0, 1, 0, 1, 0, 0],
 [1, 0, 0, 1, 0, 0, 1, 0],
 [1, 1, 1, 1, 0, 1, 0, 0],
 [0, 1, 0, 0, 0, 0, 0, 0],
 [1, 0, 0, 1, 0, 0, 0, 0],
 [1, 1, 0, 0, 1, 0, 1, 1],
 [0, 1, 0, 0, 1, 0, 0, 1],
 [0, 0, 0, 0, 1, 0, 0, 0]]

然后我们可以将此矩阵添加到其转置中,在每个有来自

2
的有向边的位置上给出
i to j
,反之亦然,在仅存在这些边之一的每个位置上给出
1
,在每个不存在边缘的位置都有一个
0

>>> B = A + A.T
>>> B
[[2, 2, 1, 1, 1, 2, 0, 0],
 [2, 0, 1, 2, 0, 1, 2, 0],
 [1, 1, 2, 1, 0, 1, 0, 0],
 [1, 2, 1, 0, 1, 0, 0, 0],
 [1, 0, 0, 1, 0, 1, 1, 1],
 [2, 1, 1, 0, 1, 0, 1, 1],
 [0, 2, 0, 0, 1, 1, 0, 1],
 [0, 0, 0, 0, 1, 1, 1, 0]]

现在,我们要对矩阵应用一个函数,以便

0
映射到
0
2
映射到
1
1
映射到行号
i
。我们可以使用
np.indices()
来获取行号,以及以下等式:
x/2 * (2*i)**(x%2)
,其中
i
是行号,
x
是元素。最后,我们需要将不存在边
ij
的位置的元素乘以
-1
。这可以向量化如下:

>>> I = np.indices(B.shape)[0] + 1
>>> H = np.multiply(B/2 * (2*I)**(B%2), 2*A-1).astype(int)
>>> H
[[ 1,  1, -1,  1, -1,  1,  0,  0],
 [ 1,  0, -2,  1,  0, -2,  1,  0],
 [ 3,  3,  1,  3,  0,  3,  0,  0],
 [-4,  1, -4,  0, -4,  0,  0,  0],
 [ 5,  0,  0,  5,  0, -5, -5, -5],
 [ 1,  6, -6,  0,  6,  0,  6,  6],
 [ 0,  1,  0,  0,  7, -7,  0,  7],
 [ 0,  0,  0,  0,  8, -8, -8,  0]]

按要求。

我们可以通过使用简单的迭代节点方法来检查这是否正确:

>>> check = np.zeros([8,8])
>>> for i in G.nodes:
        for j in G.nodes:
            if (i, j) in G.edges:
                if (j, i) in G.edges:
                    check[i-1, j-1] = 1
                else:
                    check[i-1, j-1] = i
            else:
                if (j, i) in G.edges:
                    check[i-1, j-1] = -i
                else:
                    check[i-1, j-1] = 0
>>> (check == H).all()
True
© www.soinside.com 2019 - 2024. All rights reserved.