Skip to content

Commit

Permalink
Better type based functions
Browse files Browse the repository at this point in the history
  • Loading branch information
JoeyT1994 committed Dec 23, 2023
1 parent 4548c98 commit 830667d
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 67 deletions.
4 changes: 1 addition & 3 deletions examples/partitioning.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ npartitions = 4
pg_kahypar = PartitionedGraph(g; npartitions, backend="KaHyPar")
pg_metis = PartitionedGraph(g; npartitions, backend="Metis")

@show length(NamedGraphs.vertices(partitioned_graph(pg_kahypar))) ==
length(NamedGraphs.vertices(partitioned_graph(pg_metis))) ==
npartitions
@show nv(partitioned_graph(pg_kahypar)) == nv(partitioned_graph(pg_metis)) == npartitions

@show pg_kahypar isa PartitionedGraph
@show pg_metis isa PartitionedGraph
2 changes: 1 addition & 1 deletion src/Graphs/abstractgraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ end
# to avoid method overwrite warnings, see:
# https://github.com/mauro3/SimpleTraits.jl#method-overwritten-warnings
@traitfn function undirected_graph(graph::::IsDirected)
undigraph = undirected_graph(typeof(graph))(vertices(graph))
undigraph = undirected_graph_type(typeof(graph))(vertices(graph))
for e in edges(graph)
# TODO: Check for repeated edges?
add_edge!(undigraph, e)
Expand Down
53 changes: 36 additions & 17 deletions src/Graphs/partitionedgraphs/abstractpartitionedgraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,34 @@ abstract type AbstractPartitionedGraph{V,PV} <: AbstractNamedGraph{V} end
#Needed for interface
partitioned_graph(pg::AbstractPartitionedGraph) = not_implemented()
unpartitioned_graph(pg::AbstractPartitionedGraph) = not_implemented()
function vertices(pg::AbstractPartitionedGraph, partition_vertex::AbstractPartitionVertex)
return not_implemented()
end
which_partition(pg::AbstractPartitionedGraph, vertex) = not_implemented()
copy(pg::AbstractPartitionedGraph) = not_implemented()
delete_from_vertex_map!(pg::AbstractPartitionedGraph, vertex) = not_implemented()
insert_to_vertex_map!(pg::AbstractPartitionedGraph, vertex) = not_implemented()
partition_edge(pg::AbstractPartitionedGraph, edge::AbstractEdge) = not_implemented()
partition_edge(pg::AbstractPartitionedGraph, edge) = not_implemented()
function edges(pg::AbstractPartitionedGraph, partition_edge::AbstractPartitionEdge)
return not_implemented()
end
vertices(pg::AbstractPartitionedGraph, pv::AbstractPartitionVertex) = not_implemented()
function vertices(
pg::AbstractPartitionedGraph, partition_verts::Vector{V}
) where {V<:AbstractPartitionVertex}
return not_implemented()
end
parent_graph_type(G::Type{<:AbstractPartitionedGraph}) = not_implemented()
directed_graph_type(G::Type{<:AbstractPartitionedGraph}) = not_implemented()
undirected_graph_type(G::Type{<:AbstractPartitionedGraph}) = not_implemented()

#Functions for the abstract type
vertices(pg::AbstractPartitionedGraph) = vertices(unpartitioned_graph(pg))
#edges(pg::AbstractPartitionedGraph) = edges(unpartitioned_graph(pg))
#nv(pg::AbstractPartitionedGraph) = nv(unpartitioned_graph(pg))
#outneighbors(pg::AbstractPartitionedGraph, vertex) = outneighbors(unpartitioned_graph(pg), vertex)
parent_graph(pg::AbstractPartitionedGraph) = parent_graph(unpartitioned_graph(pg))
function vertex_to_parent_vertex(pg::AbstractPartitionedGraph, vertex)
return vertex_to_parent_vertex(unpartitioned_graph(pg), vertex)
end
edgetype(pg::AbstractPartitionedGraph) = edgetype(unpartitioned_graph(pg))
function parent_graph_type(G::Type{<:AbstractPartitionedGraph})
return fieldtype(fieldtype(G, :graph), :parent_graph)
end
directed_graph(G::Type{<:AbstractPartitionedGraph}) = directed_graph(fieldtype(G, :graph))
function undirected_graph(G::Type{<:AbstractPartitionedGraph})
return unddirected_graph(fieldtype(G, :graph))
end
parent_graph_type(pg::AbstractPartitionedGraph) = parent_graph_type(unpartitioned_graph(pg))
nv(pg::AbstractPartitionedGraph, pv::AbstractPartitionVertex) = length(vertices(pg, pv))

