在 NetworkX 中构建多有向图

Building a MultiDiGraph in NetworkX

我正在尝试在 NetworkX 中创建一个 MultiDiGraph,它可以通过大门、车站、连接点或停车位的其他条目自动调整。

我的问题是创建了节点和边,但我总是收到此运行时警告,我不知道如何修复它以及这两个预期的双打是什么。

MultiDiGraph with 10 nodes and 20 edges
RuntimeWarning: Error: node g1, position (1, 30), expected two doubles
Error: node ni1, position (1, 20), expected two doubles
Error: node bd1, position (3, 30), expected two doubles
Error: node ni2, position (2, 20), expected two doubles
Error: node ni5, position (5, 20), expected two doubles
Error: node p1, position (1, 10), expected two doubles
Error: node p2, position (2, 10), expected two doubles
Error: node ni4, position (4, 20), expected two doubles
Error: node ni3, position (3, 20), expected two doubles
Error: node g2, position (2, 30), expected two doubles

另一个问题是我添加 'bd' 节点时的 '-2',因为它是手动插入的,我希望用 '-i' 来完成它,但它只会再创建一个 'bd' 这个例子的节点比需要的多。

也许您也对如何在创建的点之间建立自动连接有了初步的想法。 我愿意接受任何关于如何解决这一点的建议。非常感谢!

G = nx.MultiDiGraph()

Gates = 2
Depots = 1
ConnectingNodes = 5
Parking = 2

for i in range(1, Gates+1, 1):
    for j in range(Gates+1, Gates+Depots+1, 1):
        for m in range(1, ConnectingNodes+1, 1):
            for n in range(1, Parking+1, 1):

                G.add_node('g'+str(i), pos=(i, 30), color='turquoise', type='gates')
                G.add_node('bd'+str(j-2), pos=(j, 30), color='green', type='depots') #fix -2
                G.add_node('ni'+str(m), pos=(m, 20), color='blue')
                G.add_node('p'+str(n), pos=(n, 10), color='red', type='parking')


G.add_edge('g1', 'ni1')
G.add_edge('ni1', 'g1')
G.add_edge('ni1', 'ni2')
G.add_edge('ni2', 'ni1')
G.add_edge('bd1', 'ni2')
G.add_edge('ni2', 'bd1')
G.add_edge('ni2', 'ni3')
G.add_edge('ni3', 'ni2')
G.add_edge('ni5', 'ni4')
G.add_edge('ni4', 'ni5')
G.add_edge('p1', 'ni5')
G.add_edge('ni5', 'p1')
G.add_edge('ni4', 'p2')
G.add_edge('p2', 'ni4')
G.add_edge('g2', 'ni3')
G.add_edge('ni3', 'g2')
G.add_edge('ni1', 'ni5')
G.add_edge('ni5', 'ni1')
G.add_edge('ni3', 'ni4')
G.add_edge('ni4', 'ni3')
print(G)

K = nx.nx_agraph.to_agraph(G)
K.layout('neato')
K.draw('Test_basic.png')
plt.show()

你的问题没有说清楚网络是否需要 每个门包括一个仓库(以及 5 个连接节点和 每个门 2 个停车场),或每个门一个。我想不通 它从问题中的代码中提取出来,因为嵌套 for 循环似乎表明每个门一个仓库,但由此产生的 graph 刚刚创建了每个 gate、depot 等很多次。

我假设你真的想要 1 个 depot,嵌套的 for 循环是 只是一个错误。我在最后更改了逻辑以使用标准 networkx 绘图,而不是 graphviz。这只是一个选择, 但我认为进行这种简化是有意义的;它也是 处理有关双打的警告消息,因为 nx.draw 在整数位置和浮点数之间轻松转换(或 双打)。

那么如何以某种自动方式添加边呢?好吧,看来 所有边都是双向的,所以你可以“节省”很多 通过首先列出对的代码,然后在两者中创建边 方向。

可能还有一些可以做的,但我 没有关于基本规则的足够信息 图。似乎每个节点都只连接到一个 一个连接节点,所有连接节点都连接到它们的 数字邻居。如果是这样的话,那就是 编写执行此操作的例程相当容易。

