NetworkX:邻接矩阵与图不对应
NetworkX: adjacency matrix does not correspond to graph
假设我有两个选项来生成网络的 邻接矩阵 :nx.adjacency_matrix()
和我自己的代码。我想测试我的代码的正确性并提出了一些奇怪的不等式。
示例:3x3
格网。
import networkx as nx
N=3
G=nx.grid_2d_graph(N,N)
pos = dict( (n, n) for n in G.nodes() )
labels = dict( ((i,j), i + (N-1-j) * N ) for i, j in G.nodes() )
nx.relabel_nodes(G,labels,False)
inds=labels.keys()
vals=labels.values()
inds.sort()
vals.sort()
pos2=dict(zip(vals,inds))
plt.figure()
nx.draw_networkx(G, pos=pos2, with_labels=True, node_size = 200)
这是可视化:
具有nx.adjacency_matrix()
的邻接矩阵:
B=nx.adjacency_matrix(G)
B1=B.todense()
[[0 0 0 0 0 1 0 0 1]
[0 0 0 1 0 1 0 0 0]
[0 0 0 1 0 1 0 1 1]
[0 1 1 0 0 0 1 0 0]
[0 0 0 0 0 0 0 1 1]
[1 1 1 0 0 0 0 0 0]
[0 0 0 1 0 0 0 1 0]
[0 0 1 0 1 0 1 0 0]
[1 0 1 0 1 0 0 0 0]]
根据它,节点 0
(整个第一行和整个第一列)连接到节点 5
和 8
。但是如果你看上面的图片这是错误的,因为它连接到节点 1
和 3
.
现在我的代码(运行 在与上面相同的脚本中):
import numpy
import math
P=3
def nodes_connected(i, j):
try:
if i in G.neighbors(j):
return 1
except nx.NetworkXError:
return False
A=numpy.zeros((P*P,P*P))
for i in range(0,P*P,1):
for j in range(0,P*P,1):
if i not in G.nodes():
A[i][:]=0
A[:][i]=0
elif i in G.nodes():
A[i][j]=nodes_connected(i,j)
A[j][i]=A[i][j]
for i in range(0,P*P,1):
for j in range(0,P*P,1):
if math.isnan(A[i][j]):
A[i][j]=0
print(A)
这产生:
[[ 0. 1. 0. 1. 0. 0. 0. 0. 0.]
[ 1. 0. 1. 0. 1. 0. 0. 0. 0.]
[ 0. 1. 0. 0. 0. 1. 0. 0. 0.]
[ 1. 0. 0. 0. 1. 0. 1. 0. 0.]
[ 0. 1. 0. 1. 0. 1. 0. 1. 0.]
[ 0. 0. 1. 0. 1. 0. 0. 0. 1.]
[ 0. 0. 0. 1. 0. 0. 0. 1. 0.]
[ 0. 0. 0. 0. 1. 0. 1. 0. 1.]
[ 0. 0. 0. 0. 0. 1. 0. 1. 0.]]
表示节点 0
连接到节点 1
和 3
。 为什么会存在这样的差异?这种情况有什么问题?
Networkx 不知道您希望节点的顺序。
调用方法如下:adjacency_matrix(G, nodelist=None, weight='weight')
。
如果您想要特定的顺序,请将节点列表设置为该顺序的列表。
所以例如 adjacency_matrix(G, nodelist=range(9))
应该得到你想要的。
这是为什么?好吧,因为一个图几乎可以有任何东西作为它的节点(任何可散列的东西)。您的节点之一可能是 "parrot"
或 (1,2)
。因此它将节点作为键存储在字典中,而不是假设它是从 0 开始的非负整数。字典键 have an arbitrary order.
一个更通用的解决方案,如果您的节点有一些逻辑顺序,就像您使用 G=nx.grid_2d_graph(3,3)
生成图形的情况一样(returns 从 (0,0) 到 (2, 2), 或者在你的例子中是使用:
adjacency_matrix(G,nodelist=sorted(G.nodes()))
这对返回的 G 节点列表进行排序并将其作为节点列表传递
假设我有两个选项来生成网络的 邻接矩阵 :nx.adjacency_matrix()
和我自己的代码。我想测试我的代码的正确性并提出了一些奇怪的不等式。
示例:3x3
格网。
import networkx as nx
N=3
G=nx.grid_2d_graph(N,N)
pos = dict( (n, n) for n in G.nodes() )
labels = dict( ((i,j), i + (N-1-j) * N ) for i, j in G.nodes() )
nx.relabel_nodes(G,labels,False)
inds=labels.keys()
vals=labels.values()
inds.sort()
vals.sort()
pos2=dict(zip(vals,inds))
plt.figure()
nx.draw_networkx(G, pos=pos2, with_labels=True, node_size = 200)
这是可视化:
具有nx.adjacency_matrix()
的邻接矩阵:
B=nx.adjacency_matrix(G)
B1=B.todense()
[[0 0 0 0 0 1 0 0 1]
[0 0 0 1 0 1 0 0 0]
[0 0 0 1 0 1 0 1 1]
[0 1 1 0 0 0 1 0 0]
[0 0 0 0 0 0 0 1 1]
[1 1 1 0 0 0 0 0 0]
[0 0 0 1 0 0 0 1 0]
[0 0 1 0 1 0 1 0 0]
[1 0 1 0 1 0 0 0 0]]
根据它,节点 0
(整个第一行和整个第一列)连接到节点 5
和 8
。但是如果你看上面的图片这是错误的,因为它连接到节点 1
和 3
.
现在我的代码(运行 在与上面相同的脚本中):
import numpy
import math
P=3
def nodes_connected(i, j):
try:
if i in G.neighbors(j):
return 1
except nx.NetworkXError:
return False
A=numpy.zeros((P*P,P*P))
for i in range(0,P*P,1):
for j in range(0,P*P,1):
if i not in G.nodes():
A[i][:]=0
A[:][i]=0
elif i in G.nodes():
A[i][j]=nodes_connected(i,j)
A[j][i]=A[i][j]
for i in range(0,P*P,1):
for j in range(0,P*P,1):
if math.isnan(A[i][j]):
A[i][j]=0
print(A)
这产生:
[[ 0. 1. 0. 1. 0. 0. 0. 0. 0.]
[ 1. 0. 1. 0. 1. 0. 0. 0. 0.]
[ 0. 1. 0. 0. 0. 1. 0. 0. 0.]
[ 1. 0. 0. 0. 1. 0. 1. 0. 0.]
[ 0. 1. 0. 1. 0. 1. 0. 1. 0.]
[ 0. 0. 1. 0. 1. 0. 0. 0. 1.]
[ 0. 0. 0. 1. 0. 0. 0. 1. 0.]
[ 0. 0. 0. 0. 1. 0. 1. 0. 1.]
[ 0. 0. 0. 0. 0. 1. 0. 1. 0.]]
表示节点 0
连接到节点 1
和 3
。 为什么会存在这样的差异?这种情况有什么问题?
Networkx 不知道您希望节点的顺序。
调用方法如下:adjacency_matrix(G, nodelist=None, weight='weight')
。
如果您想要特定的顺序,请将节点列表设置为该顺序的列表。
所以例如 adjacency_matrix(G, nodelist=range(9))
应该得到你想要的。
这是为什么?好吧,因为一个图几乎可以有任何东西作为它的节点(任何可散列的东西)。您的节点之一可能是 "parrot"
或 (1,2)
。因此它将节点作为键存储在字典中,而不是假设它是从 0 开始的非负整数。字典键 have an arbitrary order.
一个更通用的解决方案,如果您的节点有一些逻辑顺序,就像您使用 G=nx.grid_2d_graph(3,3)
生成图形的情况一样(returns 从 (0,0) 到 (2, 2), 或者在你的例子中是使用:
adjacency_matrix(G,nodelist=sorted(G.nodes()))
这对返回的 G 节点列表进行排序并将其作为节点列表传递