Aaron Kruglikov
Committed by Gerrit Code Review

Rebuilding K Paths algorithm

Change-Id: I8f5223cd3004ec89b203b1f177cd226911426906
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onlab.graph;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Runs K shortest paths algorithm on a provided directed graph. Returns results in the form of an
* InnerOrderedResult so iteration through the returned paths will return paths in ascending order according to the
* provided EdgeWeight.
*/
public class KShortestPathsSearch<V extends Vertex, E extends Edge<V>> extends AbstractGraphPathSearch<V, E> {
private final Logger log = getLogger(getClass());
@Override
public Result<V, E> search(Graph<V, E> graph, V src, V dst, EdgeWeight<V, E> weight, int maxPaths) {
checkNotNull(src);
checkNotNull(dst);
//The modified edge weight removes any need to modify the original graph
InnerEdgeWeighter modifiedWeighter = new InnerEdgeWeighter(checkNotNull(weight));
checkArgument(maxPaths > 0);
Graph<V, E> originalGraph = checkNotNull(graph);
//the result contains the set of eventual results
InnerOrderedResult result = new InnerOrderedResult(src, dst, maxPaths);
ArrayList<Path<V, E>> resultPaths = new ArrayList<>(maxPaths);
ArrayList<Path<V, E>> potentialPaths = Lists.newArrayList();
DijkstraGraphSearch<V, E> dijkstraSearch = new DijkstraGraphSearch<>();
Set<Path<V, E>> dijkstraResults = dijkstraSearch.search(originalGraph, src, dst, modifiedWeighter, 1).paths();
//Checks if the dst was reachable
if (dijkstraResults.size() == 0) {
log.warn("No path was found.");
return result;
}
//If it was reachable adds the first shortest path to the set of results
resultPaths.add(dijkstraResults.iterator().next());
for (int k = 1; k < maxPaths; k++) {
for (int i = 0; i < (resultPaths.get(k - 1).edges().size() - 1); i++) {
V spurNode = resultPaths.get(k - 1).edges().get(i).src();
List<E> rootPathEdgeList = resultPaths.get(k - 1).edges().subList(0, i);
for (Path<V, E> path : resultPaths) {
if (edgeListsAreEqual(rootPathEdgeList, path.edges().subList(0, i))) {
modifiedWeighter.removedEdges.add(path.edges().get(i));
}
}
//Effectively remove all nodes from the source path
for (E edge : rootPathEdgeList) {
originalGraph.getEdgesFrom(edge.src()).forEach(e -> modifiedWeighter.removedEdges.add(e));
originalGraph.getEdgesTo(edge.src()).forEach(e -> modifiedWeighter.removedEdges.add(e));
}
dijkstraResults = dijkstraSearch.search(originalGraph, spurNode, dst, modifiedWeighter, 1).paths();
if (dijkstraResults.size() != 0) {
Path<V, E> spurPath = dijkstraResults.iterator().next();
List<E> totalPath = new ArrayList<>(rootPathEdgeList);
spurPath.edges().forEach(e -> totalPath.add(e));
//The following line must use the original weighter not the modified weighter because the modified
//weighter will count -1 values used for modifying the graph and return an inaccurate cost.
potentialPaths.add(new DefaultPath<V, E>(totalPath,
calculatePathCost(weight, totalPath)));
}
//Restore all removed paths and nodes
modifiedWeighter.removedEdges.clear();
}
if (potentialPaths.isEmpty()) {
break;
}
potentialPaths.sort(new InnerPathComparator());
resultPaths.add(potentialPaths.get(0));
potentialPaths.remove(0);
}
result.pathSet.addAll(resultPaths);
return result;
}
//Edge list equality is judges by shared endpoints, and shared endpoints should be the same
private boolean edgeListsAreEqual(List<E> edgeListOne, List<E> edgeListTwo) {
if (edgeListOne.size() != edgeListTwo.size()) {
return false;
}
E edgeOne;
E edgeTwo;
for (int i = 0; i < edgeListOne.size(); i++) {
edgeOne = edgeListOne.get(i);
edgeTwo = edgeListTwo.get(i);
if (!edgeOne.equals(edgeTwo)) {
return false;
}
}
return true;
}
private Double calculatePathCost(EdgeWeight<V, E> weighter, List<E> edges) {
Double totalCost = 0.0;
for (E edge : edges) {
totalCost += weighter.weight(edge);
}
return totalCost;
}
/**
* Weights edges to make them inaccessible if set, otherwise returns the result of the original EdgeWeight.
*/
private class InnerEdgeWeighter implements EdgeWeight<V, E> {
private Set<E> removedEdges = Sets.newConcurrentHashSet();
private EdgeWeight<V, E> innerEdgeWeight;
public InnerEdgeWeighter(EdgeWeight<V, E> weight) {
this.innerEdgeWeight = weight;
}
@Override
public double weight(E edge) {
if (removedEdges.contains(edge)) {
//THIS RELIES ON THE LOCAL DIJKSTRA ALGORITHM AVOIDING NEGATIVES
return -1;
} else {
return innerEdgeWeight.weight(edge);
}
}
}
/**
* A result modified to return paths ordered according to the provided comparator.
*/
protected class InnerOrderedResult extends DefaultResult {
private TreeSet<Path<V, E>> pathSet = new TreeSet<>(new InnerPathComparator());
public InnerOrderedResult(V src, V dst) {
super(src, dst);
}
public InnerOrderedResult(V src, V dst, int maxPaths) {
super(src, dst, maxPaths);
}
@Override
public Set<Path<V, E>> paths() {
return ImmutableSet.copyOf(pathSet);
}
}
/**
* Provides a comparator to order the set of paths.
*/
private class InnerPathComparator implements Comparator<Path<V, E>> {
@Override
public int compare(Path<V, E> pathOne, Path<V, E> pathTwo) {
int comparisonValue = Double.compare(pathOne.cost(), pathTwo.cost());
if (comparisonValue != 0) {
return comparisonValue;
} else if (edgeListsAreEqual(pathOne.edges(), pathTwo.edges())) {
return 0;
} else {
return 1;
}
}
}
}
/*
* Copyright 2014-2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onlab.graph;
import java.util.ArrayList;
//import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
//import java.util.Map;
//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.
*/
public class KshortestPathSearch<V extends Vertex, E extends Edge<V>> {
// Define class variables.
private Graph<V, E> immutableGraph;
private MutableGraph<V, E> mutableGraph;
private List<List<E>> pathResults = new ArrayList<List<E>>();
private List<List<E>> pathCandidates = new ArrayList<List<E>>();
private V source;
private V sink;
private int numK = 0;
private EdgeWeight<V, E> weight = null;
// private PriorityQueue<List<E>> pathCandidates = new PriorityQueue<List<E>>();
// Initialize the graph.
public KshortestPathSearch(Graph<V, E> graph) {
immutableGraph = graph;
mutableGraph = new MutableAdjacencyListsGraph<>(graph.getVertexes(),
graph.getEdges());
}
public List<List<E>> search(V src,
V dst,
EdgeWeight<V, E> wei,
int k) {
weight = wei;
source = src;
sink = dst;
numK = k;
// pathCandidates = new PriorityQueue<List<E>>();
pathResults.clear();
pathCandidates.clear();
// Double check the parameters
checkArguments(immutableGraph, src, dst, numK);
// DefaultResult result = new DefaultResult(src, dst);
searchKShortestPaths();
return pathResults;
}
private void checkArguments(Graph<V, E> graph, V src, V dst, int k) {
if (graph == null) {
throw new NullPointerException("graph is null");
}
if (!graph.getVertexes().contains(src)) {
throw new NullPointerException("source node does not exist");
}
if (!graph.getVertexes().contains(dst)) {
throw new NullPointerException("target node does not exist");
}
if (k <= 0) {
throw new NullPointerException("K is negative or 0");
}
if (weight == null) {
throw new NullPointerException("the cost matrix is null");
}
}
private void searchKShortestPaths() {
// Step 1: find the shortest path.
List<E> shortestPath = searchShortestPath(immutableGraph, source, sink);
// no path exists, exit.
if (shortestPath == null) {
return;
}
// Step 2: update the results.
pathResults.add(shortestPath);
// pathCandidates.add(shortestPath);
// Step 3: find the other K-1 paths.
while (/*pathCandidates.size() > 0 &&*/pathResults.size() < numK) {
// 3.1 the spur node ranges from the first node to the last node in the previous k-shortest path.
List<E> lastPath = pathResults.get(pathResults.size() - 1);
for (int i = 0; i < lastPath.size(); i++) {
// 3.1.1 convert the graph into mutable.
convertGraph();
// 3.1.2 transform the graph.
List<E> rootPath = createSpurNode(lastPath, i);
transformGraph(rootPath);
// 3.1.3 find the deviation node.
V devNode;
devNode = getDevNode(rootPath);
List<E> spurPath;
// 3.1.4 find the shortest path in the transformed graph.
spurPath = searchShortestPath(mutableGraph, devNode, sink);
// 3.1.5 update the path candidates.
if (spurPath != null) {
// totalPath = rootPath + spurPath;
rootPath.addAll(spurPath);
pathCandidates.add(rootPath);
}
}
// 3.2 if there is no spur path, exit.
if (pathCandidates.size() == 0) {
break;
}
// 3.3 add the path into the results.
addPathResult();
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
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, ALL_PATHS).paths();
Iterator<Path> itr = paths.iterator();
if (!itr.hasNext()) {
return null;
}
// return the first shortest path only.
return (List<E>) itr.next().edges();
}
private void convertGraph() {
// clear the mutableGraph first
if (mutableGraph != null) {
((MutableAdjacencyListsGraph) mutableGraph).clear();
}
// create a immutableGraph
Set<E> copyEa = immutableGraph.getEdges();
Set<V> copyVa = immutableGraph.getVertexes();
for (V vertex : copyVa) {
mutableGraph.addVertex(vertex);
}
for (E edge : copyEa) {
mutableGraph.addEdge(edge);
}
}
private V getDevNode(List<E> path) {
V srcA;
V dstB;
if (path.size() == 0) {
return source;
}
E temp1 = path.get(path.size() - 1);
srcA = temp1.src();
dstB = temp1.dst();
if (path.size() == 1) {
if (srcA.equals(source)) {
return dstB;
} else {
return srcA;
}
} else {
E temp2 = path.get(path.size() - 2);
if (srcA.equals(temp2.src()) || srcA.equals(temp2.dst())) {
return dstB;
} else {
return srcA;
}
}
}
private List<E> createSpurNode(List<E> path, int n) {
List<E> root = new ArrayList<E>();
for (int i = 0; i < n; i++) {
root.add(path.get(i));
}
return root;
}
private void transformGraph(List<E> rootPath) {
List<E> prePath;
//remove edges
for (int i = 0; i < pathResults.size(); i++) {
prePath = pathResults.get(i);
if (prePath.size() == 1) {
mutableGraph.removeEdge(prePath.get(0));
} else if (comparePath(rootPath, prePath)) {
for (int j = 0; j <= rootPath.size(); j++) {
mutableGraph.removeEdge(prePath.get(j));
}
}
}
for (int i = 0; i < pathCandidates.size(); i++) {
prePath = pathCandidates.get(i);
if (prePath.size() == 1) {
mutableGraph.removeEdge(prePath.get(0));
} else if (comparePath(rootPath, prePath)) {
for (int j = 0; j <= rootPath.size(); j++) {
mutableGraph.removeEdge(prePath.get(j));
}
}
}
if (rootPath.size() == 0) {
return;
}
//remove nodes
List<V> nodes = new ArrayList<V>();
nodes.add(source);
V pre = source;
V srcA;
V dstB;
for (int i = 0; i < rootPath.size() - 1; i++) {
E temp = rootPath.get(i);
srcA = temp.src();
dstB = temp.dst();
if (srcA.equals(pre)) {
nodes.add(dstB);
pre = dstB;
} else {
nodes.add(srcA);
pre = srcA;
}
}
for (int i = 0; i < nodes.size(); i++) {
mutableGraph.removeVertex(nodes.get(i));
}
}
private boolean comparePath(List<E> path1, List<E> path2) {
if (path1.size() > path2.size()) {
return false;
}
if (path1.size() == 0) {
return true;
}
for (int i = 0; i < path1.size(); i++) {
if (path1.get(i) != path2.get(i)) {
return false;
}
}
return true;
}
private void addPathResult() {
List<E> sp;
sp = pathCandidates.get(0);
for (int i = 1; i < pathCandidates.size(); i++) {
if (sp.size() > pathCandidates.get(i).size()) {
sp = pathCandidates.get(i);
}
}
pathResults.add(sp);
// Log.info(sp.toString());
pathCandidates.remove(sp);
}
}
package org.onlab.graph;
import com.google.common.collect.Lists;
import org.junit.Before;
import org.junit.Test;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import static com.google.common.collect.ImmutableSet.of;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* Class for test KshortestPathsSearch.
*/
public class KShortestPathsSearchTest<V extends Vertex, E extends Edge<V>> extends GraphTest {
private KShortestPathsSearch<TestVertex, TestEdge> kShortestPathsSearch = new KShortestPathsSearch<>();
private GraphPathSearch.Result<TestVertex, TestEdge> result;
@Before
public void setUp() {
graph = new AdjacencyListsGraph<>(vertexes(), edges());
}
@Test
public void noPath() {
graph = new AdjacencyListsGraph<>(of(A, B, C, D),
of(new TestEdge(A, B, 1),
new TestEdge(B, A, 1),
new TestEdge(C, D, 1),
new TestEdge(D, C, 1)));
KShortestPathsSearch<TestVertex, TestEdge> kShortestPathsSearch = new KShortestPathsSearch<>();
GraphPathSearch.Result<TestVertex, TestEdge> result = kShortestPathsSearch.search(graph, A, D, weight, 1);
Set<Path<TestVertex, TestEdge>> resultPathSet = result.paths();
assertTrue("There should not be any paths.", resultPathSet.isEmpty());
}
@Test
public void testSinglePath() {
//Tests that there is only a single path possible between A and B
graph = new AdjacencyListsGraph<>(vertexes(), edges());
this.result = kShortestPathsSearch.search(graph, A, B, weight, 2);
Iterator<Path<TestVertex, TestEdge>> itr = result.paths().iterator();
assertEquals("incorrect paths count", 1, result.paths().size());
List<TestEdge> correctEdgeList = Lists.newArrayList();
correctEdgeList.add(new TestEdge(A, B, 1));
assertTrue("That wrong path was returned.",
edgeListsAreEqual(correctEdgeList, result.paths().iterator().next().edges()));
}
@Test
public void testTwoPath() {
//Tests that there are only two paths between A and C and that they are returned in the correct order
result = kShortestPathsSearch.search(graph, A, C, weight, 3);
assertTrue("There are an unexpected number of paths.", result.paths().size() == 2);
Iterator<Path<TestVertex, TestEdge>> edgeListIterator = result.paths().iterator();
List<TestEdge> correctEdgeList = Lists.newArrayList();
correctEdgeList.add(new TestEdge(A, B, 1));
correctEdgeList.add(new TestEdge(B, C, 1));
assertTrue("The first path from A to C was incorrect.",
edgeListsAreEqual(edgeListIterator.next().edges(), correctEdgeList));
correctEdgeList.clear();
correctEdgeList.add(new TestEdge(A, C, 3));
assertTrue("The second path from A to C was incorrect.",
edgeListsAreEqual(edgeListIterator.next().edges(), correctEdgeList));
}
@Test
public void testFourPath() {
//Tests that there are only four paths between A and E and that they are returned in the correct order
//Also tests the special case where some correct solutions are equal
result = kShortestPathsSearch.search(graph, A, E, weight, 5);
assertTrue("There are an unexpected number of paths.", result.paths().size() == 4);
Iterator<Path<TestVertex, TestEdge>> edgeListIterator = result.paths().iterator();
List<TestEdge> correctEdgeList = Lists.newArrayList();
correctEdgeList.add(new TestEdge(A, B, 1));
correctEdgeList.add(new TestEdge(B, C, 1));
correctEdgeList.add(new TestEdge(C, E, 1));
assertTrue("The first path from A to E was incorrect.",
edgeListsAreEqual(edgeListIterator.next().edges(), correctEdgeList));
correctEdgeList.clear();
//There are two paths of equal length that should hold positions two and three
List<TestEdge> alternateCorrectEdgeList = Lists.newArrayList();
correctEdgeList.add(new TestEdge(A, C, 3));
correctEdgeList.add(new TestEdge(C, E, 1));
alternateCorrectEdgeList.add(new TestEdge(A, B, 1));
alternateCorrectEdgeList.add(new TestEdge(B, D, 2));
alternateCorrectEdgeList.add(new TestEdge(D, E, 1));
List<TestEdge> candidateOne = edgeListIterator.next().edges();
List<TestEdge> candidateTwo = edgeListIterator.next().edges();
if (candidateOne.size() == 2) {
assertTrue("The second path from A to E was incorrect.",
edgeListsAreEqual(candidateOne, correctEdgeList));
assertTrue("The third path from A to E was incorrect.",
edgeListsAreEqual(candidateTwo, alternateCorrectEdgeList));
} else {
assertTrue("The second path from A to E was incorrect.",
edgeListsAreEqual(candidateOne, alternateCorrectEdgeList));
assertTrue("The third path from A to E was incorrect.",
edgeListsAreEqual(candidateTwo, correctEdgeList));
}
correctEdgeList.clear();
correctEdgeList.add(new TestEdge(A, B, 1));
correctEdgeList.add(new TestEdge(B, E, 4));
assertTrue("The fourth path rom A to E was incorrect",
edgeListsAreEqual(edgeListIterator.next().edges(), correctEdgeList));
}
@Test
public void testPathsFromSink() {
//H is a sink in this topology, insure there are no paths from it to any other location
for (TestVertex vertex : vertexes()) {
assertTrue("There should be no paths from vertex H to any other node.",
kShortestPathsSearch.search(graph, H, vertex, weight, 1).paths().size() == 0);
}
}
@Test
public void testLimitPathSetSize() {
//Checks to make sure that no more than K paths are returned
result = kShortestPathsSearch.search(graph, A, E, weight, 3);
assertTrue("There are an unexpected number of paths.", result.paths().size() == 3);
result = kShortestPathsSearch.search(graph, A, G, weight, 1);
assertTrue("There are an unexpected number of paths.", result.paths().size() == 1);
}
private boolean edgeListsAreEqual(List<TestEdge> edgeListOne, List<TestEdge> edgeListTwo) {
if (edgeListOne.size() != edgeListTwo.size()) {
return false;
}
TestEdge edgeOne;
TestEdge edgeTwo;
for (int i = 0; i < edgeListOne.size(); i++) {
edgeOne = edgeListOne.get(i);
edgeTwo = edgeListTwo.get(i);
if (!edgeOne.equals(edgeTwo)) {
return false;
}
}
return true;
}
}
\ No newline at end of file
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onlab.graph;
import static com.google.common.collect.ImmutableSet.of;
import static org.junit.Assert.*;
import java.io.ByteArrayOutputStream;
//import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class KshortestPathSearchTest extends BreadthFirstSearchTest {
private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
@Test
public void noPath() {
graph = new AdjacencyListsGraph<>(of(A, B, C, D),
of(new TestEdge(A, B, 1),
new TestEdge(B, A, 1),
new TestEdge(C, D, 1),
new TestEdge(D, C, 1)));
KshortestPathSearch<TestVertex, TestEdge> gs = new KshortestPathSearch<TestVertex, TestEdge>(graph);
List<List<TestEdge>> result = gs.search(A, D, weight, 1);
List<Path> paths = new ArrayList<>();
Iterator<List<TestEdge>> itr = result.iterator();
while (itr.hasNext()) {
System.out.println(itr.next().toString());
}
assertEquals("incorrect paths count", 0, result.size());
}
@Test
public void test2Path() {
graph = new AdjacencyListsGraph<>(of(A, B, C, D),
of(new TestEdge(A, B, 1),
new TestEdge(B, A, 1),
new TestEdge(B, D, 1),
new TestEdge(D, B, 1),
new TestEdge(A, C, 1),
new TestEdge(C, A, 1),
new TestEdge(C, D, 1),
new TestEdge(D, C, 1)));
KshortestPathSearch<TestVertex, TestEdge> gs = new KshortestPathSearch<TestVertex, TestEdge>(graph);
List<List<TestEdge>> result = gs.search(A, D, weight, 2);
List<Path> paths = new ArrayList<>();
Iterator<List<TestEdge>> itr = result.iterator();
while (itr.hasNext()) {
System.out.println(itr.next().toString());
}
assertEquals("incorrect paths count", 2, result.size());
// assertEquals("printing the paths", outContent.toString());
}
@Test
public void test3Path() {
graph = new AdjacencyListsGraph<>(of(A, B, C, D),
of(new TestEdge(A, B, 1),
new TestEdge(B, A, 1),
new TestEdge(A, D, 1),
new TestEdge(D, A, 1),
new TestEdge(B, D, 1),
new TestEdge(D, B, 1),
new TestEdge(A, C, 1),
new TestEdge(C, A, 1),
new TestEdge(C, D, 1),
new TestEdge(D, C, 1)));
KshortestPathSearch<TestVertex, TestEdge> gs = new KshortestPathSearch<TestVertex, TestEdge>(graph);
List<List<TestEdge>> result = gs.search(A, D, weight, 3);
List<Path> paths = new ArrayList<>();
Iterator<List<TestEdge>> itr = result.iterator();
while (itr.hasNext()) {
System.out.println(itr.next().toString());
}
assertEquals("incorrect paths count", 3, result.size());
// assertEquals("printing the paths", outContent.toString());
}
@Test
public void test4Path() {
graph = new AdjacencyListsGraph<>(of(A, B, C, D, E, F),
of(new TestEdge(A, B, 1),
new TestEdge(B, A, 1),
new TestEdge(A, C, 1),
new TestEdge(C, A, 1),
new TestEdge(B, D, 1),
new TestEdge(D, B, 1),
new TestEdge(C, E, 1),
new TestEdge(E, C, 1),
new TestEdge(D, F, 1),
new TestEdge(F, D, 1),
new TestEdge(F, E, 1),
new TestEdge(E, F, 1),
new TestEdge(C, D, 1),
new TestEdge(D, C, 1)));
KshortestPathSearch<TestVertex, TestEdge> gs = new KshortestPathSearch<TestVertex, TestEdge>(graph);
List<List<TestEdge>> result = gs.search(A, F, weight, 4);
List<Path> paths = new ArrayList<>();
Iterator<List<TestEdge>> itr = result.iterator();
while (itr.hasNext()) {
System.out.println(itr.next().toString());
}
assertEquals("incorrect paths count", 4, result.size());
// assertEquals("printing the paths", outContent.toString());
}
@Test
public void test6Path() {
graph = new AdjacencyListsGraph<>(of(A, B, C, D, E, F),
of(new TestEdge(A, B, 1),
new TestEdge(B, A, 1),
new TestEdge(A, C, 1),
new TestEdge(C, A, 1),
new TestEdge(B, D, 1),
new TestEdge(D, B, 1),
new TestEdge(B, C, 1),
new TestEdge(C, B, 1),
new TestEdge(D, E, 1),
new TestEdge(E, D, 1),
new TestEdge(C, E, 1),
new TestEdge(E, C, 1),
new TestEdge(D, F, 1),
new TestEdge(F, D, 1),
new TestEdge(E, F, 1),
new TestEdge(F, E, 1)));
KshortestPathSearch<TestVertex, TestEdge> gs = new KshortestPathSearch<TestVertex, TestEdge>(graph);
List<List<TestEdge>> result = gs.search(A, F, weight, 6);
List<Path> paths = new ArrayList<>();
Iterator<List<TestEdge>> itr = result.iterator();
while (itr.hasNext()) {
System.out.println(itr.next().toString());
}
assertEquals("incorrect paths count", 6, result.size());
// assertEquals("printing the paths", outContent.toString());
}
@Test
public void dualEdgePath() {
graph = new AdjacencyListsGraph<>(of(A, B, C, D, E, F, G, H),
of(new TestEdge(A, B, 1), new TestEdge(A, C, 3),
new TestEdge(B, D, 2), new TestEdge(B, C, 1),
new TestEdge(B, E, 4), new TestEdge(C, E, 1),
new TestEdge(D, H, 5), new TestEdge(D, E, 1),
new TestEdge(E, F, 1), new TestEdge(F, D, 1),
new TestEdge(F, G, 1), new TestEdge(F, H, 1),
new TestEdge(A, E, 3), new TestEdge(B, D, 1)));
KshortestPathSearch<TestVertex, TestEdge> gs = new KshortestPathSearch<TestVertex, TestEdge>(graph);
List<List<TestEdge>> result = gs.search(A, G, weight, 6);
List<Path> paths = new ArrayList<>();
Iterator<List<TestEdge>> itr = result.iterator();
while (itr.hasNext()) {
System.out.println(itr.next().toString());
}
assertEquals("incorrect paths count", 6, result.size());
// assertEquals("printing the paths", outContent.toString());
}
@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
}
@Before
public void setUp() throws Exception {
// System.setOut(new PrintStream(outContent));
}
@After
public void tearDown() throws Exception {
// System.setOut(null);
}
}