Skip to content

Commit

Permalink
Eulerian paths
Browse files Browse the repository at this point in the history
  • Loading branch information
JoeyT1994 committed Jun 10, 2024
1 parent 9cb7190 commit 6668887
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib/GraphsExtensions/src/GraphsExtensions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ include("neighbors.jl")
include("shortestpaths.jl")
include("symrcm.jl")
include("partitioning.jl")
include("traversal.jl")
include("trees_and_forests.jl")
include("simplegraph.jl")
end
42 changes: 42 additions & 0 deletions src/lib/GraphsExtensions/src/traversal.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

#Given a graph, traverse it from start vertex to end vertex, covering each edge exactly once.
#Complexity is O(length(edges(g)))
function eulerian_path(g::AbstractGraph, start_vertex, end_vertex)
#Conditions on g for the required path to exist
if start_vertex != end_vertex
@assert isodd(degree(g, start_vertex) % 2)
@assert isodd(degree(g, end_vertex) % 2)
@assert all(
x -> iseven(x), degrees(g, setdiff(vertices(g), [start_vertex, end_vertex]))
)
else
@assert all(x -> iseven(x), degrees(g, vertices(g)))
end

path = []
stack = []
current_vertex = end_vertex
g_modified = copy(g)
while !isempty(stack) || !iszero(degree(g_modified, current_vertex))
if iszero(degree(g_modified, current_vertex))
append!(path, current_vertex)
last_vertex = pop!(stack)
current_vertex = last_vertex
else
append!(stack, current_vertex)
vn = first(neighbors(g_modified, current_vertex))
rem_edge!(g_modified, edgetype(g_modified)(current_vertex, vn))
current_vertex = vn
end
end

append!(path, current_vertex)

return edgetype(g_modified)[
edgetype(g_modified)(path[i], path[i + 1]) for i in 1:(length(path) - 1)
]
end

function eulerian_cycle(g::AbstractGraph, start_vertex)
return eulerian_path(g, start_vertex, start_vertex)
end
14 changes: 14 additions & 0 deletions src/lib/GraphsExtensions/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ using NamedGraphs.GraphsExtensions:
directed_graph_type,
disjoint_union,
distance_to_leaves,
_eulerian_cycle,
eulerian_cycle,
eulerian_path,
has_edges,
has_leaf_neighbor,
has_vertices,
Expand All @@ -68,6 +71,7 @@ using NamedGraphs.GraphsExtensions:
is_rooted,
is_self_loop,
leaf_vertices,
make_all_degrees_even,
minimum_distance_to_leaves,
next_nearest_neighbors,
non_leaf_edges,
Expand Down Expand Up @@ -588,5 +592,15 @@ using Test: @test, @test_broken, @test_throws, @testset
@test only(vertices_at_distance(g, 1, L - 1)) == L
@test only(next_nearest_neighbors(g, 1)) == 3
@test issetequal(vertices_at_distance(g, 5, 3), [2, 8])

#Eulerian paths
g = path_graph(L)
path = eulerian_path(g, 1, L)
@test path == [edgetype(g)(i, i + 1) for i in 1:(L - 1)]

g = add_edge(g, L => 1)
cycle = eulerian_cycle(g, 1)
correct_cycle = vcat([edgetype(g)(i, i + 1) for i in 1:(L - 1)], [edgetype(g)(L, 1)])
@test cycle == correct_cycle || reverse(reverse.(cycle)) == correct_cycle
end
end

0 comments on commit 6668887

Please sign in to comment.