Skip to content
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

Added edge-betweenness.jl to centralities #277

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
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
102 changes: 102 additions & 0 deletions src/centrality/edge-betweenness.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
"""
edge_betweenness_centrality(g, k)

Compute the [edge betweenness centrality](https://en.wikipedia.org/wiki/Centrality#Betweenness_centrality) of an edge `e`.
It is defined as the sum of the fraction of all-pairs shortest paths that pass through `e`
``
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have you checked how this displays by building the docs?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pkg> activate docs
julia> include("docs/make.jl")

bc(e) = \\sum_{s, t \\in V}
\\frac{\\sigma_{st}(e)}{\\sigma_{st}}
``.

where `V`, is the set of nodes, \\frac{\\sigma_{st}} is the number of shortest-paths, and \\frac{\\sigma_{st}(e)} is the number of those paths passing through edge.

### Optional Arguments
- `normalize=true`: If true, normalize the betweenness values by the
total number of possible distinct paths between all pairs in the graphs.
For an undirected graph, this number is ``\\frac{(|V|-1)(|V|-2)}{2}``
and for a directed graph, ``{(|V|-1)(|V|-2)}``.


### References
- Brandes 2001 & Brandes 2008
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you give more details to help us check the algorithm?


# Examples
```jldoctest
julia> using Graphs

julia> edge_betweenness_centrality(star_graph(5))
Dict{Graphs.SimpleGraphs.SimpleEdge{Int64}, Float64} with 4 entries:
Edge 1 => 2 => 0.4
Edge 1 => 3 => 0.4
Edge 1 => 4 => 0.4
Edge 1 => 5 => 0.4

julia> edge_betweenness_centrality(path_digraph(6))
Dict{Graphs.SimpleGraphs.SimpleEdge{Int64}, Float64} with 5 entries:
Edge 4 => 5 => 0.266667
Edge 1 => 2 => 0.166667
Edge 3 => 4 => 0.3
Edge 5 => 6 => 0.166667
Edge 2 => 3 => 0.266667
```
"""
gdalle marked this conversation as resolved.
Show resolved Hide resolved

function edge_betweenness_centrality(
g::AbstractGraph, vs=vertices(g), distmx::AbstractMatrix=weights(g); normalize=true
jwassmer marked this conversation as resolved.
Show resolved Hide resolved
)
edge_betweenness = Dict(edges(g) .=> 0.0)
gdalle marked this conversation as resolved.
Show resolved Hide resolved
for o in vs
state = dijkstra_shortest_paths(g, o, distmx; allpaths=true, trackvertices=true)
_accumulate_edges!(edge_betweenness, state)
end
gdalle marked this conversation as resolved.
Show resolved Hide resolved
_rescale_e!(edge_betweenness, nv(g), normalize, is_directed(g))

return edge_betweenness
end

function _accumulate_edges!(edge_betweenness::AbstractDict, state::Graphs.AbstractPathState)
σ = state.pathcounts
pred = state.predecessors
seen = state.closest_vertices
δ = Dict(seen .=> 0.0)

while length(seen) > 0
w = pop!(seen)

coeff = (1.0 + δ[w]) / σ[w]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you explain the dynamics of coeff and δ through this loop?

for v in pred[w]
c = σ[v] * coeff
if Edge(v, w) ∉ edge_betweenness.keys
jwassmer marked this conversation as resolved.
Show resolved Hide resolved
edge_betweenness[Edge(w, v)] += c
else
edge_betweenness[Edge(v, w)] += c
δ[v] += c
end
end
end
return nothing
end

function _rescale_e!(
edge_betweenness::AbstractDict, n::Integer, normalize::Bool, directed::Bool=false
)
if normalize
if n <= 1
scale = nothing # no normalization b=0 for all nodes
else
scale = 1 / (n * (n - 1))
end
else # rescale by 2 for undirected graphs
if !directed
scale = 0.5
else
scale = nothing
end
end
if scale !== nothing
for (k, v) in edge_betweenness
edge_betweenness[k] *= scale
end
end
return nothing
end