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

Commit

Permalink
Added constructors to create graphs from a vector or an iterator of e…
Browse files Browse the repository at this point in the history
…dges (#880)

* Added constructors to create SimpleGraphs and SimpleDiGraphs from a vector or an iterator of edges

* Added constructors to create SimpleGraphs and SimpleDiGraphs from a vector or an iterator of edges
  • Loading branch information
simonschoelly authored and sbromberger committed Jun 5, 2018
1 parent 3776f1d commit 8a5150b
Show file tree
Hide file tree
Showing 5 changed files with 459 additions and 3 deletions.
3 changes: 2 additions & 1 deletion src/LightGraphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ import LinearAlgebra: issymmetric, mul!
export
# Interface
AbstractGraph, AbstractEdge, AbstractEdgeIter,
Edge, Graph, SimpleGraph, DiGraph, SimpleDiGraph, vertices, edges, edgetype, nv, ne, src, dst,
Edge, Graph, SimpleGraph, SimpleGraphFromIterator, DiGraph, SimpleDiGraphFromIterator,
SimpleDiGraph, vertices, edges, edgetype, nv, ne, src, dst,
is_directed,
has_vertex, has_edge, inneighbors, outneighbors,

Expand Down
4 changes: 2 additions & 2 deletions src/SimpleGraphs/SimpleGraphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import LightGraphs:
indegree, outdegree, degree, has_self_loops, num_self_loops, insorted

export AbstractSimpleGraph, AbstractSimpleEdge,
SimpleEdge, SimpleGraph, SimpleGraphEdge,
SimpleDiGraph, SimpleDiGraphEdge,
SimpleEdge, SimpleGraph, SimpleGraphFromIterator, SimpleGraphEdge,
SimpleDiGraph, SimpleDiGraphFromIterator, SimpleDiGraphEdge,
add_vertex!, add_edge!, rem_vertex!, rem_edge!


Expand Down
143 changes: 143 additions & 0 deletions src/SimpleGraphs/simpledigraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,149 @@ function SimpleDiGraph(g::AbstractSimpleGraph)
return h
end


@inbounds function cleanupedges!(fadjlist::Vector{Vector{T}},
badjlist::Vector{Vector{T}}) where T<:Integer
neg = 0
for v in 1:length(fadjlist)
if !issorted(fadjlist[v])
sort!(fadjlist[v])
end
if !issorted(badjlist[v])
sort!(badjlist[v])
end
unique!(fadjlist[v])
unique!(badjlist[v])
neg += length(fadjlist[v])
end
return neg
end

function SimpleDiGraph(edge_list::Vector{SimpleDiGraphEdge{T}}) where T<:Integer
nvg = zero(T)
@inbounds(
for e in edge_list
nvg = max(nvg, src(e), dst(e))
end)

list_sizes_out = ones(Int, nvg)
list_sizes_in = ones(Int, nvg)
degs_out = zeros(Int, nvg)
degs_in = zeros(Int, nvg)
@inbounds(
for e in edge_list
s, d = src(e), dst(e)
(s >= 1 && d >= 1) || continue
degs_out[s] += 1
degs_in[d] += 1
end)

fadjlist = Vector{Vector{T}}(undef, nvg)
badjlist = Vector{Vector{T}}(undef, nvg)
@inbounds(
for v in 1:nvg
fadjlist[v] = Vector{T}(undef, degs_out[v])
badjlist[v] = Vector{T}(undef, degs_in[v])
end)

@inbounds(
for e in edge_list
s, d = src(e), dst(e)
(s >= 1 && d >= 1) || continue
fadjlist[s][list_sizes_out[s]] = d
list_sizes_out[s] += 1
badjlist[d][list_sizes_in[d]] = s
list_sizes_in[d] += 1
end)

neg = cleanupedges!(fadjlist, badjlist)
g = SimpleDiGraph{T}()
g.fadjlist = fadjlist
g.badjlist = badjlist
g.ne = neg

return g
end


@inbounds function add_to_lists!(fadjlist::Vector{Vector{T}},
badjlist::Vector{Vector{T}}, s::T, d::T) where T<:Integer
nvg = length(fadjlist)
nvg_new = max(nvg, s, d)
for v = (nvg+1):nvg_new
push!(fadjlist, Vector{T}())
push!(badjlist, Vector{T}())
end

push!(fadjlist[s], d)
push!(badjlist[d], s)
end

function _SimpleDiGraphFromIterator(iter)::SimpleDiGraph
T = Union{}
fadjlist = Vector{Vector{T}}()
badjlist = Vector{Vector{T}}()
@inbounds(
for e in iter
typeof(e) <: SimpleDiGraphEdge ||
throw(ArgumentError("iter must be an iterator over SimpleEdge"))
s, d = src(e), dst(e)
(s >= 1 && d >= 1) || continue
if T != eltype(e)
T = typejoin(T, eltype(e))
fadjlist = convert(Vector{Vector{T}}, fadjlist)
badjlist = convert(Vector{Vector{T}}, badjlist)
end
add_to_lists!(fadjlist, badjlist, s, d)
end)

T == Union{} && return SimpleDiGraph(0)
neg = cleanupedges!(fadjlist, badjlist)
g = SimpleDiGraph{T}()
g.fadjlist = fadjlist
g.badjlist = badjlist
g.ne = neg

return g
end

function _SimpleDiGraphFromIterator(iter, ::Type{SimpleDiGraphEdge{T}}) where T<:Integer
fadjlist = Vector{Vector{T}}()
badjlist = Vector{Vector{T}}()
@inbounds(
for e in iter
s, d = src(e), dst(e)
(s >= 1 && d >= 1) || continue
add_to_lists!(fadjlist, badjlist, s, d)
end)

g = SimpleDiGraph{T}()
neg = cleanupedges!(fadjlist, badjlist)
g.fadjlist = fadjlist
g.badjlist = badjlist
g.ne = neg

return g
end

"""
SimpleDiGraphFromIterator(iter)
Creates a SimpleDiGraph from an iterator iter. The elements in iter must
be of type <: SimpleEdge.
"""
function SimpleDiGraphFromIterator(iter)::SimpleDiGraph
if Base.IteratorEltype(iter) == Base.EltypeUnknown()
return _SimpleDiGraphFromIterator(iter)
end
# if the eltype of iter is known but is a proper supertype of SimpleDiGraphEdge
if !(eltype(iter) <: SimpleDiGraphEdge) && SimpleDiGraphEdge <: eltype(iter)
return _SimpleDiGraphFromIterator(iter)
end
return _SimpleDiGraphFromIterator(iter, eltype(iter))
end


edgetype(::SimpleDiGraph{T}) where T<: Integer = SimpleGraphEdge{T}


Expand Down
138 changes: 138 additions & 0 deletions src/SimpleGraphs/simplegraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,144 @@ function SimpleGraph(g::SimpleDiGraph)
return SimpleGraph(edgect ÷ 2, newfadj)
end

@inbounds function cleanupedges!(fadjlist::Vector{Vector{T}}) where T<:Integer
neg = 0
for v in 1:length(fadjlist)
if !issorted(fadjlist[v])
sort!(fadjlist[v])
end
unique!(fadjlist[v])
neg += length(fadjlist[v])
# self-loops should count as one edge
for w in fadjlist[v]
if w == v
neg += 1
break
end
end
end
return neg ÷ 2
end

function SimpleGraph(edge_list::Vector{SimpleGraphEdge{T}}) where T<:Integer
nvg = zero(T)
@inbounds(
for e in edge_list
nvg = max(nvg, src(e), dst(e))
end)

list_sizes = ones(Int, nvg)
degs = zeros(Int, nvg)
@inbounds(
for e in edge_list
s, d = src(e), dst(e)
(s >= 1 && d >= 1) || continue
degs[s] += 1
if s != d
degs[d] += 1
end
end)

fadjlist = Vector{Vector{T}}(undef, nvg)
@inbounds(
for v in 1:nvg
fadjlist[v] = Vector{T}(undef, degs[v])
end)

@inbounds(
for e in edge_list
s, d = src(e), dst(e)
(s >= 1 && d >= 1) || continue
fadjlist[s][list_sizes[s]] = d
list_sizes[s] += 1
if s != d
fadjlist[d][list_sizes[d]] = s
list_sizes[d] += 1
end
end)

neg = cleanupedges!(fadjlist)
g = SimpleGraph{T}()
g.fadjlist = fadjlist
g.ne = neg

return g
end


@inbounds function add_to_fadjlist!(fadjlist::Vector{Vector{T}}, s::T, d::T) where T<:Integer
nvg = length(fadjlist)
nvg_new = max(nvg, s, d)
for v = (nvg+1):nvg_new
push!(fadjlist, Vector{T}())
end

push!(fadjlist[s], d)
if s != d
push!(fadjlist[d], s)
end
end

function _SimpleGraphFromIterator(iter)::SimpleGraph
T = Union{}
fadjlist = Vector{Vector{T}}()
@inbounds(
for e in iter
typeof(e) <: SimpleGraphEdge ||
throw(ArgumentError("iter must be an iterator over SimpleEdge"))
s, d = src(e), dst(e)
(s >= 1 && d >= 1) || continue
if T != eltype(e)
T = typejoin(T, eltype(e))
fadjlist = convert(Vector{Vector{T}}, fadjlist)
end
add_to_fadjlist!(fadjlist, s, d)
end)

T == Union{} && return SimpleGraph(0)
neg = cleanupedges!(fadjlist)
g = SimpleGraph{T}()
g.fadjlist = fadjlist
g.ne = neg

return g
end

function _SimpleGraphFromIterator(iter, ::Type{SimpleGraphEdge{T}}) where T<:Integer
fadjlist = Vector{Vector{T}}()
@inbounds(
for e in iter
s, d = src(e), dst(e)
(s >= 1 && d >= 1) || continue
add_to_fadjlist!(fadjlist, s, d)
end)

neg = cleanupedges!(fadjlist)
g = SimpleGraph{T}()
g.fadjlist = fadjlist
g.ne = neg

return g
end

"""
SimpleGraphFromIterator(iter)
Creates a SimpleGraph from an iterator iter. The elements in iter must
be of type <: SimpleEdge.
"""
function SimpleGraphFromIterator(iter)::SimpleGraph
if Base.IteratorEltype(iter) == Base.EltypeUnknown()
return _SimpleGraphFromIterator(iter)
end
# if the eltype of iter is know but is a proper supertype of SimpleDiEdge
if !(eltype(iter) <: SimpleGraphEdge) && SimpleGraphEdge <: eltype(iter)
return _SimpleGraphFromIterator(iter)
end
return _SimpleGraphFromIterator(iter, eltype(iter))
end


edgetype(::SimpleGraph{T}) where T<:Integer = SimpleGraphEdge{T}

"""
Expand Down
Loading

0 comments on commit 8a5150b

Please sign in to comment.