Search in sources :

Example 11 with Edge

use of org.openkilda.pce.model.Edge in project open-kilda by telstra.

the class BestWeightAndShortestPathFinder method findNPathsBetweenSwitches.

/**
 * Find N (or less) best paths. To find N paths Yen's algorithm is used.
 *
 * @return an list of N (or less) best paths.
 */
private List<List<Edge>> findNPathsBetweenSwitches(AvailableNetwork network, SwitchId startSwitchId, SwitchId endSwitchId, int count, WeightFunction weightFunction, Function<Node, FindOneDirectionPathResult> getPath) throws UnroutableFlowException {
    Node start = network.getSwitch(startSwitchId);
    Node end = network.getSwitch(endSwitchId);
    if (start == null || end == null) {
        throw new UnroutableFlowException(format("Switch %s doesn't have links with enough bandwidth", start == null ? startSwitchId : endSwitchId));
    }
    // Determine the shortest path from the start to the end.
    List<List<Edge>> bestPaths = new ArrayList<>();
    List<Edge> firstPath = getPath.apply(start).getFoundPath();
    if (firstPath.isEmpty()) {
        return new ArrayList<>();
    }
    bestPaths.add(getPath.apply(start).getFoundPath());
    // Initialize the set to store the potential kth shortest path.
    // Use LinkedHashSet to have deterministic results.
    Set<List<Edge>> potentialKthShortestPaths = new LinkedHashSet<>();
    for (int k = 1; k < count; k++) {
        List<Edge> bestPath = bestPaths.get(k - 1);
        for (int i = 0; i < bestPath.size(); i++) {
            // Spur node is retrieved from the previous k-shortest path.
            Node spurNode = bestPath.get(i).getSrcSwitch();
            // The sequence of edges from the start to the spur node (without spur node).
            List<Edge> rootPath = new ArrayList<>(bestPath.subList(0, i));
            Set<Edge> removedEdges = new HashSet<>();
            // Remove the links that are part of the previous shortest paths which share the same root path.
            for (List<Edge> path : bestPaths) {
                if (path.size() > i && rootPath.equals(path.subList(0, i)) && spurNode.equals(path.get(i).getSrcSwitch())) {
                    removedEdges.add(path.get(i));
                    removeEdge(path.get(i));
                }
            }
            for (Edge edge : rootPath) {
                edge.getSrcSwitch().remove();
            }
            // Calculate the spur path from the spur node to the end.
            List<Edge> pathFromSpurNode = getPath.apply(spurNode).getFoundPath();
            if (!pathFromSpurNode.isEmpty()) {
                List<Edge> totalPath = new ArrayList<>(rootPath);
                // Entire path is made up of the root path and spur path.
                totalPath.addAll(pathFromSpurNode);
                // Add the potential k-shortest path to the heap.
                potentialKthShortestPaths.add(totalPath);
            }
            // Add back the edges and nodes that were removed from the graph.
            for (Edge edge : removedEdges) {
                restoreEdge(edge);
            }
            for (Edge edge : rootPath) {
                edge.getSrcSwitch().restore();
            }
        }
        if (potentialKthShortestPaths.isEmpty()) {
            break;
        }
        // Add the lowest weight path becomes the k-shortest path.
        List<Edge> newBestPath = getBestPotentialKthShortestPath(potentialKthShortestPaths, bestPaths, weightFunction);
        bestPaths.add(newBestPath);
    }
    return bestPaths;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Node(org.openkilda.pce.model.Node) UnroutableFlowException(org.openkilda.pce.exception.UnroutableFlowException) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) Collections.emptyList(java.util.Collections.emptyList) List(java.util.List) Edge(org.openkilda.pce.model.Edge) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 12 with Edge

use of org.openkilda.pce.model.Edge in project open-kilda by telstra.

the class BestWeightAndShortestPathFinderTest method shouldReturnTheShortestPath.

@Test
public void shouldReturnTheShortestPath() throws UnroutableFlowException {
    AvailableNetwork network = buildTestNetwork();
    BestWeightAndShortestPathFinder pathFinder = new BestWeightAndShortestPathFinder(ALLOWED_DEPTH);
    Pair<List<Edge>, List<Edge>> pairPath = pathFinder.findPathWithMinWeight(network, SWITCH_ID_E, SWITCH_ID_F, WEIGHT_FUNCTION).getFoundPath();
    List<Edge> fpath = pairPath.getLeft();
    assertThat(fpath, Matchers.hasSize(2));
    assertEquals(SWITCH_ID_E, fpath.get(0).getSrcSwitch().getSwitchId());
    assertEquals(SWITCH_ID_F, fpath.get(1).getDestSwitch().getSwitchId());
    List<Edge> rpath = pairPath.getRight();
    assertThat(rpath, Matchers.hasSize(2));
    assertEquals(SWITCH_ID_F, rpath.get(0).getSrcSwitch().getSwitchId());
    assertEquals(SWITCH_ID_E, rpath.get(1).getDestSwitch().getSwitchId());
}
Also used : ArrayList(java.util.ArrayList) List(java.util.List) AvailableNetwork(org.openkilda.pce.impl.AvailableNetwork) Edge(org.openkilda.pce.model.Edge) Test(org.junit.Test)

