diff --git a/Project.toml b/Project.toml index 5aaa4d7..7dd2354 100644 --- a/Project.toml +++ b/Project.toml @@ -1,14 +1,16 @@ name = "MetaGraphsNext" uuid = "fa8bd995-216d-47f1-8a91-f3b68fbeb377" -version = "0.4.1" +version = "0.5.0" [deps] Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6" JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" +SimpleTraits = "699a6c99-e7fa-54fc-8d76-47d257e15c1d" [compat] Graphs = "1.4.1" JLD2 = "0.1.11, 0.2, 0.3, 0.4" +SimpleTraits = "0.9" julia = "1.6" [extras] diff --git a/src/MetaGraphsNext.jl b/src/MetaGraphsNext.jl index 219a393..4bba836 100644 --- a/src/MetaGraphsNext.jl +++ b/src/MetaGraphsNext.jl @@ -2,15 +2,15 @@ module MetaGraphsNext using JLD2 using Graphs +using SimpleTraits -export MetaGraph, MetaDiGraph, MetaUndirectedGraph +export MetaGraph export label_for, code_for, set_data! export weighttype, default_weight, get_weight_function export MGFormat, DOTFormat include("metagraph.jl") -include("metaundigraph.jl") -include("metadigraph.jl") +include("directedness.jl") include("graphs.jl") include("dict_utils.jl") include("weights.jl") diff --git a/src/directedness.jl b/src/directedness.jl new file mode 100644 index 0000000..d2af739 --- /dev/null +++ b/src/directedness.jl @@ -0,0 +1,34 @@ +""" + arrange(graph, label_1, label_2) + +Sort two vertex labels in a default order (useful to uniquely express undirected edges). +""" +function arrange end + +@traitfn function arrange( + ::AG::IsDirected, label_1, label_2, _drop... +) where {T,AG<:AbstractGraph{T}} + return label_1, label_2 +end + +@traitfn function arrange( + ::AG::(!IsDirected), label_1, label_2, code_1, code_2 +) where {T,AG<:AbstractGraph{T}} + if code_1 < code_2 + (label_1, label_2) + else + (label_2, label_1) + end +end + +@traitfn function arrange( + meta_graph::AG::(!IsDirected), label_1, label_2 +) where {T,AG<:AbstractGraph{T}} + return arrange( + meta_graph, + label_1, + label_2, + code_for(meta_graph, label_1), + code_for(meta_graph, label_2), + ) +end diff --git a/src/graphs.jl b/src/graphs.jl index 0fd4e50..4eb85ba 100644 --- a/src/graphs.jl +++ b/src/graphs.jl @@ -41,6 +41,18 @@ function Base.issubset(meta_graph::MetaGraph, h::MetaGraph) return issubset(meta_graph.graph, h.graph) end +function Graphs.is_directed( + ::MetaGraph{Code,Label,Graph} +) where {Code,Label,Graph<:AbstractGraph} + return is_directed(Graph) +end + +function Graphs.is_directed( + ::Type{<:MetaGraph{Code,Label,Graph}} +) where {Code,Label,Graph<:AbstractGraph} + return is_directed(Graph) +end + ## Link between graph codes and metagraph labels """ @@ -210,7 +222,7 @@ function Graphs.induced_subgraph( return new_graph, code_map end -function Graphs.reverse(meta_graph::MetaDiGraph) +@traitfn function Graphs.reverse(meta_graph::MetaGraph::IsDirected) edge_data = meta_graph.edge_data reverse_edge_data = empty(edge_data) for (label_1, label_2) in keys(edge_data) diff --git a/src/metadigraph.jl b/src/metadigraph.jl deleted file mode 100644 index d790968..0000000 --- a/src/metadigraph.jl +++ /dev/null @@ -1,21 +0,0 @@ -""" - MetaDiGraph - -A `MetaGraph` whose underlying graph is of type `Graphs.SimpleDiGraph`. -""" -const MetaDiGraph = MetaGraph{<:Any,<:Any,<:SimpleDiGraph} - -function Graphs.SimpleDiGraph(meta_graph::MetaDiGraph) - return meta_graph.graph -end - -function Graphs.is_directed(::Type{<:MetaDiGraph}) - return true -end -function Graphs.is_directed(::MetaDiGraph) - return true -end - -function arrange(::MetaDiGraph, label_1, label_2, _...) - return label_1, label_2 -end diff --git a/src/metagraph.jl b/src/metagraph.jl index c11c223..a7082fb 100644 --- a/src/metagraph.jl +++ b/src/metagraph.jl @@ -1,5 +1,14 @@ """ - MetaGraph{Code<:Integer,Label,Graph,VertexData,EdgeData,GraphData,WeightFunction,Weight<:Real} <: AbstractGraph{Code} + MetaGraph{ + Code<:Integer, + Label, + Graph, + VertexData, + EdgeData, + GraphData, + WeightFunction, + Weight<:Real + } <: AbstractGraph{Code} A graph type with custom vertex labels containing vertex-, edge- and graph-level metadata. @@ -65,13 +74,6 @@ function MetaGraph( ) end -""" - arrange(graph, label_1, label_2) - -Sort two vertex labels in a default order (useful to uniquely express undirected edges). -""" -function arrange end - function Base.zero( meta_graph::MetaGraph{Code,Label,Graph,VertexData,EdgeData} ) where {Code,Label,Graph,VertexData,EdgeData} diff --git a/src/metaundigraph.jl b/src/metaundigraph.jl deleted file mode 100644 index 904dee4..0000000 --- a/src/metaundigraph.jl +++ /dev/null @@ -1,29 +0,0 @@ -""" - MetaUndirectedGraph - -A `MetaGraph` whose underlying graph is of type `Graphs.SimpleGraph`. -""" -const MetaUndirectedGraph = MetaGraph{<:Any,<:Any,<:SimpleGraph} - -Graphs.SimpleGraph(meta_graph::MetaUndirectedGraph) = meta_graph.graph - -Graphs.is_directed(::Type{<:MetaUndirectedGraph}) = false -Graphs.is_directed(::MetaUndirectedGraph) = false - -function arrange(::MetaUndirectedGraph, label_1, label_2, code_1, code_2) - if code_1 < code_2 - (label_1, label_2) - else - (label_2, label_1) - end -end - -function arrange(meta_graph::MetaUndirectedGraph, label_1, label_2) - return arrange( - meta_graph, - label_1, - label_2, - code_for(meta_graph, label_1), - code_for(meta_graph, label_2), - ) -end diff --git a/test/labels_codes.jl b/test/labels_codes.jl deleted file mode 100644 index 1a5c31b..0000000 --- a/test/labels_codes.jl +++ /dev/null @@ -1,21 +0,0 @@ -using MetaGraphsNext - -colors = MetaGraph( - Graph(); VertexData=String, EdgeData=Symbol, graph_data="graph_of_colors" -) - -labels = [:red, :yellow, :blue] -values = ["warm", "warm", "cool"] -for (label, value) in zip(labels, values) - colors[label] = value -end -for label in labels - @test label_for(colors, code_for(colors, label)) == label -end -#delete an entry and test again -rem_vertex!(colors, 1) -popfirst!(labels) -popfirst!(values) -for label in labels - @test label_for(colors, code_for(colors, label)) == label -end diff --git a/test/labels_codes_directedness.jl b/test/labels_codes_directedness.jl new file mode 100644 index 0000000..f1c0f0a --- /dev/null +++ b/test/labels_codes_directedness.jl @@ -0,0 +1,34 @@ +# undirected MetaGraph +colors = MetaGraph( + Graph(); VertexData=String, EdgeData=Symbol, graph_data="graph_of_colors" +) +@test istrait(IsDirected{typeof(colors)}) == is_directed(colors) == false +labels = [:red, :yellow, :blue] +values = ["warm", "warm", "cool"] +for (label, value) in zip(labels, values) + colors[label] = value +end +for label in labels + @test label_for(colors, code_for(colors, label)) == label +end +#delete an entry and test again +rem_vertex!(colors, 1) +popfirst!(labels) +popfirst!(values) +for label in labels + @test label_for(colors, code_for(colors, label)) == label +end +@test MetaGraphsNext.arrange(colors, :yellow, :blue) == (:blue, :yellow) + +# directed MetaGraph +dcolors = MetaGraph( + SimpleDiGraph(); VertexData=String, EdgeData=Symbol, graph_data="graph_of_colors" +) +@test istrait(IsDirected{typeof(dcolors)}) == is_directed(dcolors) == true +labels = [:red, :yellow, :blue] +values = ["warm", "warm", "cool"] +for (label, value) in zip(labels, values) + dcolors[label] = value +end +dcolors[:red, :yellow] = :redyellow +@test MetaGraphsNext.arrange(dcolors, :yellow, :blue) == (:yellow, :blue) diff --git a/test/runtests.jl b/test/runtests.jl index 72012c2..a3649d1 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -3,6 +3,7 @@ using Documenter using Graphs using JuliaFormatter using MetaGraphsNext +using SimpleTraits using Test @testset verbose = true "MetaGraphsNext" begin @@ -26,7 +27,7 @@ using Test include(joinpath("tutorial", "3_files.jl")) end end - @testset verbose = true "Labels and codes" begin - include("labels_codes.jl") + @testset verbose = true "Labels, codes, directedness" begin + include("labels_codes_directedness.jl") end end diff --git a/test/tutorial/2_graphs.jl b/test/tutorial/2_graphs.jl index 8324914..cb5651d 100644 --- a/test/tutorial/2_graphs.jl +++ b/test/tutorial/2_graphs.jl @@ -39,8 +39,6 @@ eltype(cities) #- edgetype(cities) @test edgetype(cities) == Graphs.SimpleEdge{Int} #src -#- -SimpleGraph(cities) # We can check the set of vertices: @@ -121,8 +119,6 @@ rock_paper_scissors[:paper, :rock] = "paper beats rock"; is_directed(rock_paper_scissors) @test is_directed(rock_paper_scissors) #src -#- -SimpleDiGraph(rock_paper_scissors) # Directed graphs can be reversed: