在典型的设施位置问题中,我有三个设施(Fi,i = 1,2,3)和六个节点(Dj,j = 1,2,3,4,5,6)。我想绘制所有Fi和Dj,然后根据分配矩阵Xij将节点Dj连接到设施Fi。
矩阵Xij给出为:
Xij = np.array([[1,0,0,1,1,1],
[0,1,1,0,0,0],
[0,0,0,0,0,0]])
Xij的第一行显示节点Dj(j = 0,3,4,5)被分配给设施Fi(i = 0)。第二行示出了将节点Dj(j = 1,2)分配给第二设施Fi(i = 2)。第三行显示没有节点分配给设施Fi(i = 2)。
我试图在matplotlib中执行此操作,以在指定位置绘制节点,但不知道如何连接它们。
fx = np.array([30, 30, 30])
fy = np.array([10, 20, 30])
f = np.vstack((fx, fy))
px = np.array([50, 50, 50, 50, 50])
py = np.array([10, 15, 20, 25, 30])
p = np.vstack((px, py))
plt.scatter(fx,fy, marker='D', s=100)
plt.scatter(px,py, marker='o', s=100)
然后我阅读了有关Networkx库的信息,并尝试将它们绘制为:
G1 = nx.Graph()
G2 = nx.Graph()
Fi = {0: (10,10),
1: (10,20),
2: (10,30)}
Dj ={0: (20,5),
1: (20,10),
2: (20,15),
3: (20,20),
4: (20,25),
5: (20,30)}
nx.draw_networkx(G1, Fi, node_color= 'gray', node_size=500)
nx.draw_networkx(G2, Dj, node_color= 'gray', node_size=300)
但是,无法通过任何工具弄清楚如何轻松地连接这些节点吗? 给定的问题只是更大网络的简单版本。
答案 0 :(得分:2)
一种方法是将两方分配矩阵转换为完整的邻接矩阵,然后使用该矩阵填充nx图。
Xij = np.array([[1,0,0,1,1,1],
[0,1,1,0,0,0],
[0,0,0,0,0,0]])
A = Xij
At = A.T
Z_top_left = np.zeros((A.shape[0], At.shape[1]))
Z_bottom_right = np.zeros((At.shape[0], A.shape[1]))
G = nx.from_numpy_matrix(np.vstack([np.hstack([Z_top_left,A]) , np.hstack([At, Z_bottom_right])]))
然后,您可以绘制G图形(已使用此处其他位置列出的方法列出了位置),它将包含您要查找的边。
要从分配矩阵X中获取数据,您需要在X的右上角和左下角组成一个由X以及X的转置组成的数组,并用零填充其余部分,因为从Facility到Facility没有边或“节点到节点”(以使用您的条款)。这是二部图。这就是上面的hstack和vstack调用所做的。
或者,您可以遍历分配数组,将i和j用作行/列迭代器,然后执行以下操作:
G.add_edge(i,j)
这将创建节点,并将其与边缘连接。然后,nx.draw系列命令之一将以图形方式对其进行布局。我还注意到,将来某个时候,即将有一个bipartite_layout
选项即将出现在networkx上。
答案 1 :(得分:1)
您需要使用pos
来在正确的位置进行绘制,对于边缘,应在矩阵上进行迭代:
import numpy as np
import networkx as nx
from matplotlib import pyplot as plt
Xij = np.array([[1,0,0,1,1,1],
[0,1,1,0,0,0],
[0,0,0,0,0,0]])
Fi = {'F0': [10,10],
'F1': [10,20],
'F2': [10,30]}
Dj ={'D0': [20,5],
'D1': [20,10],
'D2': [20,15],
'D3': [20,20],
'D4': [20,25],
'D5': [20,30]}
newD = dict(Dj.items()) #Build a dictionary with all the items, for position
newD.update(Fi.items())
G1 = nx.Graph()
G1.add_nodes_from(newD)
for i in range(Xij.shape[0]): # Add an edge according to the matrix
for j in range(Xij.shape[1]):
if Xij[i,j] == 1:
G1.add_edge('F'+str(i), 'D'+str(j))
nx.draw(G1, with_labels=True, pos = newD) #Draw, with locations and edges
添加了与代码内联的说明。
编辑: 对于颜色,您需要为每个节点定义颜色:
colors = ['r' if x[0] == 'D' else 'b' for x in list(G1.nodes)]
nx.draw(G1, with_labels=True,node_color=colors, pos = newD) #Draw, with locations and edges, and colors