edu.uci.ics.jung.algorithms.importance.BetweennessCentrality.java Source code

Java tutorial

Introduction

Here is the source code for edu.uci.ics.jung.algorithms.importance.BetweennessCentrality.java

Source

/*
* Copyright (c) 2003, the JUNG Project and the Regents of the University
* of California
* All rights reserved.
*
* This software is open-source under the BSD license; see either
* "license.txt" or
* http://jung.sourceforge.net/license.txt for a description.
*/
package edu.uci.ics.jung.algorithms.importance;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import org.apache.commons.collections15.Buffer;
import org.apache.commons.collections15.buffer.UnboundedFifoBuffer;

import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.UndirectedGraph;

/**
 * Computes betweenness centrality for each vertex and edge in the graph. The result is that each vertex
 * and edge has a UserData element of type MutableDouble whose key is 'centrality.BetweennessCentrality'.
 * Note: Many social network researchers like to normalize the betweenness values by dividing the values by
 * (n-1)(n-2)/2. The values given here are unnormalized.<p>
 *
 * A simple example of usage is:
 * <pre>
 * BetweennessCentrality ranker = new BetweennessCentrality(someGraph);
 * ranker.evaluate();
 * ranker.printRankings();
 * </pre>
 *
 * Running time is: O(n^2 + nm).
 * @see "Ulrik Brandes: A Faster Algorithm for Betweenness Centrality. Journal of Mathematical Sociology 25(2):163-177, 2001."
 * @author Scott White
 * @author Tom Nelson converted to jung2
 */

public class BetweennessCentrality<V, E> extends AbstractRanker<V, E> {

    public static final String CENTRALITY = "centrality.BetweennessCentrality";

    /**
     * Constructor which initializes the algorithm
     * @param g the graph whose nodes are to be analyzed
     */
    public BetweennessCentrality(Graph<V, E> g) {
        initialize(g, true, true);
    }

    public BetweennessCentrality(Graph<V, E> g, boolean rankNodes) {
        initialize(g, rankNodes, true);
    }

    public BetweennessCentrality(Graph<V, E> g, boolean rankNodes, boolean rankEdges) {
        initialize(g, rankNodes, rankEdges);
    }

    protected void computeBetweenness(Graph<V, E> graph) {

        Map<V, BetweennessData> decorator = new HashMap<V, BetweennessData>();
        Map<V, Number> bcVertexDecorator = vertexRankScores.get(getRankScoreKey());
        bcVertexDecorator.clear();
        Map<E, Number> bcEdgeDecorator = edgeRankScores.get(getRankScoreKey());
        bcEdgeDecorator.clear();

        Collection<V> vertices = graph.getVertices();

        for (V s : vertices) {

            initializeData(graph, decorator);

            decorator.get(s).numSPs = 1;
            decorator.get(s).distance = 0;

            Stack<V> stack = new Stack<V>();
            Buffer<V> queue = new UnboundedFifoBuffer<V>();
            queue.add(s);

            while (!queue.isEmpty()) {
                V v = queue.remove();
                stack.push(v);

                for (V w : getGraph().getSuccessors(v)) {

                    if (decorator.get(w).distance < 0) {
                        queue.add(w);
                        decorator.get(w).distance = decorator.get(v).distance + 1;
                    }

                    if (decorator.get(w).distance == decorator.get(v).distance + 1) {
                        decorator.get(w).numSPs += decorator.get(v).numSPs;
                        decorator.get(w).predecessors.add(v);
                    }
                }
            }

            while (!stack.isEmpty()) {
                V w = stack.pop();

                for (V v : decorator.get(w).predecessors) {

                    double partialDependency = (decorator.get(v).numSPs / decorator.get(w).numSPs);
                    partialDependency *= (1.0 + decorator.get(w).dependency);
                    decorator.get(v).dependency += partialDependency;
                    E currentEdge = getGraph().findEdge(v, w);
                    double edgeValue = bcEdgeDecorator.get(currentEdge).doubleValue();
                    edgeValue += partialDependency;
                    bcEdgeDecorator.put(currentEdge, edgeValue);
                }
                if (w != s) {
                    double bcValue = bcVertexDecorator.get(w).doubleValue();
                    bcValue += decorator.get(w).dependency;
                    bcVertexDecorator.put(w, bcValue);
                }
            }
        }

        if (graph instanceof UndirectedGraph) {
            for (V v : vertices) {
                double bcValue = bcVertexDecorator.get(v).doubleValue();
                bcValue /= 2.0;
                bcVertexDecorator.put(v, bcValue);
            }
            for (E e : graph.getEdges()) {
                double bcValue = bcEdgeDecorator.get(e).doubleValue();
                bcValue /= 2.0;
                bcEdgeDecorator.put(e, bcValue);
            }
        }

        for (V vertex : vertices) {
            decorator.remove(vertex);
        }
    }

    private void initializeData(Graph<V, E> g, Map<V, BetweennessData> decorator) {
        for (V vertex : g.getVertices()) {

            Map<V, Number> bcVertexDecorator = vertexRankScores.get(getRankScoreKey());
            if (bcVertexDecorator.containsKey(vertex) == false) {
                bcVertexDecorator.put(vertex, 0.0);
            }
            decorator.put(vertex, new BetweennessData());
        }
        for (E e : g.getEdges()) {

            Map<E, Number> bcEdgeDecorator = edgeRankScores.get(getRankScoreKey());
            if (bcEdgeDecorator.containsKey(e) == false) {
                bcEdgeDecorator.put(e, 0.0);
            }
        }
    }

    /**
     * the user datum key used to store the rank scores
     * @return the key
     */
    @Override
    public String getRankScoreKey() {
        return CENTRALITY;
    }

    @Override
    public void step() {
        computeBetweenness(getGraph());
    }

    class BetweennessData {
        double distance;
        double numSPs;
        List<V> predecessors;
        double dependency;

        BetweennessData() {
            distance = -1;
            numSPs = 0;
            predecessors = new ArrayList<V>();
            dependency = 0;
        }
    }
}