ONOS-745 Refactoring topology to compute only broadcast tree and not pre-compute paths.
ONOS-744 Refactoring graph search to allow requesting max number of paths.

Change-Id: I28467246b92df32ebb3155c45774ecc051fdd3dd
diff --git a/utils/misc/src/main/java/org/onlab/graph/AbstractGraphPathSearch.java b/utils/misc/src/main/java/org/onlab/graph/AbstractGraphPathSearch.java
index 6541ad3..9554be1 100644
--- a/utils/misc/src/main/java/org/onlab/graph/AbstractGraphPathSearch.java
+++ b/utils/misc/src/main/java/org/onlab/graph/AbstractGraphPathSearch.java
@@ -65,17 +65,31 @@
         protected final Set<Path<V, E>> paths = new HashSet<>();
         protected final Map<V, Double> costs = new HashMap<>();
         protected final Map<V, Set<E>> parents = new HashMap<>();
+        protected final int maxPaths;
 
         /**
-         * Creates the result of path search.
+         * Creates the result of a single-path search.
          *
          * @param src path source
          * @param dst optional path destination
          */
         public DefaultResult(V src, V dst) {
+            this(src, dst, 1);
+        }
+
+        /**
+         * Creates the result of path search.
+         *
+         * @param src      path source
+         * @param dst      optional path destination
+         * @param maxPaths optional limit of number of paths;
+         *                 {@link GraphPathSearch#ALL_PATHS} if no limit
+         */
+        public DefaultResult(V src, V dst, int maxPaths) {
             checkNotNull(src, "Source cannot be null");
             this.src = src;
             this.dst = dst;
+            this.maxPaths = maxPaths;
         }
 
         @Override
@@ -126,7 +140,8 @@
 
         /**
          * Updates the cost of the vertex using its existing cost plus the
-         * cost to traverse the specified edge.
+         * cost to traverse the specified edge. If the search is in single
+         * path mode, only one path will be accrued.
          *
          * @param vertex  vertex to update
          * @param edge    edge through which vertex is reached
@@ -147,7 +162,9 @@
                 if (replace) {
                     edges.clear();
                 }
-                edges.add(edge);
+                if (maxPaths == ALL_PATHS || edges.size() < maxPaths) {
+                    edges.add(edge);
+                }
             }
         }
 
@@ -203,7 +220,7 @@
             for (V v : destinations) {
                 // Ignore the source, if it is among the destinations.
                 if (!v.equals(src)) {
-                    buildAllPaths(this, src, v);
+                    buildAllPaths(this, src, v, maxPaths);
                 }
             }
         }
@@ -215,18 +232,21 @@
      * graph search result by applying breadth-first search through the parent
      * edges and vertex costs.
      *
-     * @param result graph search result
-     * @param src    source vertex
-     * @param dst    destination vertex
+     * @param result   graph search result
+     * @param src      source vertex
+     * @param dst      destination vertex
+     * @param maxPaths limit on the number of paths built;
+     *                 {@link GraphPathSearch#ALL_PATHS} if no limit
      */
