Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2015-present Open Networking Foundation
*
* 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> extends AbstractGraphPathSearch {
private final Logger log = getLogger(getClass());
@Override
protected Result internalSearch(Graph graph, V src, V dst, EdgeWeigher weigher, int maxPaths) {
//The modified edge weigher removes any need to modify the original graph
InnerEdgeWeigher modifiedWeighter = new InnerEdgeWeigher(checkNotNull(weigher));
checkArgument(maxPaths != ALL_PATHS, "KShortestPath search cannot" +
"be used with ALL_PATHS.");
checkArgument(maxPaths > 0, "The max number of paths must be greater" +
" than 0");
Graph originalGraph = checkNotNull(graph);
//the result contains the set of eventual results
InnerOrderedResult result = new InnerOrderedResult(src, dst, maxPaths);
ArrayList> resultPaths = new ArrayList<>(maxPaths);
ArrayList> potentialPaths = Lists.newArrayList();
DijkstraGraphSearch dijkstraSearch = new DijkstraGraphSearch<>();
Set> dijkstraResults = dijkstraSearch.search(originalGraph, src, dst, modifiedWeighter, 1).paths();
//Checks if the dst was reachable
if (dijkstraResults.isEmpty()) {
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(); i++) {
V spurNode = resultPaths.get(k - 1).edges().get(i).src();
List rootPathEdgeList = resultPaths.get(k - 1).edges().subList(0, i);
for (Path path : resultPaths) {
if (path.edges().size() >= i && 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.isEmpty()) {
Path spurPath = dijkstraResults.iterator().next();
List totalPath = new ArrayList<>(rootPathEdgeList);
spurPath.edges().forEach(totalPath::add);
//The following line must use the original weigher not the modified weigher because the modified
//weigher will count -1 values used for modifying the graph and return an inaccurate cost.
potentialPaths.add(new DefaultPath<>(totalPath,
calculatePathCost(weigher, 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 edgeListOne, List 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 Weight calculatePathCost(EdgeWeigher weighter, List edges) {
Weight totalCost = weighter.getInitialWeight();
for (E edge : edges) {
totalCost = totalCost.merge(weighter.weight(edge));
}
return totalCost;
}
/**
* Weights edges to make them inaccessible if set, otherwise returns the result of the original EdgeWeight.
*/
private final class InnerEdgeWeigher implements EdgeWeigher {
private Set removedEdges = Sets.newConcurrentHashSet();
private EdgeWeigher innerEdgeWeigher;
private InnerEdgeWeigher(EdgeWeigher weigher) {
this.innerEdgeWeigher = weigher;
}
@Override
public Weight weight(E edge) {
if (removedEdges.contains(edge)) {
return innerEdgeWeigher.getNonViableWeight();
}
return innerEdgeWeigher.weight(edge);
}
@Override
public Weight getInitialWeight() {
return innerEdgeWeigher.getInitialWeight();
}
@Override
public Weight getNonViableWeight() {
return innerEdgeWeigher.getNonViableWeight();
}
}
/**
* A result modified to return paths ordered according to the provided comparator.
*/
protected class InnerOrderedResult extends DefaultResult {
private TreeSet> 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> paths() {
return ImmutableSet.copyOf(pathSet);
}
}
/**
* Provides a comparator to order the set of paths.
*/
private class InnerPathComparator implements Comparator> {
@Override
public int compare(Path pathOne, Path pathTwo) {
int comparisonValue = pathOne.cost().compareTo(pathTwo.cost());
if (comparisonValue != 0) {
return comparisonValue;
} else if (edgeListsAreEqual(pathOne.edges(), pathTwo.edges())) {
return 0;
} else {
return 1;
}
}
}
}