使用分配矩阵连接节点

时间:2018-11-26 13:06:44

标签: python matplotlib plotly networkx

在典型的设施位置问题中,我有三个设施(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)

但是,无法通过任何工具弄清楚如何轻松地连接这些节点吗? 给定的问题只是更大网络的简单版本。

2 个答案:

答案 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图形(已使用此处其他位置列出的方法列出了位置),它将包含您要查找的边。

bipartite graph

要从分配矩阵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

结果:
enter image description here

添加了与代码内联的说明。

编辑: 对于颜色,您需要为每个节点定义颜色:

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