我正在使用 networkx 将 (u, v, weights) 手动输入到图形中。但是当输入变得更大时,这种手动插入节点和边将成为一项非常烦人的任务并且容易出错。我正在尝试,但还没有弄清楚如何在没有体力劳动的情况下完成这项任务。
样本输入:
my_list = [“s1[0]”、“d1[0, 2]”、“s2[0]”、“d2[1, 3]”、“d3[0, 2]”、“d4[1, 4 ]”、“d5[2, 3]”、“d6[1, 4]”]
手动插入:
在将节点插入图表之前,我需要对它们进行编号,因此“s”或“d”的第一次出现可以与后来的类似字符区分开来,例如 s1,s2,s3,... 和 d1,d2,d3,...我知道它类似于 SSA 表单(编译器),但我找不到对我的案例有帮助的东西。
手动插入 (u, v, weights) 到 DiGraph()
my_graph.add_weighted_edges_from([("s1", "d1", 0), ("d1", "s2", 0), ("d1", "d3", 2), ("s2", "d3", 0), (
"d2", "d4", 1), ("d2", "d5", 3), ("d3", "d5", 2), ("d4", "d6", 1), ("d4", "d6", 4)])
问题:
如何自动将该输入列表(my_list)转换为 DAG(my_graph),避免手动插入?
完整代码: 这是我到目前为止所写的。
import networkx as nx
from networkx.drawing.nx_agraph import write_dot, graphviz_layout
from matplotlib import pyplot as plt
my_graph = nx.DiGraph()
my_graph.add_weighted_edges_from([("s1", "d1", 0), ("d1", "s2", 0), ("d1", "d3", 2), ("s2", "d3", 0), (
"d2", "d4", 1), ("d2", "d5", 3), ("d3", "d5", 2), ("d4", "d6", 1), ("d4", "d6", 4)])
write_dot(my_graph, "graph.dot")
plt.title("draw graph")
pos = graphviz_layout(my_graph, prog='dot')
nx.draw(my_graph, pos, with_labels=True, arrows=True)
plt.show()
plt.clf()
解释:
's' 和 'd' 是一些分别需要 1 个或 2 个寄存器来执行操作的指令。
在上面的示例中,我们有 2 个 's' 操作和 6 个 'd' 操作,并且有五个寄存器 [0,1,2,3,4]。
每个操作都会执行一些计算并将结果存储在相关的寄存器中。
从输入中我们可以看到 d1 使用寄存器 0 和 2,因此在这两个寄存器都空闲之前它无法操作。因此,d1 依赖于 s1,因为 s1 位于 d1 之前并且正在使用寄存器 0。一旦 s1 完成,d1 就可以操作,因为寄存器 2 已经空闲。
例如,我们用 1 初始化所有寄存器。s1 将其输入加倍,而 d1 将两个输入相加并将结果存储在它的第二个寄存器中:
所以在 s1[0] reg-0 * 2 -> 1 * 2 => reg-0 = 2 之后
在 d1[0, 2] reg-0 + reg-2 -> 2 + 1 => reg-0 = 2 和 reg-2 = 3 之后
更新 1:该图将是基于某些资源 [0...4] 的依赖图,每个节点将需要 1(对于“s”)或 2(对于“d”)这些资源。
更新 2:两个问题引起了混淆,所以我将它们分开。现在我已经更改了我的输入列表,并且只有一个任务可以将该列表转换为 DAG。我还包括一个解释部分。
PS:如果您还没有它,您可能需要 pip install graphviz 。