From 201f545812d9d2c0e8c0a7bfbaafd3d007285218 Mon Sep 17 00:00:00 2001 From: Simon Schoelly Date: Thu, 15 Apr 2021 13:15:54 +0200 Subject: [PATCH 01/11] Add @wrap_graph! macro --- src/SimpleValueGraphs.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/SimpleValueGraphs.jl b/src/SimpleValueGraphs.jl index f3a5261..95dbcf5 100644 --- a/src/SimpleValueGraphs.jl +++ b/src/SimpleValueGraphs.jl @@ -13,7 +13,7 @@ const LG = LightGraphs import LightGraphs: nv, ne, is_directed, - eltype, vertices, add_vertex!, has_vertex, + eltype, vertices, add_vertex!, rem_vertex!, has_vertex, edgetype, edges, src, dst, reverse, weights, add_edge!, rem_edge!, has_edge, @@ -88,6 +88,7 @@ export has_edge, add_vertex!, + rem_vertex!, has_vertex, inneighbors, @@ -123,6 +124,7 @@ include("AbstractTuples.jl") include("utils.jl") include("abstractvaluegraph.jl") +include("graphwrappers.jl") include("valueedge.jl") include("valuegraph.jl") include("matrices.jl") From 5d2618daa19c06da35404c076665595003304dbd Mon Sep 17 00:00:00 2001 From: Simon Schoelly Date: Thu, 15 Apr 2021 13:16:56 +0200 Subject: [PATCH 02/11] Generate Reverse methods with @wrap_graph! --- src/operators.jl | 34 ++++++---------------------------- 1 file changed, 6 insertions(+), 28 deletions(-) diff --git a/src/operators.jl b/src/operators.jl index ccd94b4..63c0587 100644 --- a/src/operators.jl +++ b/src/operators.jl @@ -38,12 +38,11 @@ end Lazy wrapper for value graphs that reverses the directions of the graphs edges. If this object is mutated, the wrapped graph is mutated as well. """ -struct Reverse{V, V_VALS, E_VALS, G_VALS, G<:AbstractValGraph{V, V_VALS, E_VALS, G_VALS}} <: AbstractValGraph{V, V_VALS, E_VALS, G_VALS} +struct Reverse{V <: Integer, V_VALS, E_VALS, G_VALS, G<:AbstractValGraph{V, V_VALS, E_VALS, G_VALS}} <: AbstractValGraph{V, V_VALS, E_VALS, G_VALS} graph::G end -_graphtype(::Type{<:Reverse{V, V_VALS, E_VALS, G_VALS, G}}) where {V, V_VALS, E_VALS, G_VALS, G} = G """ reverse(g::AbstractValGraph) @@ -59,21 +58,13 @@ reverse(rg::Reverse) = rg.graph ## Reverse ## --------------------------------- -nv(rg::Reverse) = nv(rg.graph) +wrapped_graph(g::Reverse) = g.graph +wrapped_graph_type(::Type{<:Reverse{V, V_VALS, E_VALS, G_VALS, G}}) where {V, V_VALS, E_VALS, G_VALS, G} = G +@wrap_graph! Reverse include=[ne] exclude=[has_edge, add_edge!, rem_edge!, get_edgeval, set_edgeval!] has_edge(rg::Reverse, s::Integer, d::Integer) = has_edge(rg.graph, d, s) - -LG.is_directed(RG::Type{<:Reverse}) = is_directed(_graphtype(RG)) - -zero(RG::Type{<:Reverse}) = Reverse{_graphtype(RG)}(zero(RG)) - -get_vertexval(rg::Reverse, v::Integer, key::Integer) = get_vertexval(rg.graph, v, key) -get_vertexval(rg::Reverse, v::Integer, key::Symbol) = get_vertexval(rg.graph, v, key) -get_vertexval(rg::Reverse, v::Integer, ::Colon) = get_vertexval(rg.graph, v, :) - -set_vertexval!(rg::Reverse, v::Integer, key::Integer, value) = set_vertexval!(rg.graph, v, key, value) -set_vertexval!(rg::Reverse, v::Integer, key::Symbol, value) = set_vertexval!(rg.graph, v, key, value) -set_vertexval!(rg::Reverse, v::Integer, ::Colon, values) = set_vertexval!(rg.graph, v, :, values) +add_edge!(rg::Reverse, s::Integer, d::Integer, values) = add_edge!(rg.graph, d, s, values) +rem_edge!(rg::Reverse, s::Integer, d::Integer) = rem_edge!(rg.graph, d, s) get_edgeval(rg::Reverse, s::Integer, d::Integer, key::Integer) = get_edgeval(rg.graph, d, s, key) get_edgeval(rg::Reverse, s::Integer, d::Integer, key::Symbol) = get_edgeval(rg.graph, d, s, key) @@ -83,16 +74,3 @@ set_edgeval!(rg::Reverse, s::Integer, d::Integer, key::Integer, value) = set_edg set_edgeval!(rg::Reverse, s::Integer, d::Integer, key::Symbol, value) = set_edgeval!(rg.graph, d, s, key, value) set_edgeval!(rg::Reverse, s::Integer, d::Integer, ::Colon, values) = set_edgeval!(rg.graph, d, s, :, values) -get_graphval(rg::Reverse, key::Integer) = get_graphval(rg.graph, key) -get_graphval(rg::Reverse, key::Symbol) = get_graphval(rg.graph, key) -get_graphval(rg::Reverse, ::Colon) = get_graphval(rg.graph, :) - -set_graphval!(rg::Reverse, key::Integer, value) = set_graphval!(rg.graph, key, value) -set_graphval!(rg::Reverse, key::Symbol, value) = set_graphval!(rg.graph, key, value) -set_graphval!(rg::Reverse, ::Colon, values) = set_graphval!(rg.graph, :, values) - -add_vertex!(rg::Reverse, values) = add_vertex!(rg.graph, values) - -add_edge!(rg::Reverse, s::Integer, d::Integer, values) = add_edge!(rg.graph, d, s, values) - -ne(rg::Reverse) = ne(rg.graph) From ac694305a2b2b371e5ed24cb9eb18eb5e6a88781 Mon Sep 17 00:00:00 2001 From: Simon Schoelly Date: Thu, 15 Apr 2021 13:19:25 +0200 Subject: [PATCH 03/11] Add @wrap_graph! macro --- src/graphwrappers.jl | 195 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 src/graphwrappers.jl diff --git a/src/graphwrappers.jl b/src/graphwrappers.jl new file mode 100644 index 0000000..b3d9b67 --- /dev/null +++ b/src/graphwrappers.jl @@ -0,0 +1,195 @@ + +""" + wrapped_graph(g::MyGraphWrapper) + +Method to implement for creating graph wrapper types. +Should return the graph that is wrapped inside `g`. + +### See also +[`wrapped_graph_type`](@ref), [`@wrap_graph!`](@ref) +""" +function wrapped_graph(::AbstractValGraph) end + +""" + wrapped_graph_type{::Type{<:MyGraphWrapper}} + +Method to implement for creating graph wrapper types. +Should return the type of the graph that is wrapped inside +a graph wrapper. + +### See also +[`wrapped_graph`](@ref), [`@wrap_graph!`](@ref) + +""" +function wrapped_graph_type(::Type) end + +_DEFAULT_INCLUDE = [ + :nv, + :is_directed, + :zero, + :has_edge, + :get_graphval, + :get_vertexval, + :get_edgeval, + :set_graphval!, + :set_vertexval!, + :set_edgeval!, + :add_vertex!, + :rem_vertex!, + :add_edge!, + :rem_edge!, + ] + +_EXTRA_INCLUDE = [ + :ne, +] + +""" + @wrap_graph! MyGraphWrapper include=[] exclude=[] + +Generate default method implementations for graph wrappers. +These default implementations simply call the wrapped graph. For that, one +needs to implement `wrapped_graph` and `wrapped_graph_type` for the custom graph wrapper. + +Methods given as a `Vector` to the keyword argument `excluded` are not created. +By default, methods for the following functions are generated: +$(join(map(s -> '`' * string(s) * '`', _DEFAULT_INCLUDE), ", ")). +Additional method that can be generated are: +$(join(map(s -> '`' * string(s) * '`', _EXTRA_INCLUDE), ", ")). + +### See also +[`wrapped_graph`](@ref), [`wrapped_graph_type`](@ref) +""" +macro wrap_graph!(GT, args...) + + functions_to_generate = _DEFAULT_INCLUDE + + # TODO maybe we can somehow assert that GT is something like a type + # for now we just use an `typeintersect`. If GT is not an `AbstractValGraph` + # this will simply result in a `Union{}` type + GT = :(typeintersect(SimpleValueGraphs.AbstractValGraph, $GT)) + + for arg in args + if !(arg isa Expr) || + arg.head != :(=) || + length(arg.args) != 2 || + arg.args[1] ∉ (:include, :exclude) || + !(arg.args[2] isa Expr) || + arg.args[2].head != :vect + + error("Argument must be of the form `include=[function names...]` or exclude=[function names...]`") + end + # TODO we could also fail if there are unknown functions specified in one of the lists + if arg.args[1] == :include + include_list = intersect(arg.args[2].args, _EXTRA_INCLUDE) + union!(functions_to_generate, include_list) + else + exclude_list = arg.args[2].args + setdiff!(functions_to_generate, exclude_list) + end + + end + + return Expr(:block, map(f -> _generate_wrapped_function!(Val(f), esc(GT)), functions_to_generate)...) +end + +function _generate_wrapped_function!(::Val{:nv}, GT) + + return :(SimpleValueGraphs.nv(g::$GT) = nv(wrapped_graph(g))) +end + +function _generate_wrapped_function!(::Val{:is_directed}, GT) + + return :(SimpleValueGraphs.is_directed(G::Type{<:$GT}) = is_directed(wrapped_graph_type(G))) +end + +function _generate_wrapped_function!(::Val{:zero}, GT) + + return :(SimpleValueGraphs.zero(G::Type{<:$GT}) = zero(wrapped_graph_type(G))) +end + +function _generate_wrapped_function!(::Val{:has_edge}, GT) + + return :(SimpleValueGraphs.has_edge(g::$GT, s::Integer, d::Integer) = has_edge(wrapped_graph(g), s, d)) +end + +function _generate_wrapped_function!(::Val{:add_vertex!}, GT) + + return :(SimpleValueGraphs.add_vertex!(g::$GT, vals) = add_vertex!(wrapped_graph(g), vals)) +end + +function _generate_wrapped_function!(::Val{:rem_vertex!}, GT) + + return :(SimpleValueGraphs.rem_vertex!(g::$GT, v::Integer) = rem_vertex!(wrapped_graph(g), v)) +end + +function _generate_wrapped_function!(::Val{:add_edge!}, GT) + + return :(SimpleValueGraphs.add_edge!(g::$GT, s::Integer, d::Integer, vals) = add_edge!(wrapped_graph(g), s, d, vals)) +end + +function _generate_wrapped_function!(::Val{:rem_edge!}, GT) + + return :(SimpleValueGraphs.rem_edge!(g::$GT, s::Integer, d::Integer) = rem_edge!(wrapped_graph(g), s, d)) +end + +function _generate_wrapped_function!(::Val{:get_vertexval}, GT) + + return quote + SimpleValueGraphs.get_vertexval(g::$GT, v::Integer, key::Integer) = get_vertexval(wrapped_graph(g), v, key) + SimpleValueGraphs.get_vertexval(g::$GT, v::Integer, key::Symbol) = get_vertexval(wrapped_graph(g), v, key) + SimpleValueGraphs.get_vertexval(g::$GT, v::Integer, ::Colon) = get_vertexval(wrapped_graph(g), v, :) + end +end + +function _generate_wrapped_function!(::Val{:set_vertexval!}, GT) + + return quote + SimpleValueGraphs.set_vertexval!(g::$GT, v::Integer, key::Integer, value) = set_vertexval!(wrapped_graph(g), v, key, value) + SimpleValueGraphs.set_vertexval!(g::$GT, v::Integer, key::Symbol, value) = set_vertexval!(wrapped_graph(g), v, key, value) + SimpleValueGraphs.set_vertexval!(g::$GT, v::Integer, ::Colon, values) = set_vertexval!(wrapped_graph(g), v, :, values) + end +end + +function _generate_wrapped_function!(::Val{:get_edgeval}, GT) + + return quote + SimpleValueGraphs.get_edgeval(g::$GT, s::Integer, d::Integer, key::Integer) = get_edgeval(wrapped_graph(g), s, d, key) + SimpleValueGraphs.get_edgeval(g::$GT, s::Integer, d::Integer, key::Symbol) = get_edgeval(wrapped_graph(g), s, d, key) + SimpleValueGraphs.get_edgeval(g::$GT, s::Integer, d::Integer, ::Colon) = get_edgeval(wrapped_graph(g), s, d, :) + end +end + +function _generate_wrapped_function!(::Val{:set_edgeval!}, GT) + + return quote + SimpleValueGraphs.set_edgeval!(g::$GT, s::Integer, d::Integer, key::Integer, value) = set_edgeval!(wrapped_graph(g), s, d, key, value) + SimpleValueGraphs.set_edgeval!(g::$GT, s::Integer, d::Integer, key::Symbol, value) = set_edgeval!(wrapped_graph(g), s, d, key, value) + SimpleValueGraphs.set_edgeval!(g::$GT, s::Integer, d::Integer, ::Colon, values) = set_edgeval!(wrapped_graph(g), s, d, :, values) + end +end + +function _generate_wrapped_function!(::Val{:get_graphval}, GT) + + return quote + SimpleValueGraphs.get_graphval(g::$GT, key::Integer) = get_graphval(wrapped_graph(g), key) + SimpleValueGraphs.get_graphval(g::$GT, key::Symbol) = get_graphval(wrapped_graph(g), key) + SimpleValueGraphs.get_graphval(g::$GT, ::Colon) = get_graphval(wrapped_graph(g), :) + end +end + +function _generate_wrapped_function!(::Val{:set_graphval!}, GT) + + return quote + SimpleValueGraphs.set_graphval!(g::$GT, key::Integer, value) = set_graphval!(wrapped_graph(g), key, value) + SimpleValueGraphs.set_graphval!(g::$GT, key::Symbol, value) = set_graphval!(wrapped_graph(g), key, value) + SimpleValueGraphs.set_graphval!(g::$GT, ::Colon, values) = set_graphval!(wrapped_graph(g), :, values) + end +end + + + +function _generate_wrapped_function!(::Val{:ne}, GT) + + return :(SimpleValueGraphs.ne(g::$GT) = ne(wrapped_graph(g))) +end From 0d1915fe40040f8e406df4ae664cb5e9cd9082d1 Mon Sep 17 00:00:00 2001 From: Simon Schoelly Date: Sat, 17 Apr 2021 13:31:19 +0200 Subject: [PATCH 04/11] Add more functions for graph wrapers --- src/graphwrappers.jl | 41 +++++++++++++++++++++++++++++++++++++++-- src/operators.jl | 3 ++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/graphwrappers.jl b/src/graphwrappers.jl index b3d9b67..baa8d08 100644 --- a/src/graphwrappers.jl +++ b/src/graphwrappers.jl @@ -42,6 +42,11 @@ _DEFAULT_INCLUDE = [ _EXTRA_INCLUDE = [ :ne, + :outneighbors, + :inneighbors, + :outedgevals, + :inedgevals, + :edges ] """ @@ -187,9 +192,41 @@ function _generate_wrapped_function!(::Val{:set_graphval!}, GT) end end - - function _generate_wrapped_function!(::Val{:ne}, GT) return :(SimpleValueGraphs.ne(g::$GT) = ne(wrapped_graph(g))) end + +function _generate_wrapped_function!(::Val{:outneighbors}, GT) + + return :(SimpleValueGraphs.outneighbors(g::$GT, u) = outneighbors(wrapped_graph(g), u)) +end + +function _generate_wrapped_function!(::Val{:inneighbors}, GT) + + return :(SimpleValueGraphs.inneighbors(g::$GT, v) = inneighbors(wrapped_graph(g), v)) +end + +function _generate_wrapped_function!(::Val{:outedgevals}, GT) + + return quote + SimpleValueGraphs.outedgevals(g::$GT, u, key::Integer) = outedgevals(wrapped_graph(g), u, key) + SimpleValueGraphs.outedgevals(g::$GT, u, key::Symbol) = outedgevals(wrapped_graph(g), u, key) + SimpleValueGraphs.outedgevals(g::$GT, u, ::Colon) = outedgevals(wrapped_graph(g), u, :) + end +end + +function _generate_wrapped_function!(::Val{:inedgevals}, GT) + + return quote + SimpleValueGraphs.inedgevals(g::$GT, v, key::Integer) = inedgevals(wrapped_graph(g), v, key) + SimpleValueGraphs.inedgevals(g::$GT, v, key::Symbol) = inedgevals(wrapped_graph(g), v, key) + SimpleValueGraphs.inedgevals(g::$GT, v, ::Colon) = inedgevals(wrapped_graph(g), v, :) + end +end + +function _generate_wrapped_function!(::Val{:edges}, GT) + + return :(SimpleValueGraphs.edges(g::$GT, key=nothing) = edges(wrapped_graph(g), key)) +end + diff --git a/src/operators.jl b/src/operators.jl index 63c0587..0159cf5 100644 --- a/src/operators.jl +++ b/src/operators.jl @@ -43,7 +43,6 @@ struct Reverse{V <: Integer, V_VALS, E_VALS, G_VALS, G<:AbstractValGraph{V, V_VA graph::G end - """ reverse(g::AbstractValGraph) @@ -74,3 +73,5 @@ set_edgeval!(rg::Reverse, s::Integer, d::Integer, key::Integer, value) = set_edg set_edgeval!(rg::Reverse, s::Integer, d::Integer, key::Symbol, value) = set_edgeval!(rg.graph, d, s, key, value) set_edgeval!(rg::Reverse, s::Integer, d::Integer, ::Colon, values) = set_edgeval!(rg.graph, d, s, :, values) +outneighbors(rg::Reverse, u) = inneighbors(wrapped_graph(g), u) +inneighbors(rg::Reverse, v) = outneighbors(wrapped_graph(g), v) From 92623a0178e4173002ece789842b69e95151d69d Mon Sep 17 00:00:00 2001 From: Simon Schoelly Date: Sat, 17 Apr 2021 13:57:18 +0200 Subject: [PATCH 05/11] Add more documentation for @wrap_graph! --- src/graphwrappers.jl | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/graphwrappers.jl b/src/graphwrappers.jl index baa8d08..370a190 100644 --- a/src/graphwrappers.jl +++ b/src/graphwrappers.jl @@ -56,12 +56,23 @@ Generate default method implementations for graph wrappers. These default implementations simply call the wrapped graph. For that, one needs to implement `wrapped_graph` and `wrapped_graph_type` for the custom graph wrapper. -Methods given as a `Vector` to the keyword argument `excluded` are not created. +Methods given as a `Vector` to the keyword argument `exclude` are not created. By default, methods for the following functions are generated: $(join(map(s -> '`' * string(s) * '`', _DEFAULT_INCLUDE), ", ")). -Additional method that can be generated are: + +There are additional methods that can be generated but are not generated by default, as +these methods all have a default implementation in terms of other functions. To generate +these additional methods, specify them in a `Vector` to the keyword argument `include`. +The following methods can be additionally generated: $(join(map(s -> '`' * string(s) * '`', _EXTRA_INCLUDE), ", ")). +# Examples +```julia +# generate methods for ne, that are not generated by default and +# do not generate methods for get_graphval and set_graphval! that would +# be generated by default +@wrap_graph! MyGraphWrapper include=[ne] exclude=[get_graphval, set_graphval!] +``` ### See also [`wrapped_graph`](@ref), [`wrapped_graph_type`](@ref) """ From bb3619d974b4d7d3586598300ea723c83d8d1e90 Mon Sep 17 00:00:00 2001 From: Simon Schoelly Date: Sat, 17 Apr 2021 14:08:06 +0200 Subject: [PATCH 06/11] Remove zero from generated methods --- src/graphwrappers.jl | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/graphwrappers.jl b/src/graphwrappers.jl index 370a190..bcc49b3 100644 --- a/src/graphwrappers.jl +++ b/src/graphwrappers.jl @@ -26,7 +26,6 @@ function wrapped_graph_type(::Type) end _DEFAULT_INCLUDE = [ :nv, :is_directed, - :zero, :has_edge, :get_graphval, :get_vertexval, @@ -66,6 +65,11 @@ these additional methods, specify them in a `Vector` to the keyword argument `in The following methods can be additionally generated: $(join(map(s -> '`' * string(s) * '`', _EXTRA_INCLUDE), ", ")). +Note: To completely implement the `SimpleValueGraphs` interface for some graph one +would also have to implement `zero`. This macro currently cannot do that, as this +would knowledge of how to construct a new graph wrapper. Therefore one has to implement this +method separately. + # Examples ```julia # generate methods for ne, that are not generated by default and @@ -119,11 +123,6 @@ function _generate_wrapped_function!(::Val{:is_directed}, GT) return :(SimpleValueGraphs.is_directed(G::Type{<:$GT}) = is_directed(wrapped_graph_type(G))) end -function _generate_wrapped_function!(::Val{:zero}, GT) - - return :(SimpleValueGraphs.zero(G::Type{<:$GT}) = zero(wrapped_graph_type(G))) -end - function _generate_wrapped_function!(::Val{:has_edge}, GT) return :(SimpleValueGraphs.has_edge(g::$GT, s::Integer, d::Integer) = has_edge(wrapped_graph(g), s, d)) From 3146e7b187d1b7d5c130dec773391be221be86c5 Mon Sep 17 00:00:00 2001 From: Simon Schoelly Date: Sat, 17 Apr 2021 14:53:08 +0200 Subject: [PATCH 07/11] Add additional operators for Reverse --- src/operators.jl | 16 ++++++++++++++-- test/operators.jl | 21 +++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/operators.jl b/src/operators.jl index 0159cf5..27a5f3f 100644 --- a/src/operators.jl +++ b/src/operators.jl @@ -61,6 +61,8 @@ wrapped_graph(g::Reverse) = g.graph wrapped_graph_type(::Type{<:Reverse{V, V_VALS, E_VALS, G_VALS, G}}) where {V, V_VALS, E_VALS, G_VALS, G} = G @wrap_graph! Reverse include=[ne] exclude=[has_edge, add_edge!, rem_edge!, get_edgeval, set_edgeval!] +Base.zero(RG::Type{<:Reverse}) = Reverse(zero(wrapped_graph_type(RG))) + has_edge(rg::Reverse, s::Integer, d::Integer) = has_edge(rg.graph, d, s) add_edge!(rg::Reverse, s::Integer, d::Integer, values) = add_edge!(rg.graph, d, s, values) rem_edge!(rg::Reverse, s::Integer, d::Integer) = rem_edge!(rg.graph, d, s) @@ -73,5 +75,15 @@ set_edgeval!(rg::Reverse, s::Integer, d::Integer, key::Integer, value) = set_edg set_edgeval!(rg::Reverse, s::Integer, d::Integer, key::Symbol, value) = set_edgeval!(rg.graph, d, s, key, value) set_edgeval!(rg::Reverse, s::Integer, d::Integer, ::Colon, values) = set_edgeval!(rg.graph, d, s, :, values) -outneighbors(rg::Reverse, u) = inneighbors(wrapped_graph(g), u) -inneighbors(rg::Reverse, v) = outneighbors(wrapped_graph(g), v) +outneighbors(rg::Reverse, u) = inneighbors(wrapped_graph(rg), u) +inneighbors(rg::Reverse, v) = outneighbors(wrapped_graph(rg), v) + +outedgevals(rg::Reverse, u, key::Integer) = inedgevals(wrapped_graph(rg), u, key) +outedgevals(rg::Reverse, u, key::Symbol) = inedgevals(wrapped_graph(rg), u, key) +outedgevals(rg::Reverse, u, ::Colon) = inedgevals(wrapped_graph(rg), u, :) + +inedgevals(rg::Reverse, v, key::Integer) = outedgevals(wrapped_graph(rg), v, key) +inedgevals(rg::Reverse, v, key::Symbol) = outedgevals(wrapped_graph(rg), v, key) +inedgevals(rg::Reverse, v, ::Colon) = outedgevals(wrapped_graph(rg), v, :) + +# TODO implementing edges efficiently and with correct edge type diff --git a/test/operators.jl b/test/operators.jl index 886cae9..1946934 100644 --- a/test/operators.jl +++ b/test/operators.jl @@ -71,6 +71,27 @@ end set_graphval!(rg, :, (300,)) @test get_graphval(rg, :) == get_graphval(g2, :) == (c=300,) + @test outneighbors(rg, 1) == inneighbors(g2, 1) + @test outneighbors(rg, 2) == inneighbors(g2, 2) + @test outneighbors(rg, 3) == inneighbors(g2, 3) + @test outneighbors(rg, 4) == inneighbors(g2, 4) + + @test inneighbors(rg, 1) == outneighbors(g2, 1) + @test inneighbors(rg, 2) == outneighbors(g2, 2) + @test inneighbors(rg, 3) == outneighbors(g2, 3) + @test inneighbors(rg, 4) == outneighbors(g2, 4) + + @test outedgevals(rg, 1, 1) == inedgevals(g2, 1, 1) + @test outedgevals(rg, 2, :b) == inedgevals(g2, 2, :b) + @test outedgevals(rg, 3, :) == inedgevals(g2, 3, :) + + @test inedgevals(rg, 2, 1) == outedgevals(g2, 2, 1) + @test inedgevals(rg, 3, :b) == outedgevals(g2, 3, :b) + @test inedgevals(rg, 4, :) == outedgevals(g2, 4, :) + + # TODO Tests currently disabled as we do not have zero implemented on ValDiGraph + # @test zero(typeof(rg)) isa typeof(rg) + # @test nv(zero(typeof(rg))) == 0 end From 099c6dbddeaf25e216fc692fac498f5837a58243 Mon Sep 17 00:00:00 2001 From: Simon Schoelly Date: Sat, 17 Apr 2021 18:55:33 +0200 Subject: [PATCH 08/11] Add tests for Reverse --- test/operators.jl | 7 +++++++ test/testutils.jl | 2 ++ 2 files changed, 9 insertions(+) diff --git a/test/operators.jl b/test/operators.jl index 1946934..0e0e9d4 100644 --- a/test/operators.jl +++ b/test/operators.jl @@ -63,6 +63,13 @@ end @test !has_edge(g2, 1, 6) @test ne(rg) == ne(g2) == 5 + @test rem_edge!(rg, 1, 6) == true + @test !has_edge(rg, 1, 6) + @test !has_edge(g2, 6, 1) + @test ne(rg) == ne(g2) == 4 + @test rem_edge!(rg, 1, 6) == false + @test ne(rg) == ne(g2) == 4 + @test get_graphval(rg) == get_graphval(g2) == 100 set_graphval!(rg, 1, 200) @test get_graphval(rg, 1) == get_graphval(g2, 1) == 200 diff --git a/test/testutils.jl b/test/testutils.jl index e5a4d6c..c818212 100644 --- a/test/testutils.jl +++ b/test/testutils.jl @@ -445,3 +445,5 @@ SimpleValueGraphs.add_vertex!(g::DummyValGraph, values) = add_vertex!(g.wrapped, SimpleValueGraphs.add_edge!(g::DummyValGraph, s, d, values) = add_edge!(g.wrapped, s, d, values) +SimpleValueGraphs.rem_edge!(g::DummyValGraph, s, d) = rem_edge!(g.wrapped, s, d) + From bd2770b3f5f6fce3ebad792cc36386b1980eb154 Mon Sep 17 00:00:00 2001 From: Simon Schoelly Date: Sat, 17 Apr 2021 20:08:25 +0200 Subject: [PATCH 09/11] Add tests for graph wrappers --- src/graphwrappers.jl | 2 +- test/graphwrappers.jl | 70 +++++++++++++++++++++++++++++++++++++++++++ test/runtests.jl | 1 + 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 test/graphwrappers.jl diff --git a/src/graphwrappers.jl b/src/graphwrappers.jl index bcc49b3..4cc209a 100644 --- a/src/graphwrappers.jl +++ b/src/graphwrappers.jl @@ -82,7 +82,7 @@ method separately. """ macro wrap_graph!(GT, args...) - functions_to_generate = _DEFAULT_INCLUDE + functions_to_generate = copy(_DEFAULT_INCLUDE) # TODO maybe we can somehow assert that GT is something like a type # for now we just use an `typeintersect`. If GT is not an `AbstractValGraph` diff --git a/test/graphwrappers.jl b/test/graphwrappers.jl new file mode 100644 index 0000000..362c844 --- /dev/null +++ b/test/graphwrappers.jl @@ -0,0 +1,70 @@ + + +struct TestGraphWrapper{V <: Integer, V_VALS, E_VALS, G_VALS, GI <: AbstractValGraph{V, V_VALS, E_VALS, G_VALS}} <: AbstractValGraph{V, V_VALS, E_VALS, G_VALS} + + inner::GI +end + +SimpleValueGraphs.wrapped_graph(gw::TestGraphWrapper) = gw.inner + +SimpleValueGraphs.wrapped_graph_type(::Type{<:TestGraphWrapper{V, V_VALS, E_VALS, G_VALS, GI}}) where {V, V_VALS, E_VALS, G_VALS, GI} = GI + +SimpleValueGraphs.@wrap_graph! TestGraphWrapper include=[ne, outneighbors, inneighbors, outedgevals, inedgevals, edges] + +@testset "graph wrapper" begin + +gi = ValDiGraph{Int8}( + 4, + vertexval_types=(a=Int, b=String), + vertexval_init=v -> (a=v, b="$v"), + edgeval_types=(c=String, d=Float64), + graphvals=(e='x', f="y") +) +add_edge!(gi, 1, 2, ("1-2", 1.2)) +add_edge!(gi, 2, 1, ("2-1", 2.1)) +add_edge!(gi, 1, 4, ("1-4", 1.4)) +add_edge!(gi, 4, 4, ("4-4", 4.4)) + +gw = TestGraphWrapper(gi) + +@test nv(gw) == nv(gi) + +@test is_directed(typeof(gw)) == is_directed(typeof(gi)) + +@test has_edge(gw, 1, 2) == has_edge(gi, 1, 2) +@test has_edge(gw, 1, 3) == has_edge(gi, 1, 3) + +@test get_graphval(gw, 1) == get_graphval(gi, 1) +@test get_graphval(gw, :f) == get_graphval(gi, :f) +@test get_graphval(gw, :) == get_graphval(gi, :) + +@test get_vertexval(gw, 1, 1) == get_vertexval(gi, 1, 1) +@test get_vertexval(gw, 2, :a) == get_vertexval(gi, 2, :a) +@test get_vertexval(gw, 3, :) == get_vertexval(gi, 3, :) + +@test get_edgeval(gw, 1, 2, 1) == get_edgeval(gi, 1, 2, 1) +@test get_edgeval(gw, 2, 1, :d) == get_edgeval(gi, 2, 1, :d) +@test get_edgeval(gw, 4, 4, :) == get_edgeval(gi, 4, 4, :) + +# TODO tests for modifiers + +@test ne(gw) == ne(gi) + +@test outneighbors(gw, 1) == outneighbors(gi, 1) +@test outneighbors(gw, 3) == outneighbors(gi, 3) + +@test inneighbors(gw, 1) == inneighbors(gi, 1) +@test inneighbors(gw, 3) == inneighbors(gi, 3) + +@test outedgevals(gw, 1, 2) == outedgevals(gi, 1, 2) +@test outedgevals(gw, 2, :c) == outedgevals(gi, 2, :c) +@test outedgevals(gw, 4, :) == outedgevals(gi, 4, :) + +@test inedgevals(gw, 1, 2) == inedgevals(gi, 1, 2) +@test inedgevals(gw, 2, :c) == inedgevals(gi, 2, :c) +@test inedgevals(gw, 4, :) == inedgevals(gi, 4, :) + +@test edges(gw) == edges(gi) +@test edges(gw, :) == edges(gi, :) + +end # testset diff --git a/test/runtests.jl b/test/runtests.jl index fd4bc70..068b2cd 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -15,6 +15,7 @@ end register_test("AbstractTuples.jl") register_test("abstractvaluegraph.jl") +register_test("graphwrappers.jl") register_test("integrations/SimpleGraphs.jl") register_test("interface/constructors.jl") register_test("interface/edges.jl") From 328181d426ab6b10b835f2aabffe0f348855488d Mon Sep 17 00:00:00 2001 From: Simon Schoelly Date: Sat, 17 Apr 2021 21:25:41 +0200 Subject: [PATCH 10/11] Add a comment --- docs/make.jl | 4 +++- test/graphwrappers.jl | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/make.jl b/docs/make.jl index 6d1bc97..c2a0056 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -13,6 +13,7 @@ makedocs( "Accessing graphs" => "access.md", "Modifying graphs" => "modification.md", "Matrices" => "matrices.md", + "Comparison of graph types" => "comparison.md", ], "Custom Value Graph types" => "custom-valuegraph-types.md" # "AbstractValGraph interface" => "abstractgraph.md", @@ -23,7 +24,8 @@ makedocs( format = Documenter.HTML( prettyurls = get(ENV, "CI", nothing) == "true" ), - doctest = true + doctest = false + # doctest = true ) deploydocs(; diff --git a/test/graphwrappers.jl b/test/graphwrappers.jl index 362c844..339a3b8 100644 --- a/test/graphwrappers.jl +++ b/test/graphwrappers.jl @@ -1,5 +1,7 @@ +# test graph wrapper for testing @wrap_graph!, +# should forward everything to the wrapped graph struct TestGraphWrapper{V <: Integer, V_VALS, E_VALS, G_VALS, GI <: AbstractValGraph{V, V_VALS, E_VALS, G_VALS}} <: AbstractValGraph{V, V_VALS, E_VALS, G_VALS} inner::GI From d7dcb34b99ca47de073a217be32023241f0b6e3c Mon Sep 17 00:00:00 2001 From: Simon Schoelly Date: Sat, 17 Apr 2021 21:34:48 +0200 Subject: [PATCH 11/11] Undo accidental changes --- docs/make.jl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index c2a0056..6d1bc97 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -13,7 +13,6 @@ makedocs( "Accessing graphs" => "access.md", "Modifying graphs" => "modification.md", "Matrices" => "matrices.md", - "Comparison of graph types" => "comparison.md", ], "Custom Value Graph types" => "custom-valuegraph-types.md" # "AbstractValGraph interface" => "abstractgraph.md", @@ -24,8 +23,7 @@ makedocs( format = Documenter.HTML( prettyurls = get(ENV, "CI", nothing) == "true" ), - doctest = false - # doctest = true + doctest = true ) deploydocs(;