diff --git a/src/traversals/dfs.jl b/src/traversals/dfs.jl index 44033fc..5169cf3 100644 --- a/src/traversals/dfs.jl +++ b/src/traversals/dfs.jl @@ -25,3 +25,32 @@ end function dfs_parents(graph::AbstractNamedGraph, vertex; kwargs...) return _dfs_parents(graph, vertex; kwargs...) end + +#Given a graph, split it into its connected components, construct a spanning tree over each of them +# and take the union (adding in edges between the trees to recover a connected graph) +function spanning_forest(g::AbstractNamedGraph) + components = connected_components(g) + return reduce( + union, + NamedGraph[ + undirected_graph(bfs_tree(g[g_comp], first(g_comp))) for g_comp in components + ], + ) +end + +#Given a 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) + 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) + 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 diff --git a/test/test_forests.jl b/test/test_forests.jl new file mode 100644 index 0000000..9937e40 --- /dev/null +++ b/test/test_forests.jl @@ -0,0 +1,30 @@ +using Test +using Graphs +using NamedGraphs +using NamedGraphs: + decorate_graph_edges, + decorate_graph_vertices, + hexagonal_lattice_graph, + triangular_lattice_graph, + build_forest_cover + +@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)) + for f in forest_cover + trees = NamedGraph[f[vs] for vs in connected_components(f)] + @test all(is_tree.(trees)) + @test issetequal(vertices(f), vertices(g)) + end + end +end diff --git a/test/test_namedgraphgenerators.jl b/test/test_namedgraphgenerators.jl index 7eb7813..6b086e7 100644 --- a/test/test_namedgraphgenerators.jl +++ b/test/test_namedgraphgenerators.jl @@ -30,7 +30,6 @@ using Random @test dims[1] > dims[2] g = triangular_lattice_graph(2, 1) - @show g dims = maximum(vertices(g)) @test dims[1] > dims[2]