Initial opendaylight infrastructure commit!!
[controller.git] / third-party / net.sf.jung2 / src / main / java / edu / uci / ics / jung / algorithms / shortestpath / BFSDistanceLabeler.java
diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/BFSDistanceLabeler.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/BFSDistanceLabeler.java
new file mode 100644 (file)
index 0000000..38d3b00
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+* 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.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import edu.uci.ics.jung.graph.Hypergraph;
+
+/**
+ * Labels each node in the graph according to the BFS distance from the start node(s). If nodes are unreachable, then
+ * they are assigned a distance of -1.
+ * All nodes traversed at step k are marked as predecessors of their successors traversed at step k+1.
+ * <p>
+ * Running time is: O(m)
+ * @author Scott White
+ */
+public class BFSDistanceLabeler<V, E> {
+
+    private Map<V, Number> distanceDecorator = new HashMap<V,Number>();
+    private List<V> mCurrentList;
+    private Set<V> mUnvisitedVertices;
+    private List<V> mVerticesInOrderVisited;
+    private Map<V,HashSet<V>> mPredecessorMap;
+
+       /**
+        * Creates a new BFS labeler for the specified graph and root set
+        * The distances are stored in the corresponding Vertex objects and are of type MutableInteger
+        */
+       public BFSDistanceLabeler() {
+               mPredecessorMap = new HashMap<V,HashSet<V>>();
+       }
+
+    /**
+     * Returns the list of vertices visited in order of traversal
+     * @return the list of vertices
+     */
+    public List<V> getVerticesInOrderVisited() {
+        return mVerticesInOrderVisited;
+    }
+
+    /**
+     * Returns the set of all vertices that were not visited
+     * @return the list of unvisited vertices
+     */
+    public Set<V> getUnvisitedVertices() {
+        return mUnvisitedVertices;
+    }
+
+    /**
+     * Given a vertex, returns the shortest distance from any node in the root set to v
+     * @param v the vertex whose distance is to be retrieved
+     * @return the shortest distance from any node in the root set to v
+     */
+    public int getDistance(Hypergraph<V,E> g, V v) {
+        if (!g.getVertices().contains(v)) {
+            throw new IllegalArgumentException("Vertex is not contained in the graph.");
+        }
+
+        return distanceDecorator.get(v).intValue();
+    }
+
+    /**
+     * Returns set of predecessors of the given vertex
+     * @param v the vertex whose predecessors are to be retrieved
+     * @return the set of predecessors
+     */
+    public Set<V> getPredecessors(V v) {
+        return mPredecessorMap.get(v);
+    }
+
+    protected void initialize(Hypergraph<V,E> g, Set<V> rootSet) {
+        mVerticesInOrderVisited = new ArrayList<V>();
+        mUnvisitedVertices = new HashSet<V>();
+        for(V currentVertex : g.getVertices()) {
+            mUnvisitedVertices.add(currentVertex);
+            mPredecessorMap.put(currentVertex,new HashSet<V>());
+        }
+
+        mCurrentList = new ArrayList<V>();
+        for(V v : rootSet) {
+            distanceDecorator.put(v, new Integer(0));
+            mCurrentList.add(v);
+            mUnvisitedVertices.remove(v);
+            mVerticesInOrderVisited.add(v);
+        }
+    }
+
+    private void addPredecessor(V predecessor,V sucessor) {
+        HashSet<V> predecessors = mPredecessorMap.get(sucessor);
+        predecessors.add(predecessor);
+    }
+
+    /**
+     * Computes the distances of all the node from the starting root nodes. If there is more than one root node
+     * the minimum distance from each root node is used as the designated distance to a given node. Also keeps track
+     * of the predecessors of each node traversed as well as the order of nodes traversed.
+     * @param graph the graph to label
+     * @param rootSet the set of starting vertices to traverse from
+     */
+    public void labelDistances(Hypergraph<V,E> graph, Set<V> rootSet) {
+
+        initialize(graph,rootSet);
+
+        int distance = 1;
+        while (true) {
+            List<V> newList = new ArrayList<V>();
+            for(V currentVertex : mCurrentList) {
+               if(graph.containsVertex(currentVertex)) {
+                       for(V next : graph.getSuccessors(currentVertex)) {
+                               visitNewVertex(currentVertex,next, distance, newList);
+                       }
+               }
+            }
+            if (newList.size() == 0) break;
+            mCurrentList = newList;
+            distance++;
+        }
+
+        for(V v : mUnvisitedVertices) {
+            distanceDecorator.put(v,new Integer(-1));
+        }
+    }
+
+    /**
+     * Computes the distances of all the node from the specified root node. Also keeps track
+     * of the predecessors of each node traversed as well as the order of nodes traversed.
+     *  @param graph the graph to label
+     * @param root the single starting vertex to traverse from
+     */
+    public void labelDistances(Hypergraph<V,E> graph, V root) {
+        labelDistances(graph, Collections.singleton(root));
+    }
+
+    private void visitNewVertex(V predecessor, V neighbor, int distance, List<V> newList) {
+        if (mUnvisitedVertices.contains(neighbor)) {
+            distanceDecorator.put(neighbor, new Integer(distance));
+            newList.add(neighbor);
+            mVerticesInOrderVisited.add(neighbor);
+            mUnvisitedVertices.remove(neighbor);
+        }
+        int predecessorDistance = distanceDecorator.get(predecessor).intValue();
+        int successorDistance = distanceDecorator.get(neighbor).intValue();
+        if (predecessorDistance < successorDistance) {
+            addPredecessor(predecessor,neighbor);
+        }
+    }
+
+    /**
+     * Returns a map from vertices to minimum distances from the original source(s).
+     * Must be called after {@code labelDistances} in order to contain valid data.
+     */
+    public Map<V, Number> getDistanceDecorator() {
+        return distanceDecorator;
+    }
+}