Skip to content

Commit

Permalink
Project structure and new network analysis functionalities (#39)
Browse files Browse the repository at this point in the history
* algorithms

* s-distance

* LightGraph pkg version
  • Loading branch information
alessant authored Jun 5, 2020
1 parent 0f08fe0 commit ce5cc86
Show file tree
Hide file tree
Showing 12 changed files with 688 additions and 71 deletions.
3 changes: 2 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
LightGraphs = "093fc24a-ae57-5d10-9952-331d41423f4d"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0"
PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Expand All @@ -19,7 +20,7 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Conda = "1.4.0"
DataStructures = "0.17.10"
JSON3 = "1.0.1"
LightGraphs = "^1.1.0"
LightGraphs = "1.3"
PyCall = "1.91.2"
PyPlot = "2.8.2"
StatsBase = "0.32"
Expand Down
43 changes: 29 additions & 14 deletions src/SimpleHypergraphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,36 @@ using PyCall
using Conda
using PyPlot
using JSON3
using Random
using LinearAlgebra

export Hypergraph, getvertices, gethyperedges
export add_vertex!, add_hyperedge!, remove_vertex!, remove_hyperedge!, prune_hypergraph!, prune_hypergraph
export add_vertex!, add_hyperedge!, remove_vertex!, remove_hyperedge!
export prune_hypergraph!, prune_hypergraph
export set_vertex_meta!, get_vertex_meta
export set_hyperedge_meta!, get_hyperedge_meta
export BipartiteView, shortest_path
export TwoSectionView
export adjacency_matrix, edge_adjacency_matrix

export BipartiteView, TwoSectionView
export shortest_path
export get_twosection_adjacency_mx, get_twosection_weighted_adjacency_mx
export dual
export random_model, random_kuniform_model, random_dregular_model, random_preferential_model

export Abstract_HG_format, HGF_Format, JSON_Format
export hg_load, hg_save

export nhv, nhe
export modularity, randompartition
export AbstractCommunityFinder, CFModularityRandom, CFModularityCNMLike
export modularity, nmi
export randompartition
export AbstractCommunityFinder, CFModularityRandom, CFModularityCNMLike, CFLabelPropagationFinder
export findcommunities

export nhv, nhe
export random_walk
export get_connected_components
export conductance

export random_model, random_kuniform_model, random_dregular_model, random_preferential_model
export AbstractDistance, SnodeDistanceDijkstra, SedgeDistanceDijkstra
export distance

export HyperNetX, GraphBased
export draw
Expand Down Expand Up @@ -59,16 +68,22 @@ function support_hypernetx()

end


include("hypergraph.jl")
include("bipartite.jl")
include("io.jl")
include("twosection.jl")
include("modularity.jl")
include("conductance.jl")
include("models.jl")

include("models/bipartite.jl")
include("models/twosection.jl")
include("models/random-models.jl")
include("models/dual.jl")

include("algorithms/conductance.jl")
include("algorithms/distance.jl")

include("algorithms/community/modularity.jl")
include("algorithms/community/label-propagation.jl")

include("viz/drawing.jl")
include("viz/widget.jl")


end # module
189 changes: 189 additions & 0 deletions src/algorithms/community/label-propagation.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
"""
CFLabelPropagationFinder() <: AbstractCommunityFinder
Represents a label propagation search over the hypergraph `h` that finds
a partition into communities (subsets).
"""
struct CFLabelPropagationFinder <: AbstractCommunityFinder
max_iter::Int
seed::Int
end


"""
findcommunities(h::Hypergraph, method::CFLabelPropagationFinder)
Implements the label propagation algorithm over a hypergraph `h`.
NOTE
The algorithm works on a single connected component.
An AssertionError is thrown otherwise.
This algorithm generalizes the one proposed for graphs by Raghavan et al.
(Raghavan, U. N., Albert, R., and Kumara, S. Near linear time algorithm to detect
community structures in large-scale networks. Physical review. E, Statistical,
nonlinear, and soft matter physics 76 (2007).)
The proposed algorithm modifies the propagation rule, splitting it into two phases:
hyperedge labeling and vertex labeling.
For more information see `Section 4` in the paper
Alessia Antelmi, Gennaro Cordasco, Bogumił Kamiński, Paweł Prałat,
Vittorio Scarano, Carmine Spagnuolo, Przemyslaw Szufel
*Analyzing, Exploring, and Visualizing Complex Networks via Hypergraphs Using SimpleHypergraphs.jl.*
Journal Internet Mathematics (2020). https://doi.org/10.24166/im.01.2020
"""
function findcommunities(h::Hypergraph, method::CFLabelPropagationFinder)
@assert length(get_connected_components(h)) == 1

rng = MersenneTwister(method.seed)
vlabels = Dict{Int64,Int64}()
helabels = Dict{Int64,Int64}()

for v in 1:size(h)[1]
push!(vlabels, v=>v)
end

stop = false
iter = 0

edges = Array{Int64}(undef, size(h)[2])
for ie in 1:size(h)[2]
edges[ie] = ie
end

vertices = Array{Int64}(undef, size(h)[1])
for iv in 1:size(h)[1]
vertices[iv] = iv
end

while !stop && iter < method.max_iter
stop = true
shuffle!(rng, edges)

for e in edges
l = SimpleHypergraphs.compute_edge_label(h, e, vlabels, rng)
push!(helabels, e=>l)
end

shuffle!(rng,vertices)
for v in vertices
l = SimpleHypergraphs.compute_vertex_label(h, v, vlabels, helabels, rng)
if l != vlabels[v]
stop = false
push!(vlabels, v=>l)
end
end

iter+=1
end

np_vertices = unique(values(vlabels))
np_edges = unique(values(helabels))

comms_vertices = Dict{Int, Set}()
comms_hyperedges = Dict{Int, Set}()

for pv in vlabels
push!(
get!(comms_vertices, pv[2], Set{Int}()),
pv[1]
)
end

for pe in helabels
push!(
get!(comms_hyperedges, pe[2], Set{Int}()),
pe[1]
)
end

labels = Array{Int64}(undef, nhv(h))
for i in 1:nhv(h)
labels[i] = vlabels[i]
end

hlabels = Array{Int64}(undef, nhe(h))
for i in 1:nhe(h)
hlabels[i] = helabels[i]
end

(np=collect(values(comms_vertices)), hep=collect(values(comms_hyperedges)), vlabels=labels, helabels=hlabels, iter=iter)
end


"""
compute_vertex_label(h::Hypergraph, v::Int64, vlabels::Dict{Int64,Int64}, helabels::Dict{Int64,Int64}, rng::MersenneTwister)
Vertices labeling phase. Computes the label of each vertex according to the most
frequent label among the hyperedges it belongs to.
"""
function compute_vertex_label(h::Hypergraph, v::Int64, vlabels::Dict{Int64,Int64}, helabels::Dict{Int64,Int64}, rng::MersenneTwister)
hesᵥ = gethyperedges(h, v)
vL = Dict{Int64,Int64}()

max = 0
maxL = Set{Int64}()

for e in shuffle!(rng, collect(keys(hesᵥ)))
l = helabels[e]

if !haskey(vL, l)
push!(vL, l=>0)
end

push!(
vL,
l => vL[l] + (length(getvertices(h, e)))
)

if vL[l] == max
push!(maxL, l)
elseif vL[l] > max
max = vL[l]
maxL = Set{Int64}()
push!(maxL, l)
end
end

if in(vlabels[v], maxL)
return vlabels[v]
end

return collect(maxL)[1]
end


"""
compute_edge_label(h::Hypergraph, e::Int64, vlabels::Dict{Int64,Int64}, rng::MersenneTwister)
Hyperedges labeling phase. Computes the labels of the hyperedges according to
the most frequent label among the vertices contained in that hyperedge.
"""
function compute_edge_label(h::Hypergraph, e::Int64, vlabels::Dict{Int64,Int64}, rng::MersenneTwister)
vₑ = getvertices(h,e)
eL = Dict{Int64,Int64}()

max = 0
maxL = -1

for v in shuffle!(rng, collect(keys(vₑ)))
l = vlabels[v]

if !haskey(eL, l)
push!(eL, l=>0)
end

push!(
eL,
l => eL[l]+1
)

if eL[l] > max
max = eL[l]
maxL = l
end
end

return maxL
end
Loading

0 comments on commit ce5cc86

Please sign in to comment.