Skip to content

Commit

Permalink
Fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mtfishman committed Apr 15, 2024
1 parent 9a944fa commit 61bb29a
Show file tree
Hide file tree
Showing 13 changed files with 116 additions and 67 deletions.
40 changes: 18 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ julia> using NamedGraphs

julia> g = NamedGraph(grid((4,)), ["A", "B", "C", "D"])
NamedGraph{String} with 4 vertices:
4-element Indices{String}
4-element Dictionaries.Indices{String}
"A"
"B"
"C"
Expand All @@ -61,7 +61,7 @@ and 3 edge(s):

julia> g = NamedGraph(grid((4,)); vertices=["A", "B", "C", "D"]) # Same as above
NamedGraph{String} with 4 vertices:
4-element Indices{String}
4-element Dictionaries.Indices{String}
"A"
"B"
"C"
Expand Down Expand Up @@ -92,9 +92,9 @@ julia> neighbors(g, "B")
"A"
"C"

julia> g[["A", "B"]]
julia> subgraph(g, ["A", "B"])
NamedGraph{String} with 2 vertices:
2-element Indices{String}
2-element Dictionaries.Indices{String}
"A"
"B"

Expand All @@ -113,13 +113,12 @@ Graph operations are implemented by mapping back and forth between the generaliz


It is natural to use tuples of integers as the names for the vertices of graphs with grid connectivities.
For this, we use the convention that if a tuple is input, it is interpreted as the grid size and
the vertex names label cartesian coordinates:
For example:

```julia
julia> g = NamedGraph(grid((2, 2)); vertices=(2, 2))
julia> g = NamedGraph(grid((2, 2)); vertices=Tuple.(CartesianIndices((2, 2))))
NamedGraph{Tuple{Int64, Int64}} with 4 vertices:
4-element Indices{Tuple{Int64, Int64}}
4-element Dictionaries.Indices{Tuple{Int64, Int64}}
(1, 1)
(2, 1)
(1, 2)
Expand All @@ -134,6 +133,7 @@ and 4 edge(s):
```


In the future we will provide a shorthand notation for this, such as `cartesian_graph(grid((2, 2)), (2, 2))`.
Internally the vertices are all stored as tuples with a label in each dimension.