Example 13 with Edge

use of org.openkilda.pce.model.Edge in project open-kilda by telstra.

the class BestWeightAndShortestPathFinderTest method shouldFindSymmetricPath.

@Test
public void shouldFindSymmetricPath() throws UnroutableFlowException {
    AvailableNetwork network = buildLinearNetworkWithPairLinks();
    BestWeightAndShortestPathFinder pathFinder = new BestWeightAndShortestPathFinder(2);
    Pair<List<Edge>, List<Edge>> pathPair = pathFinder.findPathWithMinWeight(network, SWITCH_ID_1, SWITCH_ID_3, WEIGHT_FUNCTION).getFoundPath();
    List<Edge> forward = pathPair.getLeft();
    List<Edge> reverse = Lists.reverse(pathPair.getRight());
    List<Boolean> validation = IntStream.range(0, forward.size()).mapToObj(i -> Objects.equals(forward.get(i).getSrcPort(), reverse.get(i).getDestPort())).collect(Collectors.toList());
    assertFalse(validation.contains(false));
}
Also used : IntStream(java.util.stream.IntStream) PathWeight(org.openkilda.pce.model.PathWeight) Arrays(java.util.Arrays) CoreMatchers.equalTo(org.hamcrest.CoreMatchers.equalTo) Assert.assertTrue(org.junit.Assert.assertTrue) Matchers(org.hamcrest.Matchers) Test(org.junit.Test) Collectors(java.util.stream.Collectors) WeightFunction(org.openkilda.pce.model.WeightFunction) ArrayList(java.util.ArrayList) Assert.assertThat(org.junit.Assert.assertThat) Objects(java.util.Objects) UnroutableFlowException(org.openkilda.pce.exception.UnroutableFlowException) Edge(org.openkilda.pce.model.Edge) List(java.util.List) Lists(com.google.common.collect.Lists) SwitchId(org.openkilda.model.SwitchId) Pair(org.apache.commons.lang3.tuple.Pair) FindPathResult(org.openkilda.pce.model.FindPathResult) Assert.assertFalse(org.junit.Assert.assertFalse) Assert.assertEquals(org.junit.Assert.assertEquals) AvailableNetwork(org.openkilda.pce.impl.AvailableNetwork) ArrayList(java.util.ArrayList) List(java.util.List) AvailableNetwork(org.openkilda.pce.impl.AvailableNetwork) Edge(org.openkilda.pce.model.Edge) Test(org.junit.Test)

Example 14 with Edge

use of org.openkilda.pce.model.Edge in project open-kilda by telstra.

the class AvailableNetworkFactory method addIslAsEdge.

private void addIslAsEdge(IslImmutableView isl, AvailableNetwork network) {
    Node srcSwitch = network.getOrAddNode(isl.getSrcSwitchId(), isl.getSrcPop());
    Node dstSwitch = network.getOrAddNode(isl.getDestSwitchId(), isl.getDestPop());
    Edge edge = Edge.builder().srcSwitch(srcSwitch).srcPort(isl.getSrcPort()).destSwitch(dstSwitch).destPort(isl.getDestPort()).cost(isl.getCost()).latency(isl.getLatency()).underMaintenance(isl.isUnderMaintenance()).unstable(isl.isUnstable()).availableBandwidth(isl.getAvailableBandwidth()).build();
    network.addEdge(edge);
}
Also used : Node(org.openkilda.pce.model.Node) Edge(org.openkilda.pce.model.Edge)

Example 15 with Edge

use of org.openkilda.pce.model.Edge in project open-kilda by telstra.

the class BestWeightAndShortestPathFinder method removeEdge.

private void removeEdge(Edge edge) {
    edge.getSrcSwitch().getOutgoingLinks().remove(edge);
    edge.getDestSwitch().getIncomingLinks().remove(edge);
    Edge reverseEdge = edge.swap();
    reverseEdge.getSrcSwitch().getOutgoingLinks().remove(reverseEdge);
    reverseEdge.getDestSwitch().getIncomingLinks().remove(reverseEdge);
}
Also used : Edge(org.openkilda.pce.model.Edge)

Aggregations

Edge (org.openkilda.pce.model.Edge)39 Test (org.junit.Test)23 ArrayList (java.util.ArrayList)16 List (java.util.List)16 Node (org.openkilda.pce.model.Node)15 AvailableNetwork (org.openkilda.pce.impl.AvailableNetwork)13 SwitchId (org.openkilda.model.SwitchId)7 WeightFunction (org.openkilda.pce.model.WeightFunction)7 HashSet (java.util.HashSet)5 PathSegment (org.openkilda.model.PathSegment)5 UnroutableFlowException (org.openkilda.pce.exception.UnroutableFlowException)5 LinkedList (java.util.LinkedList)4 FindPathResult (org.openkilda.pce.model.FindPathResult)4 Collections.emptyList (java.util.Collections.emptyList)3 Objects (java.util.Objects)3 Set (java.util.Set)3 Collectors (java.util.stream.Collectors)3 Slf4j (lombok.extern.slf4j.Slf4j)3 PathWeight (org.openkilda.pce.model.PathWeight)3 VisibleForTesting (com.google.common.annotations.VisibleForTesting)2