Skip to content

Commit

Permalink
Edge betweenness centrality + Girvan-Newman community detection (jgra…
Browse files Browse the repository at this point in the history
…pht#1032)

* Added basic implementation of edge betweenness centrality

* [wip] Added two simple tests

* Fixed bug with integer division

* Added edge betweenness only from a subset of the vertices

* Added test for weighted case in EdgeBetweennessCentrality

* Added the Girvan-Newman clustering algorithm
  • Loading branch information
d-michail authored Feb 15, 2021
1 parent b7f701d commit d9dcb19
Show file tree
Hide file tree
Showing 5 changed files with 840 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/*
* (C) Copyright 2021-2021, by Dimitrios Michail and Contributors.
*
* JGraphT : a free Java graph-theory library
*
* See the CONTRIBUTORS.md file distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the
* GNU Lesser General Public License v2.1 or later
* which is available at
* http://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html.
*
* SPDX-License-Identifier: EPL-2.0 OR LGPL-2.1-or-later
*/
package org.jgrapht.alg.clustering;

import java.util.List;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;

import org.jgrapht.Graph;
import org.jgrapht.alg.connectivity.ConnectivityInspector;
import org.jgrapht.alg.interfaces.ClusteringAlgorithm;
import org.jgrapht.alg.scoring.EdgeBetweennessCentrality;
import org.jgrapht.alg.scoring.EdgeBetweennessCentrality.OverflowStrategy;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.graph.builder.GraphTypeBuilder;
import org.jgrapht.util.SupplierUtil;

/**
* The Girvan-Newman clustering algorithm.
*
* <p>
* The algorithm is described in: Girvan, Michelle, and Mark EJ Newman. "Community structure in
* social and biological networks." Proceedings of the national academy of sciences 99.12 (2002):
* 7821-7826.
*
* <p>
* Running time is $O(m^2 n)$ or $O(m^2n + m n^2 \log n)$ for weighted graphs.
*
* @author Dimitrios Michail
*
* @param <V> the graph vertex type
* @param <E> the graph edge type
*/
public class GirvanNewmanClustering<V, E>
implements
ClusteringAlgorithm<V>
{
private Graph<V, E> graph;
private int k;
private final Iterable<V> startVertices;
private final OverflowStrategy overflowStrategy;

/**
* Create a new clustering algorithm.
*
* @param graph the graph
* @param k the desired number of clusters
*/
public GirvanNewmanClustering(Graph<V, E> graph, int k)
{
this(graph, k, OverflowStrategy.THROW_EXCEPTION_ON_OVERFLOW, graph.vertexSet());
}

/**
* Create a new clustering algorithm.
*
* @param graph the graph
* @param k the desired number of clusters
* @param overflowStrategy strategy to use if overflow is detected
* @param startVertices vertices from which to start shortest path computations when computing
* edge centralities. This parameter allows the user to compute edge centrality
* contributions only from a subset of the vertices of the graph. If null the whole graph
* vertex set is used.
*/
public GirvanNewmanClustering(
Graph<V, E> graph, int k, OverflowStrategy overflowStrategy, Iterable<V> startVertices)
{
this.graph = Objects.requireNonNull(graph);
if (k < 1 || k > graph.vertexSet().size()) {
throw new IllegalArgumentException("Illegal number of clusters");
}
this.k = k;
this.overflowStrategy = overflowStrategy;
if (startVertices == null) {
this.startVertices = graph.vertexSet();
} else {
this.startVertices = startVertices;
}
}

@Override
public Clustering<V> getClustering()
{
// copy graph
Graph<V,
DefaultEdge> graphCopy = GraphTypeBuilder
.forGraphType(graph.getType()).edgeSupplier(SupplierUtil.DEFAULT_EDGE_SUPPLIER)
.vertexSupplier(graph.getVertexSupplier()).buildGraph();
for (V v : graph.iterables().vertices()) {
graphCopy.addVertex(v);
}
for (E e : graph.iterables().edges()) {
V sourceVertex = graph.getEdgeSource(e);
V targetVertex = graph.getEdgeTarget(e);
graphCopy.addEdge(sourceVertex, targetVertex);
}

// main algorithm
while (true) {
List<Set<V>> ccs = new ConnectivityInspector<>(graphCopy).connectedSets();
if (ccs.size() == k) {
return new ClusteringImpl<>(ccs);
}

// compute edge centralities
EdgeBetweennessCentrality<V, DefaultEdge> bc =
new EdgeBetweennessCentrality<>(graphCopy, overflowStrategy, startVertices);

// find edge with max centrality
DefaultEdge maxEdge = null;
double maxCentrality = 0d;
for (Entry<DefaultEdge, Double> entry : bc.getScores().entrySet()) {
if (Double.compare(entry.getValue(), maxCentrality) > 0 || maxEdge == null) {
maxEdge = entry.getKey();
maxCentrality = entry.getValue();
}
}

// remove edge with max centrality
graphCopy.removeEdge(maxEdge);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* (C) Copyright 2020-2020, by Dimitrios Michail and Contributors.
*
* JGraphT : a free Java graph-theory library
*
* See the CONTRIBUTORS.md file distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the
* GNU Lesser General Public License v2.1 or later
* which is available at
* http://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html.
*
* SPDX-License-Identifier: EPL-2.0 OR LGPL-2.1-or-later
*/
package org.jgrapht.alg.interfaces;

import java.util.Map;

/**
* An interface for all algorithms which assign scores to edges of a graph.
*
* @param <E> the edge type
* @param <D> the score type
*
* @author Dimitrios Michail
*/
public interface EdgeScoringAlgorithm<E, D>
{

/**
* Get a map with the scores of all edges
*
* @return a map with all scores
*/
Map<E, D> getScores();

/**
* Get an edge score
*
* @param e the edge
* @return the score
*/
D getEdgeScore(E e);

}
Loading

0 comments on commit d9dcb19

Please sign in to comment.