From 0077669a0fc7a97ce8567236e4398d1fa47cafae Mon Sep 17 00:00:00 2001 From: Dexter Date: Tue, 16 Mar 2021 23:09:07 +0100 Subject: [PATCH] Kj/metagraphs support (#3) * Create LabelledGraph package * Add LightGraphs dependency * Add MetaGraphs dependency * Add support for storing and retrieving properties * Implement storing and retrieving multiple properties * Add has_prop implementation --- Project.toml | 1 + src/LabelledGraphs.jl | 120 +++++++++++++++++++++++++++++++++++++++++- test/runtests.jl | 61 +++++++++++++++++++++ 3 files changed, 180 insertions(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index ac95af3..8258b84 100644 --- a/Project.toml +++ b/Project.toml @@ -5,6 +5,7 @@ version = "0.1.0" [deps] LightGraphs = "093fc24a-ae57-5d10-9952-331d41423f4d" +MetaGraphs = "626554b9-1ddb-594c-aa3c-2596fe9399a5" [compat] LightGraphs = "1.3" diff --git a/src/LabelledGraphs.jl b/src/LabelledGraphs.jl index 151b35f..b655281 100644 --- a/src/LabelledGraphs.jl +++ b/src/LabelledGraphs.jl @@ -1,6 +1,7 @@ module LabelledGraphs using LightGraphs + using MetaGraphs export LabelledGraph, LabelledDiGraph, LabelledEdge @@ -98,10 +99,125 @@ module LabelledGraphs add_vertex!.(Ref(lg), vertices) end + function MetaGraphs.set_prop!( + lg::LabelledGraph{S, T}, v::T, prop::Symbol, val + ) where {S <: AbstractMetaGraph, T} + set_prop!(lg.inner_graph, lg.reverse_label_map[v], prop, val) + end + + function MetaGraphs.set_prop!( + lg::LabelledGraph{S, T}, s::T, d::T, prop::Symbol, val + ) where {S <: AbstractMetaGraph, T} + set_prop!(lg.inner_graph, lg.reverse_label_map[s], lg.reverse_label_map[d], prop, val) + end + + function MetaGraphs.set_prop!( + lg::LabelledGraph{S, T}, e::LabelledEdge, prop::Symbol, val + ) where {S <: AbstractMetaGraph, T} + set_prop!(lg, src(e), dst(e), prop, val) + end + + function MetaGraphs.set_prop!( + lg::LabelledGraph{S, T}, prop::Symbol, val + ) where {S <: AbstractMetaGraph, T} + set_prop!(lg.inner_graph, prop, val) + end + + function MetaGraphs.get_prop( + lg::LabelledGraph{S, T}, v::T, prop::Symbol + ) where {S <: AbstractMetaGraph, T} + get_prop(lg.inner_graph, lg.reverse_label_map[v], prop) + end + + function MetaGraphs.get_prop( + lg::LabelledGraph{S, T}, s::T, d::T, prop::Symbol + ) where {S <: AbstractMetaGraph, T} + get_prop(lg.inner_graph, lg.reverse_label_map[s], lg.reverse_label_map[d], prop) + end + + function MetaGraphs.get_prop( + lg::LabelledGraph{S, T}, e::LabelledEdge, prop::Symbol + ) where {S <: AbstractMetaGraph, T} + get_prop(lg, src(e), dst(e), prop) + end + + function MetaGraphs.get_prop( + lg::LabelledGraph{S, T}, prop::Symbol + ) where {S <: AbstractMetaGraph, T} + get_prop(lg.inner_graph, prop) + end + + function MetaGraphs.set_props!( + lg::LabelledGraph{S, T}, v::T, dict + ) where {S <: AbstractMetaGraph, T} + set_props!(lg.inner_graph, lg.reverse_label_map[v], dict) + end + + function MetaGraphs.set_props!( + lg::LabelledGraph{S, T}, s::T, d::T, dict + ) where {S <: AbstractMetaGraph, T} + set_props!(lg.inner_graph, lg.reverse_label_map[s], lg.reverse_label_map[d], dict) + end + + function MetaGraphs.set_props!( + lg::LabelledGraph{S, T}, e::LabelledEdge, dict + ) where {S <: AbstractMetaGraph, T} + set_props!(lg, src(e), dst(e), dict) + end + + function MetaGraphs.set_props!( + lg::LabelledGraph{S, T}, dict + ) where {S <: AbstractMetaGraph, T} + set_props!(lg.inner_graph, dict) + end + + function MetaGraphs.props( + lg::LabelledGraph{S, T}, v::T + ) where {S <: AbstractMetaGraph, T} + props(lg.inner_graph, lg.reverse_label_map[v]) + end + + function MetaGraphs.props( + lg::LabelledGraph{S, T}, s::T, d::T + ) where {S <: AbstractMetaGraph, T} + props(lg.inner_graph, lg.reverse_label_map[s], lg.reverse_label_map[d]) + end + + function MetaGraphs.props( + lg::LabelledGraph{S, T}, e::LabelledEdge + ) where {S <: AbstractMetaGraph, T} + props(lg, src(e), dst(e)) + end + + function MetaGraphs.props(lg::LabelledGraph{S, T}) where {S <: AbstractMetaGraph, T} + props(lg.inner_graph) + end + + function MetaGraphs.has_prop( + lg::LabelledGraph{S, T}, v::T, prop::Symbol + ) where {S <: AbstractMetaGraph, T} + has_prop(lg.inner_graph, lg.reverse_label_map[v], prop) + end + + function MetaGraphs.has_prop( + lg::LabelledGraph{S, T}, s::T, d::T, prop::Symbol + ) where {S <: AbstractMetaGraph, T} + has_prop(lg.inner_graph, lg.reverse_label_map[s], lg.reverse_label_map[d], prop) + end + + function MetaGraphs.has_prop( + lg::LabelledGraph{S, T}, e::LabelledEdge, prop::Symbol + ) where {S <: AbstractMetaGraph, T} + has_prop(lg, src(e), dst(e), prop) + end + + function MetaGraphs.has_prop( + lg::LabelledGraph{S, T}, prop::Symbol + ) where {S <: AbstractMetaGraph, T} + has_prop(lg.inner_graph, prop) + end # --- Default-type aliases --- LabelledGraph(labels::Vector{T}) where T = LabelledGraph{SimpleGraph}(labels) LabelledDiGraph(labels::Vector{T}) where T = LabelledGraph{SimpleDiGraph}(labels) - - end diff --git a/test/runtests.jl b/test/runtests.jl index aec27be..f8f39af 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,4 +1,5 @@ using LightGraphs +using MetaGraphs using Test using LabelledGraphs @@ -217,3 +218,63 @@ end @test is_directed(lg) @test nv(lg) == 3 end + + +for graph_type ∈ (MetaGraph, MetaDiGraph) +@testset "LabelledGraph backed up by $graph_type can store metainformation" begin + lg = LabelledGraph{graph_type}([2, 5, 10]) + add_edge!(lg, 2, 5) + set_prop!(lg, 2, :x, 10.0) + set_prop!(lg, 2, 5, :y, "test") + set_prop!(lg, LabelledEdge(2, 5), :z, [1, 2,3]) + set_prop!(lg, :name, "the ising model") + + @test get_prop(lg, 2, :x) == 10.0 + @test get_prop(lg, LabelledEdge(2, 5), :z) == [1, 2, 3] + @test get_prop(lg, 2, 5, :y) == "test" + @test get_prop(lg, :name) == "the ising model" +end +end + + +for graph_type ∈ (MetaGraph, MetaDiGraph) +@testset "LabelledGraph backed up by $graph_type can store multiple metainformation at once" begin + lg = LabelledGraph{graph_type}([2, 5, 10]) + + vertex_props = Dict(:x => 10.0, :y => -1.0) + sd_props = Dict(:a => "test", :b => "Fortran") + edge_props = Dict(:u => [1, 2, 3], :v => 0) + graph_props = Dict(:name => "the", :title => "ising model") + + add_edge!(lg, 2, 5) + set_props!(lg, 2, vertex_props) + set_props!(lg, 2, 5, sd_props) + set_props!(lg, LabelledEdge(2, 5), edge_props) + set_props!(lg, graph_props) + + @test props(lg, 2) == vertex_props + @test props(lg, LabelledEdge(2, 5)) == merge(sd_props, edge_props) + @test props(lg, 2, 5) == merge(sd_props, edge_props) + @test props(lg) == graph_props +end +end + + +for graph_type ∈ (MetaGraph, MetaDiGraph) +@testset "LabelledGraph backed up by $graph_type should support querying for property existence" begin + lg = LabelledGraph{graph_type}([2, 5, 10]) + add_edge!(lg, 2, 5) + set_prop!(lg, 2, :x, 10.0) + set_prop!(lg, 2, 5, :y, "test") + set_prop!(lg, LabelledEdge(2, 5), :z, [1, 2,3]) + set_prop!(lg, :name, "the ising model") + + @test has_prop(lg, 2, :x) + @test !has_prop(lg, 2, :z) + @test has_prop(lg, LabelledEdge(2, 5), :z) + @test has_prop(lg, 2, 5, :y) + @test !has_prop(lg, 2, 5, :zenek) + @test has_prop(lg, :name) + @test !has_prop(lg, :title) +end +end