All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgrapht.alg.scoring.ClosenessCentrality Maven / Gradle / Ivy

The newest version!
/*
 * (C) Copyright 2017-2023, 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.scoring;

import org.jgrapht.*;
import org.jgrapht.alg.interfaces.*;
import org.jgrapht.alg.interfaces.ShortestPathAlgorithm.*;
import org.jgrapht.alg.shortestpath.*;
import org.jgrapht.graph.*;

import java.util.*;

/**
 * Closeness centrality.
 * 
 * 

* Computes the closeness centrality of each vertex of a graph. The closeness of a vertex $x$ is * defined as the reciprocal of the farness, that is $H(x)= 1 / \sum_{y \neq x} d(x,y)$, where * $d(x,y)$ is the shortest path distance from $x$ to $y$. When normalization is used, the score is * multiplied by $n-1$ where $n$ is the total number of vertices in the graph. For more details see * wikipedia and *

    *
  • Alex Bavelas. Communication patterns in task-oriented groups. J. Acoust. Soc. Am, * 22(6):725–730, 1950.
  • *
* *

* This implementation computes by default the closeness centrality using outgoing paths and * normalizes the scores. This behavior can be adjusted by the constructor arguments. * *

* When the graph is disconnected, the closeness centrality score equals $0$ for all vertices. In * the case of weakly connected digraphs, the closeness centrality of several vertices might be 0. * See {@link HarmonicCentrality} for a different approach in case of disconnected graphs. * *

* Shortest paths are computed either by using Dijkstra's algorithm or Floyd-Warshall depending on * whether the graph has edges with negative edge weights. Thus, the running time is either $O(n (m * +n \log n))$ or $O(n^3)$ respectively, where $n$ is the number of vertices and $m$ the number of * edges of the graph. * * @param the graph vertex type * @param the graph edge type * * @author Dimitrios Michail */ public class ClosenessCentrality implements VertexScoringAlgorithm { /** * Underlying graph */ protected final Graph graph; /** * Whether to use incoming or outgoing paths */ protected final boolean incoming; /** * Whether to normalize scores */ protected final boolean normalize; /** * The actual scores */ protected Map scores; /** * Construct a new instance. By default the centrality is normalized and computed using outgoing * paths. * * @param graph the input graph */ public ClosenessCentrality(Graph graph) { this(graph, false, true); } /** * Construct a new instance. * * @param graph the input graph * @param incoming if true incoming paths are used, otherwise outgoing paths * @param normalize whether to normalize by multiplying the closeness by $n-1$, where $n$ is the * number of vertices of the graph */ public ClosenessCentrality(Graph graph, boolean incoming, boolean normalize) { this.graph = Objects.requireNonNull(graph, "Graph cannot be null"); this.incoming = incoming; this.normalize = normalize; this.scores = null; } /** * {@inheritDoc} */ @Override public Map getScores() { if (scores == null) { compute(); } return Collections.unmodifiableMap(scores); } /** * {@inheritDoc} */ @Override public Double getVertexScore(V v) { if (!graph.containsVertex(v)) { throw new IllegalArgumentException("Cannot return score of unknown vertex"); } if (scores == null) { compute(); } return scores.get(v); } /** * Get the shortest path algorithm for the paths computation. * * @return the shortest path algorithm */ protected ShortestPathAlgorithm getShortestPathAlgorithm() { // setup graph Graph g; if (incoming && graph.getType().isDirected()) { g = new EdgeReversedGraph<>(graph); } else { g = graph; } // test if we can use Dijkstra boolean noNegativeWeights = true; for (E e : g.edgeSet()) { double w = g.getEdgeWeight(e); if (w < 0.0) { noNegativeWeights = false; break; } } // initialize shortest path algorithm ShortestPathAlgorithm alg; if (noNegativeWeights) { alg = new DijkstraShortestPath<>(g); } else { alg = new FloydWarshallShortestPaths<>(g); } return alg; } /** * Compute the centrality index */ protected void compute() { // create result container this.scores = new HashMap<>(); // initialize shortest path algorithm ShortestPathAlgorithm alg = getShortestPathAlgorithm(); // compute shortest paths int n = graph.vertexSet().size(); for (V v : graph.vertexSet()) { double sum = 0d; SingleSourcePaths paths = alg.getPaths(v); for (V u : graph.vertexSet()) { if (!u.equals(v)) { sum += paths.getWeight(u); } } if (normalize) { this.scores.put(v, (n - 1) / sum); } else { this.scores.put(v, 1 / sum); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy