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  
12  import java.util.HashMap;
13  import java.util.Map;
14  
15  import edu.uci.ics.jung.graph.Hypergraph;
16  
17  /**
18   * Computes the shortest path distances for graphs whose edges are not weighted (using BFS).
19   * 
20   * @author Scott White
21   */
22  public class UnweightedShortestPath<V, E> 
23      implements ShortestPath<V,E>, Distance<V>
24  {
25  	private Map<V,Map<V,Number>> mDistanceMap;
26  	private Map<V,Map<V,E>> mIncomingEdgeMap;
27  	private Hypergraph<V,E> mGraph;
28      private Map<V, Number> distances = new HashMap<V,Number>();
29  
30  	/**
31  	 * Constructs and initializes algorithm
32  	 * @param g the graph
33  	 */
34  	public UnweightedShortestPath(Hypergraph<V,E> g)
35  	{
36  		mDistanceMap = new HashMap<V,Map<V,Number>>();
37  		mIncomingEdgeMap = new HashMap<V,Map<V,E>>();
38  		mGraph = g;
39  	}
40  
41      /**
42       * @see edu.uci.ics.jung.algorithms.shortestpath.Distance#getDistance(Object, Object)
43       */
44  	public Number getDistance(V source, V target)
45  	{
46  		Map<V, Number> sourceSPMap = getDistanceMap(source);
47  		return sourceSPMap.get(target);
48  	}
49  
50      /**
51       * @see edu.uci.ics.jung.algorithms.shortestpath.Distance#getDistanceMap(Object)
52       */
53  	public Map<V,Number> getDistanceMap(V source)
54  	{
55  		Map<V,Number> sourceSPMap = mDistanceMap.get(source);
56  		if (sourceSPMap == null)
57  		{
58  			computeShortestPathsFromSource(source);
59  			sourceSPMap = mDistanceMap.get(source);
60  		}
61  		return sourceSPMap;
62  	}
63  
64  	/**
65  	 * @see edu.uci.ics.jung.algorithms.shortestpath.ShortestPath#getIncomingEdgeMap(Object)
66  	 */
67  	public Map<V,E> getIncomingEdgeMap(V source)
68  	{
69  		Map<V,E> sourceIEMap = mIncomingEdgeMap.get(source);
70  		if (sourceIEMap == null)
71  		{
72  			computeShortestPathsFromSource(source);
73  			sourceIEMap = mIncomingEdgeMap.get(source);
74  		}
75  		return sourceIEMap;
76  	}
77  
78  
79  	/**
80  	 * Computes the shortest path distances from a given node to all other nodes.
81  	 * @param source the source node
82  	 */
83  	private void computeShortestPathsFromSource(V source)
84  	{
85  		BFSDistanceLabeler<V,E> labeler = new BFSDistanceLabeler<V,E>();
86  		labeler.labelDistances(mGraph, source);
87          distances = labeler.getDistanceDecorator();
88  		Map<V,Number> currentSourceSPMap = new HashMap<V,Number>();
89  		Map<V,E> currentSourceEdgeMap = new HashMap<V,E>();
90  
91          for(V vertex : mGraph.getVertices()) {
92              
93  			Number distanceVal = distances.get(vertex);
94              // BFSDistanceLabeler uses -1 to indicate unreachable vertices;
95              // don't bother to store unreachable vertices
96              if (distanceVal != null && distanceVal.intValue() >= 0) 
97              {
98                  currentSourceSPMap.put(vertex, distanceVal);
99                  int minDistance = distanceVal.intValue();
100                 for(E incomingEdge : mGraph.getInEdges(vertex)) 
101                 {
102                 	for (V neighbor : mGraph.getIncidentVertices(incomingEdge))
103                 	{
104                 		if (neighbor.equals(vertex))
105                 			continue;
106 	
107 	                    Number predDistanceVal = distances.get(neighbor);
108 	
109 	                    int pred_distance = predDistanceVal.intValue();
110 	                    if (pred_distance < minDistance && pred_distance >= 0)
111 	                    {
112 	                        minDistance = predDistanceVal.intValue();
113 	                        currentSourceEdgeMap.put(vertex, incomingEdge);
114 	                    }
115                 	}
116                 }
117             }
118 		}
119 		mDistanceMap.put(source, currentSourceSPMap);
120 		mIncomingEdgeMap.put(source, currentSourceEdgeMap);
121 	}
122     
123     /**
124      * Clears all stored distances for this instance.  
125      * Should be called whenever the graph is modified (edge weights 
126      * changed or edges added/removed).  If the user knows that
127      * some currently calculated distances are unaffected by a
128      * change, <code>reset(V)</code> may be appropriate instead.
129      * 
130      * @see #reset(Object)
131      */
132     public void reset()
133     {
134         mDistanceMap.clear();
135         mIncomingEdgeMap.clear();
136     }
137     
138     /**
139      * Clears all stored distances for the specified source vertex 
140      * <code>source</code>.  Should be called whenever the stored distances
141      * from this vertex are invalidated by changes to the graph.
142      * 
143      * @see #reset()
144      * 
145      * @param v the vertex for which distances should be cleared
146      */
147     public void reset(V v)
148     {
149         mDistanceMap.remove(v);
150         mIncomingEdgeMap.remove(v);
151     }
152 }