Skip to content

Some fixes for v1.0 #66

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Sep 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ os:
- linux
- osx
julia:
- 0.6
- 0.7
- 1.0
- nightly

matrix:
Expand All @@ -16,3 +17,6 @@ notifications:
#script:
# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
# - julia --check-bounds=yes -e 'Pkg.clone(pwd()); Pkg.build("GraphPlot"); Pkg.test("GraphPlot"; coverage=true)'
after_success:
# push coverage results to Codecov
- julia -e 'cd(using Pkg; Pkg.dir("GraphPlot")); Pkg.add("Coverage"); using Coverage; Codecov.submit(Codecov.process_folder())'
8 changes: 5 additions & 3 deletions REQUIRE
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
julia 0.6
julia 0.7
ArnoldiMethod
Colors
ColorTypes
Compose
LightGraphs
Compose 0.7.0
LightGraphs 1.1.0
VisualRegressionTests 0.2.2 # this shouldn't be necessary here as it is only used by the tests
9 changes: 3 additions & 6 deletions src/GraphPlot.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
__precompile__(true)

module GraphPlot

using Compose # for plotting features
Expand All @@ -12,6 +10,8 @@ export
gplothtml,
random_layout,
circular_layout,
collapse_layout,
community_layout,
spring_layout,
spectral_layout,
shell_layout,
Expand All @@ -27,14 +27,11 @@ include("stress.jl")
include("shape.jl")
include("lines.jl")
include("plot.jl")
include("collapse_plot.jl")

# read graph
include("graphio.jl")

function test()
include(joinpath(dirname(@__DIR__), "test", "runtests.jl"))
end


# These functions are mappings to various graph packages.
# Currently only LightGraphs is supported.
Expand Down
43 changes: 20 additions & 23 deletions src/collapse_plot.jl
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
using Graphs
using GraphPlot

function collapse_graph{V}(g::AbstractGraph{V}, membership::Vector{Int})
function collapse_graph(g::AbstractGraph, membership::Vector{Int})
nb_comm = maximum(membership)

collapsed_edge_weights = Array(Dict{Int,Float64}, nb_comm)
collapsed_edge_weights = Vector{Dict{Int,Float64}}(undef, nb_comm)
for i=1:nb_comm
collapsed_edge_weights[i] = Dict{Int,Float64}()
end

for e in Graphs.edges(g)
u = source(e,g)
v = target(e,g)
u_idx = vertex_index(u,g)
v_idx = vertex_index(v,g)
u_comm = membership[u_idx]
v_comm = membership[v_idx]
for e in _edges(g)
u = _src_index(e,g)
v = _dst_index(e,g)
u_comm = membership[u]
v_comm = membership[v]

# for special case of undirected network
if !Graphs.is_directed(g)
if !_is_directed(g)
u_comm, v_comm = minmax(u_comm, v_comm)
end

Expand All @@ -29,20 +26,20 @@ function collapse_graph{V}(g::AbstractGraph{V}, membership::Vector{Int})
end
end

collapsed_graph = simple_graph(nb_comm, is_directed=false)
collapsed_graph = SimpleGraph(nb_comm)
collapsed_weights = Float64[]

for u=1:nb_comm
for (v,w) in collapsed_edge_weights[u]
Graphs.add_edge!(collapsed_graph, u, v)
add_edge!(collapsed_graph, u, v)
push!(collapsed_weights, w)
end
end

collapsed_graph, collapsed_weights
end

function community_layout{V}(g::AbstractGraph{V}, membership::Vector{Int})
function community_layout(g::AbstractGraph, membership::Vector{Int})
N = length(membership)
lx = zeros(N)
ly = zeros(N)
Expand All @@ -51,13 +48,13 @@ function community_layout{V}(g::AbstractGraph{V}, membership::Vector{Int})
if haskey(comms, lbl)
push!(comms[lbl], idx)
else
comms[lbl] = collect(idx)
comms[lbl] = Int[idx]
end
end
h, w = collapse_graph(g, membership)
clx, cly = spring_layout(h)
for (lbl, nodes) in comms
θ = linspace(0, 2pi, length(nodes) + 1)[1:end-1]
θ = range(0, stop=2pi, length=(length(nodes) + 1))[1:end-1]
for (idx, node) in enumerate(nodes)
lx[node] = 1.8*length(nodes)/N*cos(θ[idx]) + clx[lbl]
ly[node] = 1.8*length(nodes)/N*sin(θ[idx]) + cly[lbl]
Expand All @@ -66,11 +63,11 @@ function community_layout{V}(g::AbstractGraph{V}, membership::Vector{Int})
lx, ly
end

function collapse_layout{V}(g::AbstractGraph{V}, membership::Vector{Int})
lightg = LightGraphs.Graph(num_vertices(g))
for e in Graphs.edges(g)
u = vertex_index(source(e,g), g)
v = vertex_index(target(e,g), g)
function collapse_layout(g::AbstractGraph, membership::Vector{Int})
lightg = LightGraphs.SimpleGraph(_nv(g))
for e in _edges(g)
u = _src_index(e, g)
v = _dst_index(e, g)
LightGraphs.add_edge!(lightg, u, v)
end
N = length(membership)
Expand All @@ -81,15 +78,15 @@ function collapse_layout{V}(g::AbstractGraph{V}, membership::Vector{Int})
if haskey(comms, lbl)
push!(comms[lbl], idx)
else
comms[lbl] = collect(idx)
comms[lbl] = Int[idx]
end
end
h, w = collapse_graph(g, membership)
clx, cly = spring_layout(h)
for (lbl, nodes) in comms
subg = lightg[nodes]
sublx, subly = spring_layout(subg)
θ = linspace(0, 2pi, length(nodes) + 1)[1:end-1]
θ = range(0, stop=2pi, length=(length(nodes) + 1))[1:end-1]
for (idx, node) in enumerate(nodes)
lx[node] = 1.8*length(nodes)/N*sublx[idx] + clx[lbl]
ly[node] = 1.8*length(nodes)/N*subly[idx] + cly[lbl]
Expand Down
8 changes: 5 additions & 3 deletions src/graphio.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using DelimitedFiles: readdlm

