Skip to content
This repository has been archived by the owner on Oct 8, 2021. It is now read-only.

Commit

Permalink
retooling of graph constructors
Browse files Browse the repository at this point in the history
  • Loading branch information
sbromberger committed Aug 18, 2018
1 parent f8ab368 commit d1f2627
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 63 deletions.
8 changes: 8 additions & 0 deletions src/SimpleWeightedGraphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,12 @@ include("persistence.jl")
const WGraph = SimpleWeightedGraph
const WDiGraph = SimpleWeightedDiGraph

SimpleWeightedDiGraph(g::SimpleWeightedGraph) = SimpleWeightedDiGraph(g.weights)
SimpleWeightedDiGraph{T,U}(g::SimpleWeightedGraph) where T<:Integer where U<:Real =
SimpleWeightedDiGraph(SparseMatrixCSC{U, T}(g.weights))

SimpleWeightedGraph(g::SimpleWeightedDiGraph) = SimpleWeightedGraph(g.weights .+ g.weights')
SimpleWeightedGraph{T,U}(g::SimpleWeightedDiGraph) where T<:Integer where U<:Real =
SimpleWeightedGraph(SparseMatrixCSC{U, T}(g.weights .+ g.weights'))

end # module
70 changes: 29 additions & 41 deletions src/simpleweighteddigraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,34 @@ A type representing a directed graph with weights of type `U`.
"""
mutable struct SimpleWeightedDiGraph{T<:Integer, U<:Real} <: AbstractSimpleWeightedGraph{T, U}
weights::SparseMatrixCSC{U, T} # indexed by [dst, src]
function SimpleWeightedDiGraph{T, U}(adjmx::SparseMatrixCSC{U,T}, permute=true) where T <: Integer where U <: Real
dima,dimb = size(adjmx)
isequal(dima,dimb) || error("Adjacency / distance matrices must be square")
permute ? new{T, U}(permutedims(adjmx)) : new{T, U}(adjmx)
end

SimpleWeightedDiGraph{T}(adjmx::SparseMatrixCSC{U, T}, permute=true) where T<:Integer where U<:Real =
permute ? new{T, U}(permutedims(adjmx)) : new{T, U}(adjmx)

SimpleWeightedDiGraph(adjmx::SparseMatrixCSC{U, T}, permute=true) where T<:Integer where U<:Real =
permute ? new{T, U}(permutedims(adjmx)) : new{T, U}(adjmx)
end

SimpleWeightedDiGraph(m::AbstractMatrix{U}) where U <: Real =
SimpleWeightedDiGraph{Int, U}(SparseMatrixCSC{U, Int}(m))
SimpleWeightedDiGraph{T}(m::AbstractMatrix{U}) where T<:Integer where U<:Real =
SimpleWeightedDiGraph{T, U}(SparseMatrixCSC{U, T}(m))
SimpleWeightedDiGraph{T, U}(m::AbstractMatrix) where T<:Integer where U<:Real =
SimpleWeightedDiGraph{T, U}(SparseMatrixCSC{U, T}(m))

SimpleWeightedDiGraph(g::SimpleWeightedDiGraph) = SimpleWeightedDiGraph(g.weights, false)
SimpleWeightedDiGraph{T,U}(g::SimpleWeightedDiGraph) where T<:Integer where U<:Real =
SimpleWeightedDiGraph(SparseMatrixCSC{U, T}(g.weights), false)


ne(g::SimpleWeightedDiGraph) = nnz(g.weights)

# Graph{UInt8}(6), Graph{Int16}(7), Graph{UInt8}()
function (::Type{SimpleWeightedDiGraph{T, U}})(n::Integer = 0) where T<:Integer where U<:Real
function SimpleWeightedDiGraph{T,U}(n::Integer = 0) where T<:Integer where U<:Real
weights = spzeros(U, T, T(n), T(n))
return SimpleWeightedDiGraph{T, U}(weights)
end
Expand All @@ -30,61 +52,27 @@ SimpleWeightedDiGraph(::Type{T}, ::Type{U}) where T<:Integer where U<:Real = Sim
# DiGraph(AbstractSimpleGraph)
function SimpleWeightedDiGraph(g::LightGraphs.SimpleGraphs.AbstractSimpleGraph, ::Type{U}=Float64) where U <: Real
T = eltype(g)
return SimpleWeightedDiGraph{T, U}(adjacency_matrix(g)')
return SimpleWeightedDiGraph{T}(adjacency_matrix(g, U))
end

# DiGraph(AbstractSimpleGraph, defaultweight)
function SimpleWeightedDiGraph(g::LightGraphs.SimpleGraphs.AbstractSimpleGraph, x::U) where U <: Real
T = eltype(g)
return SimpleWeightedDiGraph{T, U}(x.*adjacency_matrix(g, U)')
end

# SimpleWeightedGraph{T, U}(SimpleGraph)
function (::Type{SimpleWeightedDiGraph{T, U}})(g::LightGraphs.SimpleGraphs.SimpleDiGraph) where T<:Integer where U <: Real
SimpleWeightedDiGraph{T, U}(adjacency_matrix(LightGraphs.SimpleGraphs.SimpleDiGraph{T}(g), U))
return SimpleWeightedDiGraph{T, U}(x.*adjacency_matrix(g, U))
end

# DiGraph(srcs, dsts, weights)
function SimpleWeightedDiGraph(i::AbstractVector{T}, j::AbstractVector{T}, v::AbstractVector{U}; combine = +) where T<:Integer where U<:Real
m = max(maximum(j), maximum(i))
SimpleWeightedDiGraph{T, U}(sparse(j, i, v, m, m, combine))
SimpleWeightedDiGraph{T, U}(sparse(j, i, v, m, m, combine), false)
end

# Graph{UInt8}(adjmx)
# function (::Type{SimpleWeightedDiGraph{T, U}})(adjmx::AbstractMatrix) where T<:Integer where U <: Real
# dima,dimb = size(adjmx)
# isequal(dima,dimb) || error("Adjacency / distance matrices must be square")
# issymmetric(adjmx) || error("Adjacency / distance matrices must be symmetric")
# g = SimpleWeightedDiGraph(U.(LinearAlgebra.fillstored!(copy(adjmx), 1)))
# end

# converts Graph{Int} to Graph{Int32}
# function (::Type{SimpleWeightedDiGraph{T, U}})(g::SimpleWeightedDiGraph) where T<:Integer where U<:Real
# h_fadj = [Vector{T}(x) for x in fadj(g)]
# return SimpleGraph(ne(g), h_fadj)
# end


# Graph(adjmx)
SimpleWeightedDiGraph(adjmx::AbstractMatrix) = SimpleWeightedDiGraph{Int, eltype(adjmx)}(adjmx')

# Graph(digraph). Weights will be added.
# TODO: uncomment this.
SimpleWeightedDiGraph(g::AbstractSimpleWeightedGraph) = SimpleWeightedDiGraph(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)...))
weights(g::SimpleWeightedDiGraph) = g.weights'
function inneighbors(g::SimpleWeightedDiGraph)
mat = SparseMatrixCSC(g.weights')
return [mat.rowval[mat.colptr[i]:mat.colptr[i + 1] - 1] for i in 1:nv(g)]
end

function inneighbors(g::SimpleWeightedDiGraph, v::Integer)
mat = SparseMatrixCSC(g.weights')
return mat.rowval[mat.colptr[v]:mat.colptr[v + 1] - 1]
end
inneighbors(g::SimpleWeightedDiGraph, v::Integer) = g.weights[v,:].nzind

# add_edge! will overwrite weights.
function add_edge!(g::SimpleWeightedDiGraph, e::SimpleWeightedGraphEdge)
Expand Down Expand Up @@ -113,7 +101,7 @@ function rem_edge!(g::SimpleWeightedDiGraph, e::SimpleWeightedGraphEdge)
end


copy(g::SimpleWeightedDiGraph) = SimpleWeightedDiGraph(copy(g.weights))
copy(g::SimpleWeightedDiGraph) = SimpleWeightedDiGraph(copy(g.weights'))

==(g::SimpleWeightedDiGraph, h::SimpleWeightedDiGraph) = g.weights == h.weights

Expand Down
2 changes: 2 additions & 0 deletions src/simpleweightededge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@ Tuple(e::AbstractSimpleWeightedEdge) = (src(e), dst(e), weight(e))
# Convenience functions - note that these do not use weight.
reverse(e::T) where T<:AbstractSimpleWeightedEdge = T(dst(e), src(e), weight(e))
==(e1::AbstractSimpleWeightedEdge, e2::AbstractSimpleWeightedEdge) = (src(e1) == src(e2) && dst(e1) == dst(e2))
==(e1::AbstractSimpleWeightedEdge, e2::AbstractEdge) = (src(e1) == src(e2) && dst(e1) == dst(e2))
==(e1::AbstractEdge, e2::AbstractSimpleWeightedEdge) = (src(e1) == src(e2) && dst(e1) == dst(e2))
49 changes: 30 additions & 19 deletions src/simpleweightedgraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,36 @@
A type representing an undirected graph with weights of type `U`.
"""
mutable struct SimpleWeightedGraph{T<:Integer, U<:Real} <: AbstractSimpleWeightedGraph{T, U}
weights::SparseMatrixCSC{U, T} # indexed by [dst, src]
SimpleWeightedGraph(a::SparseMatrixCSC{U, T}) where T <: Integer where U <: Real =
new copy(a')
weights::SparseMatrixCSC{U,T}
function SimpleWeightedGraph{T, U}(adjmx::SparseMatrixCSC{U, T}) where T<:Integer where U<:Real
dima,dimb = size(adjmx)
isequal(dima,dimb) || error("Adjacency / distance matrices must be square")
issymmetric(adjmx) || error("Adjacency / distance matrices must be symmetric")
new{T, U}(adjmx)
end

SimpleWeightedGraph{T}(adjmx::SparseMatrixCSC{U, T}) where T<:Integer where U<:Real =
new{T, U}(adjmx)

SimpleWeightedGraph(adjmx::SparseMatrixCSC{U, T}) where T<:Integer where U<:Real =
new{T, U}(adjmx)

end

ne(g::SimpleWeightedGraph) = nnz(g.weights) ÷ 2

SimpleWeightedGraph(m::AbstractMatrix{U}) where U <: Real =
SimpleWeightedGraph{Int, U}(SparseMatrixCSC{U, Int}(m))
SimpleWeightedGraph{T}(m::AbstractMatrix{U}) where T<:Integer where U<:Real =
SimpleWeightedGraph{T, U}(SparseMatrixCSC{U, T}(m))
SimpleWeightedGraph{T, U}(m::AbstractMatrix) where T<:Integer where U<:Real =
SimpleWeightedGraph{T, U}(SparseMatrixCSC{U, T}(m))


SimpleWeightedGraph(g::SimpleWeightedGraph) = SimpleWeightedGraph(g.weights)
SimpleWeightedGraph{T,U}(g::SimpleWeightedGraph) where T<:Integer where U<:Real =
SimpleWeightedGraph(SparseMatrixCSC{U, T}(g.weights))


# Graph{UInt8}(6), Graph{Int16}(7), Graph{UInt8}()
function (::Type{SimpleWeightedGraph{T, U}})(n::Integer = 0) where T<:Integer where U<:Real
Expand All @@ -22,7 +45,7 @@ end


# Graph()
SimpleWeightedGraph() = SimpleWeightedGraph{Int, Float64}()
SimpleWeightedGraph() = SimpleWeightedGraph(Matrix{Float64}(undef, 0, 0))

# Graph(6), Graph(0x5)
SimpleWeightedGraph(n::T) where T<:Integer = SimpleWeightedGraph{T, Float64}(n)
Expand All @@ -35,11 +58,11 @@ SimpleWeightedGraph(::Type{T}, ::Type{U}) where T<:Integer where U<:Real = Simpl

# Graph(SimpleGraph)
SimpleWeightedGraph(g::LightGraphs.SimpleGraphs.SimpleGraph{T}, ::Type{U}=Float64) where T <: Integer where U <: Real =
SimpleWeightedGraph{T, U}(adjacency_matrix(g))
SimpleWeightedGraph{T, U}(adjacency_matrix(g, U))

# Graph(SimpleDiGraph)
SimpleWeightedGraph(g::LightGraphs.SimpleGraphs.SimpleDiGraph{T}, ::Type{U}=Float64) where T <: Integer where U <: Real =
SimpleWeightedGraph{T, U}(adjacency_matrix(LightGraphs.SimpleGraphs.SimpleGraph(g)))
SimpleWeightedGraph{T, U}(adjacency_matrix(LightGraphs.SimpleGraphs.SimpleGraph(g), U))

# Graph(SimpleGraph, defaultweight)
SimpleWeightedGraph(g::LightGraphs.SimpleGraphs.SimpleGraph{T}, x::U) where T <: Integer where U <: Real =
Expand All @@ -54,25 +77,13 @@ function (::Type{SimpleWeightedGraph{T, U}})(g::LightGraphs.SimpleGraphs.SimpleG
SimpleWeightedGraph{T, U}(adjacency_matrix(LightGraphs.SimpleGraphs.SimpleGraph{T}(g), U))
end

# DiGraph(srcs, dsts, weights)
# Graph(srcs, dsts, weights)
function SimpleWeightedGraph(i::AbstractVector{T}, j::AbstractVector{T}, v::AbstractVector{U}; combine = +) where T<:Integer where U<:Real
m = max(maximum(i), maximum(j))
s = sparse(vcat(i,j), vcat(j,i), vcat(v,v), m, m, combine)
SimpleWeightedGraph{T, U}(s)
end

# Graph(adjmx)
function SimpleWeightedGraph(adjmx::AbstractMatrix)
dima,dimb = size(adjmx)
isequal(dima,dimb) || error("Adjacency / distance matrices must be square")
issymmetric(adjmx) || error("Adjacency / distance matrices must be symmetric")
SimpleWeightedGraph{Int, eltype(adjmx)}(adjmx')
end

# Graph(digraph). Weights will be added.

SimpleWeightedGraph(g::SimpleWeightedDiGraph) = SimpleWeightedGraph(g.weights .+ 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))...))
Expand Down
5 changes: 2 additions & 3 deletions test/simpleweightedgraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ using SimpleWeightedGraphs
@test @inferred(vertices(g)) == 1:4
@test SimpleWeightedEdge(2,3) in edges(g)
@test @inferred(nv(g)) == 4
@test @inferred(outneighbors(g)) == inneighbors(g)
@test @inferred(outneighbors(g,2)) == inneighbors(g,2) == neighbors(g,2)
@test @inferred(has_edge(g, 2, 3))
@test @inferred(has_edge(g, 3, 2))
Expand Down Expand Up @@ -115,8 +114,8 @@ using SimpleWeightedGraphs
@test SimpleWeightedEdge(2,3) in edges(g)
@test !(SimpleWeightedEdge(3,2) in edges(g))
@test @inferred(nv(g)) == 4
@test @inferred(outneighbors(g)[2]) == outneighbors(g, 2) == [3]
@test @inferred(inneighbors(g)[2]) == inneighbors(g, 2) == [1]
@test outneighbors(g, 2) == [3]
@test inneighbors(g, 2) == [1]

@test @inferred(has_edge(g, 2, 3))
@test @inferred(!has_edge(g, 3, 2))
Expand Down

0 comments on commit d1f2627

Please sign in to comment.