我在最近的一个项目中遇到了类似的问题,其中工作依赖于其他工作。我发现保证以正确顺序处理它们的最可靠方法是使用 DiGraph 方法topological_sort。
下面是一个最小的例子,从有向图的创建开始:
import networkx as nx
import matplotlib.pyplot as plt
from networkx.drawing.nx_pydot import graphviz_layout
# this function is optional
# just moves the node labels on the plot so they don't overlap the lines
def nudge(pos, x_shift, y_shift):
return {n:(x + x_shift, y + y_shift) for n,(x,y) in pos.items()}
# start with a directed graph
dag = nx.DiGraph()
dag.add_edges_from(
[
('root', 'a'),
('a', 'b'),
('a', 'c'),
('b', 'd'),
('d', 'e'),
('d', 'f')
]
)
# plot the graph
pos = graphviz_layout(dag, prog="dot")
pos_labels = nudge(pos, -5, 15)
fig = plt.figure(figsize=(8, 6))
ax = plt.subplot(1, 1, 1)
plt.margins(0.1)
nx.draw(
dag,
pos=pos,
ax=ax,
with_labels=False,
arrows=True,
node_size=100,
arrowsize=20
)
labels = nx.draw_networkx_labels(
dag,
pos=pos_labels,
ax=ax,
font_size=18,
font_weight='bold',
font_color='orange',
verticalalignment='bottom'
)
图形的输出图如下:
首先要做的最好的事情可能是验证图是有向无环图:
nx.is_directed_acyclic_graph(dag)
这将返回 True 或 False。接下来,我们可以使用topological_sort按依赖顺序检索节点:
list(nx.algorithms.topological_sort(dag))
这会返回:
['root', 'a', 'b', 'c', 'd', 'e', 'f']
如果您希望拥有边对而不仅仅是节点:
list(nx.topological_sort(nx.line_graph(dag)))
返回:
[('root', 'a'), ('a', 'b'), ('a', 'c'), ('b', 'd'), ('d', 'e'), ('d', 'f')]
最后,如果作业需要倒序,您可以使用reverse:
dag_reverse = dag.reverse()
重新运行命令::
list(nx.algorithms.topological_sort(dag_reverse))
给予:
['c', 'e', 'f', 'd', 'b', 'a', 'root']
和:
list(nx.topological_sort(nx.line_graph(dag_reverse)))
给予:
[('c', 'a'), ('e', 'd'), ('f', 'd'), ('d', 'b'), ('b', 'a'), ('a', 'root')]