From 11ecc7788dbc928f74d4ef121273016658ee0b0a Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Tue, 10 Mar 2026 10:39:28 -0400 Subject: [PATCH 01/36] Indexing of `Vertex/EdgeDataView` now validates key w.r.t `isassigned`. --- src/dataview.jl | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/dataview.jl b/src/dataview.jl index 158b1c7..667cd94 100644 --- a/src/dataview.jl +++ b/src/dataview.jl @@ -67,17 +67,15 @@ function Base.isassigned(view::EdgeDataView, key::Pair) end Base.getindex(view::VertexOrEdgeDataView{K}, key::K) where {K} = _getindex(view, key) -function Base.getindex(view::VertexOrEdgeDataView, key) - return _getindex(view, to_graph_index(view.graph, key)) -end +Base.getindex(view::VertexOrEdgeDataView, key) = _getindex(view, key) function _getindex(view::VertexDataView, key) - key in keys(view) || throw(IndexError("VertexDataView does not contain index: $key")) - return get_vertex_data(view.graph, key) + isassigned(view, key) || throw(IndexError("VertexDataView does not contain index $key")) + return getindex(view.graph, key) end function _getindex(view::EdgeDataView, key) - key in keys(view) || throw(IndexError("EdgeDataView does not contain index: $key")) - return get_edge_data(view.graph, key) + isassigned(view, key) || throw(IndexError("EdgeDataView does not contain index $key")) + return getindex(view.graph, key) end # Support indexing with `Indices`. From cffab6733dddda7e937f4a531c9474597e190197 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Tue, 10 Mar 2026 10:41:03 -0400 Subject: [PATCH 02/36] Concrete `GenericNamedGraph` is now `is_underlying_graph = true`; `AbstractNamedGraph` now `is_underlying_graph = false`. --- src/abstractdatagraph.jl | 2 -- src/traits/isunderlyinggraph.jl | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index 3c63b6e..5584152 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -9,8 +9,6 @@ using NamedGraphs: NamedGraphs, AbstractEdges, AbstractNamedEdge, AbstractNamedG AbstractVertices, position_graph_type using SimpleTraits: SimpleTraits, @traitfn, Not -is_underlying_graph(::Type{<:AbstractNamedGraph}) = true - abstract type AbstractDataGraph{V, VD, ED} <: AbstractNamedGraph{V} end vertex_data_type(::Type{<:AbstractGraph}) = Any diff --git a/src/traits/isunderlyinggraph.jl b/src/traits/isunderlyinggraph.jl index 428925f..16d1e20 100644 --- a/src/traits/isunderlyinggraph.jl +++ b/src/traits/isunderlyinggraph.jl @@ -10,3 +10,6 @@ is_underlying_graph(::Type{<:AbstractGraph}) = false using Graphs.SimpleGraphs: AbstractSimpleGraph is_underlying_graph(::Type{<:AbstractSimpleGraph}) = true + +using NamedGraphs: GenericNamedGraph +is_underlying_graph(::Type{<:GenericNamedGraph}) = true From cd6d4c26db3c616a7ce77e54ca6e6e23ee01a135 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Tue, 10 Mar 2026 10:54:37 -0400 Subject: [PATCH 03/36] Improve handling of `underlying_graph` on `QuotientView` using traits. Now derives the `IsUnderlyingGraph` trait from the type of the `quotient_graph`. --- .../src/DataGraphsPartitionedGraphsExt.jl | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/lib/DataGraphsPartitionedGraphsExt/src/DataGraphsPartitionedGraphsExt.jl b/src/lib/DataGraphsPartitionedGraphsExt/src/DataGraphsPartitionedGraphsExt.jl index 3373975..2453de3 100644 --- a/src/lib/DataGraphsPartitionedGraphsExt/src/DataGraphsPartitionedGraphsExt.jl +++ b/src/lib/DataGraphsPartitionedGraphsExt/src/DataGraphsPartitionedGraphsExt.jl @@ -1,9 +1,9 @@ module DataGraphsPartitionedGraphsExt -using ..DataGraphs: AbstractDataGraph, DataGraph, DataGraphs, _DataGraph, _getindex, - edge_data, edgetype, get_edge_data, get_edges_data, get_index_data, get_vertex_data, - get_vertices_data, is_edge_assigned, is_graph_index_assigned, is_vertex_assigned, - set_edge_data!, set_edges_data!, set_index_data!, set_vertex_data!, set_vertices_data!, - underlying_graph, vertex_data +using ..DataGraphs: AbstractDataGraph, DataGraph, DataGraphs, IsUnderlyingGraph, _DataGraph, + _getindex, edge_data, edgetype, get_edge_data, get_edges_data, get_index_data, + get_vertex_data, get_vertices_data, is_edge_assigned, is_graph_index_assigned, + is_underlying_graph, is_vertex_assigned, set_edge_data!, set_edges_data!, + set_index_data!, set_vertex_data!, set_vertices_data!, underlying_graph, vertex_data using Dictionaries: Dictionary, IndexError, Indices using Graphs: Graphs, AbstractEdge, AbstractGraph, edges, vertices using NamedGraphs.GraphsExtensions: @@ -14,10 +14,11 @@ using NamedGraphs.PartitionedGraphs: AbstractPartitionedGraph, PartitionedGraph, QuotientVertexSlice, QuotientVertexVertex, QuotientVertexVertices, QuotientVertices, QuotientVerticesVertices, QuotientView, departition, has_quotientedge, has_quotientvertex, parent_graph_type, partitioned_vertices, partitionedgraph, - quotient_graph, quotient_graph_vertextype, quotientedges, quotientvertex, - quotientvertices, unpartitioned_graph + quotient_graph, quotient_graph_type, quotientedges, quotientvertex, quotientvertices, + unpartitioned_graph using NamedGraphs: NamedGraphs, Edges, Vertices, get_graph_index, to_edges, to_graph_index, to_vertices +using SimpleTraits: SimpleTraits, @traitfn, Not # ======================== DataGraphs interface for QuotientView ========================= # @@ -50,7 +51,14 @@ function DataGraphs.set_edge_data!(qv::QuotientView, val, e) return qv end -DataGraphs.underlying_graph(qv::QuotientView) = underlying_graph(copy(qv)) +function DataGraphs.is_underlying_graph(qv::Type{<:QuotientView}) + return is_underlying_graph(quotient_graph_type(qv)) +end + +@traitfn DataGraphs.underlying_graph(qv::QuotientView::IsUnderlyingGraph) = copy(qv) +@traitfn function DataGraphs.underlying_graph(qv::QuotientView::(!IsUnderlyingGraph)) + return underlying_graph(copy(qv)) +end function Base.isassigned(qv::QuotientView, ind) return DataGraphs.isassigned_datagraph(qv, to_graph_index(qv, ind)) From ec32ddf60d773dd00b71ab8fe55c39530f74fe86 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Tue, 10 Mar 2026 10:55:05 -0400 Subject: [PATCH 04/36] Changes some function calls to field accessors for explictness. --- src/datagraph.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/datagraph.jl b/src/datagraph.jl index cf317f1..2f38ed4 100644 --- a/src/datagraph.jl +++ b/src/datagraph.jl @@ -69,7 +69,7 @@ function Base.copy(graph::DataGraph) # Need to manually copy the keys of Dictionaries, see: # https://github.com/andyferris/Dictionaries.jl/issues/98 return _DataGraph( - copy(underlying_graph(graph)), copy(vertex_data(graph)), copy(edge_data(graph)) + copy(graph.underlying_graph), copy(graph.vertex_data), copy(graph.edge_data) ) end From acce519154904503735d9f7f76fcc2a4f29b257d Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Tue, 10 Mar 2026 10:55:40 -0400 Subject: [PATCH 05/36] Overhaul `similar_graph` on `AbstractDataGraph`; define new four argument interface function. --- src/abstractdatagraph.jl | 165 ++++++++++++++++++++++++++++++++++++--- src/datagraph.jl | 27 ++++--- 2 files changed, 171 insertions(+), 21 deletions(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index 5584152..20dd760 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -1,12 +1,12 @@ using Dictionaries: Indices, set!, unset! -using Graphs: Graphs, AbstractEdge, IsDirected, a_star, add_edge!, add_vertex!, edges, ne, - nv, steiner_tree, vertices +using Graphs: Graphs, AbstractEdge, IsDirected, a_star, add_edge!, add_vertex!, edges, + indegree, ne, nv, outdegree, steiner_tree, vertices using NamedGraphs.GraphsExtensions: GraphsExtensions, add_vertices!, arrange_edge, incident_edges, is_edge_arranged, similar_graph, vertextype using NamedGraphs.OrdinalIndexing: OrdinalSuffixedInteger using NamedGraphs.SimilarType: similar_type using NamedGraphs: NamedGraphs, AbstractEdges, AbstractNamedEdge, AbstractNamedGraph, - AbstractVertices, position_graph_type + AbstractVertices, NamedGraph, position_graph_type using SimpleTraits: SimpleTraits, @traitfn, Not abstract type AbstractDataGraph{V, VD, ED} <: AbstractNamedGraph{V} end @@ -102,8 +102,153 @@ GraphsExtensions.directed_graph_type(::AbstractDataGraph) = not_implemented() GraphsExtensions.undirected_graph_type(::AbstractDataGraph) = not_implemented() # Thase canot be implemented abstractly. -function GraphsExtensions.convert_vertextype(vertextype::Type, graph::AbstractDataGraph) - return not_implemented() +GraphsExtensions.convert_vertextype(::Type, ::AbstractDataGraph) = not_implemented() + +# =================================== `similar_graph` ==================================== # + +# Construct a similar `AbstractDataGraph` with `vertices` and `edges`. +function GraphsExtensions.similar_graph( + graph::AbstractDataGraph, + vertices, + edges + ) + new_underlying_graph = similar_graph(underlying_graph(graph), vertices, edges) + return similar_graph(graph, new_underlying_graph) +end + +# Construct `graph_type` with `vertices` and `edges`. +function GraphsExtensions.similar_graph( + graph_type::Type{<:AbstractDataGraph}, + vertices, + edges + ) + underlying_graph = similar_graph(underlying_graph_type(graph_type), vertices, edges) + return similar_graph(graph_type, underlying_graph) +end + +# Construct a similar `AbstractDataGraph` defined by an `underlying_graph_type` with +# `vertex_data_type` and `edge_data_type`. +function GraphsExtensions.similar_graph( + graph::AbstractDataGraph, + underlying_graph_type::Type{<:AbstractGraph}, + vertex_data_type, + edge_data_type + ) + underlying_graph = similar_graph(underlying_graph_type, vertices(graph), edges(graph)) + return similar_graph(graph, underlying_graph, vertex_data_type, edge_data_type) +end +function GraphsExtensions.similar_graph( + graph::AbstractDataGraph, + underlying_graph_type::Type{<:AbstractGraph} + ) + underlying_graph = similar_graph(underlying_graph_type, vertices(graph), edges(graph)) + return similar_graph(graph, underlying_graph_type) +end + +# Construct a similar `AbstractDataGraph` defined by `underlying_graph` with `vertex_data_type` and `edge_data_type`. +# To be specialized (has fallback). +""" + similar_graph(datagraph::AbstractDataGraph, graph::AbstractGraph, [VD=vertex_data_type(datagraph), ED=edge_data_type(datagraph)]) + similar_graph(datagraph::AbstractDataGraph, G, [VD=vertex_data_type(datagraph), ED=edge_data_type(datagraph)]) + +Create an uninitialized data graph, similar to the provided `datagraph`, but with underlying +graph defined by `graph`. If instead a type `G` is given as the second argument, +then an empty underlying graph is first constructed using `graph = similar_graph(G)`. +Optionally, one may specify the vertex and edge data types, which default to those of the +provided source `datagraph`. + +Custom `AbstractDataGraph` subtypes may specialize on first method (either the two or four argument version) +to choose the return type of the resulting graph, based on the arguments. +If they do not specialize on this method, then the default is +`DataGraph(graph; vertex_data_type, edge_data_type)`. +""" +function GraphsExtensions.similar_graph( + ::AbstractDataGraph, + underlying_graph::AbstractGraph, + vertex_data_type, + edge_data_type + ) + return DataGraph(underlying_graph; vertex_data_type, edge_data_type) +end +function GraphsExtensions.similar_graph( + graph::AbstractDataGraph, + underlying_graph::AbstractGraph + ) + VD = vertex_data_type(graph) + ED = edge_data_type(graph) + return similar_graph(graph, underlying_graph, VD, ED) +end + +# Construct a subtype of `graph_type` with an empty underlying_graph of type `underlying_graph_type` +# and `vertex_data_type` and `edge_data_type`. +function GraphsExtensions.similar_graph( + graph_type::Type{<:AbstractDataGraph}, + underlying_graph_type::Type{<:AbstractGraph}, + vertex_data_type, + edge_data_type + ) + underlying_graph = similar_graph(underlying_graph_type) + return similar_graph(graph_type, underlying_graph, vertex_data_type, edge_data_type) +end +function GraphsExtensions.similar_graph( + graph_type::Type{<:AbstractDataGraph}, + underlying_graph_type::Type{<:AbstractGraph} + ) + underlying_graph = similar_graph(underlying_graph_type) + return similar_graph(graph_type, underlying_graph) +end + +# Construct a subtype of `graph_type` defined by `underlying_graph` with `vertex_data_type` and `edge_data_type`. +# To be specialized if `graph_type` doesn't have the appropriate constructor. One can +# specialize on either the two or four argument method. +""" + similar_graph(DG::Type{<:AbstractDataGraph}, graph::AbstractGraph) + similar_graph(DG::Type{<:AbstractDataGraph}, graph::AbstractGraph, VD, ED) + + similar_graph(DG::Type{<:AbstractDataGraph}, G) + similar_graph(DG::Type{<:AbstractDataGraph}, G, VD, ED) + +Create an uninitialized data graph that acts like the specified data graph type +`DG`, but with underlying graph defined by `graph`. +If instead a type `G` is given as the second argument, then +an empty underlying graph is first constructed using `graph = similar_graph(G)`. +Optionally, one may also specify the vertex and edge data types of the resulting data graph. + +By default, calls the constructors `DG(graph)` and `DG(graph, VD, ED)` respectively. +A given custom `AbstractDataGraph` subtype may specialize on the first two methods above +(in terms a graph `graph`) if such constructors do not exist for that subtype. +""" +function GraphsExtensions.similar_graph( + graph_type::Type{<:AbstractDataGraph}, + underlying_graph::AbstractGraph, + vertex_data_type, + edge_data_type + ) + return graph_type(underlying_graph, vertex_data_type, edge_data_type) +end +function GraphsExtensions.similar_graph( + graph_type::Type{<:AbstractDataGraph}, + underlying_graph::AbstractGraph + ) + return graph_type(underlying_graph) +end + +# Set the underlying graph of a data graph, preserving data. Graphs must match. +function set_underlying_graph(datagraph::AbstractDataGraph, graph::AbstractGraph) + if vertices(datagraph) != vertices(graph) || edges(datagraph) != edges(graph) + throw( + ArgumentError( + "New underlying graph must have the same vertices and edges as the data graph" + ) + ) + end + + new_datagraph = similar_graph(datagraph, graph) + + vertex_data(new_datagraph) .= vertex_data(datagraph) + edge_data(new_datagraph) .= edge_data(datagraph) + + return new_datagraph end # Fix for ambiguity error with `AbstractGraph` version @@ -155,7 +300,7 @@ function reverse_data_direction(graph::AbstractDataGraph, edge::AbstractEdge, da end @traitfn function GraphsExtensions.directed_graph(graph::AbstractDataGraph::(!IsDirected)) - digraph = directed_graph(typeof(graph))(directed_graph(underlying_graph(graph))) + digraph = similar_graph(graph, directed_graph(underlying_graph(graph))) for v in vertices(graph) # TODO: Only loop over `keys(vertex_data(graph))` if isassigned(graph, v) @@ -176,12 +321,9 @@ end end function GraphsExtensions.rename_vertices(f::Function, graph::AbstractDataGraph) - # Uses the two-argument `similar_graph` method so the new graph has correct vertex type renamed_vertices = map(f, vertices(graph)) - renamed_graph = similar_graph(graph, eltype(renamed_vertices)) - - add_vertices!(renamed_graph, renamed_vertices) + renamed_graph = similar_graph(graph, renamed_vertices) for vertex in vertices(graph) if isassigned(graph, vertex) @@ -201,9 +343,8 @@ function GraphsExtensions.rename_vertices(f::Function, graph::AbstractDataGraph) end function Base.reverse(graph::AbstractDataGraph) - reversed_graph = similar_graph(graph) + reversed_graph = similar_graph(graph, vertices(graph)) for v in vertices(graph) - add_vertex!(reversed_graph, v) if isassigned(graph, v) reversed_graph[v] = graph[v] end diff --git a/src/datagraph.jl b/src/datagraph.jl index 2f38ed4..da3a32e 100644 --- a/src/datagraph.jl +++ b/src/datagraph.jl @@ -53,16 +53,24 @@ edge_data_type(G::Type{<:DataGraph}) = eltype(fieldtype(G, :edge_data)) # Extras -function GraphsExtensions.similar_graph(T::Type{<:DataGraph}) - similar_underlying_graph = similar_graph(underlying_graph_type(T)) - return T(similar_underlying_graph) +# Overwrite the `AbstractDataGraph` fallback (even though they coincide for `DataGraph`) +function GraphsExtensions.similar_graph( + ::DataGraph, + underlying_graph::AbstractGraph, + vertex_data_type, + edge_data_type + ) + return similar_graph(DataGraph, underlying_graph, vertex_data_type, edge_data_type) end -function GraphsExtensions.similar_graph(dg::DataGraph, underlying_graph::AbstractGraph) - return DataGraph( - underlying_graph; - vertex_data_type = vertex_data_type(dg), - edge_data_type = edge_data_type(dg) + +# Constructor method needs overwritten. +function GraphsExtensions.similar_graph( + T::Type{<:DataGraph}, + underlying_graph::AbstractGraph, + vertex_data_type = vertex_data_type(T), + edge_data_type = edge_data_type(T) ) + return T(underlying_graph; vertex_data_type, edge_data_type) end function Base.copy(graph::DataGraph) @@ -74,7 +82,8 @@ function Base.copy(graph::DataGraph) end function DataGraph{V}( - underlying_graph::AbstractGraph; vertex_data_type::Type = Any, + underlying_graph::AbstractGraph; + vertex_data_type::Type = Any, edge_data_type::Type = Any ) where {V} converted_underlying_graph = convert_vertextype(V, underlying_graph) From 953c8062e4ffc35592fd9332ab32eb81f41d4c90 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Fri, 13 Mar 2026 12:23:13 -0400 Subject: [PATCH 06/36] Fix method ambiguity in `GraphsFlows.mincut` --- .../DataGraphsGraphsFlowsExt.jl | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ext/DataGraphsGraphsFlowsExt/DataGraphsGraphsFlowsExt.jl b/ext/DataGraphsGraphsFlowsExt/DataGraphsGraphsFlowsExt.jl index 4b181e8..e5dd703 100644 --- a/ext/DataGraphsGraphsFlowsExt/DataGraphsGraphsFlowsExt.jl +++ b/ext/DataGraphsGraphsFlowsExt/DataGraphsGraphsFlowsExt.jl @@ -2,7 +2,18 @@ module DataGraphsGraphsFlowsExt using DataGraphs: AbstractDataGraph, underlying_graph using GraphsFlows: GraphsFlows -function GraphsFlows.mincut(graph::AbstractDataGraph, args...; kwargs...) - return GraphsFlows.mincut(underlying_graph(graph), args...; kwargs...) +function GraphsFlows.mincut( + graph::AbstractDataGraph, + source_vertex, + target_vertex; + kwargs... + ) + return GraphsFlows.mincut( + underlying_graph(graph), + source_vertex, + target_vertex; + kwargs... + ) end + end From 6c8eacd006f117eb08b97ceabd2927a38db42a23 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Fri, 13 Mar 2026 12:24:12 -0400 Subject: [PATCH 07/36] Fix `DataGraph{V}` constructor failing when input data graph does not have all edges assigned. --- src/datagraph.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/datagraph.jl b/src/datagraph.jl index da3a32e..60edbe4 100644 --- a/src/datagraph.jl +++ b/src/datagraph.jl @@ -116,12 +116,12 @@ DataGraph{V}(graph::DataGraph{V}) where {V} = copy(graph) function DataGraph{V}(graph::DataGraph) where {V} # TODO: Make sure this properly copies converted_underlying_graph = convert_vertextype(V, underlying_graph(graph)) - converted_vertex_data = Dictionary{V}(vertex_data(graph)) - # This doesn't convert properly. - # converted_edge_data = Dictionary{edgetype(converted_underlying_graph)}(edge_data(graph)) + converted_vertex_data = Dictionary{V}(assigned_vertex_data(graph)) + + old_edge_data = assigned_edge_data(graph) converted_edge_data = Dictionary( - edgetype(converted_underlying_graph).(keys(edge_data(graph))), - values(edge_data(graph)) + edgetype(converted_underlying_graph).(keys(old_edge_data)), + collect(old_edge_data) ) return _DataGraph( converted_underlying_graph, From 3922c47cf9f47d7871246cde3e95ae504a5826e0 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Fri, 13 Mar 2026 12:24:31 -0400 Subject: [PATCH 08/36] Upgrade `NamedGraphs.jl` to v0.11 --- Project.toml | 2 +- examples/Project.toml | 2 +- test/Project.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index 140c7af..bff578b 100644 --- a/Project.toml +++ b/Project.toml @@ -22,6 +22,6 @@ DataGraphsGraphsFlowsExt = "GraphsFlows" Dictionaries = "0.4" Graphs = "1" GraphsFlows = "0.1.1" -NamedGraphs = "0.10" +NamedGraphs = "0.11" SimpleTraits = "0.9" julia = "1.7" diff --git a/examples/Project.toml b/examples/Project.toml index 44b4e85..a5215d0 100644 --- a/examples/Project.toml +++ b/examples/Project.toml @@ -9,4 +9,4 @@ path = ".." [compat] DataGraphs = "0.3" Graphs = "1.12" -NamedGraphs = "0.10" +NamedGraphs = "0.11" diff --git a/test/Project.toml b/test/Project.toml index c3279fc..0a92038 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -20,7 +20,7 @@ Dictionaries = "0.4.4" Graphs = "1.12" GraphsFlows = "0.1.1" ITensorPkgSkeleton = "0.3.42" -NamedGraphs = "0.10" +NamedGraphs = "0.11" SafeTestsets = "0.1" Suppressor = "0.2.8" Test = "1.10" From b4038c1235734d6c63e5fc10161c2589cf80f568 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Fri, 13 Mar 2026 12:26:43 -0400 Subject: [PATCH 09/36] Version bump to v0.4.0 --- Project.toml | 2 +- docs/Project.toml | 2 +- examples/Project.toml | 2 +- test/Project.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Project.toml b/Project.toml index bff578b..4f4bc03 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "DataGraphs" uuid = "b5a273c3-7e6c-41f6-98bd-8d7f1525a36a" -version = "0.3.17" +version = "0.4.0" authors = ["Matthew Fishman and contributors"] [workspace] diff --git a/docs/Project.toml b/docs/Project.toml index 6dc61c2..23e2179 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -8,7 +8,7 @@ Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306" path = ".." [compat] -DataGraphs = "0.3" +DataGraphs = "0.4" Documenter = "1.10" ITensorFormatter = "0.2.27" Literate = "2.20.1" diff --git a/examples/Project.toml b/examples/Project.toml index a5215d0..74d4a80 100644 --- a/examples/Project.toml +++ b/examples/Project.toml @@ -7,6 +7,6 @@ NamedGraphs = "678767b0-92e7-4007-89e4-4527a8725b19" path = ".." [compat] -DataGraphs = "0.3" +DataGraphs = "0.4" Graphs = "1.12" NamedGraphs = "0.11" diff --git a/test/Project.toml b/test/Project.toml index 0a92038..5ebc3e8 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -15,7 +15,7 @@ path = ".." [compat] Aqua = "0.8.11" -DataGraphs = "0.3" +DataGraphs = "0.4" Dictionaries = "0.4.4" Graphs = "1.12" GraphsFlows = "0.1.1" From df280344df1c517393f1f1b3eb99b3d0662dca9f Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Mon, 23 Mar 2026 14:18:03 -0400 Subject: [PATCH 10/36] Change `similar_graph` import from `GraphExtensions` to `NamedGraphs`. --- src/abstractdatagraph.jl | 24 +++++++++---------- src/datagraph.jl | 10 ++++---- .../src/DataGraphsPartitionedGraphsExt.jl | 7 +++--- test/test_partitionedgraphs.jl | 6 ++--- 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index 20dd760..11d16f2 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -2,11 +2,11 @@ using Dictionaries: Indices, set!, unset! using Graphs: Graphs, AbstractEdge, IsDirected, a_star, add_edge!, add_vertex!, edges, indegree, ne, nv, outdegree, steiner_tree, vertices using NamedGraphs.GraphsExtensions: GraphsExtensions, add_vertices!, arrange_edge, - incident_edges, is_edge_arranged, similar_graph, vertextype + incident_edges, is_edge_arranged, vertextype using NamedGraphs.OrdinalIndexing: OrdinalSuffixedInteger using NamedGraphs.SimilarType: similar_type using NamedGraphs: NamedGraphs, AbstractEdges, AbstractNamedEdge, AbstractNamedGraph, - AbstractVertices, NamedGraph, position_graph_type + AbstractVertices, NamedGraph, position_graph_type, similar_graph using SimpleTraits: SimpleTraits, @traitfn, Not abstract type AbstractDataGraph{V, VD, ED} <: AbstractNamedGraph{V} end @@ -107,7 +107,7 @@ GraphsExtensions.convert_vertextype(::Type, ::AbstractDataGraph) = not_implement # =================================== `similar_graph` ==================================== # # Construct a similar `AbstractDataGraph` with `vertices` and `edges`. -function GraphsExtensions.similar_graph( +function NamedGraphs.similar_graph( graph::AbstractDataGraph, vertices, edges @@ -117,7 +117,7 @@ function GraphsExtensions.similar_graph( end # Construct `graph_type` with `vertices` and `edges`. -function GraphsExtensions.similar_graph( +function NamedGraphs.similar_graph( graph_type::Type{<:AbstractDataGraph}, vertices, edges @@ -128,7 +128,7 @@ end # Construct a similar `AbstractDataGraph` defined by an `underlying_graph_type` with # `vertex_data_type` and `edge_data_type`. -function GraphsExtensions.similar_graph( +function NamedGraphs.similar_graph( graph::AbstractDataGraph, underlying_graph_type::Type{<:AbstractGraph}, vertex_data_type, @@ -137,7 +137,7 @@ function GraphsExtensions.similar_graph( underlying_graph = similar_graph(underlying_graph_type, vertices(graph), edges(graph)) return similar_graph(graph, underlying_graph, vertex_data_type, edge_data_type) end -function GraphsExtensions.similar_graph( +function NamedGraphs.similar_graph( graph::AbstractDataGraph, underlying_graph_type::Type{<:AbstractGraph} ) @@ -162,7 +162,7 @@ to choose the return type of the resulting graph, based on the arguments. If they do not specialize on this method, then the default is `DataGraph(graph; vertex_data_type, edge_data_type)`. """ -function GraphsExtensions.similar_graph( +function NamedGraphs.similar_graph( ::AbstractDataGraph, underlying_graph::AbstractGraph, vertex_data_type, @@ -170,7 +170,7 @@ function GraphsExtensions.similar_graph( ) return DataGraph(underlying_graph; vertex_data_type, edge_data_type) end -function GraphsExtensions.similar_graph( +function NamedGraphs.similar_graph( graph::AbstractDataGraph, underlying_graph::AbstractGraph ) @@ -181,7 +181,7 @@ end # Construct a subtype of `graph_type` with an empty underlying_graph of type `underlying_graph_type` # and `vertex_data_type` and `edge_data_type`. -function GraphsExtensions.similar_graph( +function NamedGraphs.similar_graph( graph_type::Type{<:AbstractDataGraph}, underlying_graph_type::Type{<:AbstractGraph}, vertex_data_type, @@ -190,7 +190,7 @@ function GraphsExtensions.similar_graph( underlying_graph = similar_graph(underlying_graph_type) return similar_graph(graph_type, underlying_graph, vertex_data_type, edge_data_type) end -function GraphsExtensions.similar_graph( +function NamedGraphs.similar_graph( graph_type::Type{<:AbstractDataGraph}, underlying_graph_type::Type{<:AbstractGraph} ) @@ -218,7 +218,7 @@ By default, calls the constructors `DG(graph)` and `DG(graph, VD, ED)` respectiv A given custom `AbstractDataGraph` subtype may specialize on the first two methods above (in terms a graph `graph`) if such constructors do not exist for that subtype. """ -function GraphsExtensions.similar_graph( +function NamedGraphs.similar_graph( graph_type::Type{<:AbstractDataGraph}, underlying_graph::AbstractGraph, vertex_data_type, @@ -226,7 +226,7 @@ function GraphsExtensions.similar_graph( ) return graph_type(underlying_graph, vertex_data_type, edge_data_type) end -function GraphsExtensions.similar_graph( +function NamedGraphs.similar_graph( graph_type::Type{<:AbstractDataGraph}, underlying_graph::AbstractGraph ) diff --git a/src/datagraph.jl b/src/datagraph.jl index 60edbe4..7e59f22 100644 --- a/src/datagraph.jl +++ b/src/datagraph.jl @@ -1,8 +1,8 @@ using Dictionaries: Dictionary using Graphs: Graphs, edgetype, has_edge, has_vertex -using NamedGraphs.GraphsExtensions: convert_vertextype, directed_graph, directed_graph_type, - rename_vertices, similar_graph, vertextype -using NamedGraphs: GenericNamedGraph +using NamedGraphs.GraphsExtensions: + convert_vertextype, directed_graph, directed_graph_type, rename_vertices, vertextype +using NamedGraphs: GenericNamedGraph, similar_graph # TODO: define VertexDataGraph, a graph with only data on the # vertices, and EdgeDataGraph, a graph with only data on the edges. @@ -54,7 +54,7 @@ edge_data_type(G::Type{<:DataGraph}) = eltype(fieldtype(G, :edge_data)) # Extras # Overwrite the `AbstractDataGraph` fallback (even though they coincide for `DataGraph`) -function GraphsExtensions.similar_graph( +function NamedGraphs.similar_graph( ::DataGraph, underlying_graph::AbstractGraph, vertex_data_type, @@ -64,7 +64,7 @@ function GraphsExtensions.similar_graph( end # Constructor method needs overwritten. -function GraphsExtensions.similar_graph( +function NamedGraphs.similar_graph( T::Type{<:DataGraph}, underlying_graph::AbstractGraph, vertex_data_type = vertex_data_type(T), diff --git a/src/lib/DataGraphsPartitionedGraphsExt/src/DataGraphsPartitionedGraphsExt.jl b/src/lib/DataGraphsPartitionedGraphsExt/src/DataGraphsPartitionedGraphsExt.jl index 2453de3..78a8c9a 100644 --- a/src/lib/DataGraphsPartitionedGraphsExt/src/DataGraphsPartitionedGraphsExt.jl +++ b/src/lib/DataGraphsPartitionedGraphsExt/src/DataGraphsPartitionedGraphsExt.jl @@ -6,8 +6,7 @@ using ..DataGraphs: AbstractDataGraph, DataGraph, DataGraphs, IsUnderlyingGraph, set_index_data!, set_vertex_data!, set_vertices_data!, underlying_graph, vertex_data using Dictionaries: Dictionary, IndexError, Indices using Graphs: Graphs, AbstractEdge, AbstractGraph, edges, vertices -using NamedGraphs.GraphsExtensions: - add_vertices!, edge_subgraph, similar_graph, subgraph, vertextype +using NamedGraphs.GraphsExtensions: add_vertices!, edge_subgraph, subgraph, vertextype using NamedGraphs.PartitionedGraphs: AbstractPartitionedGraph, PartitionedGraph, PartitionedGraphs, PartitionedView, QuotientEdge, QuotientEdgeEdge, QuotientEdgeEdges, QuotientEdgeSlice, QuotientEdges, QuotientVertex, QuotientVertexOrEdge, @@ -16,8 +15,8 @@ using NamedGraphs.PartitionedGraphs: AbstractPartitionedGraph, PartitionedGraph, has_quotientvertex, parent_graph_type, partitioned_vertices, partitionedgraph, quotient_graph, quotient_graph_type, quotientedges, quotientvertex, quotientvertices, unpartitioned_graph -using NamedGraphs: - NamedGraphs, Edges, Vertices, get_graph_index, to_edges, to_graph_index, to_vertices +using NamedGraphs: NamedGraphs, Edges, Vertices, get_graph_index, similar_graph, to_edges, + to_graph_index, to_vertices using SimpleTraits: SimpleTraits, @traitfn, Not # ======================== DataGraphs interface for QuotientView ========================= # diff --git a/test/test_partitionedgraphs.jl b/test/test_partitionedgraphs.jl index 6f18ee4..1f3e2d2 100644 --- a/test/test_partitionedgraphs.jl +++ b/test/test_partitionedgraphs.jl @@ -5,14 +5,14 @@ using DataGraphs: DataGraphs, AbstractDataGraph, DataGraph, EdgeDataView, Vertex vertex_data, vertex_data_type using Dictionaries: Dictionary, IndexError, Indices using Graphs: AbstractGraph, dst, edges, edgetype, has_edge, has_vertex, src, vertices -using NamedGraphs.GraphsExtensions: GraphsExtensions, similar_graph, subgraph, vertextype +using NamedGraphs.GraphsExtensions: GraphsExtensions, subgraph, vertextype using NamedGraphs.NamedGraphGenerators: named_path_graph using NamedGraphs.PartitionedGraphs: PartitionedGraph, PartitionedGraphs, QuotientEdge, QuotientEdges, QuotientVertex, QuotientVertexOrEdge, QuotientVertexVertex, QuotientVertexVertices, QuotientVertices, QuotientVerticesVertices, QuotientView, departition, partitionedgraph, quotient_graph, quotientedges, quotientvertices, unpartition -using NamedGraphs: NamedGraphs, Edges, NamedGraph, Vertices +using NamedGraphs: NamedGraphs, Edges, NamedGraph, Vertices, similar_graph using Test: @test, @test_throws, @testset struct TestDataGraph{V, VD, ED, DG <: DataGraph{V, VD, ED}, QDG} <: @@ -43,7 +43,7 @@ end DataGraphs.underlying_graph(graph::TestDataGraph) = underlying_graph(graph.graph) PartitionedGraphs.quotient_graph(graph::TestDataGraph) = graph.quotientgraph -function GraphsExtensions.similar_graph(dg::TestDataGraph, graph::AbstractGraph) +function NamedGraphs.similar_graph(dg::TestDataGraph, graph::AbstractGraph) dg = similar_graph(dg.graph, graph) return TestDataGraph(dg) end From f9b105e1136f42726337297d44d86cd2c8d11d10 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Mon, 23 Mar 2026 14:19:24 -0400 Subject: [PATCH 11/36] Define `AbstractDataGraph` method for `copyto!`; remove method for function `zero`. --- src/abstractdatagraph.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index 11d16f2..651972c 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -75,7 +75,11 @@ function NamedGraphs.position_graph_type(type::Type{<:AbstractDataGraph}) return position_graph_type(underlying_graph_type(type)) end -Base.zero(graph_type::Type{<:AbstractDataGraph}) = similar_graph(graph_type) +function Base.copyto!(dst_graph::AbstractDataGraph, src_graph::AbstractDataGraph) + vertex_data(dst_graph) .= vertex_data(src_graph) + edge_data(dst_graph) .= edge_data(src_graph) + return dst_graph +end # Graphs overloads function Graphs.vertices(graph::AbstractDataGraph) From 966997d7cc8b24859873c69af1943e70ff9a9294 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Mon, 23 Mar 2026 16:29:28 -0400 Subject: [PATCH 12/36] Fix: broadcasting .= with data views should now error if indices do not match. --- src/dataview.jl | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/dataview.jl b/src/dataview.jl index 667cd94..9de6768 100644 --- a/src/dataview.jl +++ b/src/dataview.jl @@ -98,9 +98,17 @@ function Base.setindex!(view::EdgeDataView{<:Any, V}, data::V, key::Pair) where end function Base.copyto!(dest::VertexOrEdgeDataView, bc::Dictionaries.BroadcastedDictionary) + + # Deal with the case where `bc` contains pairs. + graph_keys = map(key -> to_graph_index(dest.graph, key), keys(bc)) + + # Check indices match, but don't care about order. + isempty(setdiff(graph_keys, keys(dest))) || throw(IndexError("Indices do not match")) + for (key, val) in pairs(bc) - dest[to_graph_index(dest.graph, key)] = val + dest[graph_keys[key]] = val end + return dest end From 6c8d3fc1ee0d302a6e1a8b0339525cf374525059 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Mon, 23 Mar 2026 16:29:49 -0400 Subject: [PATCH 13/36] Misc changes --- src/abstractdatagraph.jl | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index 651972c..5d7ad78 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -108,6 +108,13 @@ GraphsExtensions.undirected_graph_type(::AbstractDataGraph) = not_implemented() # Thase canot be implemented abstractly. GraphsExtensions.convert_vertextype(::Type, ::AbstractDataGraph) = not_implemented() +function Base.:(==)(dg1::AbstractDataGraph, dg2::AbstractDataGraph) + underlying_graph(dg1) == underlying_graph(dg2) || return false + vertex_data(dg1) == vertex_data(dg2) || return false + edge_data(dg1) == edge_data(dg2) || return false + return true +end + # =================================== `similar_graph` ==================================== # # Construct a similar `AbstractDataGraph` with `vertices` and `edges`. @@ -146,7 +153,7 @@ function NamedGraphs.similar_graph( underlying_graph_type::Type{<:AbstractGraph} ) underlying_graph = similar_graph(underlying_graph_type, vertices(graph), edges(graph)) - return similar_graph(graph, underlying_graph_type) + return similar_graph(graph, underlying_graph) end # Construct a similar `AbstractDataGraph` defined by `underlying_graph` with `vertex_data_type` and `edge_data_type`. @@ -249,8 +256,7 @@ function set_underlying_graph(datagraph::AbstractDataGraph, graph::AbstractGraph new_datagraph = similar_graph(datagraph, graph) - vertex_data(new_datagraph) .= vertex_data(datagraph) - edge_data(new_datagraph) .= edge_data(datagraph) + copyto!(new_datagraph, datagraph) return new_datagraph end From b735ac789cfa72c4bb66f7904c20d18c25b23bfb Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Mon, 23 Mar 2026 16:29:58 -0400 Subject: [PATCH 14/36] Add tests for `similar_graph`. --- test/test_basics.jl | 56 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/test/test_basics.jl b/test/test_basics.jl index 99c4716..3599249 100644 --- a/test/test_basics.jl +++ b/test/test_basics.jl @@ -2,14 +2,14 @@ using DataGraphs: DataGraphs, DataGraph, EdgeDataView, VertexDataView, edge_data edge_data_type, underlying_graph, vertex_data, vertex_data_type using Dictionaries: Dictionaries, AbstractDictionary, AbstractIndices, Dictionary, IndexError, Indices, dictionary, unset! -using Graphs: a_star, add_edge!, bfs_tree, connected_components, degree, dfs_tree, - dijkstra_shortest_paths, dst, edges, edgetype, grid, has_edge, has_vertex, indegree, ne, - nv, outdegree, path_graph, src, steiner_tree, vertices +using Graphs: SimpleDiGraph, a_star, add_edge!, bfs_tree, connected_components, degree, + dfs_tree, dijkstra_shortest_paths, dst, edges, edgetype, grid, has_edge, has_vertex, + indegree, ne, nv, outdegree, path_graph, src, steiner_tree, vertices using GraphsFlows: GraphsFlows using NamedGraphs.GraphsExtensions: rename_vertices, subgraph, vertextype, ⊔ using NamedGraphs.NamedGraphGenerators: named_grid, named_path_graph using NamedGraphs.OrdinalIndexing: nd, rd, st, th -using NamedGraphs: NamedDiGraph, NamedEdge, NamedGraph +using NamedGraphs: NamedDiGraph, NamedEdge, NamedGraph, empty_graph, similar_graph using Test: @test, @test_broken, @testset @testset "DataGraphs.jl" begin @@ -550,4 +550,52 @@ using Test: @test, @test_broken, @testset edv["a" => "b"] = 5.0 @test g["a" => "b"] == 5.0 end + + @testset "`similar_graph`" begin + g = DataGraph( + NamedGraph(path_graph(3), ["a", "b", "c"]); + vertex_data_type = Int, + edge_data_type = Float64 + ) + + g["a"] = 1 + g["b"] = 2 + g["c"] = 3 + g["a" => "b"] = -1.0 + g["b" => "c"] = -2.0 + + g2 = similar_graph(g) + + # Test that graph has no data. + @test !isassigned(g2, "a") + @test !isassigned(g2, "b") + @test !isassigned(g2, "c") + @test !isassigned(g2, "a" => "b") + @test !isassigned(g2, "b" => "c") + + @test underlying_graph(g2) == underlying_graph(g) + @test !(underlying_graph(g2) === underlying_graph(g)) + + g2 = similar_graph(g, NamedDiGraph(SimpleDiGraph(4), ["x", "y", "z", "w"])) + + @test underlying_graph(g2) isa NamedDiGraph + + @test has_vertex(g2, "x") + @test has_vertex(g2, "y") + @test has_vertex(g2, "z") + @test has_vertex(g2, "w") + + g_copy = copy(g) + @test g_copy == g + @test !(g_copy === g) + + g_copy = copyto!(similar_graph(g_copy), g) + @test g_copy["a"] == 1 + @test g_copy["b"] == 2 + @test g_copy["c"] == 3 + @test g_copy["a" => "b"] == -1.0 + @test g_copy["b" => "c"] == -2.0 + + @test_throws IndexError copyto!(empty_graph(g_copy), g_copy) + end end From 4549f97f1afce96480ad19c0eb33871ae1c4c2d5 Mon Sep 17 00:00:00 2001 From: Matt Fishman Date: Mon, 23 Mar 2026 12:34:40 -0400 Subject: [PATCH 15/36] Apply integrationtest_pull_request_target patch (#96) --- .github/workflows/IntegrationTest.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/IntegrationTest.yml b/.github/workflows/IntegrationTest.yml index 1801cdb..373926f 100644 --- a/.github/workflows/IntegrationTest.yml +++ b/.github/workflows/IntegrationTest.yml @@ -4,6 +4,8 @@ on: branches: - "main" tags: "*" + paths: + - "Project.toml" pull_request_target: types: - "opened" From 1df44863e328e00cc521911570b4dacb19852882 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Thu, 16 Apr 2026 11:53:18 -0400 Subject: [PATCH 16/36] Improve `similar_graph` definitions; more tests. --- src/abstractdatagraph.jl | 140 +++++++++++++++++++++++++++------------ src/datagraph.jl | 24 +++++-- test/test_basics.jl | 27 ++++++++ 3 files changed, 140 insertions(+), 51 deletions(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index 5d7ad78..cad63fd 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -115,7 +115,7 @@ function Base.:(==)(dg1::AbstractDataGraph, dg2::AbstractDataGraph) return true end -# =================================== `similar_graph` ==================================== # +# ============================ `similar_graph` (value domain) ============================ # # Construct a similar `AbstractDataGraph` with `vertices` and `edges`. function NamedGraphs.similar_graph( @@ -127,40 +127,64 @@ function NamedGraphs.similar_graph( return similar_graph(graph, new_underlying_graph) end -# Construct `graph_type` with `vertices` and `edges`. function NamedGraphs.similar_graph( - graph_type::Type{<:AbstractDataGraph}, - vertices, - edges + graph::AbstractDataGraph, + G::Type{<:AbstractGraph} ) - underlying_graph = similar_graph(underlying_graph_type(graph_type), vertices, edges) - return similar_graph(graph_type, underlying_graph) + underlying_graph = similar_graph(G, vertices(graph), edges(graph)) + return similar_graph(graph, underlying_graph) end -# Construct a similar `AbstractDataGraph` defined by an `underlying_graph_type` with -# `vertex_data_type` and `edge_data_type`. function NamedGraphs.similar_graph( graph::AbstractDataGraph, - underlying_graph_type::Type{<:AbstractGraph}, - vertex_data_type, - edge_data_type + underlying_graph::AbstractGraph ) - underlying_graph = similar_graph(underlying_graph_type, vertices(graph), edges(graph)) - return similar_graph(graph, underlying_graph, vertex_data_type, edge_data_type) + VD = vertex_data_type(graph) + ED = edge_data_type(graph) + return similar_graph(graph, VD, ED, underlying_graph) end + function NamedGraphs.similar_graph( graph::AbstractDataGraph, - underlying_graph_type::Type{<:AbstractGraph} + VD::Type, + ED::Type ) - underlying_graph = similar_graph(underlying_graph_type, vertices(graph), edges(graph)) - return similar_graph(graph, underlying_graph) + new_underlying_graph = similar_graph(underlying_graph(graph)) + return similar_graph(graph, VD, ED, new_underlying_graph) +end + +function NamedGraphs.similar_graph( + graph::AbstractDataGraph, + VD::Type, + ED::Type, + vertices, + edges + ) + new_underlying_graph = similar_graph(underlying_graph(graph), vertices, edges) + return similar_graph(graph, VD, ED, new_underlying_graph) +end + +# Construct a similar `AbstractDataGraph` defined by an underlying graph type `G` with +# vertex data type `VD` and edge data type `ED`. +function NamedGraphs.similar_graph( + graph::AbstractDataGraph, + VD::Type, + ED::Type, + G::Type{<:AbstractGraph} + ) + underlying_graph = similar_graph(G, vertices(graph), edges(graph)) + return similar_graph(graph, VD, ED, underlying_graph) end # Construct a similar `AbstractDataGraph` defined by `underlying_graph` with `vertex_data_type` and `edge_data_type`. # To be specialized (has fallback). """ - similar_graph(datagraph::AbstractDataGraph, graph::AbstractGraph, [VD=vertex_data_type(datagraph), ED=edge_data_type(datagraph)]) - similar_graph(datagraph::AbstractDataGraph, G, [VD=vertex_data_type(datagraph), ED=edge_data_type(datagraph)]) + similar_graph(datagraph::AbstractDataGraph, graph::AbstractGraph) + similar_graph(datagraph::AbstractDataGraph, VD::Type, ED::Type, vertices, edges) + similar_graph(datagraph::AbstractDataGraph, VD::Type, ED::Type, graph::AbstractGraph) + + similar_graph(datagraph::AbstractDataGraph, G::Type{<:AbstractGraph}) + similar_graph(datagraph::AbstractDataGraph, VD::Type, ED::Type, G::Type{<:AbstractGraph}) Create an uninitialized data graph, similar to the provided `datagraph`, but with underlying graph defined by `graph`. If instead a type `G` is given as the second argument, @@ -173,40 +197,68 @@ to choose the return type of the resulting graph, based on the arguments. If they do not specialize on this method, then the default is `DataGraph(graph; vertex_data_type, edge_data_type)`. """ + +# Base case (overload this). function NamedGraphs.similar_graph( ::AbstractDataGraph, - underlying_graph::AbstractGraph, - vertex_data_type, - edge_data_type + VD::Type, + ED::Type, + underlying_graph::AbstractGraph + ) + return DataGraph(underlying_graph; vertex_data_type = VD, edge_data_type = ED) +end + +# ============================ `similar_graph` (type domain) ============================= # + +# Construct `graph_type` with `vertices` and `edges`. +function NamedGraphs.similar_graph( + graph_type::Type{<:AbstractDataGraph}, + vertices, + edges ) - return DataGraph(underlying_graph; vertex_data_type, edge_data_type) + underlying_graph = similar_graph(underlying_graph_type(graph_type), vertices, edges) + return similar_graph(graph_type, underlying_graph) end + function NamedGraphs.similar_graph( - graph::AbstractDataGraph, - underlying_graph::AbstractGraph + graph_type::Type{<:AbstractDataGraph}, + G::Type{<:AbstractGraph} ) - VD = vertex_data_type(graph) - ED = edge_data_type(graph) - return similar_graph(graph, underlying_graph, VD, ED) + underlying_graph = similar_graph(G) + return similar_graph(graph_type, underlying_graph) end -# Construct a subtype of `graph_type` with an empty underlying_graph of type `underlying_graph_type` -# and `vertex_data_type` and `edge_data_type`. +# Construct `graph_type` with `vertex_data_type` and `edge_data_type`. function NamedGraphs.similar_graph( graph_type::Type{<:AbstractDataGraph}, - underlying_graph_type::Type{<:AbstractGraph}, - vertex_data_type, - edge_data_type + VD::Type, + ED::Type ) - underlying_graph = similar_graph(underlying_graph_type) - return similar_graph(graph_type, underlying_graph, vertex_data_type, edge_data_type) + underlying_graph = similar_graph(underlying_graph_type(graph_type)) + return similar_graph(graph_type, VD, ED, underlying_graph) end + function NamedGraphs.similar_graph( graph_type::Type{<:AbstractDataGraph}, - underlying_graph_type::Type{<:AbstractGraph} + VD::Type, + ED::Type, + vertices, + edges ) - underlying_graph = similar_graph(underlying_graph_type) - return similar_graph(graph_type, underlying_graph) + underlying_graph = similar_graph(underlying_graph_type(graph_type), vertices, edges) + return similar_graph(graph_type, VD, ED, underlying_graph) +end + +# Construct a subtype of `graph_type` with an empty underlying_graph of type `underlying_graph_type` +# and `vertex_data_type` and `edge_data_type`. +function NamedGraphs.similar_graph( + graph_type::Type{<:AbstractDataGraph}, + VD::Type, + ED::Type, + G::Type{<:AbstractGraph} + ) + underlying_graph = similar_graph(G) + return similar_graph(graph_type, VD, ED, underlying_graph) end # Construct a subtype of `graph_type` defined by `underlying_graph` with `vertex_data_type` and `edge_data_type`. @@ -214,10 +266,10 @@ end # specialize on either the two or four argument method. """ similar_graph(DG::Type{<:AbstractDataGraph}, graph::AbstractGraph) - similar_graph(DG::Type{<:AbstractDataGraph}, graph::AbstractGraph, VD, ED) + similar_graph(DG::Type{<:AbstractDataGraph}, VD::Type, ED::Type, graph::AbstractGraph) similar_graph(DG::Type{<:AbstractDataGraph}, G) - similar_graph(DG::Type{<:AbstractDataGraph}, G, VD, ED) + similar_graph(DG::Type{<:AbstractDataGraph}, VD::Type, ED::Type, G::Type{<:AbstractGraph}) Create an uninitialized data graph that acts like the specified data graph type `DG`, but with underlying graph defined by `graph`. @@ -231,11 +283,11 @@ A given custom `AbstractDataGraph` subtype may specialize on the first two metho """ function NamedGraphs.similar_graph( graph_type::Type{<:AbstractDataGraph}, - underlying_graph::AbstractGraph, - vertex_data_type, - edge_data_type + VD::Type, + ED::Type, + underlying_graph::AbstractGraph ) - return graph_type(underlying_graph, vertex_data_type, edge_data_type) + return graph_type(VD, ED, underlying_graph) end function NamedGraphs.similar_graph( graph_type::Type{<:AbstractDataGraph}, diff --git a/src/datagraph.jl b/src/datagraph.jl index 7e59f22..b4ef5f9 100644 --- a/src/datagraph.jl +++ b/src/datagraph.jl @@ -56,19 +56,29 @@ edge_data_type(G::Type{<:DataGraph}) = eltype(fieldtype(G, :edge_data)) # Overwrite the `AbstractDataGraph` fallback (even though they coincide for `DataGraph`) function NamedGraphs.similar_graph( ::DataGraph, - underlying_graph::AbstractGraph, - vertex_data_type, - edge_data_type + vertex_data_type::Type, + edge_data_type::Type, + underlying_graph::AbstractGraph ) - return similar_graph(DataGraph, underlying_graph, vertex_data_type, edge_data_type) + return similar_graph(DataGraph, vertex_data_type, edge_data_type, underlying_graph) end # Constructor method needs overwritten. function NamedGraphs.similar_graph( T::Type{<:DataGraph}, - underlying_graph::AbstractGraph, - vertex_data_type = vertex_data_type(T), - edge_data_type = edge_data_type(T) + underlying_graph::AbstractGraph + ) + vertex_data_type = vertex_data_type(T) + edge_data_type = edge_data_type(T) + return T(underlying_graph; vertex_data_type, edge_data_type) +end + +# Constructor method needs overwritten. +function NamedGraphs.similar_graph( + T::Type{<:DataGraph}, + vertex_data_type::Type, + edge_data_type::Type, + underlying_graph::AbstractGraph ) return T(underlying_graph; vertex_data_type, edge_data_type) end diff --git a/test/test_basics.jl b/test/test_basics.jl index 3599249..23433b2 100644 --- a/test/test_basics.jl +++ b/test/test_basics.jl @@ -597,5 +597,32 @@ using Test: @test, @test_broken, @testset @test g_copy["b" => "c"] == -2.0 @test_throws IndexError copyto!(empty_graph(g_copy), g_copy) + + g2 = similar_graph(g, ["u", "v"], ["u" => "v"]) + @test similar_graph(g, ["u", "v"], ["u" => "v"]) isa typeof(g) + @test has_vertex(g2, "u") + @test has_vertex(g2, "v") + @test has_edge(g2, "u" => "v") + + g2 = similar_graph(g, Float64, Int) + @test has_vertex(g2, "a") + @test has_edge(g2, "a" => "b") + @test vertex_data_type(g2) === Float64 + @test edge_data_type(g2) === Int + + g2 = similar_graph(DataGraph, Float64, Int, NamedGraph{String}) + @test g2 isa DataGraph + @test underlying_graph(g2) isa NamedGraph{String} + @test nv(g2) == 0 + @test ne(g2) == 0 + @test vertex_data_type(g2) === Float64 + @test edge_data_type(g2) === Int + + g2 = similar_graph(g, String, Tuple, [:a, :b], [:a => :b]) + @test vertex_data_type(g2) === String + @test edge_data_type(g2) === Tuple + @test has_vertex(g2, :a) + @test has_vertex(g2, :b) + @test has_edge(g2, :a => :b) end end From 46491b65e4194d600e684ad5f9b529b9ab034462 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Thu, 16 Apr 2026 14:03:05 -0400 Subject: [PATCH 17/36] Docs fixes. --- src/abstractdatagraph.jl | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index cad63fd..da8309b 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -180,10 +180,9 @@ end # To be specialized (has fallback). """ similar_graph(datagraph::AbstractDataGraph, graph::AbstractGraph) + similar_graph(datagraph::AbstractDataGraph, G::Type{<:AbstractGraph}) similar_graph(datagraph::AbstractDataGraph, VD::Type, ED::Type, vertices, edges) similar_graph(datagraph::AbstractDataGraph, VD::Type, ED::Type, graph::AbstractGraph) - - similar_graph(datagraph::AbstractDataGraph, G::Type{<:AbstractGraph}) similar_graph(datagraph::AbstractDataGraph, VD::Type, ED::Type, G::Type{<:AbstractGraph}) Create an uninitialized data graph, similar to the provided `datagraph`, but with underlying @@ -197,7 +196,6 @@ to choose the return type of the resulting graph, based on the arguments. If they do not specialize on this method, then the default is `DataGraph(graph; vertex_data_type, edge_data_type)`. """ - # Base case (overload this). function NamedGraphs.similar_graph( ::AbstractDataGraph, @@ -266,9 +264,8 @@ end # specialize on either the two or four argument method. """ similar_graph(DG::Type{<:AbstractDataGraph}, graph::AbstractGraph) - similar_graph(DG::Type{<:AbstractDataGraph}, VD::Type, ED::Type, graph::AbstractGraph) - similar_graph(DG::Type{<:AbstractDataGraph}, G) + similar_graph(DG::Type{<:AbstractDataGraph}, VD::Type, ED::Type, graph::AbstractGraph) similar_graph(DG::Type{<:AbstractDataGraph}, VD::Type, ED::Type, G::Type{<:AbstractGraph}) Create an uninitialized data graph that acts like the specified data graph type From 40f04979b4660489a9f6f28ab061b91e706ba8df Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Fri, 17 Apr 2026 13:33:35 -0400 Subject: [PATCH 18/36] Simplify number `similar_graph` methods; add `similar_induced_subgraph` for creating data-less subgraphs. --- src/abstractdatagraph.jl | 194 ++++++++------------------------- test/test_basics.jl | 12 +- test/test_partitionedgraphs.jl | 5 + 3 files changed, 50 insertions(+), 161 deletions(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index da8309b..e7b1e94 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -1,12 +1,12 @@ using Dictionaries: Indices, set!, unset! using Graphs: Graphs, AbstractEdge, IsDirected, a_star, add_edge!, add_vertex!, edges, - indegree, ne, nv, outdegree, steiner_tree, vertices + indegree, induced_subgraph, ne, nv, outdegree, steiner_tree, vertices using NamedGraphs.GraphsExtensions: GraphsExtensions, add_vertices!, arrange_edge, incident_edges, is_edge_arranged, vertextype using NamedGraphs.OrdinalIndexing: OrdinalSuffixedInteger using NamedGraphs.SimilarType: similar_type using NamedGraphs: NamedGraphs, AbstractEdges, AbstractNamedEdge, AbstractNamedGraph, - AbstractVertices, NamedGraph, position_graph_type, similar_graph + AbstractVertices, NamedDiGraph, NamedGraph, position_graph_type, similar_graph using SimpleTraits: SimpleTraits, @traitfn, Not abstract type AbstractDataGraph{V, VD, ED} <: AbstractNamedGraph{V} end @@ -117,73 +117,12 @@ end # ============================ `similar_graph` (value domain) ============================ # -# Construct a similar `AbstractDataGraph` with `vertices` and `edges`. -function NamedGraphs.similar_graph( - graph::AbstractDataGraph, - vertices, - edges - ) - new_underlying_graph = similar_graph(underlying_graph(graph), vertices, edges) - return similar_graph(graph, new_underlying_graph) -end - -function NamedGraphs.similar_graph( - graph::AbstractDataGraph, - G::Type{<:AbstractGraph} - ) - underlying_graph = similar_graph(G, vertices(graph), edges(graph)) - return similar_graph(graph, underlying_graph) -end - -function NamedGraphs.similar_graph( - graph::AbstractDataGraph, - underlying_graph::AbstractGraph - ) - VD = vertex_data_type(graph) - ED = edge_data_type(graph) - return similar_graph(graph, VD, ED, underlying_graph) -end - -function NamedGraphs.similar_graph( - graph::AbstractDataGraph, - VD::Type, - ED::Type - ) - new_underlying_graph = similar_graph(underlying_graph(graph)) - return similar_graph(graph, VD, ED, new_underlying_graph) -end - -function NamedGraphs.similar_graph( - graph::AbstractDataGraph, - VD::Type, - ED::Type, - vertices, - edges - ) - new_underlying_graph = similar_graph(underlying_graph(graph), vertices, edges) - return similar_graph(graph, VD, ED, new_underlying_graph) -end - -# Construct a similar `AbstractDataGraph` defined by an underlying graph type `G` with -# vertex data type `VD` and edge data type `ED`. -function NamedGraphs.similar_graph( - graph::AbstractDataGraph, - VD::Type, - ED::Type, - G::Type{<:AbstractGraph} - ) - underlying_graph = similar_graph(G, vertices(graph), edges(graph)) - return similar_graph(graph, VD, ED, underlying_graph) -end - # Construct a similar `AbstractDataGraph` defined by `underlying_graph` with `vertex_data_type` and `edge_data_type`. # To be specialized (has fallback). """ - similar_graph(datagraph::AbstractDataGraph, graph::AbstractGraph) - similar_graph(datagraph::AbstractDataGraph, G::Type{<:AbstractGraph}) + similar_graph(datagraph::AbstractDataGraph, vertices, edges) + similar_graph(datagraph::AbstractDataGraph, VD::Type, ED::Type) similar_graph(datagraph::AbstractDataGraph, VD::Type, ED::Type, vertices, edges) - similar_graph(datagraph::AbstractDataGraph, VD::Type, ED::Type, graph::AbstractGraph) - similar_graph(datagraph::AbstractDataGraph, VD::Type, ED::Type, G::Type{<:AbstractGraph}) Create an uninitialized data graph, similar to the provided `datagraph`, but with underlying graph defined by `graph`. If instead a type `G` is given as the second argument, @@ -196,103 +135,47 @@ to choose the return type of the resulting graph, based on the arguments. If they do not specialize on this method, then the default is `DataGraph(graph; vertex_data_type, edge_data_type)`. """ -# Base case (overload this). function NamedGraphs.similar_graph( - ::AbstractDataGraph, - VD::Type, - ED::Type, - underlying_graph::AbstractGraph - ) - return DataGraph(underlying_graph; vertex_data_type = VD, edge_data_type = ED) -end - -# ============================ `similar_graph` (type domain) ============================= # - -# Construct `graph_type` with `vertices` and `edges`. -function NamedGraphs.similar_graph( - graph_type::Type{<:AbstractDataGraph}, + graph::AbstractDataGraph, vertices, edges ) - underlying_graph = similar_graph(underlying_graph_type(graph_type), vertices, edges) - return similar_graph(graph_type, underlying_graph) -end - -function NamedGraphs.similar_graph( - graph_type::Type{<:AbstractDataGraph}, - G::Type{<:AbstractGraph} - ) - underlying_graph = similar_graph(G) - return similar_graph(graph_type, underlying_graph) + VD = vertex_data_type(graph) + ED = edge_data_type(graph) + return similar_graph(graph, VD, ED, vertices, edges) end - -# Construct `graph_type` with `vertex_data_type` and `edge_data_type`. function NamedGraphs.similar_graph( - graph_type::Type{<:AbstractDataGraph}, + graph::AbstractDataGraph, VD::Type, ED::Type ) - underlying_graph = similar_graph(underlying_graph_type(graph_type)) - return similar_graph(graph_type, VD, ED, underlying_graph) + return similar_graph(graph, VD, ED, vertices(graph), edges(graph)) end -function NamedGraphs.similar_graph( - graph_type::Type{<:AbstractDataGraph}, +# Base case (overload this if fallback not wanted). +@traitfn function NamedGraphs.similar_graph( + ::AbstractDataGraph::(!IsDirected), VD::Type, ED::Type, vertices, edges ) - underlying_graph = similar_graph(underlying_graph_type(graph_type), vertices, edges) - return similar_graph(graph_type, VD, ED, underlying_graph) -end + underlying_graph = similar_graph(NamedGraph, vertices, edges) -# Construct a subtype of `graph_type` with an empty underlying_graph of type `underlying_graph_type` -# and `vertex_data_type` and `edge_data_type`. -function NamedGraphs.similar_graph( - graph_type::Type{<:AbstractDataGraph}, - VD::Type, - ED::Type, - G::Type{<:AbstractGraph} - ) - underlying_graph = similar_graph(G) - return similar_graph(graph_type, VD, ED, underlying_graph) + return DataGraph(underlying_graph; vertex_data_type = VD, edge_data_type = ED) end -# Construct a subtype of `graph_type` defined by `underlying_graph` with `vertex_data_type` and `edge_data_type`. -# To be specialized if `graph_type` doesn't have the appropriate constructor. One can -# specialize on either the two or four argument method. -""" - similar_graph(DG::Type{<:AbstractDataGraph}, graph::AbstractGraph) - similar_graph(DG::Type{<:AbstractDataGraph}, G) - similar_graph(DG::Type{<:AbstractDataGraph}, VD::Type, ED::Type, graph::AbstractGraph) - similar_graph(DG::Type{<:AbstractDataGraph}, VD::Type, ED::Type, G::Type{<:AbstractGraph}) - -Create an uninitialized data graph that acts like the specified data graph type -`DG`, but with underlying graph defined by `graph`. -If instead a type `G` is given as the second argument, then -an empty underlying graph is first constructed using `graph = similar_graph(G)`. -Optionally, one may also specify the vertex and edge data types of the resulting data graph. - -By default, calls the constructors `DG(graph)` and `DG(graph, VD, ED)` respectively. -A given custom `AbstractDataGraph` subtype may specialize on the first two methods above -(in terms a graph `graph`) if such constructors do not exist for that subtype. -""" -function NamedGraphs.similar_graph( - graph_type::Type{<:AbstractDataGraph}, +@traitfn function NamedGraphs.similar_graph( + ::AbstractDataGraph::IsDirected, VD::Type, ED::Type, - underlying_graph::AbstractGraph - ) - return graph_type(VD, ED, underlying_graph) -end -function NamedGraphs.similar_graph( - graph_type::Type{<:AbstractDataGraph}, - underlying_graph::AbstractGraph + vertices, + edges ) - return graph_type(underlying_graph) -end + underlying_graph = similar_graph(NamedDiGraph, vertices, edges) + return DataGraph(underlying_graph; vertex_data_type = VD, edge_data_type = ED) +end # Set the underlying graph of a data graph, preserving data. Graphs must match. function set_underlying_graph(datagraph::AbstractDataGraph, graph::AbstractGraph) if vertices(datagraph) != vertices(graph) || edges(datagraph) != edges(graph) @@ -358,8 +241,15 @@ function reverse_data_direction(graph::AbstractDataGraph, edge::AbstractEdge, da return is_edge_arranged(graph, edge) ? data : reverse_data_direction(graph, data) end +# Fallback to constructing a concrete `DataGraph`. @traitfn function GraphsExtensions.directed_graph(graph::AbstractDataGraph::(!IsDirected)) - digraph = similar_graph(graph, directed_graph(underlying_graph(graph))) + ug = similar_graph(NamedDiGraph, vertices(graph), edges(graph)) + + VD = vertex_data_type(graph) + ED = edge_data_type(graph) + + digraph = DataGraph(ug; vertex_data_type = VD, edge_data_type = ED) + for v in vertices(graph) # TODO: Only loop over `keys(vertex_data(graph))` if isassigned(graph, v) @@ -540,13 +430,7 @@ function Base.get(default::Base.Callable, graph::AbstractDataGraph, key) end function NamedGraphs.induced_subgraph_from_vertices(graph::AbstractDataGraph, subvertices) - return induced_subgraph_datagraph(graph, subvertices) -end -function induced_subgraph_datagraph(graph::AbstractDataGraph, subvertices) - underlying_subgraph, vlist = - Graphs.induced_subgraph(underlying_graph(graph), subvertices) - - subgraph = similar_graph(graph, underlying_subgraph) + subgraph, vlist = similar_induced_subgraph(graph, subvertices) for v in vertices(subgraph) if isassigned(graph, v) @@ -558,12 +442,22 @@ function induced_subgraph_datagraph(graph::AbstractDataGraph, subvertices) subgraph[e] = graph[e] end end + + return subgraph, vlist +end + +function similar_induced_subgraph(graph::AbstractDataGraph, subvertices) + underlying_subgraph, vlist = induced_subgraph(underlying_graph(graph), subvertices) + + VD = vertex_data_type(graph) + ED = edge_data_type(graph) + + subgraph = DataGraph(underlying_subgraph; vertex_data_type = VD, edge_data_type = ED) + return subgraph, vlist end -# -# Printing -# +# ======================================= printing ======================================= # function Base.show(io::IO, mime::MIME"text/plain", graph::AbstractDataGraph) println(io, "$(typeof(graph)) with $(nv(graph)) vertices:") diff --git a/test/test_basics.jl b/test/test_basics.jl index 23433b2..ccd7b66 100644 --- a/test/test_basics.jl +++ b/test/test_basics.jl @@ -576,9 +576,7 @@ using Test: @test, @test_broken, @testset @test underlying_graph(g2) == underlying_graph(g) @test !(underlying_graph(g2) === underlying_graph(g)) - g2 = similar_graph(g, NamedDiGraph(SimpleDiGraph(4), ["x", "y", "z", "w"])) - - @test underlying_graph(g2) isa NamedDiGraph + g2 = similar_graph(g, ["x", "y", "z", "w"]) @test has_vertex(g2, "x") @test has_vertex(g2, "y") @@ -610,14 +608,6 @@ using Test: @test, @test_broken, @testset @test vertex_data_type(g2) === Float64 @test edge_data_type(g2) === Int - g2 = similar_graph(DataGraph, Float64, Int, NamedGraph{String}) - @test g2 isa DataGraph - @test underlying_graph(g2) isa NamedGraph{String} - @test nv(g2) == 0 - @test ne(g2) == 0 - @test vertex_data_type(g2) === Float64 - @test edge_data_type(g2) === Int - g2 = similar_graph(g, String, Tuple, [:a, :b], [:a => :b]) @test vertex_data_type(g2) === String @test edge_data_type(g2) === Tuple diff --git a/test/test_partitionedgraphs.jl b/test/test_partitionedgraphs.jl index 1f3e2d2..f8c7993 100644 --- a/test/test_partitionedgraphs.jl +++ b/test/test_partitionedgraphs.jl @@ -48,6 +48,11 @@ function NamedGraphs.similar_graph(dg::TestDataGraph, graph::AbstractGraph) return TestDataGraph(dg) end +function DataGraphs.similar_induced_subgraph(dg::TestDataGraph, subvertices) + dg, vlist = NamedGraphs.induced_subgraph(dg.graph, subvertices) + return TestDataGraph(dg), vlist +end + for f in [ :(DataGraphs.is_vertex_assigned), :(DataGraphs.is_edge_assigned), From 890c7e97615797c74824b6341e2a1993373cc975 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Fri, 17 Apr 2026 13:38:27 -0400 Subject: [PATCH 19/36] Make `set_underlying_graph` function specific to `DataGraph` --- src/abstractdatagraph.jl | 16 ---------------- src/datagraph.jl | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index e7b1e94..a4a77c6 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -176,22 +176,6 @@ end return DataGraph(underlying_graph; vertex_data_type = VD, edge_data_type = ED) end -# Set the underlying graph of a data graph, preserving data. Graphs must match. -function set_underlying_graph(datagraph::AbstractDataGraph, graph::AbstractGraph) - if vertices(datagraph) != vertices(graph) || edges(datagraph) != edges(graph) - throw( - ArgumentError( - "New underlying graph must have the same vertices and edges as the data graph" - ) - ) - end - - new_datagraph = similar_graph(datagraph, graph) - - copyto!(new_datagraph, datagraph) - - return new_datagraph -end # Fix for ambiguity error with `AbstractGraph` version function Graphs.degree(graph::AbstractDataGraph, vertex::Integer) diff --git a/src/datagraph.jl b/src/datagraph.jl index b4ef5f9..b6fae75 100644 --- a/src/datagraph.jl +++ b/src/datagraph.jl @@ -169,3 +169,23 @@ function Graphs.rem_edge!(graph::DataGraph, edge) Graphs.rem_edge!(graph.underlying_graph, edge) return graph end + +# Set the underlying graph of a data graph, preserving data. Graphs must match. +function set_underlying_graph(datagraph::DataGraph, graph::AbstractGraph) + if vertices(datagraph) != vertices(graph) || edges(datagraph) != edges(graph) + throw( + ArgumentError( + "New underlying graph must have the same vertices and edges as the data graph" + ) + ) + end + + VD = vertex_data_type(datagraph) + ED = edge_data_type(datagraph) + + new_datagraph = DataGraph(graph; vertex_data_type = VD, edge_data_type = ED) + + copyto!(new_datagraph, datagraph) + + return new_datagraph +end From fbd27a96b4966564c979c6f6d277e8bd093ccf61 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Fri, 17 Apr 2026 13:52:29 -0400 Subject: [PATCH 20/36] Rename variable. --- src/abstractdatagraph.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index a4a77c6..e3faf70 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -227,12 +227,12 @@ end # Fallback to constructing a concrete `DataGraph`. @traitfn function GraphsExtensions.directed_graph(graph::AbstractDataGraph::(!IsDirected)) - ug = similar_graph(NamedDiGraph, vertices(graph), edges(graph)) + underlying_digraph = similar_graph(NamedDiGraph, vertices(graph), edges(graph)) VD = vertex_data_type(graph) ED = edge_data_type(graph) - digraph = DataGraph(ug; vertex_data_type = VD, edge_data_type = ED) + digraph = DataGraph(underlying_digraph; vertex_data_type = VD, edge_data_type = ED) for v in vertices(graph) # TODO: Only loop over `keys(vertex_data(graph))` From 5d0e1e21cdc071b0699827075c72379d4135a8f2 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Fri, 17 Apr 2026 13:53:16 -0400 Subject: [PATCH 21/36] Remove `set_underlying_graph`. --- src/datagraph.jl | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/datagraph.jl b/src/datagraph.jl index b6fae75..b4ef5f9 100644 --- a/src/datagraph.jl +++ b/src/datagraph.jl @@ -169,23 +169,3 @@ function Graphs.rem_edge!(graph::DataGraph, edge) Graphs.rem_edge!(graph.underlying_graph, edge) return graph end - -# Set the underlying graph of a data graph, preserving data. Graphs must match. -function set_underlying_graph(datagraph::DataGraph, graph::AbstractGraph) - if vertices(datagraph) != vertices(graph) || edges(datagraph) != edges(graph) - throw( - ArgumentError( - "New underlying graph must have the same vertices and edges as the data graph" - ) - ) - end - - VD = vertex_data_type(datagraph) - ED = edge_data_type(datagraph) - - new_datagraph = DataGraph(graph; vertex_data_type = VD, edge_data_type = ED) - - copyto!(new_datagraph, datagraph) - - return new_datagraph -end From 45814858eaed11e56575303010300859e93d05af Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Mon, 20 Apr 2026 09:57:46 +0100 Subject: [PATCH 22/36] Fix concrete DataGraph `similar_graph` methods. --- src/datagraph.jl | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/datagraph.jl b/src/datagraph.jl index b4ef5f9..9567f6f 100644 --- a/src/datagraph.jl +++ b/src/datagraph.jl @@ -55,32 +55,36 @@ edge_data_type(G::Type{<:DataGraph}) = eltype(fieldtype(G, :edge_data)) # Overwrite the `AbstractDataGraph` fallback (even though they coincide for `DataGraph`) function NamedGraphs.similar_graph( - ::DataGraph, + graph::DataGraph, vertex_data_type::Type, edge_data_type::Type, - underlying_graph::AbstractGraph + vertices, + edges ) - return similar_graph(DataGraph, vertex_data_type, edge_data_type, underlying_graph) -end - -# Constructor method needs overwritten. -function NamedGraphs.similar_graph( - T::Type{<:DataGraph}, - underlying_graph::AbstractGraph + new_underlying_graph = similar_graph( + underlying_graph(graph), + vertices, + edges ) - vertex_data_type = vertex_data_type(T) - edge_data_type = edge_data_type(T) - return T(underlying_graph; vertex_data_type, edge_data_type) + + return DataGraph(new_underlying_graph; vertex_data_type, edge_data_type) end -# Constructor method needs overwritten. function NamedGraphs.similar_graph( - T::Type{<:DataGraph}, - vertex_data_type::Type, - edge_data_type::Type, - underlying_graph::AbstractGraph + graph_type::Type{<:DataGraph}, + vertices, + edges + ) + new_underlying_graph = similar_graph( + underlying_graph_type(graph_type), + vertices, + edges ) - return T(underlying_graph; vertex_data_type, edge_data_type) + + VD = vertex_data_type(graph_type) + ED = edge_data_type(graph_type) + + return DataGraph(new_underlying_graph; vertex_data_type = VD, edge_data_type = ED) end function Base.copy(graph::DataGraph) From f4977ea82851ec6455cae1cd505692d8940c321c Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Mon, 20 Apr 2026 10:04:54 +0100 Subject: [PATCH 23/36] Add `similar_graph` method that takes a single data type; fix docstrings. The single data type defines both the vertex data type and the edge data type. --- src/abstractdatagraph.jl | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index e3faf70..460c417 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -121,19 +121,15 @@ end # To be specialized (has fallback). """ similar_graph(datagraph::AbstractDataGraph, vertices, edges) + similar_graph(datagraph::AbstractDataGraph, D::Type) similar_graph(datagraph::AbstractDataGraph, VD::Type, ED::Type) + similar_graph(datagraph::AbstractDataGraph, D::Type, vertices, edges) similar_graph(datagraph::AbstractDataGraph, VD::Type, ED::Type, vertices, edges) -Create an uninitialized data graph, similar to the provided `datagraph`, but with underlying -graph defined by `graph`. If instead a type `G` is given as the second argument, -then an empty underlying graph is first constructed using `graph = similar_graph(G)`. -Optionally, one may specify the vertex and edge data types, which default to those of the -provided source `datagraph`. - -Custom `AbstractDataGraph` subtypes may specialize on first method (either the two or four argument version) -to choose the return type of the resulting graph, based on the arguments. -If they do not specialize on this method, then the default is -`DataGraph(graph; vertex_data_type, edge_data_type)`. +Create an uninitialized data graph, similar to the provided `datagraph`, but with `vertices` +and `edges`. If vertices and edges are not provided, then the vertices and edges of `datagraph` are used. +One may also provide a vertex data type `VD` and an edge data type `ED` or +a type `D` such that `VD = ED = D`. """ function NamedGraphs.similar_graph( graph::AbstractDataGraph, @@ -144,6 +140,12 @@ function NamedGraphs.similar_graph( ED = edge_data_type(graph) return similar_graph(graph, VD, ED, vertices, edges) end +function NamedGraphs.similar_graph( + graph::AbstractDataGraph, + D::Type + ) + return similar_graph(graph, D, D) +end function NamedGraphs.similar_graph( graph::AbstractDataGraph, VD::Type, @@ -151,7 +153,14 @@ function NamedGraphs.similar_graph( ) return similar_graph(graph, VD, ED, vertices(graph), edges(graph)) end - +function NamedGraphs.similar_graph( + graph::AbstractDataGraph, + D::Type, + vertices, + edges + ) + return similar_graph(graph, D, D, vertices, edges) +end # Base case (overload this if fallback not wanted). @traitfn function NamedGraphs.similar_graph( ::AbstractDataGraph::(!IsDirected), @@ -427,6 +436,8 @@ function NamedGraphs.induced_subgraph_from_vertices(graph::AbstractDataGraph, su end end + # copyto!(subgraph, graph) + return subgraph, vlist end From 60cd7f55e41765859402bb7e4a4f20df823ec2dc Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Mon, 20 Apr 2026 11:38:50 +0100 Subject: [PATCH 24/36] Remove `similar_graph` methods taking edges as input; update tests. --- src/abstractdatagraph.jl | 65 ++++++++++++++++++++++++++-------------- src/datagraph.jl | 12 +++----- test/test_basics.jl | 10 +++---- 3 files changed, 52 insertions(+), 35 deletions(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index 460c417..7be2762 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -1,8 +1,8 @@ using Dictionaries: Indices, set!, unset! using Graphs: Graphs, AbstractEdge, IsDirected, a_star, add_edge!, add_vertex!, edges, indegree, induced_subgraph, ne, nv, outdegree, steiner_tree, vertices -using NamedGraphs.GraphsExtensions: GraphsExtensions, add_vertices!, arrange_edge, - incident_edges, is_edge_arranged, vertextype +using NamedGraphs.GraphsExtensions: GraphsExtensions, add_edges!, add_vertices!, + arrange_edge, incident_edges, is_edge_arranged, vertextype using NamedGraphs.OrdinalIndexing: OrdinalSuffixedInteger using NamedGraphs.SimilarType: similar_type using NamedGraphs: NamedGraphs, AbstractEdges, AbstractNamedEdge, AbstractNamedGraph, @@ -132,56 +132,77 @@ One may also provide a vertex data type `VD` and an edge data type `ED` or a type `D` such that `VD = ED = D`. """ function NamedGraphs.similar_graph( - graph::AbstractDataGraph, - vertices, - edges + graph::AbstractDataGraph ) VD = vertex_data_type(graph) ED = edge_data_type(graph) - return similar_graph(graph, VD, ED, vertices, edges) + return similar_graph(graph, VD, ED) end + function NamedGraphs.similar_graph( graph::AbstractDataGraph, - D::Type + vertices ) - return similar_graph(graph, D, D) + VD = vertex_data_type(graph) + ED = edge_data_type(graph) + return similar_graph(graph, VD, ED, vertices) end function NamedGraphs.similar_graph( graph::AbstractDataGraph, - VD::Type, - ED::Type + D::Type ) - return similar_graph(graph, VD, ED, vertices(graph), edges(graph)) + return similar_graph(graph, D, D) end + function NamedGraphs.similar_graph( graph::AbstractDataGraph, D::Type, - vertices, - edges + vertices ) - return similar_graph(graph, D, D, vertices, edges) + return similar_graph(graph, D, D, vertices) end + # Base case (overload this if fallback not wanted). @traitfn function NamedGraphs.similar_graph( - ::AbstractDataGraph::(!IsDirected), + graph::AbstractDataGraph::(!IsDirected), + VD::Type, + ED::Type + ) + underlying_graph = similar_graph(NamedGraph, vertices(graph)) + + add_edges!(underlying_graph, edges(graph)) + + return DataGraph(underlying_graph; vertex_data_type = VD, edge_data_type = ED) +end +@traitfn function NamedGraphs.similar_graph( + graph::AbstractDataGraph::(!IsDirected), VD::Type, ED::Type, - vertices, - edges + vertices ) - underlying_graph = similar_graph(NamedGraph, vertices, edges) + underlying_graph = similar_graph(NamedGraph, vertices) return DataGraph(underlying_graph; vertex_data_type = VD, edge_data_type = ED) end @traitfn function NamedGraphs.similar_graph( - ::AbstractDataGraph::IsDirected, + graph::AbstractDataGraph::IsDirected, + VD::Type, + ED::Type + ) + underlying_graph = similar_graph(NamedDiGraph, vertices(graph)) + + add_edges!(underlying_graph, edges(graph)) + + return DataGraph(underlying_graph; vertex_data_type = VD, edge_data_type = ED) +end +@traitfn function NamedGraphs.similar_graph( + graph::AbstractDataGraph::IsDirected, VD::Type, ED::Type, - vertices, - edges + vertices ) - underlying_graph = similar_graph(NamedDiGraph, vertices, edges) + underlying_graph = similar_graph(NamedDiGraph, vertices) return DataGraph(underlying_graph; vertex_data_type = VD, edge_data_type = ED) end diff --git a/src/datagraph.jl b/src/datagraph.jl index 9567f6f..5839c96 100644 --- a/src/datagraph.jl +++ b/src/datagraph.jl @@ -58,13 +58,11 @@ function NamedGraphs.similar_graph( graph::DataGraph, vertex_data_type::Type, edge_data_type::Type, - vertices, - edges + vertices... ) new_underlying_graph = similar_graph( underlying_graph(graph), - vertices, - edges + vertices... ) return DataGraph(new_underlying_graph; vertex_data_type, edge_data_type) @@ -72,13 +70,11 @@ end function NamedGraphs.similar_graph( graph_type::Type{<:DataGraph}, - vertices, - edges + vertices... ) new_underlying_graph = similar_graph( underlying_graph_type(graph_type), - vertices, - edges + vertices... ) VD = vertex_data_type(graph_type) diff --git a/test/test_basics.jl b/test/test_basics.jl index ccd7b66..10bd9c9 100644 --- a/test/test_basics.jl +++ b/test/test_basics.jl @@ -596,11 +596,11 @@ using Test: @test, @test_broken, @testset @test_throws IndexError copyto!(empty_graph(g_copy), g_copy) - g2 = similar_graph(g, ["u", "v"], ["u" => "v"]) - @test similar_graph(g, ["u", "v"], ["u" => "v"]) isa typeof(g) + g2 = similar_graph(g, ["u", "v"]) + @test similar_graph(g2) isa typeof(g) @test has_vertex(g2, "u") @test has_vertex(g2, "v") - @test has_edge(g2, "u" => "v") + @test ne(g2) == 0 g2 = similar_graph(g, Float64, Int) @test has_vertex(g2, "a") @@ -608,11 +608,11 @@ using Test: @test, @test_broken, @testset @test vertex_data_type(g2) === Float64 @test edge_data_type(g2) === Int - g2 = similar_graph(g, String, Tuple, [:a, :b], [:a => :b]) + g2 = similar_graph(g, String, Tuple, [:a, :b]) @test vertex_data_type(g2) === String @test edge_data_type(g2) === Tuple @test has_vertex(g2, :a) @test has_vertex(g2, :b) - @test has_edge(g2, :a => :b) + @test ne(g2) == 0 end end From 86452605aa4670e4064046060fd8cef2fcbca03a Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Mon, 20 Apr 2026 14:00:41 +0100 Subject: [PATCH 25/36] Refactor `similar_graph` methods to simplify. --- src/abstractdatagraph.jl | 23 +++++------------------ src/datagraph.jl | 19 ++----------------- 2 files changed, 7 insertions(+), 35 deletions(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index 7be2762..c3985c3 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -163,16 +163,15 @@ function NamedGraphs.similar_graph( end # Base case (overload this if fallback not wanted). -@traitfn function NamedGraphs.similar_graph( - graph::AbstractDataGraph::(!IsDirected), +function NamedGraphs.similar_graph( + graph::AbstractDataGraph, VD::Type, ED::Type ) - underlying_graph = similar_graph(NamedGraph, vertices(graph)) - - add_edges!(underlying_graph, edges(graph)) + new_graph = similar_graph(graph, VD, ED, vertices(graph)) + add_edges!(new_graph, edges(graph)) - return DataGraph(underlying_graph; vertex_data_type = VD, edge_data_type = ED) + return new_graph end @traitfn function NamedGraphs.similar_graph( graph::AbstractDataGraph::(!IsDirected), @@ -184,18 +183,6 @@ end return DataGraph(underlying_graph; vertex_data_type = VD, edge_data_type = ED) end - -@traitfn function NamedGraphs.similar_graph( - graph::AbstractDataGraph::IsDirected, - VD::Type, - ED::Type - ) - underlying_graph = similar_graph(NamedDiGraph, vertices(graph)) - - add_edges!(underlying_graph, edges(graph)) - - return DataGraph(underlying_graph; vertex_data_type = VD, edge_data_type = ED) -end @traitfn function NamedGraphs.similar_graph( graph::AbstractDataGraph::IsDirected, VD::Type, diff --git a/src/datagraph.jl b/src/datagraph.jl index 5839c96..f74f4bd 100644 --- a/src/datagraph.jl +++ b/src/datagraph.jl @@ -58,31 +58,16 @@ function NamedGraphs.similar_graph( graph::DataGraph, vertex_data_type::Type, edge_data_type::Type, - vertices... + vertices ) new_underlying_graph = similar_graph( underlying_graph(graph), - vertices... + vertices ) return DataGraph(new_underlying_graph; vertex_data_type, edge_data_type) end -function NamedGraphs.similar_graph( - graph_type::Type{<:DataGraph}, - vertices... - ) - new_underlying_graph = similar_graph( - underlying_graph_type(graph_type), - vertices... - ) - - VD = vertex_data_type(graph_type) - ED = edge_data_type(graph_type) - - return DataGraph(new_underlying_graph; vertex_data_type = VD, edge_data_type = ED) -end - function Base.copy(graph::DataGraph) # Need to manually copy the keys of Dictionaries, see: # https://github.com/andyferris/Dictionaries.jl/issues/98 From e16c31c8bc7174d62222bc81ace4487705dcfc21 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Mon, 20 Apr 2026 14:16:52 +0100 Subject: [PATCH 26/36] Remove assumption of `underlying_graph` of `AbstractDataGraph` in `PartitionedGraphs` ext. --- .../src/DataGraphsPartitionedGraphsExt.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib/DataGraphsPartitionedGraphsExt/src/DataGraphsPartitionedGraphsExt.jl b/src/lib/DataGraphsPartitionedGraphsExt/src/DataGraphsPartitionedGraphsExt.jl index 78a8c9a..e38a523 100644 --- a/src/lib/DataGraphsPartitionedGraphsExt/src/DataGraphsPartitionedGraphsExt.jl +++ b/src/lib/DataGraphsPartitionedGraphsExt/src/DataGraphsPartitionedGraphsExt.jl @@ -165,13 +165,13 @@ function DataGraphs.edge_data_type(T::Type{<:QuotientView}) return Base.promote_op(getindex, PGT, QuotientEdge{vertextype(T), edgetype(T)}) end +# ================================== DataGraph specific ================================== # + # PartitionedGraphs interface -function PartitionedGraphs.partitioned_vertices(dg::AbstractDataGraph) +function PartitionedGraphs.partitioned_vertices(dg::DataGraph) return partitioned_vertices(underlying_graph(dg)) end -# ================================== DataGraph specific ================================== # - function PartitionedGraphs.partitionedgraph(dg::DataGraph, parts) pg = partitionedgraph(underlying_graph(dg), parts) vd = copy(vertex_data(dg)) @@ -195,13 +195,13 @@ function PartitionedGraphs.departition(dg::DataGraph) end end -function quotient_graph_vertex_data(dg) +function quotient_graph_vertex_data(dg::DataGraph) ug = underlying_graph(dg) qvs = QuotientVertexSlice(QuotientVertices(ug)) return map(v -> dg[QuotientVertex(v)], Indices(qvs)) end -function quotient_graph_edge_data(dg) +function quotient_graph_edge_data(dg::DataGraph) ug = underlying_graph(dg) qes = QuotientEdgeSlice(QuotientEdges(ug)) return map(e -> dg[QuotientEdge(e)], Indices(qes)) From dc578126a923be725aa743578a708cffd4ce490d Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Mon, 20 Apr 2026 14:20:46 +0100 Subject: [PATCH 27/36] Fix tests --- test/test_partitionedgraphs.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/test_partitionedgraphs.jl b/test/test_partitionedgraphs.jl index f8c7993..2ee519d 100644 --- a/test/test_partitionedgraphs.jl +++ b/test/test_partitionedgraphs.jl @@ -10,8 +10,8 @@ using NamedGraphs.NamedGraphGenerators: named_path_graph using NamedGraphs.PartitionedGraphs: PartitionedGraph, PartitionedGraphs, QuotientEdge, QuotientEdges, QuotientVertex, QuotientVertexOrEdge, QuotientVertexVertex, QuotientVertexVertices, QuotientVertices, QuotientVerticesVertices, QuotientView, - departition, partitionedgraph, quotient_graph, quotientedges, quotientvertices, - unpartition + departition, partitioned_vertices, partitionedgraph, quotient_graph, quotientedges, + quotientvertices, unpartition using NamedGraphs: NamedGraphs, Edges, NamedGraph, Vertices, similar_graph using Test: @test, @test_throws, @testset @@ -43,6 +43,10 @@ end DataGraphs.underlying_graph(graph::TestDataGraph) = underlying_graph(graph.graph) PartitionedGraphs.quotient_graph(graph::TestDataGraph) = graph.quotientgraph +function PartitionedGraphs.partitioned_vertices(graph::TestDataGraph) + return partitioned_vertices(graph.graph) +end + function NamedGraphs.similar_graph(dg::TestDataGraph, graph::AbstractGraph) dg = similar_graph(dg.graph, graph) return TestDataGraph(dg) From 861f6cfa2cfd5749a95f291b53f4969ebf1d8fa7 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Mon, 20 Apr 2026 14:40:25 +0100 Subject: [PATCH 28/36] Fix code comment referring to wrong method. --- src/abstractdatagraph.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index c3985c3..f21eebc 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -162,7 +162,6 @@ function NamedGraphs.similar_graph( return similar_graph(graph, D, D, vertices) end -# Base case (overload this if fallback not wanted). function NamedGraphs.similar_graph( graph::AbstractDataGraph, VD::Type, @@ -173,6 +172,8 @@ function NamedGraphs.similar_graph( return new_graph end + +# Base case(s) (overload these if fallback not wanted). @traitfn function NamedGraphs.similar_graph( graph::AbstractDataGraph::(!IsDirected), VD::Type, From 718168bc061c11f409f774caeac8fe537269ca19 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Mon, 20 Apr 2026 15:52:47 +0100 Subject: [PATCH 29/36] Remove some redundant methods used for resolving method ambiguities. --- src/abstractdatagraph.jl | 60 ++++------------------------------------ src/datagraph.jl | 2 +- test/test_basics.jl | 4 +-- 3 files changed, 8 insertions(+), 58 deletions(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index f21eebc..55c9c92 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -196,44 +196,12 @@ end end # Fix for ambiguity error with `AbstractGraph` version -function Graphs.degree(graph::AbstractDataGraph, vertex::Integer) - return Graphs.degree(underlying_graph(graph), vertex) -end - -# Fix for ambiguity error with `AbstractGraph` version -function Graphs.dijkstra_shortest_paths( - graph::AbstractDataGraph, vertices::Vector{<:Integer} - ) - return Graphs.dijkstra_shortest_paths(underlying_graph(graph), vertices) -end - -# Fix for ambiguity error with `AbstractGraph` version -function Graphs.eccentricity(graph::AbstractDataGraph, distmx::AbstractMatrix) - return Graphs.eccentricity(underlying_graph(graph), distmx) -end - -# Fix for ambiguity error with `AbstractGraph` version -function Graphs.indegree(graph::AbstractDataGraph, vertex::Integer) - return indegree(underlying_graph(graph), vertex) -end - -# Fix for ambiguity error with `AbstractGraph` version -function Graphs.outdegree(graph::AbstractDataGraph, vertex::Integer) - return outdegree(underlying_graph(graph), vertex) -end - -# Fix for ambiguity error with `AbstractGraph` version -function Graphs.a_star( - graph::AbstractDataGraph, source::Integer, destination::Integer, args... - ) - return a_star(underlying_graph(graph), source, destination, args...) -end - -# Fix for ambiguity error with `AbstractGraph` version -@traitfn function Graphs.steiner_tree( - graph::AbstractDataGraph::(!IsDirected), term_vert::Vector{<:Integer}, args... +function Graphs.eccentricity( + graph::AbstractDataGraph, + vertex::Integer, + distmx::AbstractMatrix{<:Real} = NamedGraphs.weights(graph) ) - return steiner_tree(underlying_graph(graph), term_vert, args...) + return NamedGraphs.namedgraph_eccentricity(graph, vertex, distmx) end @traitfn GraphsExtensions.directed_graph(graph::AbstractDataGraph::IsDirected) = graph @@ -371,24 +339,6 @@ function Graphs.rem_edge!(graph::AbstractDataGraph, edge) return graph end -# Fix ambiguity with: -# Graphs.neighbors(graph::AbstractGraph, v::Integer) -function Graphs.neighbors(graph::AbstractDataGraph, v::Integer) - return Graphs.neighbors(underlying_graph(graph), v) -end - -# Fix ambiguity with: -# Graphs.bfs_tree(graph::AbstractGraph, s::Integer; dir) -function Graphs.bfs_tree(graph::AbstractDataGraph, s::Integer; kwargs...) - return Graphs.bfs_tree(underlying_graph(graph), s; kwargs...) -end - -# Fix ambiguity with: -# Graphs.dfs_tree(graph::AbstractGraph, s::Integer; dir) -function Graphs.dfs_tree(graph::AbstractDataGraph, s::Integer; kwargs...) - return Graphs.dfs_tree(underlying_graph(graph), s; kwargs...) -end - function map_vertex_data(f, graph::AbstractGraph; vertices = nothing) new_graph = copy(graph) vs = isnothing(vertices) ? Graphs.vertices(graph) : vertices diff --git a/src/datagraph.jl b/src/datagraph.jl index f74f4bd..7691b91 100644 --- a/src/datagraph.jl +++ b/src/datagraph.jl @@ -1,5 +1,5 @@ using Dictionaries: Dictionary -using Graphs: Graphs, edgetype, has_edge, has_vertex +using Graphs: Graphs, bfs_tree, dfs_tree, edgetype, has_edge, has_vertex using NamedGraphs.GraphsExtensions: convert_vertextype, directed_graph, directed_graph_type, rename_vertices, vertextype using NamedGraphs: GenericNamedGraph, similar_graph diff --git a/test/test_basics.jl b/test/test_basics.jl index 10bd9c9..b50bcd6 100644 --- a/test/test_basics.jl +++ b/test/test_basics.jl @@ -355,13 +355,13 @@ using Test: @test, @test_broken, @testset t = bfs_tree(g, 2) es = [2 => 1, 2 => 3, 3 => 4] - @test t isa NamedDiGraph{Int} + @test underlying_graph(t) isa NamedDiGraph{Int} @test nv(t) == nv(g) @test ne(t) == nv(g) - 1 @test all(e -> has_edge(t, e), es) t = dfs_tree(g, 2) - @test t isa NamedDiGraph{Int} + @test underlying_graph(t) isa NamedDiGraph{Int} @test nv(t) == nv(g) @test ne(t) == nv(g) - 1 @test all(e -> has_edge(t, e), es) From 9980b2bf30fceb19bbd7785c722744f6587f664d Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Tue, 21 Apr 2026 09:51:04 +0100 Subject: [PATCH 30/36] Add comments indicating methods required for ambiguity resolution. --- src/dataview.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/dataview.jl b/src/dataview.jl index 9de6768..8eb055f 100644 --- a/src/dataview.jl +++ b/src/dataview.jl @@ -66,8 +66,9 @@ function Base.isassigned(view::EdgeDataView, key::Pair) return isassigned(view, to_graph_index(view.graph, key)) end -Base.getindex(view::VertexOrEdgeDataView{K}, key::K) where {K} = _getindex(view, key) Base.getindex(view::VertexOrEdgeDataView, key) = _getindex(view, key) +# For method ambiguity: +Base.getindex(view::VertexOrEdgeDataView{K}, key::K) where {K} = _getindex(view, key) function _getindex(view::VertexDataView, key) isassigned(view, key) || throw(IndexError("VertexDataView does not contain index $key")) @@ -133,7 +134,9 @@ end Base.keys(dvs::SubDataView) = dvs.inds Base.getindex(view::SubDataView, key) = getindex_dataview(view, key) +# For method ambiguity: Base.getindex(view::SubDataView{K}, key::K) where {K} = getindex_dataview(view, key) + function getindex_dataview(dvs::SubDataView, key) isassigned(dvs, key) || throw(IndexError("Dictionary does not contain index: $key")) return dvs.view[key] From 7fb2f8530505f711899a0a80335ebe2db9009485 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Tue, 21 Apr 2026 10:31:50 +0100 Subject: [PATCH 31/36] Add missing `similar_graph` type domain method for `DataGraph`. --- src/datagraph.jl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/datagraph.jl b/src/datagraph.jl index 7691b91..4a6b2fd 100644 --- a/src/datagraph.jl +++ b/src/datagraph.jl @@ -68,6 +68,22 @@ function NamedGraphs.similar_graph( return DataGraph(new_underlying_graph; vertex_data_type, edge_data_type) end +function NamedGraphs.similar_graph( + G::Type{<:DataGraph}, + vertices + ) + new_underlying_graph = similar_graph( + underlying_graph_type(G), + vertices + ) + + VD = vertex_data_type(G) + ED = edge_data_type(G) + + V = vertextype(G) + + return DataGraph{V}(new_underlying_graph; vertex_data_type = VD, edge_data_type = ED) +end function Base.copy(graph::DataGraph) # Need to manually copy the keys of Dictionaries, see: # https://github.com/andyferris/Dictionaries.jl/issues/98 From 345ebc12a1351346a4d56a4ead7b90fa861b35de Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Tue, 21 Apr 2026 09:52:47 +0100 Subject: [PATCH 32/36] Refactor `reverse` function to use `rem_edges`. --- src/abstractdatagraph.jl | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index 55c9c92..0f9a729 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -2,7 +2,7 @@ using Dictionaries: Indices, set!, unset! using Graphs: Graphs, AbstractEdge, IsDirected, a_star, add_edge!, add_vertex!, edges, indegree, induced_subgraph, ne, nv, outdegree, steiner_tree, vertices using NamedGraphs.GraphsExtensions: GraphsExtensions, add_edges!, add_vertices!, - arrange_edge, incident_edges, is_edge_arranged, vertextype + arrange_edge, incident_edges, is_edge_arranged, rem_edges, vertextype using NamedGraphs.OrdinalIndexing: OrdinalSuffixedInteger using NamedGraphs.SimilarType: similar_type using NamedGraphs: NamedGraphs, AbstractEdges, AbstractNamedEdge, AbstractNamedGraph, @@ -262,12 +262,7 @@ function GraphsExtensions.rename_vertices(f::Function, graph::AbstractDataGraph) end function Base.reverse(graph::AbstractDataGraph) - reversed_graph = similar_graph(graph, vertices(graph)) - for v in vertices(graph) - if isassigned(graph, v) - reversed_graph[v] = graph[v] - end - end + reversed_graph = rem_edges(graph, edges(graph)) for e in edges(graph) add_edge!(reversed_graph, reverse(e)) if isassigned(graph, e) From 29354f86da6a6589f78ca8613455966974c208c1 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Wed, 22 Apr 2026 12:19:29 +0100 Subject: [PATCH 33/36] Fix bug in `directed_graph` calling removed `similar_graph` method; add tests. --- src/abstractdatagraph.jl | 2 +- test/test_basics.jl | 30 ++++++++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index 0f9a729..21c8bad 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -213,7 +213,7 @@ end # Fallback to constructing a concrete `DataGraph`. @traitfn function GraphsExtensions.directed_graph(graph::AbstractDataGraph::(!IsDirected)) - underlying_digraph = similar_graph(NamedDiGraph, vertices(graph), edges(graph)) + underlying_digraph = similar_graph(NamedDiGraph, vertices(graph)) # edgeless VD = vertex_data_type(graph) ED = edge_data_type(graph) diff --git a/test/test_basics.jl b/test/test_basics.jl index b50bcd6..727da8d 100644 --- a/test/test_basics.jl +++ b/test/test_basics.jl @@ -4,9 +4,9 @@ using Dictionaries: Dictionaries, AbstractDictionary, AbstractIndices, Dictionar IndexError, Indices, dictionary, unset! using Graphs: SimpleDiGraph, a_star, add_edge!, bfs_tree, connected_components, degree, dfs_tree, dijkstra_shortest_paths, dst, edges, edgetype, grid, has_edge, has_vertex, - indegree, ne, nv, outdegree, path_graph, src, steiner_tree, vertices + indegree, is_directed, ne, nv, outdegree, path_graph, src, steiner_tree, vertices using GraphsFlows: GraphsFlows -using NamedGraphs.GraphsExtensions: rename_vertices, subgraph, vertextype, ⊔ +using NamedGraphs.GraphsExtensions: directed_graph, rename_vertices, subgraph, vertextype, ⊔ using NamedGraphs.NamedGraphGenerators: named_grid, named_path_graph using NamedGraphs.OrdinalIndexing: nd, rd, st, th using NamedGraphs: NamedDiGraph, NamedEdge, NamedGraph, empty_graph, similar_graph @@ -153,6 +153,32 @@ using Test: @test, @test_broken, @testset @test dg[2 => "Y"] == "edge_Y2" @test dg["Y" => 2] == "edge_Y2" end + @testset "(un)directed graph" begin + dg = DataGraph(named_path_graph(3)) + dg[1 => 2] = "edge_12" + @test dg[1 => 2] == "edge_12" + @test dg[2 => 1] == "edge_12" + dg[2 => 1] = "edge_21" + @test dg[1 => 2] == "edge_21" + @test dg[2 => 1] == "edge_21" + + dg = DataGraph(named_path_graph(3)) + + dg[1 => 2] = "edge_12" + + ddg = directed_graph(dg) + @test !is_directed(dg) + @test is_directed(ddg) + @test isassigned(ddg, 1 => 2) + @test isassigned(ddg, 2 => 1) + @test ddg[1 => 2] == ddg[2 => 1] + + ddg[1 => 2] = "edge_12" + ddg[2 => 1] = "edge_21" + + @test ddg[1 => 2] == "edge_12" + @test ddg[2 => 1] == "edge_21" + end @testset "get and get! functions" begin g = named_grid(4) From 836d8fff4c191ef49ba1201e387eb3a76b2afce0 Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Wed, 22 Apr 2026 14:10:18 +0100 Subject: [PATCH 34/36] Fix `similar_graph` docstring. --- src/abstractdatagraph.jl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index 21c8bad..54189c8 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -120,16 +120,16 @@ end # Construct a similar `AbstractDataGraph` defined by `underlying_graph` with `vertex_data_type` and `edge_data_type`. # To be specialized (has fallback). """ - similar_graph(datagraph::AbstractDataGraph, vertices, edges) similar_graph(datagraph::AbstractDataGraph, D::Type) + similar_graph(datagraph::AbstractDataGraph, D::Type, vertices) similar_graph(datagraph::AbstractDataGraph, VD::Type, ED::Type) - similar_graph(datagraph::AbstractDataGraph, D::Type, vertices, edges) - similar_graph(datagraph::AbstractDataGraph, VD::Type, ED::Type, vertices, edges) + similar_graph(datagraph::AbstractDataGraph, VD::Type, ED::Type, vertices) -Create an uninitialized data graph, similar to the provided `datagraph`, but with `vertices` -and `edges`. If vertices and edges are not provided, then the vertices and edges of `datagraph` are used. -One may also provide a vertex data type `VD` and an edge data type `ED` or -a type `D` such that `VD = ED = D`. +Create an uninitialized data graph, similar to the provided `datagraph`, but with vertices +defined by `vertices` and a vertex and edge data type `D`. One may also provide separate +vertex and edge data types `VD` and `ED`. +If vertices are not provided, then the graph is constructed with the same vertices and edges +as the input graph. """ function NamedGraphs.similar_graph( graph::AbstractDataGraph From 6d9407720806641c28400264a6ef31bf706ecc2f Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Mon, 27 Apr 2026 09:54:42 -0400 Subject: [PATCH 35/36] Improve TODO code comment --- src/abstractdatagraph.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index 54189c8..952eb17 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -390,7 +390,7 @@ function NamedGraphs.induced_subgraph_from_vertices(graph::AbstractDataGraph, su end end - # copyto!(subgraph, graph) + # TODO: It would be nice to have `copyto!(subgraph, graph)` do the above. return subgraph, vlist end From b5680d43ee146005a7e334096eccfac23b3913fc Mon Sep 17 00:00:00 2001 From: Jack Dunham Date: Mon, 27 Apr 2026 15:00:57 -0400 Subject: [PATCH 36/36] Remove stale code comment. --- src/abstractdatagraph.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index 952eb17..2fefa68 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -117,8 +117,6 @@ end # ============================ `similar_graph` (value domain) ============================ # -# Construct a similar `AbstractDataGraph` defined by `underlying_graph` with `vertex_data_type` and `edge_data_type`. -# To be specialized (has fallback). """ similar_graph(datagraph::AbstractDataGraph, D::Type) similar_graph(datagraph::AbstractDataGraph, D::Type, vertices)