/*
* 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.shortestpath;
import java.util.Collection;
import org.apache.commons.collections15.Transformer;
import edu.uci.ics.jung.algorithms.scoring.ClosenessCentrality;
import edu.uci.ics.jung.algorithms.scoring.util.VertexScoreTransformer;
import edu.uci.ics.jung.graph.Hypergraph;
/**
* Statistics relating to vertex-vertex distances in a graph.
*
* <p>Formerly known as <code>GraphStatistics</code> in JUNG 1.x.</p>
*
* @author Scott White
* @author Joshua O'Madadhain
*/
public class DistanceStatistics
{
/**
* For each vertex <code>v</code> in <code>graph</code>,
* calculates the average shortest path length from <code>v</code>
* to all other vertices in <code>graph</code> using the metric
* specified by <code>d</code>, and returns the results in a
* <code>Map</code> from vertices to <code>Double</code> values.
* If there exists an ordered pair <code><u,v></code>
* for which <code>d.getDistance(u,v)</code> returns <code>null</code>,
* then the average distance value for <code>u</code> will be stored
* as <code>Double.POSITIVE_INFINITY</code>).
*
* <p>Does not include self-distances (path lengths from <code>v</code>
* to <code>v</code>).
*
* <p>To calculate the average distances, ignoring edge weights if any:
* <pre>
* Map distances = DistanceStatistics.averageDistances(g, new UnweightedShortestPath(g));
* </pre>
* To calculate the average distances respecting edge weights:
* <pre>
* DijkstraShortestPath dsp = new DijkstraShortestPath(g, nev);
* Map distances = DistanceStatistics.averageDistances(g, dsp);
* </pre>
* where <code>nev</code> is an instance of <code>Transformer</code> that
* is used to fetch the weight for each edge.
*
* @see edu.uci.ics.jung.algorithms.shortestpath.UnweightedShortestPath
* @see edu.uci.ics.jung.algorithms.shortestpath.DijkstraDistance
*/
public static <V,E> Transformer<V,Double> averageDistances(Hypergraph<V,E> graph, Distance<V> d)
{
final ClosenessCentrality<V,E> cc = new ClosenessCentrality<V,E>(graph, d);
return new VertexScoreTransformer<V, Double>(cc);
}
/**
* For each vertex <code>v</code> in <code>g</code>,
* calculates the average shortest path length from <code>v</code>
* to all other vertices in <code>g</code>, ignoring edge weights.
* @see #diameter(Hypergraph)
* @see edu.uci.ics.jung.algorithms.scoring.ClosenessCentrality
*/
public static <V,E> Transformer<V, Double> averageDistances(Hypergraph<V,E> g)
{
final ClosenessCentrality<V,E> cc = new ClosenessCentrality<V,E>(g,
new UnweightedShortestPath<V,E>(g));
return new VertexScoreTransformer<V, Double>(cc);
}
/**
* Returns the diameter of <code>g</code> using the metric
* specified by <code>d</code>. The diameter is defined to be
* the maximum, over all pairs of vertices <code>u,v</code>,
* of the length of the shortest path from <code>u</code> to
* <code>v</code>. If the graph is disconnected (that is, not
* all pairs of vertices are reachable from one another), the
* value returned will depend on <code>use_max</code>:
* if <code>use_max == true</code>, the value returned
* will be the the maximum shortest path length over all pairs of <b>connected</b>
* vertices; otherwise it will be <code>Double.POSITIVE_INFINITY</code>.
*/
public static <V, E> double diameter(Hypergraph<V,E> g, Distance<V> d, boolean use_max)
{
double diameter = 0;
Collection<V> vertices = g.getVertices();
for(V v : vertices) {
for(V w : vertices) {
if (v.equals(w) == false) // don't include self-distances
{
Number dist = d.getDistance(v, w);
if (dist == null)
{
if (!use_max)
return Double.POSITIVE_INFINITY;
}
else
diameter = Math.max(diameter, dist.doubleValue());
}
}
}
return diameter;
}
/**
* Returns the diameter of <code>g</code> using the metric
* specified by <code>d</code>. The diameter is defined to be
* the maximum, over all pairs of vertices <code>u,v</code>,
* of the length of the shortest path from <code>u</code> to
* <code>v</code>, or <code>Double.POSITIVE_INFINITY</code>
* if any of these distances do not exist.
* @see #diameter(Hypergraph, Distance, boolean)
*/
public static <V, E> double diameter(Hypergraph<V,E> g, Distance<V> d)
{
return diameter(g, d, false);
}
/**
* Returns the diameter of <code>g</code>, ignoring edge weights.
* @see #diameter(Hypergraph, Distance, boolean)
*/
public static <V, E> double diameter(Hypergraph<V,E> g)
{
return diameter(g, new UnweightedShortestPath<V,E>(g));
}
}