-    private void buildAllPaths(DefaultResult result, V src, V dst) {
+    private void buildAllPaths(DefaultResult result, V src, V dst, int maxPaths) {
         DefaultMutablePath<V, E> basePath = new DefaultMutablePath<>();
         basePath.setCost(result.cost(dst));
 
         Set<DefaultMutablePath<V, E>> pendingPaths = new HashSet<>();
         pendingPaths.add(basePath);
 
-        while (!pendingPaths.isEmpty()) {
+        while (!pendingPaths.isEmpty() &&
+                (maxPaths == ALL_PATHS || result.paths.size() < maxPaths)) {
             Set<DefaultMutablePath<V, E>> frontier = new HashSet<>();
 
             for (DefaultMutablePath<V, E> path : pendingPaths) {
diff --git a/utils/misc/src/main/java/org/onlab/graph/BellmanFordGraphSearch.java b/utils/misc/src/main/java/org/onlab/graph/BellmanFordGraphSearch.java
index caf8019..39e39e8 100644
--- a/utils/misc/src/main/java/org/onlab/graph/BellmanFordGraphSearch.java
+++ b/utils/misc/src/main/java/org/onlab/graph/BellmanFordGraphSearch.java
@@ -24,11 +24,11 @@
 
     @Override
     public Result<V, E> search(Graph<V, E> graph, V src, V dst,
-                               EdgeWeight<V, E> weight) {
+                               EdgeWeight<V, E> weight, int maxPaths) {
         checkArguments(graph, src, dst);
 
         // Prepare the graph search result.
-        DefaultResult result = new DefaultResult(src, dst);
+        DefaultResult result = new DefaultResult(src, dst, maxPaths);
 
         // The source vertex has cost 0, of course.
         result.updateVertex(src, null, 0.0, true);
diff --git a/utils/misc/src/main/java/org/onlab/graph/BreadthFirstSearch.java b/utils/misc/src/main/java/org/onlab/graph/BreadthFirstSearch.java
index f5c60db..588b0fe 100644
--- a/utils/misc/src/main/java/org/onlab/graph/BreadthFirstSearch.java
+++ b/utils/misc/src/main/java/org/onlab/graph/BreadthFirstSearch.java
@@ -26,11 +26,11 @@
 
     @Override
     public Result<V, E> search(Graph<V, E> graph, V src, V dst,
-                               EdgeWeight<V, E> weight) {
+                               EdgeWeight<V, E> weight, int maxPaths) {
         checkArguments(graph, src, dst);
 
         // Prepare the graph result.
-        DefaultResult result = new DefaultResult(src, dst);
+        DefaultResult result = new DefaultResult(src, dst, maxPaths);
 
         // Setup the starting frontier with the source as the sole vertex.
         Set<V> frontier = new HashSet<>();
diff --git a/utils/misc/src/main/java/org/onlab/graph/DepthFirstSearch.java b/utils/misc/src/main/java/org/onlab/graph/DepthFirstSearch.java
index e61a9c1..f839fff 100644
--- a/utils/misc/src/main/java/org/onlab/graph/DepthFirstSearch.java
+++ b/utils/misc/src/main/java/org/onlab/graph/DepthFirstSearch.java
@@ -36,11 +36,11 @@
 
     @Override
     public SpanningTreeResult search(Graph<V, E> graph, V src, V dst,
-                                     EdgeWeight<V, E> weight) {
+                                     EdgeWeight<V, E> weight, int maxPaths) {
         checkArguments(graph, src, dst);
 
         // Prepare the search result.
-        SpanningTreeResult result = new SpanningTreeResult(src, dst);
+        SpanningTreeResult result = new SpanningTreeResult(src, dst, maxPaths);
 
         // The source vertex has cost 0, of course.
         result.updateVertex(src, null, 0.0, true);
@@ -141,11 +141,12 @@
         /**
          * Creates a new spanning tree result.
          *
-         * @param src search source
-         * @param dst optional search destination
+         * @param src      search source
+         * @param dst      optional search destination
+         * @param maxPaths limit on the number of paths
          */
-        public SpanningTreeResult(V src, V dst) {
-            super(src, dst);
+        public SpanningTreeResult(V src, V dst, int maxPaths) {
+            super(src, dst, maxPaths);
         }
 
         /**
diff --git a/utils/misc/src/main/java/org/onlab/graph/DijkstraGraphSearch.java b/utils/misc/src/main/java/org/onlab/graph/DijkstraGraphSearch.java
index eada84c..53d211a 100644
--- a/utils/misc/src/main/java/org/onlab/graph/DijkstraGraphSearch.java
+++ b/utils/misc/src/main/java/org/onlab/graph/DijkstraGraphSearch.java
@@ -28,12 +28,12 @@
 
     @Override
     public Result<V, E> search(Graph<V, E> graph, V src, V dst,
-                               EdgeWeight<V, E> weight) {
+                               EdgeWeight<V, E> weight, int maxPaths) {
         checkArguments(graph, src, dst);
 
         // Use the default result to remember cumulative costs and parent
         // edges to each each respective vertex.
-        DefaultResult result = new DefaultResult(src, dst);
+        DefaultResult result = new DefaultResult(src, dst, maxPaths);
 
         // Cost to reach the source vertex is 0 of course.
         result.updateVertex(src, null, 0.0, false);
diff --git a/utils/misc/src/main/java/org/onlab/graph/GraphPathSearch.java b/utils/misc/src/main/java/org/onlab/graph/GraphPathSearch.java
index b838421..f869a02 100644
--- a/utils/misc/src/main/java/org/onlab/graph/GraphPathSearch.java
+++ b/utils/misc/src/main/java/org/onlab/graph/GraphPathSearch.java
@@ -26,6 +26,8 @@
  */
 public interface GraphPathSearch<V extends Vertex, E extends Edge<V>> {
 
+    public static int ALL_PATHS = -1;
+
     /**
      * Abstraction of a path search result.
      */
@@ -68,16 +70,18 @@
     }
 
     /**
-     * Searches the specified graph.
+     * Searches the specified graph for paths between vertices.
      *
-     * @param graph  graph to be searched
-     * @param src    optional source vertex
-     * @param dst    optional destination vertex; if null paths to all vertex
-     *               destinations will be searched
-     * @param weight optional edge-weight; if null cost of each edge will be
-     *               assumed to be 1.0
+     * @param graph    graph to be searched
+     * @param src      optional source vertex
+     * @param dst      optional destination vertex; if null paths to all vertex
+     *                 destinations will be searched
+     * @param weight   optional edge-weight; if null cost of each edge will be
+     *                 assumed to be 1.0
+     * @param maxPaths limit on number of paths; {@link GraphPathSearch#ALL_PATHS} if no limit
      * @return search results
      */
-    Result<V, E> search(Graph<V, E> graph, V src, V dst, EdgeWeight<V, E> weight);
+    Result<V, E> search(Graph<V, E> graph, V src, V dst,
+                        EdgeWeight<V, E> weight, int maxPaths);
 
 }
diff --git a/utils/misc/src/main/java/org/onlab/graph/KshortestPathSearch.java b/utils/misc/src/main/java/org/onlab/graph/KshortestPathSearch.java
index 86f29ef..db8402d 100644
--- a/utils/misc/src/main/java/org/onlab/graph/KshortestPathSearch.java
+++ b/utils/misc/src/main/java/org/onlab/graph/KshortestPathSearch.java
@@ -23,6 +23,8 @@
 //import java.util.PriorityQueue;
 import java.util.Set;
 
+import static org.onlab.graph.GraphPathSearch.ALL_PATHS;
+
 /**
  * K-shortest-path graph search algorithm capable of finding not just one,
  * but K shortest paths with ascending order between the source and destinations.
@@ -137,7 +139,7 @@
     private List<E> searchShortestPath(Graph<V, E> graph, V src, V dst) {
         // Determine the shortest path from the source to the destination by using the Dijkstra algorithm.
         DijkstraGraphSearch dijkstraAlg = new DijkstraGraphSearch();
-        Set<Path> paths =  dijkstraAlg.search(graph, src, dst, weight).paths();
+        Set<Path> paths =  dijkstraAlg.search(graph, src, dst, weight, ALL_PATHS).paths();
         Iterator<Path> itr = paths.iterator();
         if (!itr.hasNext()) {
             return null;