提交 cc8b5e2d authored 作者: Ian Goodfellow's avatar Ian Goodfellow

Big speedup! Got rid of set of visited nodes altogether

上级 13d85861
...@@ -157,23 +157,40 @@ def _contains_cycle(fgraph, orderings): ...@@ -157,23 +157,40 @@ def _contains_cycle(fgraph, orderings):
node_to_children.setdefault(r, []).append(node) node_to_children.setdefault(r, []).append(node)
lifo_queue.extend(parents) lifo_queue.extend(parents)
else: else:
fifo_queue.append(node) visitable.append(node)
node_to_parents[node] = parents parent_counts[node] = len(parents)
rset = set() # at this point,
visit_count = 0 # node_to_parents.keys() == fgraph.apply_nodes + fgraph.variables
while fifo_queue:
node = fifo_queue.popleft()
if node not in rset:
visit_count += 1 # Now we actually check for cycles
rset.add(node) # As long as there are nodes that can be visited while respecting
for client in node_to_children.get(node, []): # the topology, we keep visiting nodes
node_to_parents[client] = [a for a in node_to_parents[client] if a is not node] # If we run out of visitable nodes and we haven't visited all nodes,
if not node_to_parents[client]: # then there was a cycle. It blocked the traversal because some
fifo_queue.append(client) # node couldn't be visited until one of its descendants had been
# visited too.
# This is a standard cycle detection algorithm.
return visit_count != len(node_to_parents)
visited = 0
while visitable:
# Since each node is inserted into the visitable queue exactly
# once, it comes out of the queue exactly once
# That means we can decrement its children's unvisited parent count
# and increment the visited node count without double-counting
node = visitable.popleft()
visited += 1
for client in node_to_children.get(node, []):
parent_counts[client] -= 1
# If all of a node's parents have been visited,
# it may now be visited too
if not parent_counts[client]:
visitable.append(client)
return visited != len(parent_counts)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论