"""
read some famous graphs

Expand All @@ -21,9 +23,9 @@ end
"""read graph from in edgelist format"""
function readedgelist(filename; is_directed::Bool=false, start_index::Int=0, delim::Char=' ')
es = readdlm(filename, delim, Int)
es = unique(es, 1)
es = unique(es, dims=1)
if start_index == 0
es = es + 1
es = es .+ 1
end
N = maximum(es)
if is_directed
Expand All @@ -38,7 +40,7 @@ function readedgelist(filename; is_directed::Bool=false, start_index::Int=0, del
es[i,1], es[i,2] = es[i,2], es[i,1]
end
end
es = unique(es, 1)
es = unique(es, dims=1)
g = Graph(N)
for i=1:size(es,1)
add_edge!(g, es[i,1], es[i,2])
Expand Down
36 changes: 22 additions & 14 deletions src/layout.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
using SparseArrays: SparseMatrixCSC, sparse
using ArnoldiMethod: LR
using LinearAlgebra: eigen

"""
Position nodes uniformly at random in the unit square.
For every node, a position is generated by choosing each of dim
Expand Down Expand Up @@ -56,7 +60,7 @@ function circular_layout(G)
return [0.0], [0.0]
else
# Discard the extra angle since it matches 0 radians.
θ = linspace(0, 2pi, _nv(G) + 1)[1:end-1]
θ = range(0, stop=2pi, length=_nv(G)+1)[1:end-1]
return cos.(θ), sin.(θ)
end
end
Expand Down Expand Up @@ -96,11 +100,11 @@ julia> locs_x, locs_y = spring_layout(g)
function spring_layout(G, locs_x=2*rand(_nv(G)).-1.0, locs_y=2*rand(_nv(G)).-1.0; C=2.0, MAXITER=100, INITTEMP=2.0)

#size(adj_matrix, 1) != size(adj_matrix, 2) && error("Adj. matrix must be square.")
const N = _nv(G)
N = _nv(G)
adj_matrix = _adjacency_matrix(G)

# The optimal distance bewteen vertices
const K = C * sqrt(4.0 / N)
K = C * sqrt(4.0 / N)

# Store forces and apply at end of iteration all at once
force_x = zeros(N)
Expand Down Expand Up @@ -183,7 +187,7 @@ julia> nlist[2] = [6:num_vertiecs(g)]
julia> locs_x, locs_y = shell_layout(g, nlist)
```
"""
function shell_layout(G, nlist::Union{Void, Vector{Vector{Int}}} = nothing)
function shell_layout(G, nlist::Union{Nothing, Vector{Vector{Int}}} = nothing)
if _nv(G) == 1
return [0.0], [0.0]
end
Expand All @@ -199,7 +203,7 @@ function shell_layout(G, nlist::Union{Void, Vector{Vector{Int}}} = nothing)
locs_y = Float64[]
for nodes in nlist
# Discard the extra angle since it matches 0 radians.
θ = linspace(0, 2pi, length(nodes) + 1)[1:end-1]
θ = range(0, stop=2pi, length=length(nodes)+1)[1:end-1]
append!(locs_x, radius*cos.(θ))
append!(locs_y, radius*sin.(θ))
radius += 1.0
Expand Down Expand Up @@ -229,37 +233,41 @@ julia> weight = rand(num_edges(g))
julia> locs_x, locs_y = spectral_layout(g, weight)
```
"""
function spectral_layout(G)
function spectral_layout(G, weight=nothing)
if _nv(G) == 1
return [0.0], [0.0]
elseif _nv(G) == 2
return [0.0, 1.0], [0.0, 0.0]
end

if weight == nothing
weight = ones(length(_edges(G)))
end
if _nv(G) > 500
A = sparse(Int[_src_index(e) for e in _edges(G)],
Int[_dst_index(e) for e in _edges(G)],
A = sparse(Int[_src_index(e, G) for e in _edges(G)],
Int[_dst_index(e, G) for e in _edges(G)],
weight, _nv(G), _nv(G))
if _is_directed(G)
A = A + A'
end
return _spectral(A)
else
L = _laplacian_matrix(G)
return _spectral(full(L))
return _spectral(Matrix(L))
end
end

function _spectral(L::Matrix)
eigenvalues, eigenvectors = eig(L)
eigenvalues, eigenvectors = eigen(L)
index = sortperm(eigenvalues)[2:3]
eigenvectors[:, index[1]], eigenvectors[:, index[2]]
end

function _spectral(A::SparseMatrixCSC)
data = collect(sum(A, 1))
D = sparse([1:length(data)], [1:length(data)], data)
data = vec(sum(A, dims=1))
D = sparse(Base.OneTo(length(data)), Base.OneTo(length(data)), data)
L = D - A
ncv = max(7, int(sqrt(length(data))))
eigenvalues, eigenvectors = eigs(L, nev=3, ncv=ncv)
eigenvalues, eigenvectors = LightGraphs.LinAlg.eigs(L, nev=3, which=LR())
index = sortperm(real(eigenvalues))[2:3]
real(eigenvectors[:, index[1]]), real(eigenvectors[:, index[2]])
end
Loading