View Javadoc
1   /*
2   * Copyright (c) 2003, The JUNG Authors 
3   *
4   * All rights reserved.
5   *
6   * This software is open-source under the BSD license; see either
7   * "license.txt" or
8   * https://github.com/jrtom/jung/blob/master/LICENSE for a description.
9   */
10  package edu.uci.ics.jung.algorithms.shortestpath;
11  import java.util.Collection;
12  
13  import com.google.common.base.Function;
14  
15  import edu.uci.ics.jung.algorithms.scoring.ClosenessCentrality;
16  import edu.uci.ics.jung.algorithms.scoring.util.VertexScoreTransformer;
17  import edu.uci.ics.jung.graph.Hypergraph;
18  
19  /**
20   * Statistics relating to vertex-vertex distances in a graph.
21   * 
22   * <p>Formerly known as <code>GraphStatistics</code> in JUNG 1.x.
23   * 
24   * @author Scott White
25   * @author Joshua O'Madadhain
26   */
27  public class DistanceStatistics 
28  {
29  	/**
30       * For each vertex <code>v</code> in <code>graph</code>, 
31       * calculates the average shortest path length from <code>v</code> 
32       * to all other vertices in <code>graph</code> using the metric 
33       * specified by <code>d</code>, and returns the results in a
34       * <code>Map</code> from vertices to <code>Double</code> values.
35       * If there exists an ordered pair <code>&lt;u,v&gt;</code>
36       * for which <code>d.getDistance(u,v)</code> returns <code>null</code>,
37       * then the average distance value for <code>u</code> will be stored
38       * as <code>Double.POSITIVE_INFINITY</code>).
39       * 
40       * <p>Does not include self-distances (path lengths from <code>v</code>
41       * to <code>v</code>).
42       * 
43       * <p>To calculate the average distances, ignoring edge weights if any:
44       * <pre>
45       * Map distances = DistanceStatistics.averageDistances(g, new UnweightedShortestPath(g));
46       * </pre>
47       * To calculate the average distances respecting edge weights:
48       * <pre>
49       * DijkstraShortestPath dsp = new DijkstraShortestPath(g, nev);
50       * Map distances = DistanceStatistics.averageDistances(g, dsp);
51       * </pre>
52       * where <code>nev</code> is an instance of <code>Transformer</code> that
53       * is used to fetch the weight for each edge.
54       * 
55       * @see edu.uci.ics.jung.algorithms.shortestpath.UnweightedShortestPath
56       * @see edu.uci.ics.jung.algorithms.shortestpath.DijkstraDistance
57  	 * 
58  	 * @param graph the graph for which distances are to be calculated
59  	 * @param d the distance metric to use for the calculation
60  	 * @param <V> the vertex type
61  	 * @param <E> the edge type
62  	 * @return a map from each vertex to the mean distance to each other (reachable) vertex
63  	 */
64      public static <V,E> Function<V,Double> averageDistances(Hypergraph<V,E> graph, Distance<V> d)
65      {
66      	final ClosenessCentrality<V,E> cc = new ClosenessCentrality<V,E>(graph, d);
67      	return new VertexScoreTransformer<V, Double>(cc);
68      }
69      
70      /**
71       * For each vertex <code>v</code> in <code>g</code>, 
72       * calculates the average shortest path length from <code>v</code> 
73       * to all other vertices in <code>g</code>, ignoring edge weights.
74       * @see #diameter(Hypergraph)
75       * @see edu.uci.ics.jung.algorithms.scoring.ClosenessCentrality
76       *
77       * @param g the graph for which distances are to be calculated
78  	 * @param <V> the vertex type
79  	 * @param <E> the edge type
80  	 * @return a map from each vertex to the mean distance to each other (reachable) vertex
81       */
82      public static <V,E> Function<V, Double> averageDistances(Hypergraph<V,E> g)
83      {
84      	final ClosenessCentrality<V,E> cc = new ClosenessCentrality<V,E>(g, 
85      			new UnweightedShortestPath<V,E>(g));
86          return new VertexScoreTransformer<V, Double>(cc);
87      }
88      
89      /**
90       * Returns the diameter of <code>g</code> using the metric 
91       * specified by <code>d</code>.  The diameter is defined to be
92       * the maximum, over all pairs of vertices <code>u,v</code>,
93       * of the length of the shortest path from <code>u</code> to 
94       * <code>v</code>.  If the graph is disconnected (that is, not 
95       * all pairs of vertices are reachable from one another), the
96       * value returned will depend on <code>use_max</code>:  
97       * if <code>use_max == true</code>, the value returned
98       * will be the the maximum shortest path length over all pairs of <b>connected</b> 
99       * vertices; otherwise it will be <code>Double.POSITIVE_INFINITY</code>.
100      * 
101 	 * @param g the graph for which distances are to be calculated
102 	 * @param d the distance metric to use for the calculation
103 	 * @param use_max if {@code true}, return the maximum shortest path length for all graphs;
104 	 *     otherwise, return {@code Double.POSITIVE_INFINITY} for disconnected graphs
105 	 * @param <V> the vertex type
106 	 * @param <E> the edge type
107 	 * @return the longest distance from any vertex to any other
108      */
109     public static <V, E> double diameter(Hypergraph<V,E> g, Distance<V> d, boolean use_max)
110     {
111         double diameter = 0;
112         Collection<V> vertices = g.getVertices();
113         for(V v : vertices) {
114             for(V w : vertices) {
115 
116                 if (v.equals(w) == false) // don't include self-distances
117                 {
118                     Number dist = d.getDistance(v, w);
119                     if (dist == null)
120                     {
121                         if (!use_max)
122                             return Double.POSITIVE_INFINITY;
123                     }
124                     else
125                         diameter = Math.max(diameter, dist.doubleValue());
126                 }
127             }
128         }
129         return diameter;
130     }
131     
132     /**
133      * Returns the diameter of <code>g</code> using the metric 
134      * specified by <code>d</code>.  The diameter is defined to be
135      * the maximum, over all pairs of vertices <code>u,v</code>,
136      * of the length of the shortest path from <code>u</code> to 
137      * <code>v</code>, or <code>Double.POSITIVE_INFINITY</code>
138      * if any of these distances do not exist.
139      * @see #diameter(Hypergraph, Distance, boolean)
140      * 
141 	 * @param g the graph for which distances are to be calculated
142 	 * @param d the distance metric to use for the calculation
143 	 * @param <V> the vertex type
144 	 * @param <E> the edge type
145 	 * @return the longest distance from any vertex to any other
146      */
147     public static <V, E> double diameter(Hypergraph<V,E> g, Distance<V> d)
148     {
149         return diameter(g, d, false);
150     }
151     
152     /**
153      * Returns the diameter of <code>g</code>, ignoring edge weights.
154      * @see #diameter(Hypergraph, Distance, boolean)
155      * 
156 	 * @param g the graph for which distances are to be calculated
157 	 * @param <V> the vertex type
158 	 * @param <E> the edge type
159 	 * @return the longest distance from any vertex to any other
160      */
161     public static <V, E> double diameter(Hypergraph<V,E> g)
162     {
163         return diameter(g, new UnweightedShortestPath<V,E>(g));
164     }
165 }