diff --git a/Project.toml b/Project.toml index b640b78..c839c81 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "NamedGraphs" uuid = "678767b0-92e7-4007-89e4-4527a8725b19" authors = ["Matthew Fishman , Joseph Tindall and contributors"] -version = "0.6.9" +version = "0.7.0" [deps] AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c" diff --git a/docs/Project.toml b/docs/Project.toml index b91d65d..16ff40a 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -4,6 +4,6 @@ Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306" NamedGraphs = "678767b0-92e7-4007-89e4-4527a8725b19" [compat] -Documenter = "1.10.0" +Documenter = "1.10" Literate = "2.20.1" -NamedGraphs = "0.6.5" +NamedGraphs = "0.7" diff --git a/examples/Project.toml b/examples/Project.toml index a7bf512..123e6c3 100644 --- a/examples/Project.toml +++ b/examples/Project.toml @@ -4,4 +4,4 @@ NamedGraphs = "678767b0-92e7-4007-89e4-4527a8725b19" [compat] Graphs = "1.12.0" -NamedGraphs = "0.6.6" +NamedGraphs = "0.7.0" diff --git a/src/lib/PartitionedGraphs/src/PartitionedGraphs.jl b/src/lib/PartitionedGraphs/src/PartitionedGraphs.jl index 57a6b71..a14d5ef 100644 --- a/src/lib/PartitionedGraphs/src/PartitionedGraphs.jl +++ b/src/lib/PartitionedGraphs/src/PartitionedGraphs.jl @@ -5,4 +5,5 @@ include("abstractpartitionedgraph.jl") include("partitionvertex.jl") include("partitionedge.jl") include("partitionedgraph.jl") +include("partitionsgraphview.jl") end diff --git a/src/lib/PartitionedGraphs/src/abstractpartitionedgraph.jl b/src/lib/PartitionedGraphs/src/abstractpartitionedgraph.jl index 246dfe3..3e9143d 100644 --- a/src/lib/PartitionedGraphs/src/abstractpartitionedgraph.jl +++ b/src/lib/PartitionedGraphs/src/abstractpartitionedgraph.jl @@ -16,7 +16,7 @@ using ..NamedGraphs.GraphsExtensions: abstract type AbstractPartitionedGraph{V,PV} <: AbstractNamedGraph{V} end #Needed for interface -partitioned_graph(pg::AbstractPartitionedGraph) = not_implemented() +partitions_graph(pg::AbstractPartitionedGraph) = not_implemented() unpartitioned_graph(pg::AbstractPartitionedGraph) = not_implemented() function unpartitioned_graph_type(pg::Type{<:AbstractPartitionedGraph}) return not_implemented() @@ -75,11 +75,11 @@ end function Graphs.has_vertex( pg::AbstractPartitionedGraph, partitionvertex::AbstractPartitionVertex ) - return has_vertex(partitioned_graph(pg), parent(partitionvertex)) + return has_vertex(partitions_graph(pg), parent(partitionvertex)) end function Graphs.has_edge(pg::AbstractPartitionedGraph, partitionedge::AbstractPartitionEdge) - return has_edge(partitioned_graph(pg), parent(partitionedge)) + return has_edge(partitions_graph(pg), parent(partitionedge)) end function is_boundary_edge(pg::AbstractPartitionedGraph, edge::AbstractEdge) @@ -91,17 +91,17 @@ function Graphs.add_edge!(pg::AbstractPartitionedGraph, edge::AbstractEdge) add_edge!(unpartitioned_graph(pg), edge) pg_edge = parent(partitionedge(pg, edge)) if src(pg_edge) != dst(pg_edge) - add_edge!(partitioned_graph(pg), pg_edge) + add_edge!(partitions_graph(pg), pg_edge) end return pg end function Graphs.rem_edge!(pg::AbstractPartitionedGraph, edge::AbstractEdge) pg_edge = partitionedge(pg, edge) - if has_edge(partitioned_graph(pg), pg_edge) + if has_edge(partitions_graph(pg), pg_edge) g_edges = edges(pg, pg_edge) if length(g_edges) == 1 - rem_edge!(partitioned_graph(pg), pg_edge) + rem_edge!(partitions_graph(pg), pg_edge) end end return rem_edge!(unpartitioned_graph(pg), edge) @@ -118,7 +118,7 @@ function Graphs.add_vertex!( pg::AbstractPartitionedGraph, vertex, partitionvertex::AbstractPartitionVertex ) add_vertex!(unpartitioned_graph(pg), vertex) - add_vertex!(partitioned_graph(pg), parent(partitionvertex)) + add_vertex!(partitions_graph(pg), parent(partitionvertex)) insert_to_vertex_map!(pg, vertex, partitionvertex) return pg end @@ -148,7 +148,7 @@ function Graphs.rem_vertex!(pg::AbstractPartitionedGraph, vertex) delete_from_vertex_map!(pg, pv, vertex) rem_vertex!(unpartitioned_graph(pg), vertex) if !haskey(partitioned_vertices(pg), parent(pv)) - rem_vertex!(partitioned_graph(pg), parent(pv)) + rem_vertex!(partitions_graph(pg), parent(pv)) end return pg end @@ -174,7 +174,7 @@ end function Base.:(==)(pg1::AbstractPartitionedGraph, pg2::AbstractPartitionedGraph) if unpartitioned_graph(pg1) != unpartitioned_graph(pg2) || - partitioned_graph(pg1) != partitioned_graph(pg2) + partitions_graph(pg1) != partitions_graph(pg2) return false end for v in vertices(pg1) diff --git a/src/lib/PartitionedGraphs/src/partitionedgraph.jl b/src/lib/PartitionedGraphs/src/partitionedgraph.jl index 5fa1ade..4ac0a51 100644 --- a/src/lib/PartitionedGraphs/src/partitionedgraph.jl +++ b/src/lib/PartitionedGraphs/src/partitionedgraph.jl @@ -10,7 +10,7 @@ using ..NamedGraphs: NamedEdge, NamedGraph struct PartitionedGraph{V,PV,G<:AbstractGraph{V},PG<:AbstractGraph{PV}} <: AbstractPartitionedGraph{V,PV} graph::G - partitioned_graph::PG + partitions_graph::PG partitioned_vertices::Dictionary which_partition::Dictionary end @@ -46,7 +46,7 @@ function PartitionedGraph(g::AbstractGraph; kwargs...) end #Needed for interface -partitioned_graph(pg::PartitionedGraph) = getfield(pg, :partitioned_graph) +partitions_graph(pg::PartitionedGraph) = PartitionsGraphView(pg) unpartitioned_graph(pg::PartitionedGraph) = getfield(pg, :graph) function unpartitioned_graph_type(graph_type::Type{<:PartitionedGraph}) return fieldtype(graph_type, :graph) @@ -70,7 +70,7 @@ function partitionvertices(pg::PartitionedGraph, verts) end function partitionvertices(pg::PartitionedGraph) - return PartitionVertex.(vertices(partitioned_graph(pg))) + return PartitionVertex.(vertices(pg.partitions_graph)) end function partitionedge(pg::PartitionedGraph, edge::AbstractEdge) @@ -86,7 +86,7 @@ function partitionedges(pg::PartitionedGraph, edges::Vector) end function partitionedges(pg::PartitionedGraph) - return PartitionEdge.(edges(partitioned_graph(pg))) + return PartitionEdge.(edges(pg.partitions_graph)) end function Graphs.edges(pg::PartitionedGraph, partitionedge::PartitionEdge) @@ -105,7 +105,7 @@ end function boundary_partitionedges(pg::PartitionedGraph, partitionvertices; kwargs...) return PartitionEdge.( - boundary_edges(partitioned_graph(pg), parent.(partitionvertices); kwargs...) + boundary_edges(pg.partitions_graph, parent.(partitionvertices); kwargs...) ) end @@ -118,7 +118,7 @@ end function Base.copy(pg::PartitionedGraph) return PartitionedGraph( copy(unpartitioned_graph(pg)), - copy(partitioned_graph(pg)), + copy(pg.partitions_graph), copy(partitioned_vertices(pg)), copy(which_partition(pg)), ) @@ -160,7 +160,7 @@ end function partitionedgraph_induced_subgraph(pg::PartitionedGraph, vertices::Vector) sub_pg_graph, _ = induced_subgraph(unpartitioned_graph(pg), vertices) sub_partitioned_vertices = copy(partitioned_vertices(pg)) - for pv in NamedGraphs.vertices(partitioned_graph(pg)) + for pv in NamedGraphs.vertices(pg.partitions_graph) vs = intersect(vertices, sub_partitioned_vertices[pv]) if !isempty(vs) sub_partitioned_vertices[pv] = vs diff --git a/src/lib/PartitionedGraphs/src/partitionsgraphview.jl b/src/lib/PartitionedGraphs/src/partitionsgraphview.jl new file mode 100644 index 0000000..20d294b --- /dev/null +++ b/src/lib/PartitionedGraphs/src/partitionsgraphview.jl @@ -0,0 +1,35 @@ +struct PartitionsGraphView{V,G<:AbstractGraph{V}} <: AbstractNamedGraph{V} + graph::G +end + +Base.copy(g::PartitionsGraphView) = PartitionsGraphView(copy(g.graph)) + +using Graphs: AbstractGraph +partitions_graph(g::AbstractGraph) = PartitionsGraphView(PartitionedGraph(g, [vertices(g)])) + +# Graphs.jl and NamedGraphs.jl interface overloads for `PartitionsGraphView` wrapping +# a `PartitionedGraph`. +function NamedGraphs.position_graph_type( + type::Type{<:PartitionsGraphView{V,G}} +) where {V,G<:PartitionedGraph{V}} + return fieldtype(fieldtype(fieldtype(type, :graph), :partitions_graph), :position_graph) +end +for f in [ + :(Graphs.add_vertex!), + :(Graphs.edges), + :(Graphs.vertices), + :(Graphs.rem_vertex!), + :(NamedGraphs.position_graph), + :(NamedGraphs.vertex_positions), + :(NamedGraphs.ordered_vertices), + :(NamedGraphs.edgetype), + :(NamedGraphs.vertextype), +] + @eval begin + function $f( + g::PartitionsGraphView{V,G}, args...; kwargs... + ) where {V,G<:PartitionedGraph{V}} + return $f(g.graph.partitions_graph, args...; kwargs...) + end + end +end diff --git a/test/Project.toml b/test/Project.toml index 2bb21dc..e75deaf 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -20,16 +20,16 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" AbstractTrees = "0.4.5" Aqua = "0.8.11" Dictionaries = "0.4.4" -Graphs = "1.12.0" +Graphs = "1.12" GraphsFlows = "0.1.1" KaHyPar = "0.3.1" Metis = "1.5.0" -NamedGraphs = "0.6.6" +NamedGraphs = "0.7.0" SafeTestsets = "0.1.0" SimpleGraphAlgorithms = "0.6.0" SimpleGraphConverter = "0.1.0" Suppressor = "0.2.8" SymRCM = "0.2.2" -Pkg = "1.10.0" -Random = "1.10.0" -Test = "1.10.0" +Pkg = "1.10" +Random = "1.10" +Test = "1.10" diff --git a/test/test_partitionedgraph.jl b/test/test_partitionedgraph.jl index 6d3e034..8f42a9c 100644 --- a/test/test_partitionedgraph.jl +++ b/test/test_partitionedgraph.jl @@ -1,19 +1,23 @@ @eval module $(gensym()) using Graphs: + a_star, center, + connected_components, diameter, edges, has_vertex, is_connected, + is_directed, is_tree, ne, + neighbors, nv, radius, random_regular_graph, rem_vertex!, vertices using Metis: Metis -using NamedGraphs: NamedEdge, NamedGraph +using NamedGraphs: NamedEdge, NamedGraph, NamedGraphs using NamedGraphs.GraphsExtensions: add_edges!, add_vertices!, @@ -31,10 +35,11 @@ using NamedGraphs.NamedGraphGenerators: using NamedGraphs.OrderedDictionaries: OrderedDictionary using NamedGraphs.PartitionedGraphs: PartitionEdge, - PartitionedGraph, PartitionVertex, + PartitionedGraph, + PartitionsGraphView, boundary_partitionedges, - partitioned_graph, + partitions_graph, partitionedge, partitionedges, partitionvertex, @@ -51,20 +56,27 @@ using Test: @test, @testset #Partition it column-wise (into a 1D chain) partitions = [[(i, j) for j in 1:ny] for i in 1:nx] pg = PartitionedGraph(g, partitions) - @test vertextype(partitioned_graph(pg)) == Int64 + @test vertextype(partitions_graph(pg)) == Int64 @test vertextype(unpartitioned_graph(pg)) == vertextype(g) @test isa(partitionvertices(pg), OrderedDictionary{Int64,PartitionVertex{Int64}}) @test isa(partitionedges(pg), Vector{PartitionEdge{Int64,NamedEdge{Int64}}}) - @test is_tree(partitioned_graph(pg)) + @test is_tree(partitions_graph(pg)) @test nv(pg) == nx * ny - @test nv(partitioned_graph(pg)) == nx + @test nv(partitions_graph(pg)) == nx pg_c = copy(pg) @test pg_c == pg + #PartionsGraphView test + pgv = PartitionsGraphView(pg) + @test vertices(pgv) == parent.(partitionvertices(pg)) + @test edges(pgv) == parent.(partitionedges(pg)) + @test is_tree(pgv) == true + @test neighbors(pgv, 1) == [2] + #Same partitioning but with a dictionary constructor partition_dict = Dictionary([first(partition) for partition in partitions], partitions) pg = PartitionedGraph(g, partition_dict) - @test vertextype(partitioned_graph(pg)) == vertextype(g) + @test vertextype(partitions_graph(pg)) == vertextype(g) @test vertextype(unpartitioned_graph(pg)) == vertextype(g) @test isa( partitionvertices(pg), @@ -74,19 +86,19 @@ using Test: @test, @testset partitionedges(pg), Vector{PartitionEdge{Tuple{Int64,Int64},NamedEdge{Tuple{Int64,Int64}}}}, ) - @test is_tree(partitioned_graph(pg)) + @test is_tree(partitions_graph(pg)) @test nv(pg) == nx * ny - @test nv(partitioned_graph(pg)) == nx + @test nv(partitions_graph(pg)) == nx pg_c = copy(pg) @test pg_c == pg #Partition the whole thing into just 1 vertex pg = PartitionedGraph([i for i in 1:nx]) - @test unpartitioned_graph(pg) == partitioned_graph(pg) + @test unpartitioned_graph(pg) == partitions_graph(pg) @test nv(pg) == nx - @test nv(partitioned_graph(pg)) == nx + @test nv(partitions_graph(pg)) == nx @test ne(pg) == 0 - @test ne(partitioned_graph(pg)) == 0 + @test ne(partitions_graph(pg)) == 0 pg_c = copy(pg) @test pg_c == pg end @@ -132,22 +144,22 @@ end #Strip the middle column from pg via the partitioned graph vertex, and make a new pg rem_vertex!(pg, pv) - @test !is_connected(unpartitioned_graph(pg)) && !is_connected(partitioned_graph(pg)) - @test parent(pv) ∉ vertices(partitioned_graph(pg)) + @test !is_connected(unpartitioned_graph(pg)) && !is_connected(partitions_graph(pg)) + @test parent(pv) ∉ vertices(partitions_graph(pg)) @test !has_vertex(pg, pv) @test nv(pg) == (nx - 1) * ny - @test nv(partitioned_graph(pg)) == nx - 1 - @test !is_tree(partitioned_graph(pg)) + @test nv(partitions_graph(pg)) == nx - 1 + @test !is_tree(partitions_graph(pg)) #Add the column back to the in place graph add_vertices!(pg, v_set, pv) add_edges!(pg, edges_involving_v_set) - @test is_connected(pg.graph) && is_path_graph(partitioned_graph(pg)) - @test parent(pv) ∈ vertices(partitioned_graph(pg)) + @test is_connected(pg.graph) && is_path_graph(partitions_graph(pg)) + @test parent(pv) ∈ vertices(partitions_graph(pg)) @test has_vertex(pg, pv) - @test is_tree(partitioned_graph(pg)) + @test is_tree(partitions_graph(pg)) @test nv(pg) == nx * ny - @test nv(partitioned_graph(pg)) == nx + @test nv(partitions_graph(pg)) == nx end @testset "Test Partitioned Graph Subgraph Functionality" begin @@ -167,7 +179,7 @@ end pg_2 = subgraph(pg, subgraph_vertices) @test pg_1 == pg_2 @test nv(pg_1) == length(subgraph_vertices) - @test nv(partitioned_graph(pg_1)) == length(subgraph_partitioned_vertices) + @test nv(partitions_graph(pg_1)) == length(subgraph_partitioned_vertices) subgraph_partitioned_vertex = 3 subgraph_vertices = partitions[subgraph_partitioned_vertex] @@ -190,9 +202,9 @@ end pg = PartitionedGraph(g, [vertices(g)]) @test f(pg) == f(unpartitioned_graph(pg)) @test nv(pg) == nv(g) - @test nv(partitioned_graph(pg)) == 1 + @test nv(partitions_graph(pg)) == 1 @test ne(pg) == ne(g) - @test ne(partitioned_graph(pg)) == 0 + @test ne(partitions_graph(pg)) == 0 end end end @@ -209,7 +221,7 @@ end for backend in backends pg = PartitionedGraph(g; npartitions, backend="metis") @test pg isa PartitionedGraph - @test nv(partitioned_graph(pg)) == npartitions + @test nv(partitions_graph(pg)) == npartitions end end end