Aaron Kruglikov
Committed by Gerrit Code Review

Rebuilding K Paths algorithm

Change-Id: I8f5223cd3004ec89b203b1f177cd226911426906
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onlab.graph;
17 +
18 +import com.google.common.collect.ImmutableSet;
19 +import com.google.common.collect.Lists;
20 +import com.google.common.collect.Sets;
21 +import org.slf4j.Logger;
22 +
23 +import java.util.ArrayList;
24 +import java.util.Comparator;
25 +import java.util.List;
26 +import java.util.Set;
27 +import java.util.TreeSet;
28 +
29 +import static com.google.common.base.Preconditions.checkArgument;
30 +import static com.google.common.base.Preconditions.checkNotNull;
31 +import static org.slf4j.LoggerFactory.getLogger;
32 +
33 +/**
34 + * Runs K shortest paths algorithm on a provided directed graph. Returns results in the form of an
35 + * InnerOrderedResult so iteration through the returned paths will return paths in ascending order according to the
36 + * provided EdgeWeight.
37 + */
38 +public class KShortestPathsSearch<V extends Vertex, E extends Edge<V>> extends AbstractGraphPathSearch<V, E> {
39 +
40 + private final Logger log = getLogger(getClass());
41 +
42 + @Override
43 + public Result<V, E> search(Graph<V, E> graph, V src, V dst, EdgeWeight<V, E> weight, int maxPaths) {
44 + checkNotNull(src);
45 + checkNotNull(dst);
46 + //The modified edge weight removes any need to modify the original graph
47 + InnerEdgeWeighter modifiedWeighter = new InnerEdgeWeighter(checkNotNull(weight));
48 + checkArgument(maxPaths > 0);
49 + Graph<V, E> originalGraph = checkNotNull(graph);
50 + //the result contains the set of eventual results
51 + InnerOrderedResult result = new InnerOrderedResult(src, dst, maxPaths);
52 + ArrayList<Path<V, E>> resultPaths = new ArrayList<>(maxPaths);
53 + ArrayList<Path<V, E>> potentialPaths = Lists.newArrayList();
54 +
55 + DijkstraGraphSearch<V, E> dijkstraSearch = new DijkstraGraphSearch<>();
56 + Set<Path<V, E>> dijkstraResults = dijkstraSearch.search(originalGraph, src, dst, modifiedWeighter, 1).paths();
57 + //Checks if the dst was reachable
58 + if (dijkstraResults.size() == 0) {
59 + log.warn("No path was found.");
60 + return result;
61 + }
62 + //If it was reachable adds the first shortest path to the set of results
63 + resultPaths.add(dijkstraResults.iterator().next());
64 +
65 + for (int k = 1; k < maxPaths; k++) {
66 +
67 + for (int i = 0; i < (resultPaths.get(k - 1).edges().size() - 1); i++) {
68 + V spurNode = resultPaths.get(k - 1).edges().get(i).src();
69 + List<E> rootPathEdgeList = resultPaths.get(k - 1).edges().subList(0, i);
70 +
71 + for (Path<V, E> path : resultPaths) {
72 + if (edgeListsAreEqual(rootPathEdgeList, path.edges().subList(0, i))) {
73 + modifiedWeighter.removedEdges.add(path.edges().get(i));
74 + }
75 + }
76 +
77 + //Effectively remove all nodes from the source path
78 + for (E edge : rootPathEdgeList) {
79 + originalGraph.getEdgesFrom(edge.src()).forEach(e -> modifiedWeighter.removedEdges.add(e));
80 + originalGraph.getEdgesTo(edge.src()).forEach(e -> modifiedWeighter.removedEdges.add(e));
81 + }
82 +
83 + dijkstraResults = dijkstraSearch.search(originalGraph, spurNode, dst, modifiedWeighter, 1).paths();
84 + if (dijkstraResults.size() != 0) {
85 + Path<V, E> spurPath = dijkstraResults.iterator().next();
86 + List<E> totalPath = new ArrayList<>(rootPathEdgeList);
87 + spurPath.edges().forEach(e -> totalPath.add(e));
88 + //The following line must use the original weighter not the modified weighter because the modified
89 + //weighter will count -1 values used for modifying the graph and return an inaccurate cost.
90 + potentialPaths.add(new DefaultPath<V, E>(totalPath,
91 + calculatePathCost(weight, totalPath)));
92 + }
93 +
94 + //Restore all removed paths and nodes
95 + modifiedWeighter.removedEdges.clear();
96 + }
97 + if (potentialPaths.isEmpty()) {
98 + break;
99 + }
100 + potentialPaths.sort(new InnerPathComparator());
101 + resultPaths.add(potentialPaths.get(0));
102 + potentialPaths.remove(0);
103 + }
104 + result.pathSet.addAll(resultPaths);
105 +
106 + return result;
107 + }
108 + //Edge list equality is judges by shared endpoints, and shared endpoints should be the same
109 + private boolean edgeListsAreEqual(List<E> edgeListOne, List<E> edgeListTwo) {
110 + if (edgeListOne.size() != edgeListTwo.size()) {
111 + return false;
112 + }
113 + E edgeOne;
114 + E edgeTwo;
115 + for (int i = 0; i < edgeListOne.size(); i++) {
116 + edgeOne = edgeListOne.get(i);
117 + edgeTwo = edgeListTwo.get(i);
118 + if (!edgeOne.equals(edgeTwo)) {
119 + return false;
120 + }
121 + }
122 + return true;
123 + }
124 +
125 + private Double calculatePathCost(EdgeWeight<V, E> weighter, List<E> edges) {
126 + Double totalCost = 0.0;
127 + for (E edge : edges) {
128 + totalCost += weighter.weight(edge);
129 + }
130 + return totalCost;
131 + }
132 +
133 + /**
134 + * Weights edges to make them inaccessible if set, otherwise returns the result of the original EdgeWeight.
135 + */
136 + private class InnerEdgeWeighter implements EdgeWeight<V, E> {
137 +
138 + private Set<E> removedEdges = Sets.newConcurrentHashSet();
139 + private EdgeWeight<V, E> innerEdgeWeight;
140 +
141 + public InnerEdgeWeighter(EdgeWeight<V, E> weight) {
142 + this.innerEdgeWeight = weight;
143 + }
144 +
145 + @Override
146 + public double weight(E edge) {
147 + if (removedEdges.contains(edge)) {
148 + //THIS RELIES ON THE LOCAL DIJKSTRA ALGORITHM AVOIDING NEGATIVES
149 + return -1;
150 + } else {
151 + return innerEdgeWeight.weight(edge);
152 + }
153 + }
154 + }
155 +
156 + /**
157 + * A result modified to return paths ordered according to the provided comparator.
158 + */
159 + protected class InnerOrderedResult extends DefaultResult {
160 +
161 + private TreeSet<Path<V, E>> pathSet = new TreeSet<>(new InnerPathComparator());
162 +
163 + public InnerOrderedResult(V src, V dst) {
164 + super(src, dst);
165 + }
166 +
167 + public InnerOrderedResult(V src, V dst, int maxPaths) {
168 + super(src, dst, maxPaths);
169 + }
170 +
171 + @Override
172 + public Set<Path<V, E>> paths() {
173 + return ImmutableSet.copyOf(pathSet);
174 + }
175 + }
176 +
177 + /**
178 + * Provides a comparator to order the set of paths.
179 + */
180 + private class InnerPathComparator implements Comparator<Path<V, E>> {
181 +
182 + @Override
183 + public int compare(Path<V, E> pathOne, Path<V, E> pathTwo) {
184 + int comparisonValue = Double.compare(pathOne.cost(), pathTwo.cost());
185 + if (comparisonValue != 0) {
186 + return comparisonValue;
187 + } else if (edgeListsAreEqual(pathOne.edges(), pathTwo.edges())) {
188 + return 0;
189 + } else {
190 + return 1;
191 + }
192 + }
193 + }
194 +}
1 -/*
2 - * Copyright 2014-2015 Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.graph;
17 -
18 -import java.util.ArrayList;
19 -//import java.util.HashMap;
20 -import java.util.Iterator;
21 -import java.util.List;
22 -//import java.util.Map;
23 -//import java.util.PriorityQueue;
24 -import java.util.Set;
25 -
26 -import static org.onlab.graph.GraphPathSearch.ALL_PATHS;
27 -
28 -/**
29 - * K-shortest-path graph search algorithm capable of finding not just one,
30 - * but K shortest paths with ascending order between the source and destinations.
31 - */
32 -
33 -public class KshortestPathSearch<V extends Vertex, E extends Edge<V>> {
34 -
35 - // Define class variables.
36 - private Graph<V, E> immutableGraph;
37 - private MutableGraph<V, E> mutableGraph;
38 - private List<List<E>> pathResults = new ArrayList<List<E>>();
39 - private List<List<E>> pathCandidates = new ArrayList<List<E>>();
40 - private V source;
41 - private V sink;
42 - private int numK = 0;
43 - private EdgeWeight<V, E> weight = null;
44 - // private PriorityQueue<List<E>> pathCandidates = new PriorityQueue<List<E>>();
45 -
46 - // Initialize the graph.
47 - public KshortestPathSearch(Graph<V, E> graph) {
48 - immutableGraph = graph;
49 - mutableGraph = new MutableAdjacencyListsGraph<>(graph.getVertexes(),
50 - graph.getEdges());
51 - }
52 -
53 - public List<List<E>> search(V src,
54 - V dst,
55 - EdgeWeight<V, E> wei,
56 - int k) {
57 -
58 - weight = wei;
59 - source = src;
60 - sink = dst;
61 - numK = k;
62 - // pathCandidates = new PriorityQueue<List<E>>();
63 -
64 - pathResults.clear();
65 - pathCandidates.clear();
66 -
67 - // Double check the parameters
68 - checkArguments(immutableGraph, src, dst, numK);
69 -
70 - // DefaultResult result = new DefaultResult(src, dst);
71 -
72 - searchKShortestPaths();
73 -
74 - return pathResults;
75 - }
76 -
77 - private void checkArguments(Graph<V, E> graph, V src, V dst, int k) {
78 - if (graph == null) {
79 - throw new NullPointerException("graph is null");
80 - }
81 - if (!graph.getVertexes().contains(src)) {
82 - throw new NullPointerException("source node does not exist");
83 - }
84 - if (!graph.getVertexes().contains(dst)) {
85 - throw new NullPointerException("target node does not exist");
86 - }
87 - if (k <= 0) {
88 - throw new NullPointerException("K is negative or 0");
89 - }
90 - if (weight == null) {
91 - throw new NullPointerException("the cost matrix is null");
92 - }
93 - }
94 -
95 - private void searchKShortestPaths() {
96 - // Step 1: find the shortest path.
97 - List<E> shortestPath = searchShortestPath(immutableGraph, source, sink);
98 - // no path exists, exit.
99 - if (shortestPath == null) {
100 - return;
101 - }
102 -
103 - // Step 2: update the results.
104 - pathResults.add(shortestPath);
105 - // pathCandidates.add(shortestPath);
106 -
107 - // Step 3: find the other K-1 paths.
108 - while (/*pathCandidates.size() > 0 &&*/pathResults.size() < numK) {
109 - // 3.1 the spur node ranges from the first node to the last node in the previous k-shortest path.
110 - List<E> lastPath = pathResults.get(pathResults.size() - 1);
111 - for (int i = 0; i < lastPath.size(); i++) {
112 - // 3.1.1 convert the graph into mutable.
113 - convertGraph();
114 - // 3.1.2 transform the graph.
115 - List<E> rootPath = createSpurNode(lastPath, i);
116 - transformGraph(rootPath);
117 - // 3.1.3 find the deviation node.
118 - V devNode;
119 - devNode = getDevNode(rootPath);
120 - List<E> spurPath;
121 - // 3.1.4 find the shortest path in the transformed graph.
122 - spurPath = searchShortestPath(mutableGraph, devNode, sink);
123 - // 3.1.5 update the path candidates.
124 - if (spurPath != null) {
125 - // totalPath = rootPath + spurPath;
126 - rootPath.addAll(spurPath);
127 - pathCandidates.add(rootPath);
128 - }
129 - }
130 - // 3.2 if there is no spur path, exit.
131 - if (pathCandidates.size() == 0) {
132 - break;
133 - }
134 - // 3.3 add the path into the results.
135 - addPathResult();
136 - }
137 - }
138 -
139 - @SuppressWarnings({ "rawtypes", "unchecked" })
140 - private List<E> searchShortestPath(Graph<V, E> graph, V src, V dst) {
141 - // Determine the shortest path from the source to the destination by using the Dijkstra algorithm.
142 - DijkstraGraphSearch dijkstraAlg = new DijkstraGraphSearch();
143 - Set<Path> paths = dijkstraAlg.search(graph, src, dst, weight, ALL_PATHS).paths();
144 - Iterator<Path> itr = paths.iterator();
145 - if (!itr.hasNext()) {
146 - return null;
147 - }
148 - // return the first shortest path only.
149 - return (List<E>) itr.next().edges();
150 - }
151 -
152 - private void convertGraph() {
153 - // clear the mutableGraph first
154 - if (mutableGraph != null) {
155 - ((MutableAdjacencyListsGraph) mutableGraph).clear();
156 - }
157 -
158 - // create a immutableGraph
159 - Set<E> copyEa = immutableGraph.getEdges();
160 - Set<V> copyVa = immutableGraph.getVertexes();
161 - for (V vertex : copyVa) {
162 - mutableGraph.addVertex(vertex);
163 - }
164 - for (E edge : copyEa) {
165 - mutableGraph.addEdge(edge);
166 - }
167 - }
168 -
169 - private V getDevNode(List<E> path) {
170 - V srcA;
171 - V dstB;
172 -
173 - if (path.size() == 0) {
174 - return source;
175 - }
176 -
177 - E temp1 = path.get(path.size() - 1);
178 - srcA = temp1.src();
179 - dstB = temp1.dst();
180 -
181 - if (path.size() == 1) {
182 - if (srcA.equals(source)) {
183 - return dstB;
184 - } else {
185 - return srcA;
186 - }
187 - } else {
188 - E temp2 = path.get(path.size() - 2);
189 - if (srcA.equals(temp2.src()) || srcA.equals(temp2.dst())) {
190 - return dstB;
191 - } else {
192 - return srcA;
193 - }
194 - }
195 - }
196 -
197 - private List<E> createSpurNode(List<E> path, int n) {
198 - List<E> root = new ArrayList<E>();
199 -
200 - for (int i = 0; i < n; i++) {
201 - root.add(path.get(i));
202 - }
203 - return root;
204 - }
205 -
206 - private void transformGraph(List<E> rootPath) {
207 - List<E> prePath;
208 - //remove edges
209 - for (int i = 0; i < pathResults.size(); i++) {
210 - prePath = pathResults.get(i);
211 - if (prePath.size() == 1) {
212 - mutableGraph.removeEdge(prePath.get(0));
213 - } else if (comparePath(rootPath, prePath)) {
214 - for (int j = 0; j <= rootPath.size(); j++) {
215 - mutableGraph.removeEdge(prePath.get(j));
216 - }
217 - }
218 - }
219 - for (int i = 0; i < pathCandidates.size(); i++) {
220 - prePath = pathCandidates.get(i);
221 - if (prePath.size() == 1) {
222 - mutableGraph.removeEdge(prePath.get(0));
223 - } else if (comparePath(rootPath, prePath)) {
224 - for (int j = 0; j <= rootPath.size(); j++) {
225 - mutableGraph.removeEdge(prePath.get(j));
226 - }
227 - }
228 - }
229 -
230 - if (rootPath.size() == 0) {
231 - return;
232 - }
233 -
234 - //remove nodes
235 - List<V> nodes = new ArrayList<V>();
236 - nodes.add(source);
237 - V pre = source;
238 - V srcA;
239 - V dstB;
240 - for (int i = 0; i < rootPath.size() - 1; i++) {
241 - E temp = rootPath.get(i);
242 - srcA = temp.src();
243 - dstB = temp.dst();
244 -
245 - if (srcA.equals(pre)) {
246 - nodes.add(dstB);
247 - pre = dstB;
248 - } else {
249 - nodes.add(srcA);
250 - pre = srcA;
251 - }
252 - }
253 - for (int i = 0; i < nodes.size(); i++) {
254 - mutableGraph.removeVertex(nodes.get(i));
255 - }
256 - }
257 -
258 - private boolean comparePath(List<E> path1, List<E> path2) {
259 - if (path1.size() > path2.size()) {
260 - return false;
261 - }
262 - if (path1.size() == 0) {
263 - return true;
264 - }
265 - for (int i = 0; i < path1.size(); i++) {
266 - if (path1.get(i) != path2.get(i)) {
267 - return false;
268 - }
269 - }
270 - return true;
271 - }
272 -
273 - private void addPathResult() {
274 - List<E> sp;
275 - sp = pathCandidates.get(0);
276 - for (int i = 1; i < pathCandidates.size(); i++) {
277 - if (sp.size() > pathCandidates.get(i).size()) {
278 - sp = pathCandidates.get(i);
279 - }
280 - }
281 - pathResults.add(sp);
282 - // Log.info(sp.toString());
283 - pathCandidates.remove(sp);
284 - }
285 -
286 -}
1 +package org.onlab.graph;
2 +
3 +import com.google.common.collect.Lists;
4 +import org.junit.Before;
5 +import org.junit.Test;
6 +
7 +import java.util.Iterator;
8 +import java.util.List;
9 +import java.util.Set;
10 +
11 +import static com.google.common.collect.ImmutableSet.of;
12 +import static org.junit.Assert.assertEquals;
13 +import static org.junit.Assert.assertTrue;
14 +
15 +/**
16 + * Class for test KshortestPathsSearch.
17 + */
18 +public class KShortestPathsSearchTest<V extends Vertex, E extends Edge<V>> extends GraphTest {
19 + private KShortestPathsSearch<TestVertex, TestEdge> kShortestPathsSearch = new KShortestPathsSearch<>();
20 + private GraphPathSearch.Result<TestVertex, TestEdge> result;
21 +
22 + @Before
23 + public void setUp() {
24 + graph = new AdjacencyListsGraph<>(vertexes(), edges());
25 + }
26 + @Test
27 + public void noPath() {
28 + graph = new AdjacencyListsGraph<>(of(A, B, C, D),
29 + of(new TestEdge(A, B, 1),
30 + new TestEdge(B, A, 1),
31 + new TestEdge(C, D, 1),
32 + new TestEdge(D, C, 1)));
33 + KShortestPathsSearch<TestVertex, TestEdge> kShortestPathsSearch = new KShortestPathsSearch<>();
34 + GraphPathSearch.Result<TestVertex, TestEdge> result = kShortestPathsSearch.search(graph, A, D, weight, 1);
35 + Set<Path<TestVertex, TestEdge>> resultPathSet = result.paths();
36 + assertTrue("There should not be any paths.", resultPathSet.isEmpty());
37 + }
38 +
39 + @Test
40 + public void testSinglePath() {
41 + //Tests that there is only a single path possible between A and B
42 + graph = new AdjacencyListsGraph<>(vertexes(), edges());
43 + this.result = kShortestPathsSearch.search(graph, A, B, weight, 2);
44 + Iterator<Path<TestVertex, TestEdge>> itr = result.paths().iterator();
45 + assertEquals("incorrect paths count", 1, result.paths().size());
46 + List<TestEdge> correctEdgeList = Lists.newArrayList();
47 + correctEdgeList.add(new TestEdge(A, B, 1));
48 + assertTrue("That wrong path was returned.",
49 + edgeListsAreEqual(correctEdgeList, result.paths().iterator().next().edges()));
50 + }
51 +
52 + @Test
53 + public void testTwoPath() {
54 + //Tests that there are only two paths between A and C and that they are returned in the correct order
55 + result = kShortestPathsSearch.search(graph, A, C, weight, 3);
56 + assertTrue("There are an unexpected number of paths.", result.paths().size() == 2);
57 + Iterator<Path<TestVertex, TestEdge>> edgeListIterator = result.paths().iterator();
58 + List<TestEdge> correctEdgeList = Lists.newArrayList();
59 + correctEdgeList.add(new TestEdge(A, B, 1));
60 + correctEdgeList.add(new TestEdge(B, C, 1));
61 + assertTrue("The first path from A to C was incorrect.",
62 + edgeListsAreEqual(edgeListIterator.next().edges(), correctEdgeList));
63 + correctEdgeList.clear();
64 + correctEdgeList.add(new TestEdge(A, C, 3));
65 + assertTrue("The second path from A to C was incorrect.",
66 + edgeListsAreEqual(edgeListIterator.next().edges(), correctEdgeList));
67 + }
68 +
69 + @Test
70 + public void testFourPath() {
71 + //Tests that there are only four paths between A and E and that they are returned in the correct order
72 + //Also tests the special case where some correct solutions are equal
73 + result = kShortestPathsSearch.search(graph, A, E, weight, 5);
74 + assertTrue("There are an unexpected number of paths.", result.paths().size() == 4);
75 + Iterator<Path<TestVertex, TestEdge>> edgeListIterator = result.paths().iterator();
76 + List<TestEdge> correctEdgeList = Lists.newArrayList();
77 + correctEdgeList.add(new TestEdge(A, B, 1));
78 + correctEdgeList.add(new TestEdge(B, C, 1));
79 + correctEdgeList.add(new TestEdge(C, E, 1));
80 + assertTrue("The first path from A to E was incorrect.",
81 + edgeListsAreEqual(edgeListIterator.next().edges(), correctEdgeList));
82 + correctEdgeList.clear();
83 + //There are two paths of equal length that should hold positions two and three
84 + List<TestEdge> alternateCorrectEdgeList = Lists.newArrayList();
85 + correctEdgeList.add(new TestEdge(A, C, 3));
86 + correctEdgeList.add(new TestEdge(C, E, 1));
87 + alternateCorrectEdgeList.add(new TestEdge(A, B, 1));
88 + alternateCorrectEdgeList.add(new TestEdge(B, D, 2));
89 + alternateCorrectEdgeList.add(new TestEdge(D, E, 1));
90 + List<TestEdge> candidateOne = edgeListIterator.next().edges();
91 + List<TestEdge> candidateTwo = edgeListIterator.next().edges();
92 + if (candidateOne.size() == 2) {
93 + assertTrue("The second path from A to E was incorrect.",
94 + edgeListsAreEqual(candidateOne, correctEdgeList));
95 + assertTrue("The third path from A to E was incorrect.",
96 + edgeListsAreEqual(candidateTwo, alternateCorrectEdgeList));
97 + } else {
98 + assertTrue("The second path from A to E was incorrect.",
99 + edgeListsAreEqual(candidateOne, alternateCorrectEdgeList));
100 + assertTrue("The third path from A to E was incorrect.",
101 + edgeListsAreEqual(candidateTwo, correctEdgeList));
102 + }
103 + correctEdgeList.clear();
104 + correctEdgeList.add(new TestEdge(A, B, 1));
105 + correctEdgeList.add(new TestEdge(B, E, 4));
106 + assertTrue("The fourth path rom A to E was incorrect",
107 + edgeListsAreEqual(edgeListIterator.next().edges(), correctEdgeList));
108 +
109 + }
110 +
111 + @Test
112 + public void testPathsFromSink() {
113 + //H is a sink in this topology, insure there are no paths from it to any other location
114 + for (TestVertex vertex : vertexes()) {
115 + assertTrue("There should be no paths from vertex H to any other node.",
116 + kShortestPathsSearch.search(graph, H, vertex, weight, 1).paths().size() == 0);
117 + }
118 + }
119 +
120 + @Test
121 + public void testLimitPathSetSize() {
122 + //Checks to make sure that no more than K paths are returned
123 + result = kShortestPathsSearch.search(graph, A, E, weight, 3);
124 + assertTrue("There are an unexpected number of paths.", result.paths().size() == 3);
125 + result = kShortestPathsSearch.search(graph, A, G, weight, 1);
126 + assertTrue("There are an unexpected number of paths.", result.paths().size() == 1);
127 + }
128 +
129 + private boolean edgeListsAreEqual(List<TestEdge> edgeListOne, List<TestEdge> edgeListTwo) {
130 + if (edgeListOne.size() != edgeListTwo.size()) {
131 + return false;
132 + }
133 + TestEdge edgeOne;
134 + TestEdge edgeTwo;
135 + for (int i = 0; i < edgeListOne.size(); i++) {
136 + edgeOne = edgeListOne.get(i);
137 + edgeTwo = edgeListTwo.get(i);
138 + if (!edgeOne.equals(edgeTwo)) {
139 + return false;
140 + }
141 + }
142 + return true;
143 + }
144 +}
...\ No newline at end of file ...\ No newline at end of file
1 -/*
2 - * Copyright 2014 Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onlab.graph;
17 -
18 -import static com.google.common.collect.ImmutableSet.of;
19 -import static org.junit.Assert.*;
20 -
21 -import java.io.ByteArrayOutputStream;
22 -//import java.io.PrintStream;
23 -import java.util.ArrayList;
24 -import java.util.Iterator;
25 -import java.util.List;
26 -
27 -import org.junit.After;
28 -import org.junit.AfterClass;
29 -import org.junit.Before;
30 -import org.junit.BeforeClass;
31 -import org.junit.Test;
32 -
33 -public class KshortestPathSearchTest extends BreadthFirstSearchTest {
34 -
35 - private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
36 -
37 - @Test
38 - public void noPath() {
39 - graph = new AdjacencyListsGraph<>(of(A, B, C, D),
40 - of(new TestEdge(A, B, 1),
41 - new TestEdge(B, A, 1),
42 - new TestEdge(C, D, 1),
43 - new TestEdge(D, C, 1)));
44 - KshortestPathSearch<TestVertex, TestEdge> gs = new KshortestPathSearch<TestVertex, TestEdge>(graph);
45 - List<List<TestEdge>> result = gs.search(A, D, weight, 1);
46 - List<Path> paths = new ArrayList<>();
47 - Iterator<List<TestEdge>> itr = result.iterator();
48 - while (itr.hasNext()) {
49 - System.out.println(itr.next().toString());
50 - }
51 - assertEquals("incorrect paths count", 0, result.size());
52 - }
53 -
54 - @Test
55 - public void test2Path() {
56 - graph = new AdjacencyListsGraph<>(of(A, B, C, D),
57 - of(new TestEdge(A, B, 1),
58 - new TestEdge(B, A, 1),
59 - new TestEdge(B, D, 1),
60 - new TestEdge(D, B, 1),
61 - new TestEdge(A, C, 1),
62 - new TestEdge(C, A, 1),
63 - new TestEdge(C, D, 1),
64 - new TestEdge(D, C, 1)));
65 - KshortestPathSearch<TestVertex, TestEdge> gs = new KshortestPathSearch<TestVertex, TestEdge>(graph);
66 - List<List<TestEdge>> result = gs.search(A, D, weight, 2);
67 - List<Path> paths = new ArrayList<>();
68 - Iterator<List<TestEdge>> itr = result.iterator();
69 - while (itr.hasNext()) {
70 - System.out.println(itr.next().toString());
71 - }
72 - assertEquals("incorrect paths count", 2, result.size());
73 - // assertEquals("printing the paths", outContent.toString());
74 - }
75 -
76 - @Test
77 - public void test3Path() {
78 - graph = new AdjacencyListsGraph<>(of(A, B, C, D),
79 - of(new TestEdge(A, B, 1),
80 - new TestEdge(B, A, 1),
81 - new TestEdge(A, D, 1),
82 - new TestEdge(D, A, 1),
83 - new TestEdge(B, D, 1),
84 - new TestEdge(D, B, 1),
85 - new TestEdge(A, C, 1),
86 - new TestEdge(C, A, 1),
87 - new TestEdge(C, D, 1),
88 - new TestEdge(D, C, 1)));
89 - KshortestPathSearch<TestVertex, TestEdge> gs = new KshortestPathSearch<TestVertex, TestEdge>(graph);
90 - List<List<TestEdge>> result = gs.search(A, D, weight, 3);
91 - List<Path> paths = new ArrayList<>();
92 - Iterator<List<TestEdge>> itr = result.iterator();
93 - while (itr.hasNext()) {
94 - System.out.println(itr.next().toString());
95 - }
96 - assertEquals("incorrect paths count", 3, result.size());
97 - // assertEquals("printing the paths", outContent.toString());
98 - }
99 -
100 - @Test
101 - public void test4Path() {
102 - graph = new AdjacencyListsGraph<>(of(A, B, C, D, E, F),
103 - of(new TestEdge(A, B, 1),
104 - new TestEdge(B, A, 1),
105 - new TestEdge(A, C, 1),
106 - new TestEdge(C, A, 1),
107 - new TestEdge(B, D, 1),
108 - new TestEdge(D, B, 1),
109 - new TestEdge(C, E, 1),
110 - new TestEdge(E, C, 1),
111 - new TestEdge(D, F, 1),
112 - new TestEdge(F, D, 1),
113 - new TestEdge(F, E, 1),
114 - new TestEdge(E, F, 1),
115 - new TestEdge(C, D, 1),
116 - new TestEdge(D, C, 1)));
117 - KshortestPathSearch<TestVertex, TestEdge> gs = new KshortestPathSearch<TestVertex, TestEdge>(graph);
118 - List<List<TestEdge>> result = gs.search(A, F, weight, 4);
119 - List<Path> paths = new ArrayList<>();
120 - Iterator<List<TestEdge>> itr = result.iterator();
121 - while (itr.hasNext()) {
122 - System.out.println(itr.next().toString());
123 - }
124 - assertEquals("incorrect paths count", 4, result.size());
125 - // assertEquals("printing the paths", outContent.toString());
126 - }
127 -
128 - @Test
129 - public void test6Path() {
130 - graph = new AdjacencyListsGraph<>(of(A, B, C, D, E, F),
131 - of(new TestEdge(A, B, 1),
132 - new TestEdge(B, A, 1),
133 - new TestEdge(A, C, 1),
134 - new TestEdge(C, A, 1),
135 - new TestEdge(B, D, 1),
136 - new TestEdge(D, B, 1),
137 - new TestEdge(B, C, 1),
138 - new TestEdge(C, B, 1),
139 - new TestEdge(D, E, 1),
140 - new TestEdge(E, D, 1),
141 - new TestEdge(C, E, 1),
142 - new TestEdge(E, C, 1),
143 - new TestEdge(D, F, 1),
144 - new TestEdge(F, D, 1),
145 - new TestEdge(E, F, 1),
146 - new TestEdge(F, E, 1)));
147 - KshortestPathSearch<TestVertex, TestEdge> gs = new KshortestPathSearch<TestVertex, TestEdge>(graph);
148 - List<List<TestEdge>> result = gs.search(A, F, weight, 6);
149 - List<Path> paths = new ArrayList<>();
150 - Iterator<List<TestEdge>> itr = result.iterator();
151 - while (itr.hasNext()) {
152 - System.out.println(itr.next().toString());
153 - }
154 - assertEquals("incorrect paths count", 6, result.size());
155 - // assertEquals("printing the paths", outContent.toString());
156 - }
157 -
158 - @Test
159 - public void dualEdgePath() {
160 - graph = new AdjacencyListsGraph<>(of(A, B, C, D, E, F, G, H),
161 - of(new TestEdge(A, B, 1), new TestEdge(A, C, 3),
162 - new TestEdge(B, D, 2), new TestEdge(B, C, 1),
163 - new TestEdge(B, E, 4), new TestEdge(C, E, 1),
164 - new TestEdge(D, H, 5), new TestEdge(D, E, 1),
165 - new TestEdge(E, F, 1), new TestEdge(F, D, 1),
166 - new TestEdge(F, G, 1), new TestEdge(F, H, 1),
167 - new TestEdge(A, E, 3), new TestEdge(B, D, 1)));
168 - KshortestPathSearch<TestVertex, TestEdge> gs = new KshortestPathSearch<TestVertex, TestEdge>(graph);
169 - List<List<TestEdge>> result = gs.search(A, G, weight, 6);
170 - List<Path> paths = new ArrayList<>();
171 - Iterator<List<TestEdge>> itr = result.iterator();
172 - while (itr.hasNext()) {
173 - System.out.println(itr.next().toString());
174 - }
175 - assertEquals("incorrect paths count", 6, result.size());
176 - // assertEquals("printing the paths", outContent.toString());
177 - }
178 -
179 - @BeforeClass
180 - public static void setUpBeforeClass() throws Exception {
181 - }
182 -
183 - @AfterClass
184 - public static void tearDownAfterClass() throws Exception {
185 - }
186 -
187 - @Before
188 - public void setUp() throws Exception {
189 - // System.setOut(new PrintStream(outContent));
190 - }
191 -
192 - @After
193 - public void tearDown() throws Exception {
194 - // System.setOut(null);
195 - }
196 -
197 -}