diff --git a/Project.toml b/Project.toml index d263a4f..6492d09 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "DataGraphs" uuid = "b5a273c3-7e6c-41f6-98bd-8d7f1525a36a" authors = ["Matthew Fishman and contributors"] -version = "0.2.7" +version = "0.2.8" [deps] Dictionaries = "85a47980-9c8c-11e8-2b9f-f7ca1fa99fb4" @@ -19,7 +19,7 @@ DataGraphsGraphsFlowsExt = "GraphsFlows" Dictionaries = "0.4" Graphs = "1" GraphsFlows = "0.1.1" -NamedGraphs = "0.6.0" +NamedGraphs = "0.6.9" SimpleTraits = "0.9" julia = "1.7" diff --git a/src/DataGraphs.jl b/src/DataGraphs.jl index d15f1bf..7569491 100644 --- a/src/DataGraphs.jl +++ b/src/DataGraphs.jl @@ -3,7 +3,6 @@ module DataGraphs include("utils.jl") include("traits/isunderlyinggraph.jl") include("abstractdatagraph.jl") -include("arrange.jl") include("datagraph.jl") # TODO: Turn into a weak dependency once `GraphsExtensions` # is split off from `NamedGraphs`. diff --git a/src/abstractdatagraph.jl b/src/abstractdatagraph.jl index f6d46db..d6e2612 100644 --- a/src/abstractdatagraph.jl +++ b/src/abstractdatagraph.jl @@ -11,7 +11,8 @@ using Graphs: nv, steiner_tree, vertices -using NamedGraphs.GraphsExtensions: GraphsExtensions, incident_edges, vertextype +using NamedGraphs.GraphsExtensions: + GraphsExtensions, arrange_edge, incident_edges, is_edge_arranged, vertextype using NamedGraphs.SimilarType: similar_type using SimpleTraits: SimpleTraits, Not, @traitfn @@ -157,6 +158,11 @@ end @traitfn GraphsExtensions.directed_graph(graph::AbstractDataGraph::IsDirected) = graph +reverse_data_direction(graph::AbstractDataGraph, data) = data +function reverse_data_direction(graph::AbstractDataGraph, edge::AbstractEdge, data) + return is_edge_arranged(graph, edge) ? data : reverse_data_direction(graph, data) +end + @traitfn function GraphsExtensions.directed_graph(graph::AbstractDataGraph::(!IsDirected)) digraph = directed_graph(typeof(graph))(directed_graph(underlying_graph(graph))) for v in vertices(graph) @@ -335,9 +341,8 @@ function Base.get!(graph::AbstractDataGraph, vertex, default) end function Base.getindex(graph::AbstractDataGraph, edge::AbstractEdge) - is_edge_arranged_ = is_edge_arranged(graph, edge) - data = edge_data(graph)[arrange(is_edge_arranged_, edge)] - return reverse_data_direction(is_edge_arranged_, graph, data) + data = edge_data(graph)[arrange_edge(graph, edge)] + return reverse_data_direction(graph, edge, data) end # Support syntax `g[v1 => v2]` @@ -346,9 +351,8 @@ function Base.getindex(graph::AbstractDataGraph, edge::Pair) end function Base.get(graph::AbstractDataGraph, edge::AbstractEdge, default) - is_edge_arranged_ = is_edge_arranged(graph, edge) - data = get(edge_data(graph), arrange(is_edge_arranged_, edge), default) - return reverse_data_direction(is_edge_arranged_, graph, data) + data = get(edge_data(graph), arrange_edge(graph, edge), default) + return reverse_data_direction(graph, edge, data) end function Base.get(graph::AbstractDataGraph, edge::Pair, default) @@ -356,9 +360,8 @@ function Base.get(graph::AbstractDataGraph, edge::Pair, default) end function Base.get!(graph::AbstractDataGraph, edge::AbstractEdge, default) - is_edge_arranged_ = is_edge_arranged(graph, edge) - data = get!(edge_data(graph), arrange(is_edge_arranged_, edge), default) - return reverse_data_direction(is_edge_arranged_, graph, data) + data = get!(edge_data(graph), arrange_edge(graph, edge), default) + return reverse_data_direction(graph, edge, data) end function Base.get!(graph::AbstractDataGraph, edge::Pair, default) @@ -374,12 +377,12 @@ function Base.isassigned(graph::AbstractDataGraph, vertex) return isassigned(vertex_data(graph), vertex) end -function Base.isassigned(graph::AbstractDataGraph, vertex::AbstractEdge) - return isassigned(edge_data(graph), arrange(graph, vertex)) +function Base.isassigned(graph::AbstractDataGraph, edge::AbstractEdge) + return isassigned(edge_data(graph), arrange_edge(graph, edge)) end -function Base.isassigned(graph::AbstractDataGraph, vertex::Pair) - return isassigned(graph, edgetype(graph)(vertex)) +function Base.isassigned(graph::AbstractDataGraph, edge::Pair) + return isassigned(graph, edgetype(graph)(edge)) end function Base.setindex!(graph::AbstractDataGraph, data, vertex) @@ -388,9 +391,8 @@ function Base.setindex!(graph::AbstractDataGraph, data, vertex) end function Base.setindex!(graph::AbstractDataGraph, data, edge::AbstractEdge) - is_edge_arranged_ = is_edge_arranged(graph, edge) - arranged_edge = arrange(is_edge_arranged_, edge) - arranged_data = reverse_data_direction(is_edge_arranged_, graph, data) + arranged_edge = arrange_edge(graph, edge) + arranged_data = reverse_data_direction(graph, edge, data) set!(edge_data(graph), arranged_edge, arranged_data) return graph end diff --git a/src/arrange.jl b/src/arrange.jl deleted file mode 100644 index 3948340..0000000 --- a/src/arrange.jl +++ /dev/null @@ -1,63 +0,0 @@ -using Graphs: IsDirected, src, dst -using SimpleTraits: SimpleTraits, Not, @traitfn - -# TODO: Use a function `arrange` like in MetaGraphsNext: -# https://github.com/JuliaGraphs/MetaGraphsNext.jl/blob/1539095ee6088aba0d5b1cb057c339ad92557889/src/metagraph.jl#L75-L80 -# to sort the vertices, only directed graphs should store data -# in both edge directions. Also, define `reverse_data_direction` as a function -# stored in directed AbstractDataGraph types (which by default returns nothing, -# indicating not to automatically store data in both directions) -# TODO: Use `Graphs.is_ordered`? https://juliagraphs.org/Graphs.jl/v1.7/core_functions/core/#Graphs.is_ordered-Tuple{AbstractEdge} -function is_arranged(src, dst) - if !hasmethod(isless, typeof.((src, dst))) - return is_arranged_by_hash(src, dst) - end - return isless(src, dst) -end - -function is_arranged_by_hash(src, dst) - src_hash = hash(src) - dst_hash = hash(dst) - if (src_hash == dst_hash) && (src ≠ dst) - @warn "Hash collision when arranging vertices to extract edge data. Setting or extracting data may be ill-defined." - end - return isless(src_hash, dst_hash) -end - -# https://github.com/JuliaLang/julia/blob/v1.8.5/base/tuple.jl#L470-L482 -is_arranged(::Tuple{}, ::Tuple{}) = false -is_arranged(::Tuple{}, ::Tuple) = true -is_arranged(::Tuple, ::Tuple{}) = false - -function is_arranged(t1::Tuple, t2::Tuple) - a, b = t1[1], t2[1] - return is_arranged(a, b) || (isequal(a, b) && is_arranged(Base.tail(t1), Base.tail(t2))) -end - -@traitfn function is_edge_arranged(graph::AbstractDataGraph::IsDirected, src, dst) - return true -end - -@traitfn function is_edge_arranged(graph::AbstractDataGraph::(!IsDirected), src, dst) - return is_arranged(src, dst) -end - -function is_edge_arranged(graph::AbstractDataGraph, edge::AbstractEdge) - return is_edge_arranged(graph, src(edge), dst(edge)) -end - -function arrange(graph::AbstractDataGraph, edge::AbstractEdge) - return arrange(is_edge_arranged(graph, edge), edge) -end - -function arrange(is_arranged::Bool, edge::AbstractEdge) - return is_arranged ? edge : reverse(edge) -end - -# TODO: Store `reverse_data_direction` inside `AbstractDataGraph` -# to control data direction reversal by instance instead of -# just by type. -reverse_data_direction(graph::AbstractDataGraph, data) = data -function reverse_data_direction(is_arranged::Bool, graph::AbstractDataGraph, data) - return is_arranged ? data : reverse_data_direction(graph, data) -end diff --git a/test/test_basics.jl b/test/test_basics.jl index 1a5eefd..427cf63 100644 --- a/test/test_basics.jl +++ b/test/test_basics.jl @@ -1,11 +1,5 @@ using DataGraphs: - DataGraphs, - DataGraph, - edge_data, - edge_data_eltype, - is_arranged, - vertex_data, - vertex_data_eltype + DataGraphs, DataGraph, edge_data, edge_data_eltype, vertex_data, vertex_data_eltype using Dictionaries: AbstractIndices, Dictionary, Indices, dictionary using Graphs: add_edge!, @@ -37,8 +31,6 @@ using NamedGraphs.NamedGraphGenerators: named_grid, named_path_graph using NamedGraphs.OrdinalIndexing: nd, st, rd, th using Test: @test, @test_broken, @testset -using DataGraphs: is_arranged - @testset "DataGraphs.jl" begin @eval module $(gensym()) using DataGraphs: DataGraphs @@ -54,25 +46,6 @@ using DataGraphs: is_arranged end end - @testset "is_arranged" begin - for (a, b) in [ - (1, 2), - ([1], [2]), - ([1, 2], [2, 1]), - ([1, 2], [2]), - ([2], [2, 1]), - ((1,), (2,)), - ((1, 2), (2, 1)), - ((1, 2), (2,)), - ((2,), (2, 1)), - ("X", 1), - (("X",), (1, 2)), - ] - @test is_arranged(a, b) - @test !is_arranged(b, a) - end - end - @testset "Basics" begin g = grid((4,)) dg = DataGraph(g; vertex_data_eltype=String, edge_data_eltype=Symbol)