Skip to content

Commit 237d345

Browse files
aurorarossiLiozousimonschoelly
authored
fix is_cyclic (#168)
* fix is_cyclic * fix unconnected graphs * fixed graph for test * better performance with dfs * new version * test inferred corrected Co-authored-by: Lionel Zoubritzky <[email protected]> * removed empty line Co-authored-by: Lionel Zoubritzky <[email protected]> * better style in push Co-authored-by: Lionel Zoubritzky <[email protected]> * vector improved Co-authored-by: Lionel Zoubritzky <[email protected]> * update parent Co-authored-by: Lionel Zoubritzky <[email protected]> * Update src/traversals/dfs.jl Co-authored-by: Lionel Zoubritzky <[email protected]> * spaces Co-authored-by: Lionel Zoubritzky <[email protected]> * Update src/traversals/dfs.jl Co-authored-by: Lionel Zoubritzky <[email protected]> * new version thanks to @Liozou * fixed tests and documentation self-loops * self loops undirected * Update src/traversals/dfs.jl Co-authored-by: Simon Schölly <[email protected]> Co-authored-by: Lionel Zoubritzky <[email protected]> Co-authored-by: Simon Schölly <[email protected]>
1 parent 70e5667 commit 237d345

File tree

2 files changed

+51
-5
lines changed

2 files changed

+51
-5
lines changed

src/traversals/dfs.jl

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,29 @@
77
Return `true` if graph `g` contains a cycle.
88
99
### Implementation Notes
10-
Uses DFS.
10+
The algorithm uses a DFS. Self-loops are counted as cycles.
1111
"""
1212
function is_cyclic end
13-
@traitfn is_cyclic(g::::(!IsDirected)) = ne(g) > 0
13+
@enum Vertex_state unvisited visited
14+
@traitfn function is_cyclic(g::AG::(!IsDirected)) where {T, AG<:AbstractGraph{T}}
15+
visited = falses(nv(g))
16+
for v in vertices(g)
17+
visited[v] && continue
18+
visited[v] = true
19+
S = [(v,v)]
20+
while !isempty(S)
21+
parent, w = pop!(S)
22+
for u in neighbors(g, w)
23+
u == w && return true # self-loop
24+
u == parent && continue
25+
visited[u] && return true
26+
visited[u] = true
27+
push!(S, (w, u))
28+
end
29+
end
30+
end
31+
return false
32+
end
1433
# see https://github.com/mauro3/SimpleTraits.jl/issues/47#issuecomment-327880153 for syntax
1534
@traitfn function is_cyclic(g::AG::IsDirected) where {T, AG<:AbstractGraph{T}}
1635
vcolor = zeros(UInt8, nv(g))

test/traversals/dfs.jl

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
@testset "DFS" begin
2-
2+
gnodes_directed=SimpleDiGraph(4)
3+
gnodes_undirected=SimpleGraph(4)
4+
gloop_directed=SimpleDiGraph(1)
5+
add_edge!(gloop_directed, 1, 1);
6+
gloop_undirected=SimpleGraph(1)
7+
add_edge!(gloop_undirected, 1, 1);
38
g5 = SimpleDiGraph(4)
49
add_edge!(g5, 1, 2); add_edge!(g5, 2, 3); add_edge!(g5, 1, 3); add_edge!(g5, 3, 4)
510
gx = cycle_digraph(3)
6-
11+
gcyclic = SimpleGraph([0 1 1 0 0; 1 0 1 0 0; 1 1 0 0 0; 0 0 0 0 1; 0 0 0 1 0])
12+
gtree = SimpleGraph([0 1 1 1 0 0 0; 1 0 0 0 0 0 0; 1 0 0 0 0 0 0; 1 0 0 0 1 1 1; 0 0 0 1 0 0 0; 0 0 0 1 0 0 0; 0 0 0 1 0 0 0])
713
@testset "dfs_tree" begin
814
for g in testdigraphs(g5)
915
z = @inferred(dfs_tree(g, 1))
@@ -26,8 +32,29 @@
2632

2733
@testset "is_cyclic" begin
2834
for g in testgraphs(path_graph(2))
35+
@test !@inferred(is_cyclic(g))
36+
@test !@inferred(is_cyclic(zero(g)))
37+
end
38+
for g in testgraphs(gcyclic)
39+
@test @inferred(is_cyclic(g))
40+
end
41+
for g in testgraphs(gtree)
42+
@test !@inferred(is_cyclic(g))
43+
end
44+
for g in testgraphs(g5)
45+
@test !@inferred(is_cyclic(g))
46+
end
47+
for g in testgraphs(gnodes_directed)
48+
@test !@inferred(is_cyclic(g))
49+
end
50+
for g in testgraphs(gnodes_undirected)
51+
@test !@inferred(is_cyclic(g))
52+
end
53+
for g in testgraphs(gloop_directed)
54+
@test @inferred(is_cyclic(g))
55+
end
56+
for g in testgraphs(gloop_undirected)
2957
@test @inferred(is_cyclic(g))
30-
@test @inferred(!is_cyclic(zero(g)))
3158
end
3259
end
3360

0 commit comments

Comments
 (0)