function has_vertex(pg::AbstractPartitionedGraph, partition_vertex::AbstractPartitionVertex)
return has_vertex(partitioned_graph(pg), parent(partition_vertex))
end
Expand All @@ -49,6 +49,8 @@ function add_edge!(pg::AbstractPartitionedGraph, edge::AbstractEdge)
if src(pg_edge) != dst(pg_edge)
add_edge!(partitioned_graph(pg), pg_edge)
end

return pg
end

function rem_edge!(pg::AbstractPartitionedGraph, edge::AbstractEdge)
Expand Down Expand Up @@ -79,6 +81,8 @@ function rem_edges!(
for pe in partition_edges
rem_edge!(pg, pe)
end

return pg
end

function rem_edges(
Expand Down Expand Up @@ -108,6 +112,8 @@ function add_vertices!(
for (v, pv) in zip(vertices, partition_vertices)
add_vertex!(pg, v, pv)
end

return pg
end

function add_vertices!(
Expand All @@ -117,12 +123,13 @@ function add_vertices!(
end

function rem_vertex!(pg::AbstractPartitionedGraph, vertex)
rem_vertex!(unpartitioned_graph(pg), vertex)
pv = which_partition(pg, vertex)
if length(vertices(pg, pv)) == 1
delete_from_vertex_map!(pg, pv, vertex)
rem_vertex!(unpartitioned_graph(pg), vertex)
if iszero(nv(pg, pv))
rem_vertex!(partitioned_graph(pg), parent(pv))
end
return delete_from_vertex_map!(pg, vertex)
return pg
end

function rem_vertex!(
Expand All @@ -143,6 +150,8 @@ function rem_vertices!(
for pv in partition_vertices
rem_vertex!(pg, pv)
end

return pg
end

function rem_vertices(
Expand Down Expand Up @@ -171,3 +180,13 @@ function (pg1::AbstractPartitionedGraph == pg2::AbstractPartitionedGraph)

return true
end

function subgraph(pg::AbstractPartitionedGraph, partition_vertex::AbstractPartitionVertex)
return first(induced_subgraph(unpartitioned_graph(pg), vertices(pg, [partition_vertex])))
end

function induced_subgraph(
pg::AbstractPartitionedGraph, partition_vertex::AbstractPartitionVertex
)
return subgraph(pg, partition_vertex), nothing
end
2 changes: 1 addition & 1 deletion src/Graphs/partitionedgraphs/partitionedge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ end
parent(pe::PartitionEdge) = getfield(pe, :edge)
src(pe::PartitionEdge) = PartitionVertex(src(parent(pe)))
dst(pe::PartitionEdge) = PartitionVertex(dst(parent(pe)))
PartitionEdge(p::Pair) = PartitionEdge(NamedEdge(p.first => p.second))
PartitionEdge(p::Pair) = PartitionEdge(NamedEdge(first(p) => last(p)))
62 changes: 34 additions & 28 deletions src/Graphs/partitionedgraphs/partitionedgraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,21 @@ partitioned_graph(pg::PartitionedGraph) = getfield(pg, :partitioned_graph)
unpartitioned_graph(pg::PartitionedGraph) = getfield(pg, :graph)
partitioned_vertices(pg::PartitionedGraph) = getfield(pg, :partitioned_vertices)
which_partition(pg::PartitionedGraph) = getfield(pg, :which_partition)
parent_graph_type(PG::Type{<:PartitionedGraph}) = fieldtype(PG, :graph)
function directed_graph_type(PG::Type{<:PartitionedGraph})
return directed_graph_type(fieldtype(PG, :graph))
end
function undirected_graph_type(PG::Type{<:PartitionedGraph})
return undirected_graph_type(fieldtype(PG, :graph))
end
function vertices(pg::PartitionedGraph, partition_vert::PartitionVertex)
return partitioned_vertices(pg)[parent(partition_vert)]
if haskey(partitioned_vertices(pg), parent(partition_vert))
return partitioned_vertices(pg)[parent(partition_vert)]
else
return []
end
end
function vertices(
pg::PartitionedGraph, partition_verts::Vector{V}
) where {V<:PartitionVertex}
function vertices(pg::PartitionedGraph, partition_verts::Vector{<:PartitionVertex})
return unique(reduce(vcat, [vertices(pg, pv) for pv in partition_verts]))
end
function which_partition(pg::PartitionedGraph, vertex)
Expand All @@ -61,19 +70,15 @@ function partition_edge(pg::PartitionedGraph, edge::AbstractEdge)
end

function partition_edges(pg::PartitionedGraph, partition_edge::PartitionEdge)
psrc_vs, pdst_vs = vertices(pg, PartitionVertex(src(partition_edge))),
vertices(pg, PartitionVertex(dst(partition_edge)))
psrc_subgraph, pdst_subgraph, full_subgraph = subgraph(unpartitioned_graph(pg), psrc_vs),
subgraph(pg, pdst_vs),
subgraph(pg, vcat(psrc_vs, pdst_vs))

return setdiff(
NamedGraphs.edges(full_subgraph),
vcat(NamedGraphs.edges(psrc_subgraph), NamedGraphs.edges(pdst_subgraph)),
)
psrc_vs = vertices(pg, PartitionVertex(src(partition_edge)))
pdst_vs = vertices(pg, PartitionVertex(dst(partition_edge)))
psrc_subgraph = subgraph(unpartitioned_graph(pg), psrc_vs)
pdst_subgraph = subgraph(pg, pdst_vs)
full_subgraph = subgraph(pg, vcat(psrc_vs, pdst_vs))

return setdiff(edges(full_subgraph), vcat(edges(psrc_subgraph), edges(pdst_subgraph)))
end

#Copy on dictionaries is dodgy?!
function copy(pg::PartitionedGraph)
return PartitionedGraph(
copy(unpartitioned_graph(pg)),
Expand All @@ -93,17 +98,26 @@ function insert_to_vertex_map!(
pg.partitioned_vertices[pv] = unique(vcat(vertices(pg, partition_vertex), [vertex]))
end

return insert!(NamedGraphs.which_partition(pg), vertex, pv)
insert!(which_partition(pg), vertex, pv)
return pg
end

function delete_from_vertex_map!(pg::PartitionedGraph, vertex)
pv = which_partition(pg, vertex)
vs = vertices(pg, pv)
delete!(partitioned_vertices(pg), parent(pv))
return delete_from_vertex_map!(pg, pv, vertex)
end

function delete_from_vertex_map!(
pg::PartitionedGraph, partitioned_vertex::PartitionVertex, vertex
)
vs = vertices(pg, partitioned_vertex)
delete!(partitioned_vertices(pg), parent(partitioned_vertex))
if length(vs) != 1
insert!(partitioned_vertices(pg), parent(pv), setdiff(vs, [vertex]))
insert!(partitioned_vertices(pg), parent(partitioned_vertex), setdiff(vs, [vertex]))
end
return delete!(pg.which_partition, vertex)

delete!(which_partition(pg), vertex)
return partitioned_vertex
end

### PartitionedGraph Specific Functions
Expand All @@ -127,11 +141,3 @@ function induced_subgraph(
) where {V<:PartitionVertex}
return induced_subgraph(pg, vertices(pg, partition_verts))
end

function subgraph(pg::PartitionedGraph, partition_vertex::PartitionVertex)
return first(induced_subgraph(unpartitioned_graph(pg), vertices(pg, [partition_vertex])))
end

function induced_subgraph(pg::PartitionedGraph, partition_vertex::PartitionVertex)
return subgraph(pg, partition_vertex), nothing
end
1 change: 1 addition & 0 deletions src/NamedGraphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ export NamedGraph,
neighborhood,
neighborhood_dists,
neighbors,
nv,
partitioned_graph,
path_digraph,
path_graph,
Expand Down
8 changes: 4 additions & 4 deletions src/abstractnamedgraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ end

# TODO: rename `edge_type`?
edgetype(graph::AbstractNamedGraph) = not_implemented()
directed_graph(G::Type{<:AbstractNamedGraph}) = not_implemented()
undirected_graph(G::Type{<:AbstractNamedGraph}) = not_implemented()
directed_graph_type(G::Type{<:AbstractNamedGraph}) = not_implemented()
undirected_graph_type(G::Type{<:AbstractNamedGraph}) = not_implemented()

# In terms of `parent_graph_type`
# is_directed(::Type{<:AbstractNamedGraph}) = not_implemented()
Expand All @@ -61,7 +61,7 @@ zero(G::Type{<:AbstractNamedGraph}) = G()

# TODO: Implement using `copyto!`?
function directed_graph(graph::AbstractNamedGraph)
digraph = directed_graph(typeof(graph))(vertices(graph))
digraph = directed_graph_type(typeof(graph))(vertices(graph))
for e in edges(graph)
add_edge!(digraph, e)
add_edge!(digraph, reverse(e))
Expand Down Expand Up @@ -530,7 +530,7 @@ function tree(graph::AbstractNamedGraph, parents)
n = length(parents)
# TODO: Use `directed_graph` here to make more generic?
## t = GenericNamedGraph(DiGraph(n), vertices(graph))
t = directed_graph(typeof(graph))(vertices(graph))
t = directed_graph_type(typeof(graph))(vertices(graph))
for destination in eachindex(parents)
source = parents[destination]
if source != destination
Expand Down
4 changes: 2 additions & 2 deletions src/namedgraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,10 @@ function set_vertices(graph::GenericNamedGraph, vertices)
return GenericNamedGraph(parent_graph(graph), vertices)
end

function directed_graph(G::Type{<:GenericNamedGraph})
function directed_graph_type(G::Type{<:GenericNamedGraph})
return GenericNamedGraph{vertextype(G),directed_graph(parent_graph_type(G))}
end
function undirected_graph(G::Type{<:GenericNamedGraph})
function undirected_graph_type(G::Type{<:GenericNamedGraph})
return GenericNamedGraph{vertextype(G),undirected_graph(parent_graph_type(G))}
end

Expand Down
13 changes: 2 additions & 11 deletions test/test_partitionedgraph.jl
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
using Test
using NamedGraphs
using NamedGraphs:
spanning_forest,
subvertices,
spanning_tree,
forest_cover,
rem_edge!,
PartitionEdge,
rem_edges!,
PartitionVertex,
parent,
_npartitions
spanning_forest, spanning_tree, forest_cover, PartitionEdge, PartitionVertex, parent
using Dictionaries
using Graphs

Expand Down Expand Up @@ -120,7 +111,7 @@ end
for f in functions
for g in gs
pg = PartitionedGraph(g, [vertices(g)])
@test f(pg) == f(pg.graph)
@test f(pg) == f(unpartitioned_graph(pg))
@test nv(pg) == nv(g)
@test nv(partitioned_graph(pg)) == 1
@test ne(pg) == ne(g)
Expand Down

0 comments on commit 830667d

Please sign in to comment.