import networkx as nx
import matplotlib.pyplot as plt

Gates = 2
Depots = 1
ConnectingNodes = 5
Parking = 2

G = nx.MultiDiGraph()
for i in range(1, Gates+1, 1):
    G.add_node('g'+str(i), pos=(i, 40), color='turquoise', type='gates')
for j in range(1, Depots+1, 1):
    G.add_node('bd'+str(j), pos=(j+0.5, 30), color='green', type='depots')
for m in range(1, ConnectingNodes+1, 1):
    G.add_node('ni'+str(m), pos=(m, 20), color='blue')
for n in range(1, Parking+1, 1):
    G.add_node('p'+str(n), pos=(n, 10), color='red', type='parking')

G.add_edge('g1', 'ni1')
G.add_edge('ni1', 'g1')
G.add_edge('ni1', 'ni2')
G.add_edge('ni2', 'ni1')
G.add_edge('bd1', 'ni2')
G.add_edge('ni2', 'bd1')
G.add_edge('ni2', 'ni3')
G.add_edge('ni3', 'ni2')
G.add_edge('ni5', 'ni4')
G.add_edge('ni4', 'ni5')
G.add_edge('p1', 'ni5')
G.add_edge('ni5', 'p1')
G.add_edge('ni4', 'p2')
G.add_edge('p2', 'ni4')
G.add_edge('g2', 'ni3')
G.add_edge('ni3', 'g2')
G.add_edge('ni1', 'ni5')
G.add_edge('ni5', 'ni1')
G.add_edge('ni3', 'ni4')
G.add_edge('ni4', 'ni3')

# Extract positions and colors from nodes for drawing
pos = {node: G.nodes[node]['pos'] for node in G}
colors = [G.nodes[node]['color'] for node in G]
nx.draw(G, pos, node_size=400, node_color=colors, with_labels=True)
plt.show()

生成的图形如下所示:

谢谢大家的评论!它帮助我改进了我的代码。

这是我的更新版本:

Gates = 2
Depots = 2
ConnectingNodes = 6
Parking = 2

G = nx.MultiDiGraph()
for i in range(1, Gates+1, 1):
    G.add_node('g' + str(i), pos=(i, 30), color='turquoise', type='gates')
for j in range(1, Depots+1, 1):
    G.add_node('bd' + str(j), pos=(j+Gates, 30), color='green', type='depots')
for m in range(1, ConnectingNodes+1, 1):
    G.add_node('ni' + str(m), pos=(m, 20), color='blue')
for n in range(1, Parking+1, 1):
    G.add_node('p' + str(n), pos=(n+Gates+Depots, 10), color='red', type='parking')

for i in range(1, Gates+1, 1):
    G.add_edge('ni' + str(i), 'g' + str(i))
    G.add_edge('g' + str(i), 'ni' + str(i))
for j in range(1, Depots+1, 1):
    G.add_edge('ni' + str(j + Gates), 'bd' + str(j))
    G.add_edge('bd' + str(j), 'ni' + str(j + Gates))
for z in range(1, Parkping+1, 1):
    G.add_edge('ni' + str(z + Gates + Depots), 'p' + str(z))
    G.add_edge('p' + str(z), 'ni' + str(z + Gates + Depots))
for r in range(1, ConnectingNodes, 1):
    G.add_edge('ni' + str(r), 'ni' + str(r+1))
    G.add_edge('ni' + str(r+1), 'ni' + str(r))

print(G)

for all in G.edges():
    weight = 200


#positions and colors from nodes for drawing
pos = {node: G.nodes[node]['pos'] for node in G}
colors = [G.nodes[node]['color'] for node in G]
nx.draw(G, pos, node_size=400, node_color=colors, with_labels=True)
plt.show()

重要的是Connecting Nodes的数量大于Gates+Depots+Parking Positions。我在读取输入时使用 'while not' 条件在我的扩展代码中修复了此问题。

门或类似东西所需的仓库数量之间也没有条件。它应该是一个灵活的结构,可以根据客户的需要进行调整。

也许有更简单的方法来创建边缘,但这非常有效。

现在我可以继续我的项目并创建不同大小的实例了,谢谢!