Expand Down Expand Up @@ -162,7 +162,7 @@ You can use vertex names to get [induced subgraphs](https://juliagraphs.org/Grap
```julia
julia> subgraph(v -> v[1] == 1, g)
NamedGraph{Tuple{Int64, Int64}} with 2 vertices:
2-element Indices{Tuple{Int64, Int64}}
2-element Dictionaries.Indices{Tuple{Int64, Int64}}
(1, 1)
(1, 2)

Expand All @@ -172,17 +172,17 @@ and 1 edge(s):

julia> subgraph(v -> v[2] == 2, g)
NamedGraph{Tuple{Int64, Int64}} with 2 vertices:
2-element Indices{Tuple{Int64, Int64}}
2-element Dictionaries.Indices{Tuple{Int64, Int64}}
(1, 2)
(2, 2)

and 1 edge(s):
(1, 2) => (2, 2)


julia> g[[(1, 1), (2, 2)]]
julia> subgraph(g, [(1, 1), (2, 2)])
NamedGraph{Tuple{Int64, Int64}} with 2 vertices:
2-element Indices{Tuple{Int64, Int64}}
2-element Dictionaries.Indices{Tuple{Int64, Int64}}
(1, 1)
(2, 2)

Expand All @@ -191,16 +191,12 @@ and 0 edge(s):
```


Note that this is similar to multidimensional array slicing, and we may support syntax like `subgraph(v, 1, :)` in the future.



You can also take [disjoint unions](https://en.wikipedia.org/wiki/Disjoint_union) or concatenations of graphs:

```julia
julia> g₁ = g
NamedGraph{Tuple{Int64, Int64}} with 4 vertices:
4-element Indices{Tuple{Int64, Int64}}
4-element Dictionaries.Indices{Tuple{Int64, Int64}}
(1, 1)
(2, 1)
(1, 2)
Expand All @@ -215,7 +211,7 @@ and 4 edge(s):

julia> g₂ = g
NamedGraph{Tuple{Int64, Int64}} with 4 vertices:
4-element Indices{Tuple{Int64, Int64}}
4-element Dictionaries.Indices{Tuple{Int64, Int64}}
(1, 1)
(2, 1)
(1, 2)
Expand All @@ -230,7 +226,7 @@ and 4 edge(s):

julia> disjoint_union(g₁, g₂)
NamedGraph{Tuple{Tuple{Int64, Int64}, Int64}} with 8 vertices:
8-element Indices{Tuple{Tuple{Int64, Int64}, Int64}}
8-element Dictionaries.Indices{Tuple{Tuple{Int64, Int64}, Int64}}
((1, 1), 1)
((2, 1), 1)
((1, 2), 1)
Expand All @@ -253,7 +249,7 @@ and 8 edge(s):

julia> g₁ g₂ # Same as above
NamedGraph{Tuple{Tuple{Int64, Int64}, Int64}} with 8 vertices:
8-element Indices{Tuple{Tuple{Int64, Int64}, Int64}}
8-element Dictionaries.Indices{Tuple{Tuple{Int64, Int64}, Int64}}
((1, 1), 1)
((2, 1), 1)
((1, 2), 1)
Expand Down Expand Up @@ -293,7 +289,7 @@ The original graphs can be obtained from subgraphs:
```julia
julia> rename_vertices(v -> v[1], subgraph(v -> v[2] == 1, g₁ g₂))
NamedGraph{Tuple{Int64, Int64}} with 4 vertices:
4-element Indices{Tuple{Int64, Int64}}
4-element Dictionaries.Indices{Tuple{Int64, Int64}}
(1, 1)
(2, 1)
(1, 2)
Expand All @@ -308,7 +304,7 @@ and 4 edge(s):

julia> rename_vertices(v -> v[1], subgraph(v -> v[2] == 2, g₁ g₂))
NamedGraph{Tuple{Int64, Int64}} with 4 vertices:
4-element Indices{Tuple{Int64, Int64}}
4-element Dictionaries.Indices{Tuple{Int64, Int64}}
(1, 1)
(2, 1)
(1, 2)
Expand Down
1 change: 1 addition & 0 deletions examples/Project.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[deps]
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
NamedGraphs = "678767b0-92e7-4007-89e4-4527a8725b19"
Weave = "44d3d7a6-8a23-5bf8-98c5-b353f8df5ec9"
12 changes: 5 additions & 7 deletions examples/README.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,19 @@ has_vertex(g, "A")
has_edge(g, "A" => "B")
has_edge(g, "A" => "C")
neighbors(g, "B")
g[["A", "B"]]
subgraph(g, ["A", "B"])

#' Internally, this type wraps a `SimpleGraph`, and stores a `Dictionary` from the [Dictionaries.jl](https://github.com/andyferris/Dictionaries.jl) package that maps the vertex names to the linear indices of the underlying `SimpleGraph`.

#' Graph operations are implemented by mapping back and forth between the generalized named vertices and the linear index vertices of the `SimpleGraph`.

#' It is natural to use tuples of integers as the names for the vertices of graphs with grid connectivities.
#' For this, we use the convention that if a tuple is input, it is interpreted as the grid size and
#' the vertex names label cartesian coordinates:
#' For example:
#+ term=true

g = NamedGraph(grid((2, 2)); vertices=(2, 2))
g = NamedGraph(grid((2, 2)); vertices=Tuple.(CartesianIndices((2, 2))))

#' In the future we will provide a shorthand notation for this, such as `cartesian_graph(grid((2, 2)), (2, 2))`.
#' Internally the vertices are all stored as tuples with a label in each dimension.

#' Vertices can be referred to by their tuples:
Expand All @@ -65,9 +65,7 @@ neighbors(g, (2, 2))

subgraph(v -> v[1] == 1, g)
subgraph(v -> v[2] == 2, g)
g[[(1, 1), (2, 2)]]

#' Note that this is similar to multidimensional array slicing, and we may support syntax like `subgraph(v, 1, :)` in the future.
subgraph(g, [(1, 1), (2, 2)])

#' You can also take [disjoint unions](https://en.wikipedia.org/wiki/Disjoint_union) or concatenations of graphs:
#+ term=true
Expand Down
4 changes: 1 addition & 3 deletions src/Graphs/abstractgraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@ vertextype(graph::AbstractGraph) = vertextype(typeof(graph))

# Function `f` maps original vertices `vᵢ` of `g`
# to new vertices `f(vᵢ)` of the output graph.
function rename_vertices(f::Function, g::AbstractGraph)
return set_vertices(g, f.(vertices(g)))
end
rename_vertices(f::Function, g::AbstractGraph) = not_implemented()

function rename_vertices(g::AbstractGraph, name_map)
return rename_vertices(v -> name_map[v], g)
Expand Down
3 changes: 3 additions & 0 deletions src/Graphs/partitionedgraphs/abstractpartitionedgraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ 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
function parent_vertex_to_vertex(pg::AbstractPartitionedGraph, parent_vertex)
return parent_vertex_to_vertex(unpartitioned_graph(pg), parent_vertex)
end
edgetype(pg::AbstractPartitionedGraph) = edgetype(unpartitioned_graph(pg))
parent_graph_type(pg::AbstractPartitionedGraph) = parent_graph_type(unpartitioned_graph(pg))
nv(pg::AbstractPartitionedGraph, pv::AbstractPartitionVertex) = length(vertices(pg, pv))
Expand Down
23 changes: 15 additions & 8 deletions src/Graphs/partitionedgraphs/partitionedgraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function partitionvertex(pg::PartitionedGraph, vertex)
return PartitionVertex(which_partition(pg)[vertex])
end

function partitionvertices(pg::PartitionedGraph, verts::Vector)
function partitionvertices(pg::PartitionedGraph, verts)
return unique(partitionvertex(pg, v) for v in verts)
end

Expand Down Expand Up @@ -94,9 +94,7 @@ function edges(pg::PartitionedGraph, partitionedges::Vector{<:PartitionEdge})
return unique(reduce(vcat, [edges(pg, pe) for pe in partitionedges]))
end

function boundary_partitionedges(
pg::PartitionedGraph, partitionvertices::Vector{<:PartitionVertex}; kwargs...
)
function boundary_partitionedges(pg::PartitionedGraph, partitionvertices; kwargs...)
return PartitionEdge.(
boundary_edges(partitioned_graph(pg), parent.(partitionvertices); kwargs...)
)
Expand Down Expand Up @@ -150,7 +148,7 @@ function delete_from_vertex_map!(
end

### PartitionedGraph Specific Functions
function induced_subgraph(pg::PartitionedGraph, vertices::Vector)
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))
Expand All @@ -165,8 +163,17 @@ function induced_subgraph(pg::PartitionedGraph, vertices::Vector)
return PartitionedGraph(sub_pg_graph, sub_partitioned_vertices), nothing
end

function induced_subgraph(
pg::PartitionedGraph, partitionverts::Vector{V}
) where {V<:PartitionVertex}
function partitionedgraph_induced_subgraph(
pg::PartitionedGraph, partitionverts::Vector{<:PartitionVertex}
)
return induced_subgraph(pg, vertices(pg, partitionverts))
end

function Graphs.induced_subgraph(pg::PartitionedGraph, vertices)
return partitionedgraph_induced_subgraph(pg, vertices)
end

# Fixes ambiguity error with `Graphs.jl`.
function Graphs.induced_subgraph(pg::PartitionedGraph, vertices::Vector{<:Integer})
return partitionedgraph_induced_subgraph(pg, vertices)
end
25 changes: 18 additions & 7 deletions src/abstractnamedgraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ parent_graph_type(graph::AbstractNamedGraph) = not_implemented()
rem_vertex!(graph::AbstractNamedGraph, vertex) = not_implemented()
add_vertex!(graph::AbstractNamedGraph, vertex) = not_implemented()

rename_vertices(f::Function, g::AbstractNamedGraph) = not_implemented()

# Convert vertex to parent vertex
# Inverse map of `parent_vertex_to_vertex`.
vertex_to_parent_vertex(graph::AbstractNamedGraph, vertex) = not_implemented()
Expand Down Expand Up @@ -521,29 +523,38 @@ function tree(graph::AbstractNamedGraph, parents)
return t
end

function _bfs_tree(graph::AbstractNamedGraph, vertex; kwargs...)
function namedgraph_bfs_tree(graph::AbstractNamedGraph, vertex; kwargs...)
return tree(graph, bfs_parents(graph, vertex; kwargs...))
end
# Disambiguation from Graphs.bfs_tree
function bfs_tree(graph::AbstractNamedGraph, vertex::Integer; kwargs...)
return _bfs_tree(graph, vertex; kwargs...)
return namedgraph_bfs_tree(graph, vertex; kwargs...)
end
function bfs_tree(graph::AbstractNamedGraph, vertex; kwargs...)
return namedgraph_bfs_tree(graph, vertex; kwargs...)
end
bfs_tree(graph::AbstractNamedGraph, vertex; kwargs...) = _bfs_tree(graph, vertex; kwargs...)

# Returns a Dictionary mapping a vertex to it's parent
# vertex in the traversal/spanning tree.
function _bfs_parents(graph::AbstractNamedGraph, vertex; kwargs...)
function namedgraph_bfs_parents(graph::AbstractNamedGraph, vertex; kwargs...)
parent_bfs_parents = bfs_parents(
parent_graph(graph), vertex_to_parent_vertex(graph, vertex); kwargs...
)
return Dictionary(vertices(graph), parent_vertices_to_vertices(graph, parent_bfs_parents))
# Works around issue in this `Dictionary` constructor:
# https://github.com/andyferris/Dictionaries.jl/blob/v0.4.1/src/Dictionary.jl#L139-L145
# when `inds` has holes. This removes the holes.
# TODO: Raise an issue with `Dictionaries.jl`.
## vertices_graph = Indices(collect(vertices(graph)))
# This makes the vertices ordered according to the parent vertices.
vertices_graph = parent_vertices_to_vertices(graph, parent_vertices(graph))
return Dictionary(vertices_graph, parent_vertices_to_vertices(graph, parent_bfs_parents))
end
# Disambiguation from Graphs.bfs_tree
function bfs_parents(graph::AbstractNamedGraph, vertex::Integer; kwargs...)
return _bfs_parents(graph, vertex; kwargs...)
return namedgraph_bfs_parents(graph, vertex; kwargs...)
end
function bfs_parents(graph::AbstractNamedGraph, vertex; kwargs...)
return _bfs_parents(graph, vertex; kwargs...)
return namedgraph_bfs_parents(graph, vertex; kwargs...)
end

#
Expand Down
25 changes: 20 additions & 5 deletions src/namedgraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ end
function parent_vertex_to_vertex(graph::GenericNamedGraph, parent_vertex)
return graph.parent_vertex_to_vertex[parent_vertex]
end

# TODO: Order them according to the internal ordering?
vertices(graph::GenericNamedGraph) = keys(graph.vertex_to_parent_vertex)

function add_vertex!(graph::GenericNamedGraph, vertex)
Expand All @@ -38,15 +40,20 @@ function rem_vertex!(graph::GenericNamedGraph, vertex)
last_vertex = last(graph.parent_vertex_to_vertex)
graph.parent_vertex_to_vertex[parent_vertex] = last_vertex
last_vertex = pop!(graph.parent_vertex_to_vertex)
# Insert the last vertex into the position of the vertex
# that is being deleted, then remove the last vertex.
graph.vertex_to_parent_vertex[last_vertex] = parent_vertex
delete!(graph.vertex_to_parent_vertex, vertex)
return true
end

function rename_vertices(f::Function, g::GenericNamedGraph)
# TODO: Could be `set_vertices(g, f.(g.parent_vertex_to_vertex))`.
return GenericNamedGraph(g.parent_graph, f.(g.parent_vertex_to_vertex))
end

function convert_vertextype(V::Type, graph::GenericNamedGraph)
return GenericNamedGraph(parent_graph(graph), convert(Vector{V}, vertices(graph)))
return GenericNamedGraph(
parent_graph(graph), convert(Vector{V}, graph.parent_vertex_to_vertex)
)
end

#
Expand Down Expand Up @@ -182,7 +189,7 @@ end
# graph = set_parent_graph(graph, copy(parent_graph(graph)))
# graph = set_vertices(graph, copy(vertices(graph)))
function copy(graph::GenericNamedGraph)
return GenericNamedGraph(copy(parent_graph(graph)), copy(vertices(graph)))
return GenericNamedGraph(copy(graph.parent_graph), copy(graph.parent_vertex_to_vertex))
end

edgetype(G::Type{<:GenericNamedGraph}) = NamedEdge{vertextype(G)}
Expand All @@ -202,7 +209,7 @@ end
is_directed(G::Type{<:GenericNamedGraph}) = is_directed(parent_graph_type(G))

# TODO: Implement an edgelist version
function induced_subgraph(graph::AbstractNamedGraph, subvertices)
function namedgraph_induced_subgraph(graph::AbstractGraph, subvertices)
subgraph = typeof(graph)(subvertices)
subvertices_set = Set(subvertices)
for src in subvertices
Expand All @@ -215,6 +222,14 @@ function induced_subgraph(graph::AbstractNamedGraph, subvertices)
return subgraph, nothing
end

function induced_subgraph(graph::AbstractNamedGraph, subvertices)
return namedgraph_induced_subgraph(graph, subvertices)
end

function induced_subgraph(graph::AbstractNamedGraph, subvertices::Vector{<:Integer})
return namedgraph_induced_subgraph(graph, subvertices)
end

#
# Type aliases
#
Expand Down
Loading

0 comments on commit 61bb29a

Please sign in to comment.