From 9e9a873de6c38b2862fa1f049349b07b5f410874 Mon Sep 17 00:00:00 2001 From: Seth Bromberger Date: Wed, 11 Mar 2020 10:27:31 -0700 Subject: [PATCH 1/7] fixes structural zeros issues --- src/SimpleWeightedGraphs.jl | 4 ++-- src/simpleweighteddigraph.jl | 6 +++--- src/simpleweightedgraph.jl | 6 +++--- test/simpleweightedgraph.jl | 12 ++++++------ 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/SimpleWeightedGraphs.jl b/src/SimpleWeightedGraphs.jl index c1c6315..3d9471f 100644 --- a/src/SimpleWeightedGraphs.jl +++ b/src/SimpleWeightedGraphs.jl @@ -5,6 +5,7 @@ using LinearAlgebra using Markdown using SparseArrays +using Base.Iterators import Base: convert, eltype, show, ==, Pair, Tuple, copy, length, issubset, zero @@ -59,7 +60,6 @@ convert(::Type{SparseMatrixCSC{T, U}}, g::AbstractSimpleWeightedGraph) where T<: - ### INTERFACE nv(g::AbstractSimpleWeightedGraph{T, U}) where T where U = T(size(g.weights, 1)) @@ -116,7 +116,7 @@ end function outneighbors(g::AbstractSimpleWeightedGraph, v::Integer) mat = g.weights - return view(mat.rowval, mat.colptr[v]:mat.colptr[v+1]-1) + return Iterators.filter(!iszero, view(mat.rowval, mat.colptr[v]:mat.colptr[v+1]-1)) end get_weight(g::AbstractSimpleWeightedGraph, u::Integer, v::Integer) = g.weights[v, u] diff --git a/src/simpleweighteddigraph.jl b/src/simpleweighteddigraph.jl index 9e59657..7e3004b 100644 --- a/src/simpleweighteddigraph.jl +++ b/src/simpleweighteddigraph.jl @@ -34,7 +34,7 @@ SimpleWeightedDiGraph{T,U}(g::SimpleWeightedDiGraph) where T<:Integer where U<:R SimpleWeightedDiGraph(SparseMatrixCSC{U, T}(g.weights); permute=false) -ne(g::SimpleWeightedDiGraph) = nnz(g.weights) +ne(g::SimpleWeightedDiGraph) = length(filter(!iszero, nonzeros(g.weights))) function SimpleWeightedDiGraph{T,U}(n::Integer = 0) where T<:Integer where U<:Real weights = spzeros(U, T, T(n), T(n)) @@ -75,10 +75,10 @@ LightGraphs.SimpleDiGraph(g::SimpleWeightedDiGraph) = SimpleDiGraph(g.weights) edgetype(::SimpleWeightedDiGraph{T, U}) where T<:Integer where U<:Real = SimpleWeightedGraphEdge{T,U} -edges(g::SimpleWeightedDiGraph) = (SimpleWeightedEdge(x[2], x[1], x[3]) for x in zip(findnz(g.weights)...)) +edges(g::SimpleWeightedDiGraph) = Iterators.filter(!iszero ∘ weight, SimpleWeightedEdge(x[2], x[1], x[3]) for x in zip(findnz(g.weights)...)) weights(g::SimpleWeightedDiGraph) = g.weights' -inneighbors(g::SimpleWeightedDiGraph, v::Integer) = g.weights[v,:].nzind +inneighbors(g::SimpleWeightedDiGraph, v::Integer) = Iterators.filter(!iszero, g.weights[v,:].nzind) # add_edge! will overwrite weights. function add_edge!(g::SimpleWeightedDiGraph, e::SimpleWeightedGraphEdge) diff --git a/src/simpleweightedgraph.jl b/src/simpleweightedgraph.jl index 1201095..10e3f2a 100644 --- a/src/simpleweightedgraph.jl +++ b/src/simpleweightedgraph.jl @@ -19,7 +19,7 @@ mutable struct SimpleWeightedGraph{T<:Integer, U<:Real} <: AbstractSimpleWeighte end -ne(g::SimpleWeightedGraph) = nnz(g.weights) ÷ 2 +ne(g::SimpleWeightedGraph) = length(filter(!iszero, nonzeros(g.weights))) ÷ 2 SimpleWeightedGraph{T}(adjmx::SparseMatrixCSC{U, T}) where T<:Integer where U<:Real = SimpleWeightedGraph{T, U}(adjmx) @@ -91,8 +91,8 @@ LightGraphs.SimpleGraph(g::SimpleWeightedGraph) = SimpleGraph(g.weights) edgetype(::SimpleWeightedGraph{T, U}) where T<:Integer where U<:Real= SimpleWeightedGraphEdge{T,U} -edges(g::SimpleWeightedGraph) = (SimpleWeightedEdge(x[1], x[2], x[3]) for x in zip(findnz(triu(g.weights))...)) -weights(g::SimpleWeightedGraph) = g.weights +edges(g::SimpleWeightedGraph) = Iterators.filter(!iszero ∘ weight, SimpleWeightedEdge(x[1], x[2], x[3]) for x in zip(findnz(triu(g.weights))...)) +weights(g::AbstractSimpleWeightedGraph) = g.weights inneighbors(g::SimpleWeightedGraph, x...) = outneighbors(g, x...) # add_edge! will overwrite weights. diff --git a/test/simpleweightedgraph.jl b/test/simpleweightedgraph.jl index 519ef6f..9b18bc9 100644 --- a/test/simpleweightedgraph.jl +++ b/test/simpleweightedgraph.jl @@ -64,7 +64,7 @@ using SimpleWeightedGraphs gc = copy(g) @test add_edge!(gc, 4, 1) && gc == SimpleWeightedGraph(cycle_graph(4)) - @test @inferred(inneighbors(g, 2)) == @inferred(outneighbors(g, 2)) == @inferred(neighbors(g,2)) == [1,3] + @test @inferred(collect(inneighbors(g, 2))) == @inferred(collect(outneighbors(g, 2))) == @inferred(collect(neighbors(g,2))) == [1,3] @test @inferred(add_vertex!(gc)) # out of order, but we want it for issubset @test @inferred(g ⊆ gc) @test @inferred(has_vertex(gc, 5)) @@ -115,8 +115,8 @@ using SimpleWeightedGraphs @test SimpleWeightedEdge(2,3) in edges(g) @test !(SimpleWeightedEdge(3,2) in edges(g)) @test @inferred(nv(g)) == 4 - @test outneighbors(g, 2) == [3] - @test inneighbors(g, 2) == [1] + @test collect(outneighbors(g, 2)) == [3] + @test collect(inneighbors(g, 2)) == [1] @test @inferred(has_edge(g, 2, 3)) @test @inferred(!has_edge(g, 3, 2)) @@ -130,8 +130,8 @@ using SimpleWeightedGraphs gc = @inferred(copy(g)) @test @inferred(add_edge!(gc, 4, 1)) && gc == SimpleWeightedDiGraph(cycle_digraph(4)) - @test @inferred(inneighbors(g, 2)) == [1] - @test @inferred(outneighbors(g, 2)) == @inferred(neighbors(g,2)) == [3] + @test @inferred(collect(inneighbors(g, 2))) == [1] + @test @inferred(collect(outneighbors(g, 2))) == @inferred(collect(neighbors(g,2))) == [3] @test @inferred(add_vertex!(gc)) # out of order, but we want it for issubset @test @inferred(g ⊆ gc) @test @inferred(has_vertex(gc, 5)) @@ -182,7 +182,7 @@ using SimpleWeightedGraphs @test @inferred(get_weight(g, 1, 2)) == 3 g = SimpleWeightedDiGraph(path_graph(5), 4.0) - @test sum(weights(g)) == ne(g) * 4.0 + @test sum(collect(weights(g)))== ne(g) * 4.0 gx = Graph(4,3) for g in testsimplegraphs(gx) From f2d59ee737e7ffa3980cea3ee3d353d8cda67d9c Mon Sep 17 00:00:00 2001 From: Seth Bromberger Date: Wed, 11 Mar 2020 10:46:38 -0700 Subject: [PATCH 2/7] tests --- test/simpleweightedgraph.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/simpleweightedgraph.jl b/test/simpleweightedgraph.jl index 9b18bc9..f95710a 100644 --- a/test/simpleweightedgraph.jl +++ b/test/simpleweightedgraph.jl @@ -222,4 +222,12 @@ using SimpleWeightedGraphs @test SimpleDiGraph(SimpleWeightedDiGraph(cycle_graph(4))) == SimpleDiGraph(cycle_graph(4)) @test SimpleGraph(SimpleWeightedGraph(path_graph(5))) == path_graph(5) + # test structural zeros. + g = SimpleWeightedDiGraph(path_digraph(5)) + add_edge!(g, 2, 3, 5) + @test has_edge(g, 2, 3) + rem_edge!(g, 2, 3) + @test !has_edge(g, 2, 3) + @test SimpleWeightedEdge(2, 3) ∉ edges(g) + @test weights(g)[2, 3] == 0 end From 279c44236bdb62001dae228237afe34f9b55df50 Mon Sep 17 00:00:00 2001 From: Seth Bromberger Date: Wed, 11 Mar 2020 20:28:43 -0700 Subject: [PATCH 3/7] bump to 2.0.0 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 2523d92..1a54be6 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "SimpleWeightedGraphs" uuid = "47aef6b3-ad0c-573a-a1e2-d07658019622" -version = "1.1.1" +version = "2.0.0" [deps] LightGraphs = "093fc24a-ae57-5d10-9952-331d41423f4d" From 3b28c484ef378b02f2b90e370556eb7b0ff31dbe Mon Sep 17 00:00:00 2001 From: Seth Bromberger Date: Thu, 12 Mar 2020 08:09:30 -0700 Subject: [PATCH 4/7] Update src/simpleweighteddigraph.jl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Mathieu Besançon --- src/simpleweighteddigraph.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simpleweighteddigraph.jl b/src/simpleweighteddigraph.jl index 0c11068..b2110bf 100644 --- a/src/simpleweighteddigraph.jl +++ b/src/simpleweighteddigraph.jl @@ -38,7 +38,7 @@ SimpleWeightedDiGraph{T,U}(g::SimpleWeightedDiGraph) where {T <: Integer, U <: R SimpleWeightedDiGraph(SparseMatrixCSC{U, T}(copy(g.weights)), permute=false) -ne(g::SimpleWeightedDiGraph) = length(filter(!iszero, nonzeros(g.weights))) +ne(g::SimpleWeightedDiGraph) = count(!iszero, nonzeros(g.weights)) function SimpleWeightedDiGraph{T,U}(n::Integer = 0) where {T<:Integer, U<:Real} weights = spzeros(U, T, T(n), T(n)) From 12af66e279b1a4c04f9a9bf14f5639f86b197c63 Mon Sep 17 00:00:00 2001 From: Seth Bromberger Date: Thu, 12 Mar 2020 08:14:21 -0700 Subject: [PATCH 5/7] Update src/simpleweightedgraph.jl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Mathieu Besançon --- src/simpleweightedgraph.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simpleweightedgraph.jl b/src/simpleweightedgraph.jl index 0c8fd35..29b2e88 100644 --- a/src/simpleweightedgraph.jl +++ b/src/simpleweightedgraph.jl @@ -18,7 +18,7 @@ mutable struct SimpleWeightedGraph{T<:Integer, U<:Real} <: AbstractSimpleWeighte end -ne(g::SimpleWeightedGraph) = length(filter(!iszero, nonzeros(g.weights))) ÷ 2 +ne(g::SimpleWeightedGraph) = count(!iszero, nonzeros(g.weights))) ÷ 2 SimpleWeightedGraph{T}(adjmx::SparseMatrixCSC{U, T}) where {T <: Integer, U <: Real} = SimpleWeightedGraph{T, U}(adjmx) From c51e590044952475f481979433f89b6f01bbe4e6 Mon Sep 17 00:00:00 2001 From: Seth Bromberger Date: Thu, 12 Mar 2020 08:18:15 -0700 Subject: [PATCH 6/7] Update simpleweightedgraph.jl --- src/simpleweightedgraph.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simpleweightedgraph.jl b/src/simpleweightedgraph.jl index 29b2e88..38edd25 100644 --- a/src/simpleweightedgraph.jl +++ b/src/simpleweightedgraph.jl @@ -18,7 +18,7 @@ mutable struct SimpleWeightedGraph{T<:Integer, U<:Real} <: AbstractSimpleWeighte end -ne(g::SimpleWeightedGraph) = count(!iszero, nonzeros(g.weights))) ÷ 2 +ne(g::SimpleWeightedGraph) = count(!iszero, nonzeros(g.weights)) ÷ 2 SimpleWeightedGraph{T}(adjmx::SparseMatrixCSC{U, T}) where {T <: Integer, U <: Real} = SimpleWeightedGraph{T, U}(adjmx) From eee4b0da4a7689381736d2fb929200433a188129 Mon Sep 17 00:00:00 2001 From: Seth Bromberger Date: Thu, 12 Mar 2020 09:10:09 -0700 Subject: [PATCH 7/7] fix bugs resulting from iteration --- src/SimpleWeightedGraphs.jl | 2 ++ src/simpleweighteddigraph.jl | 3 ++- test/simpleweightedgraph.jl | 13 +++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/SimpleWeightedGraphs.jl b/src/SimpleWeightedGraphs.jl index c30c9b7..c4d3275 100644 --- a/src/SimpleWeightedGraphs.jl +++ b/src/SimpleWeightedGraphs.jl @@ -117,6 +117,8 @@ function outneighbors(g::AbstractSimpleWeightedGraph, v::Integer) return Iterators.filter(!iszero, view(mat.rowval, mat.colptr[v]:mat.colptr[v+1]-1)) end +outdegree(g::AbstractSimpleWeightedGraph, v::Integer) = length(outneighbors(g, v).itr) + get_weight(g::AbstractSimpleWeightedGraph, u::Integer, v::Integer) = g.weights[v, u] zero(g::T) where T<:AbstractSimpleWeightedGraph = T() diff --git a/src/simpleweighteddigraph.jl b/src/simpleweighteddigraph.jl index 0c11068..3ed05c5 100644 --- a/src/simpleweighteddigraph.jl +++ b/src/simpleweighteddigraph.jl @@ -78,7 +78,7 @@ function SimpleWeightedDiGraph(i::AbstractVector{T}, j::AbstractVector{T}, v::Ab SimpleWeightedDiGraph{T, U}(sparse(j, i, v, m, m, combine), permute=false) end -LightGraphs.SimpleDiGraph(g::SimpleWeightedDiGraph) = SimpleDiGraph(g.weights) +LightGraphs.SimpleDiGraph(g::SimpleWeightedDiGraph) = SimpleDiGraph(g.weights') edgetype(::SimpleWeightedDiGraph{T, U}) where T<:Integer where U<:Real = SimpleWeightedGraphEdge{T,U} @@ -86,6 +86,7 @@ edges(g::SimpleWeightedDiGraph) = Iterators.filter(!iszero ∘ weight, SimpleWei weights(g::SimpleWeightedDiGraph) = g.weights' inneighbors(g::SimpleWeightedDiGraph, v::Integer) = Iterators.filter(!iszero, g.weights[v,:].nzind) +indegree(g::SimpleWeightedDiGraph, v::Integer) = length(inneighbors(g, v).itr) # add_edge! will overwrite weights. function add_edge!(g::SimpleWeightedDiGraph, e::SimpleWeightedGraphEdge) diff --git a/test/simpleweightedgraph.jl b/test/simpleweightedgraph.jl index 986c3f3..5c33430 100644 --- a/test/simpleweightedgraph.jl +++ b/test/simpleweightedgraph.jl @@ -329,4 +329,17 @@ using SimpleWeightedGraphs @test g[1, 3, Val{:weight}()] ≈ 0 @test g[2, 3, Val{:weight}()] ≈ 0.5 end + + # test digraph construction + g = LightGraphs.path_digraph(4) + h = SimpleWeightedDiGraph(g) + @test collect(edges(g)) == collect(edges(h)) + + # test degrees + @test outdegree(h) == [1, 1, 1, 0] + for v in 1:nv(h) + @test outdegree(h, v) == outdegree(h)[v] + @test indegree(h, v) == indegree(h)[v] + @test degree(h, v) == outdegree(h, v) + indegree(h, v) + end end