Skip to content

Commit 6846e87

Browse files
New similar_graph interface for AbstractDataGraph; misc bug fixes. (#94)
This PR includes some bug fixes and a new `AbstractDataGraph` specific method for the function `similar_graph` from the `NamedGraphs.GraphsExtensions `library. - Remove the `similar_graph` methods that take underlying_graph as an input, and reconsider parts of the code where this is used. - Removed `set_underlying_graph` function - GraphsExtensions.directed_graph now returns a default (say NamedDiGraph in that case) unless specified for concrete types (like DataGraph). --------- Co-authored-by: Matt Fishman <mtfishman@users.noreply.github.com>
1 parent b3fe03b commit 6846e87

13 files changed

Lines changed: 332 additions & 141 deletions

File tree

.github/workflows/IntegrationTest.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ on:
44
branches:
55
- "main"
66
tags: "*"
7+
paths:
8+
- "Project.toml"
79
pull_request_target:
810
types:
911
- "opened"

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "DataGraphs"
22
uuid = "b5a273c3-7e6c-41f6-98bd-8d7f1525a36a"
3-
version = "0.3.17"
3+
version = "0.4.0"
44
authors = ["Matthew Fishman <mfishman@flatironinstitute.org> and contributors"]
55

66
[workspace]
@@ -22,6 +22,6 @@ DataGraphsGraphsFlowsExt = "GraphsFlows"
2222
Dictionaries = "0.4"
2323
Graphs = "1"
2424
GraphsFlows = "0.1.1"
25-
NamedGraphs = "0.10"
25+
NamedGraphs = "0.11"
2626
SimpleTraits = "0.9"
2727
julia = "1.7"

docs/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
88
path = ".."
99

1010
[compat]
11-
DataGraphs = "0.3"
11+
DataGraphs = "0.4"
1212
Documenter = "1.10"
1313
ITensorFormatter = "0.2.27"
1414
Literate = "2.20.1"

examples/Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ NamedGraphs = "678767b0-92e7-4007-89e4-4527a8725b19"
77
path = ".."
88

99
[compat]
10-
DataGraphs = "0.3"
10+
DataGraphs = "0.4"
1111
Graphs = "1.12"
12-
NamedGraphs = "0.10"
12+
NamedGraphs = "0.11"

ext/DataGraphsGraphsFlowsExt/DataGraphsGraphsFlowsExt.jl

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,18 @@ module DataGraphsGraphsFlowsExt
22
using DataGraphs: AbstractDataGraph, underlying_graph
33
using GraphsFlows: GraphsFlows
44

5-
function GraphsFlows.mincut(graph::AbstractDataGraph, args...; kwargs...)
6-
return GraphsFlows.mincut(underlying_graph(graph), args...; kwargs...)
5+
function GraphsFlows.mincut(
6+
graph::AbstractDataGraph,
7+
source_vertex,
8+
target_vertex;
9+
kwargs...
10+
)
11+
return GraphsFlows.mincut(
12+
underlying_graph(graph),
13+
source_vertex,
14+
target_vertex;
15+
kwargs...
16+
)
717
end
18+
819
end

src/abstractdatagraph.jl

Lines changed: 114 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
using Dictionaries: Indices, set!, unset!
2-
using Graphs: Graphs, AbstractEdge, IsDirected, a_star, add_edge!, add_vertex!, edges, ne,
3-
nv, steiner_tree, vertices
4-
using NamedGraphs.GraphsExtensions: GraphsExtensions, add_vertices!, arrange_edge,
5-
incident_edges, is_edge_arranged, similar_graph, vertextype
2+
using Graphs: Graphs, AbstractEdge, IsDirected, a_star, add_edge!, add_vertex!, edges,
3+
indegree, induced_subgraph, ne, nv, outdegree, steiner_tree, vertices
4+
using NamedGraphs.GraphsExtensions: GraphsExtensions, add_edges!, add_vertices!,
5+
arrange_edge, incident_edges, is_edge_arranged, rem_edges, vertextype
66
using NamedGraphs.OrdinalIndexing: OrdinalSuffixedInteger
77
using NamedGraphs.SimilarType: similar_type
88
using NamedGraphs: NamedGraphs, AbstractEdges, AbstractNamedEdge, AbstractNamedGraph,
9-
AbstractVertices, position_graph_type
9+
AbstractVertices, NamedDiGraph, NamedGraph, position_graph_type, similar_graph
1010
using SimpleTraits: SimpleTraits, @traitfn, Not
1111

12-
is_underlying_graph(::Type{<:AbstractNamedGraph}) = true
13-
1412
abstract type AbstractDataGraph{V, VD, ED} <: AbstractNamedGraph{V} end
1513

1614
vertex_data_type(::Type{<:AbstractGraph}) = Any
@@ -77,7 +75,11 @@ function NamedGraphs.position_graph_type(type::Type{<:AbstractDataGraph})
7775
return position_graph_type(underlying_graph_type(type))
7876
end
7977

80-
Base.zero(graph_type::Type{<:AbstractDataGraph}) = similar_graph(graph_type)
78+
function Base.copyto!(dst_graph::AbstractDataGraph, src_graph::AbstractDataGraph)
79+
vertex_data(dst_graph) .= vertex_data(src_graph)
80+
edge_data(dst_graph) .= edge_data(src_graph)
81+
return dst_graph
82+
end
8183

8284
# Graphs overloads
8385
function Graphs.vertices(graph::AbstractDataGraph)
@@ -104,49 +106,100 @@ GraphsExtensions.directed_graph_type(::AbstractDataGraph) = not_implemented()
104106
GraphsExtensions.undirected_graph_type(::AbstractDataGraph) = not_implemented()
105107

106108
# Thase canot be implemented abstractly.
107-
function GraphsExtensions.convert_vertextype(vertextype::Type, graph::AbstractDataGraph)
108-
return not_implemented()
109+
GraphsExtensions.convert_vertextype(::Type, ::AbstractDataGraph) = not_implemented()
110+
111+
function Base.:(==)(dg1::AbstractDataGraph, dg2::AbstractDataGraph)
112+
underlying_graph(dg1) == underlying_graph(dg2) || return false
113+
vertex_data(dg1) == vertex_data(dg2) || return false
114+
edge_data(dg1) == edge_data(dg2) || return false
115+
return true
116+
end
117+
118+
# ============================ `similar_graph` (value domain) ============================ #
119+
120+
"""
121+
similar_graph(datagraph::AbstractDataGraph, D::Type)
122+
similar_graph(datagraph::AbstractDataGraph, D::Type, vertices)
123+
similar_graph(datagraph::AbstractDataGraph, VD::Type, ED::Type)
124+
similar_graph(datagraph::AbstractDataGraph, VD::Type, ED::Type, vertices)
125+
126+
Create an uninitialized data graph, similar to the provided `datagraph`, but with vertices
127+
defined by `vertices` and a vertex and edge data type `D`. One may also provide separate
128+
vertex and edge data types `VD` and `ED`.
129+
If vertices are not provided, then the graph is constructed with the same vertices and edges
130+
as the input graph.
131+
"""
132+
function NamedGraphs.similar_graph(
133+
graph::AbstractDataGraph
134+
)
135+
VD = vertex_data_type(graph)
136+
ED = edge_data_type(graph)
137+
return similar_graph(graph, VD, ED)
109138
end
110139

111-
# Fix for ambiguity error with `AbstractGraph` version
112-
function Graphs.degree(graph::AbstractDataGraph, vertex::Integer)
113-
return Graphs.degree(underlying_graph(graph), vertex)
140+
function NamedGraphs.similar_graph(
141+
graph::AbstractDataGraph,
142+
vertices
143+
)
144+
VD = vertex_data_type(graph)
145+
ED = edge_data_type(graph)
146+
return similar_graph(graph, VD, ED, vertices)
114147
end
115-
116-
# Fix for ambiguity error with `AbstractGraph` version
117-
function Graphs.dijkstra_shortest_paths(
118-
graph::AbstractDataGraph, vertices::Vector{<:Integer}
148+
function NamedGraphs.similar_graph(
149+
graph::AbstractDataGraph,
150+
D::Type
119151
)
120-
return Graphs.dijkstra_shortest_paths(underlying_graph(graph), vertices)
152+
return similar_graph(graph, D, D)
121153
end
122154

123-
# Fix for ambiguity error with `AbstractGraph` version
124-
function Graphs.eccentricity(graph::AbstractDataGraph, distmx::AbstractMatrix)
125-
return Graphs.eccentricity(underlying_graph(graph), distmx)
155+
function NamedGraphs.similar_graph(
156+
graph::AbstractDataGraph,
157+
D::Type,
158+
vertices
159+
)
160+
return similar_graph(graph, D, D, vertices)
126161
end
127162

128-
# Fix for ambiguity error with `AbstractGraph` version
129-
function Graphs.indegree(graph::AbstractDataGraph, vertex::Integer)
130-
return indegree(underlying_graph(graph), vertex)
131-
end
163+
function NamedGraphs.similar_graph(
164+
graph::AbstractDataGraph,
165+
VD::Type,
166+
ED::Type
167+
)
168+
new_graph = similar_graph(graph, VD, ED, vertices(graph))
169+
add_edges!(new_graph, edges(graph))
132170

133-
# Fix for ambiguity error with `AbstractGraph` version
134-
function Graphs.outdegree(graph::AbstractDataGraph, vertex::Integer)
135-
return outdegree(underlying_graph(graph), vertex)
171+
return new_graph
136172
end
137173

138-
# Fix for ambiguity error with `AbstractGraph` version
139-
function Graphs.a_star(
140-
graph::AbstractDataGraph, source::Integer, destination::Integer, args...
174+
# Base case(s) (overload these if fallback not wanted).
175+
@traitfn function NamedGraphs.similar_graph(
176+
graph::AbstractDataGraph::(!IsDirected),
177+
VD::Type,
178+
ED::Type,
179+
vertices
180+
)
181+
underlying_graph = similar_graph(NamedGraph, vertices)
182+
183+
return DataGraph(underlying_graph; vertex_data_type = VD, edge_data_type = ED)
184+
end
185+
@traitfn function NamedGraphs.similar_graph(
186+
graph::AbstractDataGraph::IsDirected,
187+
VD::Type,
188+
ED::Type,
189+
vertices
141190
)
142-
return a_star(underlying_graph(graph), source, destination, args...)
191+
underlying_graph = similar_graph(NamedDiGraph, vertices)
192+
193+
return DataGraph(underlying_graph; vertex_data_type = VD, edge_data_type = ED)
143194
end
144195

145196
# Fix for ambiguity error with `AbstractGraph` version
146-
@traitfn function Graphs.steiner_tree(
147-
graph::AbstractDataGraph::(!IsDirected), term_vert::Vector{<:Integer}, args...
197+
function Graphs.eccentricity(
198+
graph::AbstractDataGraph,
199+
vertex::Integer,
200+
distmx::AbstractMatrix{<:Real} = NamedGraphs.weights(graph)
148201
)
149-
return steiner_tree(underlying_graph(graph), term_vert, args...)
202+
return NamedGraphs.namedgraph_eccentricity(graph, vertex, distmx)
150203
end
151204

152205
@traitfn GraphsExtensions.directed_graph(graph::AbstractDataGraph::IsDirected) = graph
@@ -156,8 +209,15 @@ function reverse_data_direction(graph::AbstractDataGraph, edge::AbstractEdge, da
156209
return is_edge_arranged(graph, edge) ? data : reverse_data_direction(graph, data)
157210
end
158211

212+
# Fallback to constructing a concrete `DataGraph`.
159213
@traitfn function GraphsExtensions.directed_graph(graph::AbstractDataGraph::(!IsDirected))
160-
digraph = directed_graph(typeof(graph))(directed_graph(underlying_graph(graph)))
214+
underlying_digraph = similar_graph(NamedDiGraph, vertices(graph)) # edgeless
215+
216+
VD = vertex_data_type(graph)
217+
ED = edge_data_type(graph)
218+
219+
digraph = DataGraph(underlying_digraph; vertex_data_type = VD, edge_data_type = ED)
220+
161221
for v in vertices(graph)
162222
# TODO: Only loop over `keys(vertex_data(graph))`
163223
if isassigned(graph, v)
@@ -178,12 +238,9 @@ end
178238
end
179239

180240
function GraphsExtensions.rename_vertices(f::Function, graph::AbstractDataGraph)
181-
182241
# Uses the two-argument `similar_graph` method so the new graph has correct vertex type
183242
renamed_vertices = map(f, vertices(graph))
184-
renamed_graph = similar_graph(graph, eltype(renamed_vertices))
185-
186-
add_vertices!(renamed_graph, renamed_vertices)
243+
renamed_graph = similar_graph(graph, renamed_vertices)
187244

188245
for vertex in vertices(graph)
189246
if isassigned(graph, vertex)
@@ -203,13 +260,7 @@ function GraphsExtensions.rename_vertices(f::Function, graph::AbstractDataGraph)
203260
end
204261

205262
function Base.reverse(graph::AbstractDataGraph)
206-
reversed_graph = similar_graph(graph)
207-
for v in vertices(graph)
208-
add_vertex!(reversed_graph, v)
209-
if isassigned(graph, v)
210-
reversed_graph[v] = graph[v]
211-
end
212-
end
263+
reversed_graph = rem_edges(graph, edges(graph))
213264
for e in edges(graph)
214265
add_edge!(reversed_graph, reverse(e))
215266
if isassigned(graph, e)
@@ -281,24 +332,6 @@ function Graphs.rem_edge!(graph::AbstractDataGraph, edge)
281332
return graph
282333
end
283334

284-
# Fix ambiguity with:
285-
# Graphs.neighbors(graph::AbstractGraph, v::Integer)
286-
function Graphs.neighbors(graph::AbstractDataGraph, v::Integer)
287-
return Graphs.neighbors(underlying_graph(graph), v)
288-
end
289-
290-
# Fix ambiguity with:
291-
# Graphs.bfs_tree(graph::AbstractGraph, s::Integer; dir)
292-
function Graphs.bfs_tree(graph::AbstractDataGraph, s::Integer; kwargs...)
293-
return Graphs.bfs_tree(underlying_graph(graph), s; kwargs...)
294-
end
295-
296-
# Fix ambiguity with:
297-
# Graphs.dfs_tree(graph::AbstractGraph, s::Integer; dir)
298-
function Graphs.dfs_tree(graph::AbstractDataGraph, s::Integer; kwargs...)
299-
return Graphs.dfs_tree(underlying_graph(graph), s; kwargs...)
300-
end
301-
302335
function map_vertex_data(f, graph::AbstractGraph; vertices = nothing)
303336
new_graph = copy(graph)
304337
vs = isnothing(vertices) ? Graphs.vertices(graph) : vertices
@@ -342,13 +375,7 @@ function Base.get(default::Base.Callable, graph::AbstractDataGraph, key)
342375
end
343376

344377
function NamedGraphs.induced_subgraph_from_vertices(graph::AbstractDataGraph, subvertices)
345-
return induced_subgraph_datagraph(graph, subvertices)
346-
end
347-
function induced_subgraph_datagraph(graph::AbstractDataGraph, subvertices)
348-
underlying_subgraph, vlist =
349-
Graphs.induced_subgraph(underlying_graph(graph), subvertices)
350-
351-
subgraph = similar_graph(graph, underlying_subgraph)
378+
subgraph, vlist = similar_induced_subgraph(graph, subvertices)
352379

353380
for v in vertices(subgraph)
354381
if isassigned(graph, v)
@@ -360,12 +387,24 @@ function induced_subgraph_datagraph(graph::AbstractDataGraph, subvertices)
360387
subgraph[e] = graph[e]
361388
end
362389
end
390+
391+
# TODO: It would be nice to have `copyto!(subgraph, graph)` do the above.
392+
393+
return subgraph, vlist
394+
end
395+
396+
function similar_induced_subgraph(graph::AbstractDataGraph, subvertices)
397+
underlying_subgraph, vlist = induced_subgraph(underlying_graph(graph), subvertices)
398+
399+
VD = vertex_data_type(graph)
400+
ED = edge_data_type(graph)
401+
402+
subgraph = DataGraph(underlying_subgraph; vertex_data_type = VD, edge_data_type = ED)
403+
363404
return subgraph, vlist
364405
end
365406

366-
#
367-
# Printing
368-
#
407+
# ======================================= printing ======================================= #
369408

370409
function Base.show(io::IO, mime::MIME"text/plain", graph::AbstractDataGraph)
371410
println(io, "$(typeof(graph)) with $(nv(graph)) vertices:")

0 commit comments

Comments
 (0)