Skip to content

Commit

Permalink
Better spanning tree interface. More tests. File Separation
Browse files Browse the repository at this point in the history
  • Loading branch information
JoeyT1994 committed Oct 25, 2023
1 parent 4b87693 commit b34511a
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 25 deletions.
1 change: 1 addition & 0 deletions src/NamedGraphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ include("distance.jl")
include("distances_and_capacities.jl")
include(joinpath("steiner_tree", "steiner_tree.jl"))
include(joinpath("traversals", "dfs.jl"))
include(joinpath("traversals", "trees_and_forests.jl"))
include("namedgraph.jl")
include(joinpath("generators", "named_staticgraphs.jl"))
include(joinpath("Graphs", "generators", "staticgraphs.jl"))
Expand Down
43 changes: 43 additions & 0 deletions src/traversals/trees_and_forests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
default_root_vertex(g) = last(findmax(eccentricities(g)))

function spanning_tree(
g::AbstractNamedGraph; root_vertex=default_root_vertex(g), alg::String="BFS"
)
@assert !NamedGraphs.is_directed(g)
if alg == "BFS"
return undirected_graph(bfs_tree(g, root_vertex))
elseif alg == "RandomBFS"
return undirected_graph(random_bfs_tree(g, root_vertex))
elseif alg == "DFS"
return undirected_graph(dfs_tree(g, root_vertex))
else
error("Algorithm not current supported")
end
end

#Given a graph, split it into its connected components, construct a spanning tree over each of them
# and take the union.
function spanning_forest(
g::AbstractNamedGraph; spanning_tree_function=g -> spanning_tree(g)
)
return reduce(union, (spanning_tree_function(g[vs]) for vs in connected_components(g)))
end

#Given an undirected graph g with vertex set V, build a set of forests (each with vertex set V) which covers all edges in g
# (see https://en.wikipedia.org/wiki/Arboricity) We do not find the minimum but our tests show this algorithm performs well
function build_forest_cover(
g::AbstractNamedGraph; spanning_tree_function=g -> spanning_tree(g)
)
edges_collected = edgetype(g)[]
remaining_edges = edges(g)
forests = NamedGraph[]
while !isempty(remaining_edges)
g_reduced = rem_edges(g, edges_collected)
g_reduced_spanning_forest = spanning_forest(g_reduced; spanning_tree_function)
push!(edges_collected, edges(g_reduced_spanning_forest)...)
push!(forests, g_reduced_spanning_forest)
setdiff!(remaining_edges, edges(g_reduced_spanning_forest))
end

return forests
end
25 changes: 0 additions & 25 deletions test/test_forests.jl

This file was deleted.

46 changes: 46 additions & 0 deletions test/test_trees_and_forests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using Test
using Graphs
using NamedGraphs
using NamedGraphs:
hexagonal_lattice_graph, triangular_lattice_graph, build_forest_cover, spanning_tree

@testset "Test Spanning Trees" begin
gs = [
named_grid((6, 1)),
named_grid((3, 3, 3)),
hexagonal_lattice_graph(6, 6),
named_comb_tree((4, 4)),
named_grid((10, 10)),
triangular_lattice_graph(5, 5; periodic=true),
]
algs = ["BFS", "DFS", "RandomBFS"]
for g in gs
for alg in algs
s_tree = spanning_tree(g; alg)
@test is_tree(s_tree)
@test Set(vertices(s_tree)) == Set(vertices(g))
@test issubset(Set(edges(s_tree)), Set(edges(g)))
end
end
end

@testset "Test Forest Cover" begin
gs = [
named_grid((6, 1)),
named_grid((3, 3, 3)),
hexagonal_lattice_graph(6, 6),
named_comb_tree((4, 4)),
named_grid((10, 10)),
triangular_lattice_graph(5, 5; periodic=true),
]
for g in gs
forest_cover = build_forest_cover(g)
cover_edges = reduce(vcat, edges.(forest_cover))
@test issetequal(cover_edges, edges(g))
@test all(issetequal(vertices(f), vertices(g)) for f in forest_cover)
for f in forest_cover
trees = NamedGraph[f[vs] for vs in connected_components(f)]
@test all(is_tree.(trees))
end
end
end

0 comments on commit b34511a

Please sign in to comment.