【发布时间】:2017-09-27 13:17:51
【问题描述】:
卡恩在62向topologically sort任意DAG(有向无环图)提出算法,伪代码抄自维基百科:
L ← Empty list that will contain the sorted elements
S ← Set of all nodes with no incoming edges
while S is non-empty do
remove a node n from S
add n to tail of L
for each node m with an edge e from n to m do
remove edge e from the graph # This is a DESTRUCTIVE step!
if m has no other incoming edges then
insert m into S if graph has edges then
return error (graph has at least one cycle) else
return L (a topologically sorted order)
我需要使用 IPython3 来实现它,并使用以下 DAG 实现:
class Node(object):
def __init__(self, name, parents):
assert isinstance(name, str)
assert all(isinstance(_, RandomVariable) for _ in parents)
self.name, self.parents = name, parents
其中name 是节点的标签,parents 存储其所有父节点。那么DAG类实现为:
class DAG(object):
def __init__(self, *nodes):
assert all(isinstance(_, Node) for _ in nodes)
self.nodes = nodes
(DAG 实现是固定的,不会改进。) 然后我需要将 Kahn 算法实现为函数 top_order,它接受 DAG 实例并返回类似 (node_1, node_2, ..., node_n) 的排序.主要问题是,该算法具有破坏性,因为它的一个步骤是remove edge e from the graph(第 5 行),它将删除m.parents 的一个成员。但是,我必须保持 DAG 实例完好无损。
目前我能想到的一种方法是创建一个深副本的 DAG 实例(即使是浅副本也无法完成这项工作,因为算法仍然会通过以下方式破坏原始实例引用),并对这个副本执行破坏性算法,然后得到这个副本的节点名称的正确排序(假设节点之间没有命名冲突),然后使用这个名称排序来推断节点的正确排序原始实例,大致如下:
def top_order(network):
'''takes in a DAG, prints and returns a topological ordering.'''
assert type(network) == DAG
temp = copy.deepcopy(network) # to leave the original instance intact
ordering_name = []
roots = [node for node in temp.nodes if not node.parents]
while roots:
n_node = roots[0]
del roots[0]
ordering_name.append(n_node.name)
for m_node in temp.nodes:
if n_node in m_node.parents:
temp_list = list(m_node.parents)
temp_list.remove(n_node)
m_node.parents = tuple(temp_list)
if not m_node.parents:
roots.append(m_node)
print(ordering_name) # print ordering by name
# gets ordering of nodes of the original instance
ordering = []
for name in ordering_name:
for node in network.nodes:
if node.name == name:
ordering.append(node)
return tuple(ordering)
两个问题:第一,当network很大时,深拷贝会消耗资源;其次,我想改进我的嵌套for 循环,它可以获取原始实例的顺序。 (第二次我想到了类似sorted 方法之类的东西。)
有什么建议吗?
【问题讨论】:
标签: python-3.x class graph immutability deep-copy