Python 如何对子/嵌套图进行拓扑排序?
我创建了一个轻量级图形库,它有3个对象(顶点、边、图形)和1个函数(拓扑排序),看起来像:Python 如何对子/嵌套图进行拓扑排序?,python,graph,python-3.x,topological-sort,subgraph,Python,Graph,Python 3.x,Topological Sort,Subgraph,我创建了一个轻量级图形库,它有3个对象(顶点、边、图形)和1个函数(拓扑排序),看起来像: class DAGError(Exception): pass def topo_sort(graph): sorted_list = [] def visit(vertex): nonlocal sorted_list if vertex.idle: raise DAGError('Graph has at least one c
class DAGError(Exception): pass
def topo_sort(graph):
sorted_list = []
def visit(vertex):
nonlocal sorted_list
if vertex.idle:
raise DAGError('Graph has at least one cycle.')
if not vertex.done:
vertex.idle = True
for neighbor in vertex.vertices():
visit(neighbor)
vertex.done = True
vertex.idle = False
sorted_list.insert(0, vertex)
queue = [vertex for vertex in graph.vertices() if not vertex.done]
while queue:
visit(queue.pop(0))
return iter(sorted_list)
如果我有一个扁平的DAG,这个很好用。但我想要实现的是将子图(或嵌套图)添加到我的主图中,正如您在我绘制的这幅插图中所看到的:
这仍然是一个DAG,所以如果我在上面运行我的函数,正常的topo_sort
输出将如下所示:
V0, V3, V1, V5, V4, V8, V7, V12, V11, V13, V14, V2, V6, V10, V9, V15, V17, V16
V0, V1, V8, # vertices of maingraph
V3, V5, V4, V12 # vertices of subgraph_0
V7, V11, V13, # vertices of subgraph_1
V14 # vertex of subgraph_0
V2 # vertex of maingraph
V6, V10, V9, V15 # vertices of subgraph_2
V16, V17 # vertices of maingraph
然而,我更喜欢的输出是当子图所依赖的所有顶点在子图的顶点被处理之前被“处理”时——因此它应该是这样的:
V0, V3, V1, V5, V4, V8, V7, V12, V11, V13, V14, V2, V6, V10, V9, V15, V17, V16
V0, V1, V8, # vertices of maingraph
V3, V5, V4, V12 # vertices of subgraph_0
V7, V11, V13, # vertices of subgraph_1
V14 # vertex of subgraph_0
V2 # vertex of maingraph
V6, V10, V9, V15 # vertices of subgraph_2
V16, V17 # vertices of maingraph
但我在以下方面找不到任何资源:
- 如何“标记”或“存储”图中的顶点作为子图的一部分
- 如何根据顶点的子图依赖关系对顶点进行排序(如上例所示)
- 如何获取或处理作为独立图的子图
编辑:
我发现了这个问题,看起来它解决了一个非常类似的问题(或者完全一样),虽然我不熟悉C++,但是我不明白它是如何工作的,它到底在做什么,但是我把它放在这里,也许有人会发现它有助于回答我的问题。
编辑2:
我也接受伪代码,而不仅仅是python!当然,如果一个现有的python库知道这一点,我对它很感兴趣,但是,我不想使用像
图形工具这样的大型库,这就是我创建自己的库的原因,因此,我更喜欢实现而不是libs。阅读您关于图形工具的陈述,但仍然不确定您是否喜欢使用库来完成某项工作,或者您是否喜欢了解如何自己编写它
也许你看看
General Samples
[http://networkx.github.io/examples.html][1]
DAG Example
[http://networkx.lanl.gov/archive/networkx-1.6/_modules/networkx/algorithms/dag.html][2]
看看它是否能帮你解决问题?对你来说可能有点晚了,但对其他有类似问题的人来说:
如何“标记”或“存储”图中的顶点作为子图的一部分
为什么不给顶点对象一个属性子图
,该属性包含一个整数或一个标记顶点所属子图的字符串?(如果要使用NetworkX,请使用)
这样,您可以在排序算法中检查此子图属性
如何根据顶点的子图依赖关系对顶点进行排序(如上面的>示例)
我不是拓扑排序方面的专家,但如果每个顶点“知道”它所属的子图,这就是我提出的(使用NetworkX,但您可以轻松实现我在您自己的库中使用的片段):下面的代码收集了您描述的所有“依赖项”(需要在当前顶点之前出现的所有顶点)。您可以使用此信息修改topol_sort()函数,使其仅将当前顶点附加到列表中,前提是其依赖项中的所有顶点都不在列表中
import networkx as nx
# define the graph and the subgraphs suitable for NetworkX
G = ...
subgraphs = ...
for subgraph in subgraphs:
# find all vertices that the current subgraph depends on
dependencies = set()
for vertex in subgraph:
anc = nx.ancestors(G, vertex) # anc is the set of all vertices having a path to 'vertex'
dependencies.union(anc)
dependencies -= subgraph.nodes()
# store these dependencies under every vertex of the current subgraph
for vertex in subgraph:
G[vertex].node['depends'] = dependencies
# run modified topological sorting
topo_sort_mod(G)
如何获取或处理作为独立图的子图
我不知道你到底想要什么。可能有帮助(同样,使用NetworkX),尤其是这一部分:
要使用自己的边/节点属性副本创建子图,请使用:nx.Graph(G.subgraph(nbunch))
如果边属性是容器,则可以使用:G.subgraph(nbunch).copy()获得深度副本
我希望这对任何人都有帮助……:) 谢谢@Peter——我已经知道了networkx
,但是我对它进行了重新检查,尽管我读到它似乎没有我想要的功能(或者至少,我不知道)——虽然它有一个子图()
方法,但它只重新引用了一部分图,这不会影响排序算法。无论如何,再次感谢你,但是这些链接都没有帮助….(顺便说一句,我更愿意自己理解和实现)