Skip to content

Commit 3171d20

Browse files
committed
Update traversal.jl
only visit each node once
1 parent 3e38ddb commit 3171d20

1 file changed

Lines changed: 42 additions & 13 deletions

File tree

src/dependencies/traversal.jl

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,40 +39,55 @@ function traverse_dependency_graph(
3939
visit_hard_dep=true
4040
)
4141
var = []
42+
node_visited = Set()
4243
for (p, root) in graph.roots
43-
traverse_dependency_graph!(root, f, var; visit_hard_dep=visit_hard_dep)
44+
traverse_dependency_graph!(root, f, var; visit_hard_dep=visit_hard_dep, node_visited=node_visited)
4445
end
4546

4647
return var
4748
end
4849

4950

50-
function traverse_dependency_graph!(f::Function, graph::DependencyGraph; visit_hard_dep=true)
51+
function traverse_dependency_graph!(f::Function, graph::DependencyGraph; visit_hard_dep=true, node_visited::Set{AbstractDependencyNode}=Set())
5152
for (p, root) in graph.roots
52-
traverse_dependency_graph!(f, root, visit_hard_dep=visit_hard_dep)
53+
traverse_dependency_graph!(f, root, visit_hard_dep=visit_hard_dep, node_visited=node_visited)
5354
end
5455
end
5556

56-
function traverse_dependency_graph!(f::Function, node::SoftDependencyNode; visit_hard_dep=true)
57+
function traverse_dependency_graph!(f::Function, node::SoftDependencyNode; visit_hard_dep=true, node_visited::Set{AbstractDependencyNode}=Set())
58+
if node in node_visited
59+
return nothing
60+
end
61+
5762
f(node)
63+
64+
push!(node_visited, node)
65+
5866
# Traverse the hard dependencies of the SoftDependencyNode if any:
5967
if visit_hard_dep && node isa SoftDependencyNode
6068
# draw a branching guide if there's more soft dependencies after this one:
6169
for child in node.hard_dependency
62-
traverse_dependency_graph!(f, child)
70+
traverse_dependency_graph!(f, child; visit_hard_dep=visit_hard_dep, node_visited=node_visited)
6371
end
6472
end
6573

6674
for child in node.children
67-
traverse_dependency_graph!(f, child; visit_hard_dep=visit_hard_dep)
75+
traverse_dependency_graph!(f, child; visit_hard_dep=visit_hard_dep, node_visited=node_visited)
6876
end
6977
end
7078

71-
function traverse_dependency_graph!(f::Function, node::HardDependencyNode; visit_hard_dep=true)
79+
function traverse_dependency_graph!(f::Function, node::HardDependencyNode; visit_hard_dep=true, node_visited::Set{AbstractDependencyNode}=Set())
80+
if node in node_visited
81+
return nothing
82+
end
83+
7284
f(node)
85+
86+
push!(node_visited, node)
87+
7388
# Traverse all hard dependencies:
7489
for child in node.children
75-
traverse_dependency_graph!(f, child)
90+
traverse_dependency_graph!(f, child; visit_hard_dep=visit_hard_dep, node_visited=node_visited)
7691
end
7792
end
7893

@@ -89,20 +104,27 @@ function traverse_dependency_graph!(
89104
node::SoftDependencyNode,
90105
f::Function,
91106
var::Vector;
92-
visit_hard_dep=true
107+
visit_hard_dep=true,
108+
node_visited::Set{AbstractDependencyNode}=Set()
93109
)
110+
if node in node_visited
111+
return nothing
112+
end
113+
94114
push!(var, node.process => f(node))
95115

116+
push!(node_visited, node)
117+
96118
# Traverse the hard dependencies of the SoftDependencyNode if any:
97119
if visit_hard_dep && node isa SoftDependencyNode
98120
# draw a branching guide if there's more soft dependencies after this one:
99121
for child in node.hard_dependency
100-
traverse_dependency_graph!(child, f, var)
122+
traverse_dependency_graph!(child, f, var; visit_hard_dep=visit_hard_dep, node_visited=node_visited)
101123
end
102124
end
103125

104126
for child in node.children
105-
traverse_dependency_graph!(child, f, var; visit_hard_dep=visit_hard_dep)
127+
traverse_dependency_graph!(child, f, var; visit_hard_dep=visit_hard_dep, node_visited=node_visited)
106128
end
107129
end
108130

@@ -117,11 +139,18 @@ function traverse_dependency_graph!(
117139
node::HardDependencyNode,
118140
f::Function,
119141
var::Vector;
120-
visit_hard_dep=true # Just to be compatible with a call shared with SoftDependencyNode method
142+
visit_hard_dep=true, # Just to be compatible with a call shared with SoftDependencyNode method
143+
node_visited::Set{AbstractDependencyNode}=Set()
121144
)
145+
if node in node_visited
146+
return nothing
147+
end
148+
122149
push!(var, node.process => f(node))
123150

151+
push!(node_visited, node)
152+
124153
for child in node.children
125-
traverse_dependency_graph!(child, f, var)
154+
traverse_dependency_graph!(child, f, var; visit_hard_dep=visit_hard_dep, node_visited=node_visited)
126155
end
127156
end

0 commit comments

Comments
 (0)