问题描述
我试图找到一种 Pythonic 方法来计算 Python 中的 hermitian 邻接矩阵,但我真的很挣扎。 hermitian Adjacency 矩阵的定义如下图所示:
它的工作原理如下。假设我们有两个名为 i
和 j
的节点。如果 i to j
和 j to i
都有一条有向边,则位置 [ i,j ] 处的相应矩阵值应设置为 1。如果只有一条来自i to j
的有向边,则位置[i,j]处的矩阵元素应设置为+i。如果只有来自 j to i
的有向边,则位置 [i,j] 处的矩阵元素应设置为 -i。所有其他矩阵值都设置为 0。
我想不出一种聪明的方法来制作这个 hermitian Adjacency Matrix,它不涉及一个接一个地遍历我的节点。有什么建议吗?
解决方法
我认为没有内置的解决方案,所以我拼凑了自己的矢量化解决方案:
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]]
然后我们可以将这个矩阵添加到它的转置中,在每个位置都有2
,从i to j
有一个有向边,反之亦然,每个位置都有一个1
其中只有一条边存在,并且在每个不存在边的位置都有一个 0
:
>>> B = A + A.T
>>> B
[[2,2,[2,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,-2,[ 3,3,[-4,-4,[ 5,5,-5,-5],6,-6,6],[ 0,7,-7,7],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,j-1] = -i
else:
check[i-1,j-1] = 0
>>> (check == H).all()
True