Skip to content

Commit

Permalink
Using AsWeightedGraph and fixing bug with sequential calls to getPaths.
Browse files Browse the repository at this point in the history
  • Loading branch information
mizrachi committed Jul 23, 2018
1 parent b1c0628 commit e66b65c
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ abstract class BaseKDisjointShortestPathsAlgorithm<V, E> implements KShortestPat

protected Set<E> overlappingEdges;

protected HashMap<E, Double> weightMap;

protected Graph<V, E> originalGraph;

/**
Expand All @@ -56,12 +54,8 @@ public BaseKDisjointShortestPathsAlgorithm(Graph<V, E> graph) {
GraphTests.requireDirected(graph);
if (!GraphTests.isSimple(graph)) {
throw new IllegalArgumentException("Graph must be simple");
}
//Assuring all weights modifications are not applied to original graph
this.weightMap = new HashMap<>();
this.workingGraph = new AsWeightedGraph<>(new DefaultDirectedGraph<>(
this.originalGraph.getVertexSupplier(), this.originalGraph.getEdgeSupplier(), false), weightMap);
Graphs.addGraph(workingGraph, this.originalGraph);
}

}

/**
Expand All @@ -88,19 +82,18 @@ public List<GraphPath<V, E>> getPaths(V startVertex, V endVertex, int k)
if (endVertex.equals(startVertex)) {
throw new IllegalArgumentException("The end vertex is the same as the start vertex!");
}
if (!workingGraph.vertexSet().contains(startVertex)) {
if (!originalGraph.containsVertex(startVertex)) {
throw new IllegalArgumentException("graph must contain the start vertex!");
}
if (!workingGraph.vertexSet().contains(endVertex)) {
if (!originalGraph.containsVertex(endVertex)) {
throw new IllegalArgumentException("graph must contain the end vertex!");
}
}

//original edge weights may have changed due to previous calls
if (this.originalGraph.getType().isWeighted()) {
this.originalGraph.edgeSet().forEach(e -> {
this.weightMap.put(e, this.originalGraph.getEdgeWeight(e));
});
}
//avoiding original graph modifications and residuals from previous calls
this.workingGraph = new AsWeightedGraph<>(new DefaultDirectedWeightedGraph<>(
this.originalGraph.getVertexSupplier(), this.originalGraph.getEdgeSupplier()),
new HashMap<>(), false);
Graphs.addGraph(workingGraph, this.originalGraph);

GraphPath<V, E> currentPath;
this.pathList = new ArrayList<>();
Expand Down Expand Up @@ -163,7 +156,7 @@ private List<GraphPath<V, E>> buildPaths(V startVertex, V endVertex)
.collect(Collectors.toSet());

for (E e : nonOverlappingEdges) {
V u = workingGraph.getEdgeSource(e);
V u = getEdgeSource(e);
if (u.equals(startVertex)) { // start of a new path
List<E> path = new ArrayList<>();
path.add(e);
Expand All @@ -178,11 +171,11 @@ private List<GraphPath<V, E>> buildPaths(V startVertex, V endVertex)

// Build the paths using the lookup table
for (List<E> path : paths) {
V v = workingGraph.getEdgeTarget(path.get(0));
V v = getEdgeTarget(path.get(0));
while (!v.equals(endVertex)) {
E e = sourceToEdgeLookup.get(v).poll();
path.add(e);
v = workingGraph.getEdgeTarget(e);
v = getEdgeTarget(e);
}
}

Expand All @@ -205,8 +198,8 @@ private void findOverlappingEdges()
Map<UnorderedPair<V, V>, Integer> edgeOccurrenceCount = new HashMap<>();
for (List<E> path : pathList) {
for (E e : path) {
V v = this.workingGraph.getEdgeSource(e);
V u = this.workingGraph.getEdgeTarget(e);
V v = this.getEdgeSource(e);
V u = this.getEdgeTarget(e);
UnorderedPair<V, V> edgePair = new UnorderedPair<>(v, u);

if (edgeOccurrenceCount.containsKey(edgePair)) {
Expand All @@ -219,8 +212,8 @@ private void findOverlappingEdges()

this.overlappingEdges = pathList.stream().flatMap(List::stream).filter(
e -> edgeOccurrenceCount.get(new UnorderedPair<>(
this.workingGraph.getEdgeSource(e),
this.workingGraph.getEdgeTarget(e))) > 1)
this.getEdgeSource(e),
this.getEdgeTarget(e))) > 1)
.collect(Collectors.toSet());
}

Expand All @@ -232,6 +225,14 @@ private GraphPath<V, E> createGraphPath(List<E> edgeList, V startVertex, V endVe
}
return new GraphWalk<>(originalGraph, startVertex, endVertex, edgeList, weight);
}

private V getEdgeSource(E e) {
return this.workingGraph.containsEdge(e) ? this.workingGraph.getEdgeSource(e) : this.originalGraph.getEdgeSource(e);
}

private V getEdgeTarget(E e) {
return this.workingGraph.containsEdge(e) ? this.workingGraph.getEdgeTarget(e) : this.originalGraph.getEdgeTarget(e);
}


/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,11 @@ protected void prepare(List<E> previousPath)
for (E originalEdge : previousPath) {
source = workingGraph.getEdgeSource(originalEdge);
target = workingGraph.getEdgeTarget(originalEdge);
double originalEdgeWeight = workingGraph.getEdgeWeight(originalEdge);
workingGraph.removeEdge(originalEdge);
reversedEdge = workingGraph.addEdge(target, source);
if (reversedEdge != null) {
workingGraph.setEdgeWeight(reversedEdge, -workingGraph.getEdgeWeight(originalEdge));
workingGraph.setEdgeWeight(reversedEdge, -originalEdgeWeight);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,26 @@ public void testThreeDisjointPaths()
assertEquals(9.0, pathList.get(2).getWeight(), 0.0);

}

/**
* Tests that sequential calls return the same result.
*/
@Test
public void testSequentialCallsSanity() {
DefaultDirectedWeightedGraph<Integer, DefaultWeightedEdge> graph =
new DefaultDirectedWeightedGraph<>(DefaultWeightedEdge.class);
graph.addVertex(1);
graph.addVertex(2);
DefaultWeightedEdge edge = graph.addEdge(1, 2);
graph.setEdgeWeight(edge, 8);
KShortestPathAlgorithm<Integer, DefaultWeightedEdge> alg = getKShortestPathAlgorithm(graph);

List<GraphPath<Integer, DefaultWeightedEdge>> pathList_1 = alg.getPaths(1, 2, 5);
List<GraphPath<Integer, DefaultWeightedEdge>> pathList_2 = alg.getPaths(1, 2, 5);

assertEquals(pathList_1, pathList_2);

}

private Graph<Integer, DefaultWeightedEdge> createThreeDisjointPathsGraph()
{
Expand Down

0 comments on commit e66b65c

Please sign in to comment.