K-shorest path algorithm to support UC1, it can be used by other modules as well.
Change-Id: I736ec55c6211a505d6cf43ab22e1197fdb86ecf3
Showing
3 changed files
with
636 additions
and
0 deletions
| 1 | +/* | ||
| 2 | + * Licensed to the Apache Software Foundation (ASF) under one | ||
| 3 | + * or more contributor license agreements. See the NOTICE file | ||
| 4 | + * distributed with this work for additional information | ||
| 5 | + * regarding copyright ownership. The ASF licenses this file | ||
| 6 | + * to you under the Apache License, Version 2.0 (the | ||
| 7 | + * "License"); you may not use this file except in compliance | ||
| 8 | + * with the License. You may obtain a copy of the License at | ||
| 9 | + * | ||
| 10 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 11 | + * | ||
| 12 | + * Unless required by applicable law or agreed to in writing, | ||
| 13 | + * software distributed under the License is distributed on an | ||
| 14 | + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| 15 | + * KIND, either express or implied. See the License for the | ||
| 16 | + * specific language governing permissions and limitations | ||
| 17 | + * under the License. | ||
| 18 | + */ | ||
| 19 | +package org.onlab.graph; | ||
| 20 | + | ||
| 21 | +import java.util.ArrayList; | ||
| 22 | +//import java.util.HashMap; | ||
| 23 | +import java.util.Iterator; | ||
| 24 | +import java.util.List; | ||
| 25 | +//import java.util.Map; | ||
| 26 | +//import java.util.PriorityQueue; | ||
| 27 | +import java.util.Set; | ||
| 28 | + | ||
| 29 | +//import org.apache.commons.lang3.tuple.Pair; | ||
| 30 | +//import org.onlab.graph.AbstractGraphPathSearch.DefaultResult; | ||
| 31 | + | ||
| 32 | +/** | ||
| 33 | + * K-shortest-path graph search algorithm capable of finding not just one, | ||
| 34 | + * but K shortest paths with descending order between the source and destinations. | ||
| 35 | + */ | ||
| 36 | + | ||
| 37 | +public class KshortestPathSearch<V extends Vertex, E extends Edge<V>> { | ||
| 38 | + | ||
| 39 | + // Define class variables. | ||
| 40 | + private Graph<V, E> immutableGraph; | ||
| 41 | + private MutableGraph<V, E> mutableGraph; | ||
| 42 | + private List<List<E>> pathResults = new ArrayList<List<E>>(); | ||
| 43 | + private List<List<E>> pathCandidates = new ArrayList<List<E>>(); | ||
| 44 | + private V source; | ||
| 45 | + private V sink; | ||
| 46 | + private int numK = 0; | ||
| 47 | + private EdgeWeight<V, E> weight = null; | ||
| 48 | + // private PriorityQueue<List<E>> pathCandidates = new PriorityQueue<List<E>>(); | ||
| 49 | + | ||
| 50 | + // Initialize the graph. | ||
| 51 | + public KshortestPathSearch(Graph<V, E> graph) { | ||
| 52 | + immutableGraph = graph; | ||
| 53 | + mutableGraph = new MutableAdjacencyListsGraph(graph.getVertexes(), | ||
| 54 | + graph.getEdges()); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + public List<List<E>> search(V src, | ||
| 58 | + V dst, | ||
| 59 | + EdgeWeight<V, E> wei, | ||
| 60 | + int k) { | ||
| 61 | + | ||
| 62 | + weight = wei; | ||
| 63 | + source = src; | ||
| 64 | + sink = dst; | ||
| 65 | + numK = k; | ||
| 66 | + // pathCandidates = new PriorityQueue<List<E>>(); | ||
| 67 | + | ||
| 68 | + pathResults.clear(); | ||
| 69 | + pathCandidates.clear(); | ||
| 70 | + | ||
| 71 | + // Double check the parameters | ||
| 72 | + checkArguments(immutableGraph, src, dst, numK); | ||
| 73 | + | ||
| 74 | + // DefaultResult result = new DefaultResult(src, dst); | ||
| 75 | + | ||
| 76 | + searchKShortestPaths(); | ||
| 77 | + | ||
| 78 | + return pathResults; | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + private void checkArguments(Graph<V, E> graph, V src, V dst, int k) { | ||
| 82 | + if (graph == null) { | ||
| 83 | + throw new NullPointerException("graph is null"); | ||
| 84 | + } | ||
| 85 | + if (!graph.getVertexes().contains(src)) { | ||
| 86 | + throw new NullPointerException("source node does not exist"); | ||
| 87 | + } | ||
| 88 | + if (!graph.getVertexes().contains(dst)) { | ||
| 89 | + throw new NullPointerException("target node does not exist"); | ||
| 90 | + } | ||
| 91 | + if (k <= 0) { | ||
| 92 | + throw new NullPointerException("K is negative or 0"); | ||
| 93 | + } | ||
| 94 | + if (weight == null) { | ||
| 95 | + throw new NullPointerException("the cost matrix is null"); | ||
| 96 | + } | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + private void searchKShortestPaths() { | ||
| 100 | + // Step 1: find the shortest path. | ||
| 101 | + List<E> shortestPath = searchShortestPath(immutableGraph, source, sink); | ||
| 102 | + // no path exists, exit. | ||
| 103 | + if (shortestPath == null) { | ||
| 104 | + return; | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + // Step 2: update the results. | ||
| 108 | + pathResults.add(shortestPath); | ||
| 109 | + // pathCandidates.add(shortestPath); | ||
| 110 | + | ||
| 111 | + // Step 3: find the other K-1 paths. | ||
| 112 | + while (/*pathCandidates.size() > 0 &&*/pathResults.size() < numK) { | ||
| 113 | + // 3.1 the spur node ranges from the first node to the last node in the previous k-shortest path. | ||
| 114 | + List<E> lastPath = pathResults.get(pathResults.size() - 1); | ||
| 115 | + for (int i = 0; i < lastPath.size(); i++) { | ||
| 116 | + // 4.1 convert the graph into mutable. | ||
| 117 | + convertGraph(); | ||
| 118 | + // 4.2 transform the graph. | ||
| 119 | + List<E> rootPath = createSpurNode(lastPath, i); | ||
| 120 | + transformGraph(rootPath); | ||
| 121 | + // 4.3 find the deviation node. | ||
| 122 | + V devNode; | ||
| 123 | + devNode = getDevNode(rootPath); | ||
| 124 | + List<E> spurPath; | ||
| 125 | + // 4.4 find the shortest path in the transformed graph. | ||
| 126 | + spurPath = searchShortestPath(mutableGraph, devNode, sink); | ||
| 127 | + // 4.5 update the path candidates. | ||
| 128 | + if (spurPath != null) { | ||
| 129 | + // totalPath = rootPath + spurPath; | ||
| 130 | + rootPath.addAll(spurPath); | ||
| 131 | + pathCandidates.add(rootPath); | ||
| 132 | + } | ||
| 133 | + } | ||
| 134 | + // 3.2 if there is no spur path, exit. | ||
| 135 | + if (pathCandidates.size() == 0) { | ||
| 136 | + break; | ||
| 137 | + } | ||
| 138 | + // 3.3 add the path into the results. | ||
| 139 | + addPathResult(); | ||
| 140 | + } | ||
| 141 | + } | ||
| 142 | + | ||
| 143 | + private List<E> searchShortestPath(Graph<V, E> graph, V src, V dst) { | ||
| 144 | + // Determine the shortest path from the source to the destination by using the Dijkstra algorithm. | ||
| 145 | + DijkstraGraphSearch dijkstraAlg = new DijkstraGraphSearch(); | ||
| 146 | + Set<Path> paths = dijkstraAlg.search(graph, src, dst, weight).paths(); | ||
| 147 | + Iterator<Path> itr = paths.iterator(); | ||
| 148 | + if (!itr.hasNext()) { | ||
| 149 | + return null; | ||
| 150 | + } | ||
| 151 | + // return the first shortest path only. | ||
| 152 | + return (List<E>) itr.next().edges(); | ||
| 153 | + } | ||
| 154 | + | ||
| 155 | + private void convertGraph() { | ||
| 156 | + // clear the mutableGraph first | ||
| 157 | + if (mutableGraph != null) { | ||
| 158 | + ((MutableAdjacencyListsGraph) mutableGraph).clear(); | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + // create a immutableGraph | ||
| 162 | + Set<E> copyEa = immutableGraph.getEdges(); | ||
| 163 | + Set<V> copyVa = immutableGraph.getVertexes(); | ||
| 164 | + for (V vertex : copyVa) { | ||
| 165 | + mutableGraph.addVertex(vertex); | ||
| 166 | + } | ||
| 167 | + for (E edge : copyEa) { | ||
| 168 | + mutableGraph.addEdge(edge); | ||
| 169 | + } | ||
| 170 | + } | ||
| 171 | + | ||
| 172 | + private V getDevNode(List<E> path) { | ||
| 173 | + V srcA; | ||
| 174 | + V dstB; | ||
| 175 | + | ||
| 176 | + if (path.size() == 0) { | ||
| 177 | + return source; | ||
| 178 | + } | ||
| 179 | + | ||
| 180 | + E temp1 = path.get(path.size() - 1); | ||
| 181 | + srcA = temp1.src(); | ||
| 182 | + dstB = temp1.dst(); | ||
| 183 | + | ||
| 184 | + if (path.size() == 1) { | ||
| 185 | + if (srcA.equals(source)) { | ||
| 186 | + return dstB; | ||
| 187 | + } else { | ||
| 188 | + return srcA; | ||
| 189 | + } | ||
| 190 | + } else { | ||
| 191 | + E temp2 = path.get(path.size() - 2); | ||
| 192 | + if (srcA.equals(temp2.src()) || srcA.equals(temp2.dst())) { | ||
| 193 | + return dstB; | ||
| 194 | + } else { | ||
| 195 | + return srcA; | ||
| 196 | + } | ||
| 197 | + } | ||
| 198 | + } | ||
| 199 | + | ||
| 200 | + private List<E> createSpurNode(List<E> path, int n) { | ||
| 201 | + List<E> root = new ArrayList<E>(); | ||
| 202 | + | ||
| 203 | + for (int i = 0; i < n; i++) { | ||
| 204 | + root.add(path.get(i)); | ||
| 205 | + } | ||
| 206 | + return root; | ||
| 207 | + } | ||
| 208 | + | ||
| 209 | + private void transformGraph(List<E> rootPath) { | ||
| 210 | + List<E> prePath; | ||
| 211 | + //remove edges | ||
| 212 | + for (int i = 0; i < pathResults.size(); i++) { | ||
| 213 | + prePath = pathResults.get(i); | ||
| 214 | + if (prePath.size() == 1) { | ||
| 215 | + mutableGraph.removeEdge(prePath.get(0)); | ||
| 216 | + } else if (comparePath(rootPath, prePath)) { | ||
| 217 | + for (int j = 0; j <= rootPath.size(); j++) { | ||
| 218 | + mutableGraph.removeEdge(prePath.get(j)); | ||
| 219 | + } | ||
| 220 | + } | ||
| 221 | + } | ||
| 222 | + for (int i = 0; i < pathCandidates.size(); i++) { | ||
| 223 | + prePath = pathCandidates.get(i); | ||
| 224 | + if (prePath.size() == 1) { | ||
| 225 | + mutableGraph.removeEdge(prePath.get(0)); | ||
| 226 | + } else if (comparePath(rootPath, prePath)) { | ||
| 227 | + for (int j = 0; j <= rootPath.size(); j++) { | ||
| 228 | + mutableGraph.removeEdge(prePath.get(j)); | ||
| 229 | + } | ||
| 230 | + } | ||
| 231 | + } | ||
| 232 | + | ||
| 233 | + if (rootPath.size() == 0) { | ||
| 234 | + return; | ||
| 235 | + } | ||
| 236 | + | ||
| 237 | + //remove nodes | ||
| 238 | + List<V> nodes = new ArrayList<V>(); | ||
| 239 | + nodes.add(source); | ||
| 240 | + V pre = source; | ||
| 241 | + V srcA; | ||
| 242 | + V dstB; | ||
| 243 | + for (int i = 0; i < rootPath.size() - 1; i++) { | ||
| 244 | + E temp = rootPath.get(i); | ||
| 245 | + srcA = temp.src(); | ||
| 246 | + dstB = temp.dst(); | ||
| 247 | + | ||
| 248 | + if (srcA.equals(pre)) { | ||
| 249 | + nodes.add(dstB); | ||
| 250 | + pre = dstB; | ||
| 251 | + } else { | ||
| 252 | + nodes.add(srcA); | ||
| 253 | + pre = srcA; | ||
| 254 | + } | ||
| 255 | + } | ||
| 256 | + for (int i = 0; i < nodes.size(); i++) { | ||
| 257 | + mutableGraph.removeVertex(nodes.get(i)); | ||
| 258 | + } | ||
| 259 | + } | ||
| 260 | + | ||
| 261 | + private boolean comparePath(List<E> path1, List<E> path2) { | ||
| 262 | + if (path1.size() > path2.size()) { | ||
| 263 | + return false; | ||
| 264 | + } | ||
| 265 | + if (path1.size() == 0) { | ||
| 266 | + return true; | ||
| 267 | + } | ||
| 268 | + for (int i = 0; i < path1.size(); i++) { | ||
| 269 | + if (path1.get(i) != path2.get(i)) { | ||
| 270 | + return false; | ||
| 271 | + } | ||
| 272 | + } | ||
| 273 | + return true; | ||
| 274 | + } | ||
| 275 | + | ||
| 276 | + private void addPathResult() { | ||
| 277 | + List<E> sp; | ||
| 278 | + sp = pathCandidates.get(0); | ||
| 279 | + for (int i = 1; i < pathCandidates.size(); i++) { | ||
| 280 | + if (sp.size() > pathCandidates.get(i).size()) { | ||
| 281 | + sp = pathCandidates.get(i); | ||
| 282 | + } | ||
| 283 | + } | ||
| 284 | + pathResults.add(sp); | ||
| 285 | + // Log.info(sp.toString()); | ||
| 286 | + pathCandidates.remove(sp); | ||
| 287 | + } | ||
| 288 | + | ||
| 289 | +} |
| 1 | +package org.onlab.graph; | ||
| 2 | + | ||
| 3 | +import static com.google.common.base.MoreObjects.toStringHelper; | ||
| 4 | + | ||
| 5 | +import java.util.HashSet; | ||
| 6 | +import java.util.Objects; | ||
| 7 | +import java.util.Set; | ||
| 8 | + | ||
| 9 | +import com.google.common.collect.HashMultimap; | ||
| 10 | +import com.google.common.collect.SetMultimap; | ||
| 11 | + | ||
| 12 | +public class MutableAdjacencyListsGraph<V extends Vertex, E extends Edge<V>> | ||
| 13 | +implements MutableGraph<V, E> { | ||
| 14 | + private Set<V> vertexes = new HashSet<V>(); | ||
| 15 | + private Set<E> edges = new HashSet<E>(); | ||
| 16 | + | ||
| 17 | + private SetMultimap<V, E> sources = HashMultimap.create(); | ||
| 18 | + private SetMultimap<V, E> destinations = HashMultimap.create(); | ||
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * Creates a graph comprising of the specified vertexes and edges. | ||
| 22 | + * | ||
| 23 | + * @param vertexes set of graph vertexes | ||
| 24 | + * @param edges set of graph edges | ||
| 25 | + */ | ||
| 26 | + public MutableAdjacencyListsGraph(Set<V> vertex, Set<E> edge) { | ||
| 27 | + vertexes.addAll(vertex); | ||
| 28 | + edges.addAll(edge); | ||
| 29 | + for (E e : edge) { | ||
| 30 | + sources.put(e.src(), e); | ||
| 31 | + vertexes.add(e.src()); | ||
| 32 | + destinations.put(e.dst(), e); | ||
| 33 | + vertexes.add(e.dst()); | ||
| 34 | + } | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + @Override | ||
| 38 | + public Set<V> getVertexes() { | ||
| 39 | + return vertexes; | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + @Override | ||
| 43 | + public Set<E> getEdges() { | ||
| 44 | + return edges; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + @Override | ||
| 48 | + public Set<E> getEdgesFrom(V src) { | ||
| 49 | + return sources.get(src); | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + @Override | ||
| 53 | + public Set<E> getEdgesTo(V dst) { | ||
| 54 | + return destinations.get(dst); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + @Override | ||
| 58 | + public boolean equals(Object obj) { | ||
| 59 | + if (this == obj) { | ||
| 60 | + return true; | ||
| 61 | + } | ||
| 62 | + if (obj instanceof MutableAdjacencyListsGraph) { | ||
| 63 | + MutableAdjacencyListsGraph that = (MutableAdjacencyListsGraph) obj; | ||
| 64 | + return this.getClass() == that.getClass() && | ||
| 65 | + Objects.equals(this.vertexes, that.vertexes) && | ||
| 66 | + Objects.equals(this.edges, that.edges); | ||
| 67 | + } | ||
| 68 | + return false; | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + @Override | ||
| 72 | + public int hashCode() { | ||
| 73 | + return Objects.hash(vertexes, edges); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + @Override | ||
| 77 | + public String toString() { | ||
| 78 | + return toStringHelper(this) | ||
| 79 | + .add("vertexes", vertexes) | ||
| 80 | + .add("edges", edges) | ||
| 81 | + .toString(); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + | ||
| 85 | + @Override | ||
| 86 | + public void addVertex(V vertex) { | ||
| 87 | + if (vertexes != null) { | ||
| 88 | + if (!vertexes.contains(vertex)) { | ||
| 89 | + vertexes.add(vertex); | ||
| 90 | + } | ||
| 91 | + } | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + @Override | ||
| 95 | + public void removeVertex(V vertex) { | ||
| 96 | + // TODO Auto-generated method stub | ||
| 97 | + if (vertexes != null && edges != null) { | ||
| 98 | + if (vertexes.contains(vertex)) { | ||
| 99 | + vertexes.remove(vertex); | ||
| 100 | + Set<E> srcEdgesList = sources.get(vertex); | ||
| 101 | + Set<E> dstEdgesList = destinations.get(vertex); | ||
| 102 | + edges.removeAll(srcEdgesList); | ||
| 103 | + edges.removeAll(dstEdgesList); | ||
| 104 | + sources.remove(vertex, srcEdgesList); | ||
| 105 | + sources.remove(vertex, dstEdgesList); | ||
| 106 | + } | ||
| 107 | + } | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + @Override | ||
| 111 | + public void addEdge(E edge) { | ||
| 112 | + if (edges != null) { | ||
| 113 | + if (!edges.contains(edge)) { | ||
| 114 | + edges.add(edge); | ||
| 115 | + sources.put(edge.src(), edge); | ||
| 116 | + destinations.put(edge.dst(), edge); | ||
| 117 | + } | ||
| 118 | + } | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + @Override | ||
| 122 | + public void removeEdge(E edge) { | ||
| 123 | + if (edges != null) { | ||
| 124 | + if (edges.contains(edge)) { | ||
| 125 | + edges.remove(edge); | ||
| 126 | + sources.remove(edge.src(), edge); | ||
| 127 | + destinations.remove(edge.dst(), edge); | ||
| 128 | + } | ||
| 129 | + } | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + @Override | ||
| 133 | + public Graph<V, E> toImmutable() { | ||
| 134 | + // TODO Auto-generated method stub | ||
| 135 | + return null; | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + /** | ||
| 139 | + * Clear the graph. | ||
| 140 | + */ | ||
| 141 | + public void clear() { | ||
| 142 | + edges.clear(); | ||
| 143 | + vertexes.clear(); | ||
| 144 | + sources.clear(); | ||
| 145 | + destinations.clear(); | ||
| 146 | + } | ||
| 147 | +} |
| 1 | +/* | ||
| 2 | + * Licensed to the Apache Software Foundation (ASF) under one | ||
| 3 | + * or more contributor license agreements. See the NOTICE file | ||
| 4 | + * distributed with this work for additional information | ||
| 5 | + * regarding copyright ownership. The ASF licenses this file | ||
| 6 | + * to you under the Apache License, Version 2.0 (the | ||
| 7 | + * "License"); you may not use this file except in compliance | ||
| 8 | + * with the License. You may obtain a copy of the License at | ||
| 9 | + * | ||
| 10 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 11 | + * | ||
| 12 | + * Unless required by applicable law or agreed to in writing, | ||
| 13 | + * software distributed under the License is distributed on an | ||
| 14 | + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| 15 | + * KIND, either express or implied. See the License for the | ||
| 16 | + * specific language governing permissions and limitations | ||
| 17 | + * under the License. | ||
| 18 | + */ | ||
| 19 | +package org.onlab.graph; | ||
| 20 | + | ||
| 21 | +import static com.google.common.collect.ImmutableSet.of; | ||
| 22 | +import static org.junit.Assert.*; | ||
| 23 | + | ||
| 24 | +import java.io.ByteArrayOutputStream; | ||
| 25 | +//import java.io.PrintStream; | ||
| 26 | +import java.util.ArrayList; | ||
| 27 | +import java.util.Iterator; | ||
| 28 | +import java.util.List; | ||
| 29 | + | ||
| 30 | +import org.junit.After; | ||
| 31 | +import org.junit.AfterClass; | ||
| 32 | +import org.junit.Before; | ||
| 33 | +import org.junit.BeforeClass; | ||
| 34 | +import org.junit.Test; | ||
| 35 | + | ||
| 36 | +public class KshortestPathSearchTest extends BreadthFirstSearchTest { | ||
| 37 | + | ||
| 38 | + private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); | ||
| 39 | + | ||
| 40 | + @Test | ||
| 41 | + public void noPath() { | ||
| 42 | + graph = new AdjacencyListsGraph<>(of(A, B, C, D), | ||
| 43 | + of(new TestEdge(A, B, 1), | ||
| 44 | + new TestEdge(B, A, 1), | ||
| 45 | + new TestEdge(C, D, 1), | ||
| 46 | + new TestEdge(D, C, 1))); | ||
| 47 | + KshortestPathSearch<TestVertex, TestEdge> gs = new KshortestPathSearch<TestVertex, TestEdge>(graph); | ||
| 48 | + List<List<TestEdge>> result = gs.search(A, D, weight, 1); | ||
| 49 | + List<Path> paths = new ArrayList<>(); | ||
| 50 | + Iterator<List<TestEdge>> itr = result.iterator(); | ||
| 51 | + while (itr.hasNext()) { | ||
| 52 | + System.out.println(itr.next().toString()); | ||
| 53 | + } | ||
| 54 | + assertEquals("incorrect paths count", 0, result.size()); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + @Test | ||
| 58 | + public void test2Path() { | ||
| 59 | + graph = new AdjacencyListsGraph<>(of(A, B, C, D), | ||
| 60 | + of(new TestEdge(A, B, 1), | ||
| 61 | + new TestEdge(B, A, 1), | ||
| 62 | + new TestEdge(B, D, 1), | ||
| 63 | + new TestEdge(D, B, 1), | ||
| 64 | + new TestEdge(A, C, 1), | ||
| 65 | + new TestEdge(C, A, 1), | ||
| 66 | + new TestEdge(C, D, 1), | ||
| 67 | + new TestEdge(D, C, 1))); | ||
| 68 | + KshortestPathSearch<TestVertex, TestEdge> gs = new KshortestPathSearch<TestVertex, TestEdge>(graph); | ||
| 69 | + List<List<TestEdge>> result = gs.search(A, D, weight, 2); | ||
| 70 | + List<Path> paths = new ArrayList<>(); | ||
| 71 | + Iterator<List<TestEdge>> itr = result.iterator(); | ||
| 72 | + while (itr.hasNext()) { | ||
| 73 | + System.out.println(itr.next().toString()); | ||
| 74 | + } | ||
| 75 | + assertEquals("incorrect paths count", 2, result.size()); | ||
| 76 | + // assertEquals("printing the paths", outContent.toString()); | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + @Test | ||
| 80 | + public void test3Path() { | ||
| 81 | + graph = new AdjacencyListsGraph<>(of(A, B, C, D), | ||
| 82 | + of(new TestEdge(A, B, 1), | ||
| 83 | + new TestEdge(B, A, 1), | ||
| 84 | + new TestEdge(A, D, 1), | ||
| 85 | + new TestEdge(D, A, 1), | ||
| 86 | + new TestEdge(B, D, 1), | ||
| 87 | + new TestEdge(D, B, 1), | ||
| 88 | + new TestEdge(A, C, 1), | ||
| 89 | + new TestEdge(C, A, 1), | ||
| 90 | + new TestEdge(C, D, 1), | ||
| 91 | + new TestEdge(D, C, 1))); | ||
| 92 | + KshortestPathSearch<TestVertex, TestEdge> gs = new KshortestPathSearch<TestVertex, TestEdge>(graph); | ||
| 93 | + List<List<TestEdge>> result = gs.search(A, D, weight, 3); | ||
| 94 | + List<Path> paths = new ArrayList<>(); | ||
| 95 | + Iterator<List<TestEdge>> itr = result.iterator(); | ||
| 96 | + while (itr.hasNext()) { | ||
| 97 | + System.out.println(itr.next().toString()); | ||
| 98 | + } | ||
| 99 | + assertEquals("incorrect paths count", 3, result.size()); | ||
| 100 | + // assertEquals("printing the paths", outContent.toString()); | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + @Test | ||
| 104 | + public void test4Path() { | ||
| 105 | + graph = new AdjacencyListsGraph<>(of(A, B, C, D, E, F), | ||
| 106 | + of(new TestEdge(A, B, 1), | ||
| 107 | + new TestEdge(B, A, 1), | ||
| 108 | + new TestEdge(A, C, 1), | ||
| 109 | + new TestEdge(C, A, 1), | ||
| 110 | + new TestEdge(B, D, 1), | ||
| 111 | + new TestEdge(D, B, 1), | ||
| 112 | + new TestEdge(C, E, 1), | ||
| 113 | + new TestEdge(E, C, 1), | ||
| 114 | + new TestEdge(D, F, 1), | ||
| 115 | + new TestEdge(F, D, 1), | ||
| 116 | + new TestEdge(F, E, 1), | ||
| 117 | + new TestEdge(E, F, 1), | ||
| 118 | + new TestEdge(C, D, 1), | ||
| 119 | + new TestEdge(D, C, 1))); | ||
| 120 | + KshortestPathSearch<TestVertex, TestEdge> gs = new KshortestPathSearch<TestVertex, TestEdge>(graph); | ||
| 121 | + List<List<TestEdge>> result = gs.search(A, F, weight, 4); | ||
| 122 | + List<Path> paths = new ArrayList<>(); | ||
| 123 | + Iterator<List<TestEdge>> itr = result.iterator(); | ||
| 124 | + while (itr.hasNext()) { | ||
| 125 | + System.out.println(itr.next().toString()); | ||
| 126 | + } | ||
| 127 | + assertEquals("incorrect paths count", 4, result.size()); | ||
| 128 | + // assertEquals("printing the paths", outContent.toString()); | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | + @Test | ||
| 132 | + public void test6Path() { | ||
| 133 | + graph = new AdjacencyListsGraph<>(of(A, B, C, D, E, F), | ||
| 134 | + of(new TestEdge(A, B, 1), | ||
| 135 | + new TestEdge(B, A, 1), | ||
| 136 | + new TestEdge(A, C, 1), | ||
| 137 | + new TestEdge(C, A, 1), | ||
| 138 | + new TestEdge(B, D, 1), | ||
| 139 | + new TestEdge(D, B, 1), | ||
| 140 | + new TestEdge(B, C, 1), | ||
| 141 | + new TestEdge(C, B, 1), | ||
| 142 | + new TestEdge(D, E, 1), | ||
| 143 | + new TestEdge(E, D, 1), | ||
| 144 | + new TestEdge(C, E, 1), | ||
| 145 | + new TestEdge(E, C, 1), | ||
| 146 | + new TestEdge(D, F, 1), | ||
| 147 | + new TestEdge(F, D, 1), | ||
| 148 | + new TestEdge(E, F, 1), | ||
| 149 | + new TestEdge(F, E, 1))); | ||
| 150 | + KshortestPathSearch<TestVertex, TestEdge> gs = new KshortestPathSearch<TestVertex, TestEdge>(graph); | ||
| 151 | + List<List<TestEdge>> result = gs.search(A, F, weight, 6); | ||
| 152 | + List<Path> paths = new ArrayList<>(); | ||
| 153 | + Iterator<List<TestEdge>> itr = result.iterator(); | ||
| 154 | + while (itr.hasNext()) { | ||
| 155 | + System.out.println(itr.next().toString()); | ||
| 156 | + } | ||
| 157 | + assertEquals("incorrect paths count", 6, result.size()); | ||
| 158 | + // assertEquals("printing the paths", outContent.toString()); | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + @Test | ||
| 162 | + public void dualEdgePath() { | ||
| 163 | + graph = new AdjacencyListsGraph<>(of(A, B, C, D, E, F, G, H), | ||
| 164 | + of(new TestEdge(A, B, 1), new TestEdge(A, C, 3), | ||
| 165 | + new TestEdge(B, D, 2), new TestEdge(B, C, 1), | ||
| 166 | + new TestEdge(B, E, 4), new TestEdge(C, E, 1), | ||
| 167 | + new TestEdge(D, H, 5), new TestEdge(D, E, 1), | ||
| 168 | + new TestEdge(E, F, 1), new TestEdge(F, D, 1), | ||
| 169 | + new TestEdge(F, G, 1), new TestEdge(F, H, 1), | ||
| 170 | + new TestEdge(A, E, 3), new TestEdge(B, D, 1))); | ||
| 171 | + KshortestPathSearch<TestVertex, TestEdge> gs = new KshortestPathSearch<TestVertex, TestEdge>(graph); | ||
| 172 | + List<List<TestEdge>> result = gs.search(A, G, weight, 6); | ||
| 173 | + List<Path> paths = new ArrayList<>(); | ||
| 174 | + Iterator<List<TestEdge>> itr = result.iterator(); | ||
| 175 | + while (itr.hasNext()) { | ||
| 176 | + System.out.println(itr.next().toString()); | ||
| 177 | + } | ||
| 178 | + assertEquals("incorrect paths count", 6, result.size()); | ||
| 179 | + // assertEquals("printing the paths", outContent.toString()); | ||
| 180 | + } | ||
| 181 | + | ||
| 182 | + @BeforeClass | ||
| 183 | + public static void setUpBeforeClass() throws Exception { | ||
| 184 | + } | ||
| 185 | + | ||
| 186 | + @AfterClass | ||
| 187 | + public static void tearDownAfterClass() throws Exception { | ||
| 188 | + } | ||
| 189 | + | ||
| 190 | + @Before | ||
| 191 | + public void setUp() throws Exception { | ||
| 192 | + // System.setOut(new PrintStream(outContent)); | ||
| 193 | + } | ||
| 194 | + | ||
| 195 | + @After | ||
| 196 | + public void tearDown() throws Exception { | ||
| 197 | + // System.setOut(null); | ||
| 198 | + } | ||
| 199 | + | ||
| 200 | +} |
-
Please register or login to post a comment