arrow-left

All pages
gitbookPowered by GitBook
1 of 5

Loading...

Loading...

Loading...

Loading...

Loading...

9.3. Simplex Algorithm

hashtag
Max-Flow Min-Cut Theorem

Let SSS - TTT cut be a set of edges whose removal disconnects any path between SSS and TTT:

What is the relationship between max-flow and min-cut?

hashtag
Simplex: Prime

hashtag
Simplex: Dual

Maximize p = 0x1 + x2 + 0x3 + x4 subject to
x1 <= 4
x2 <= 2
x3 <= 3
x4 <= 2
x2 - x1 <= 0
x4 - x3 <= 0

Maximize p = 0x1 + 0x2 + 0x3 + 0x4 + 0x5 + 0x6 + x7 + x8  subject to
x1 <= 4
x2 <= 2
x3 <= 3
x4 <= 2
x5 <= 3
x6 <= 1
x7 <= 2
x8 <= 4
x3 - x1 <= 0
x4 + x5 - x2 - x6 <= 0
x6 + x7 - x3 - x4 <= 0
x8 - x5 <= 0
Minimize p = 4x1 + 2x2 + 3x3 + 2x4 + 0y1 + 0y3  subject to
x1 + y1 >= 1
x3 + y3 >= 1
x2 - y1 >= 0
x4 - y3 >= 0

Minimize p = 4x1 + 2x2 + 3x3 + 2x4 +
3x5 + x6 + 2x7 + 4x8 + 0y1 + 0y2 + 0y3 + 0y4  subject to
x1 + y1 >= 1
x2 + y2 >= 1
x3 - y1 + y3 >= 0
x4 - y2 + y3 >= 0
x5 - y2 + y4 >= 0
x6 - y3 + y2 >= 0
x7 - y3 >= 0
x8 - y4 >= 0

9.1. Flow Network

This section describes how to implement a flow network.

A flow network is a directed graph that has the following properties:

hashtag
Max Flow

Let us define the MaxFlowarrow-up-right class that keeps track of the amount of flows in every edge used to find the maximum flow:

  • L2: consists of (edge, flow) as the key-value pair.

  • L3: stores the total amount of flows to the target vertices.

  • L13-14: initializes all flows to 0.

Let us define getter methods:

  • L5: returns the remaining residual that can be used to push more flows.

    • L6: the edge weight represents the total capacity.

Finally, let us define setter methods:

  • L1: takes the path from a source and a target.

    • L2: updates the flow of every edge in the path with the specific flow.

public class MaxFlow {
    private Map<Edge, Double> flow_map;
    private double maxflow;

    public MaxFlow(Graph graph) {
        init(graph);
    }

    public void init(Graph graph) {
        flow_map = new HashMap<>();
        maxflow = 0;

        for (Edge edge : graph.getAllEdges())
            flow_map.put(edge, 0d);
    }
}
L3
: updates the overall flow.
  • L6: adds the specific flow to the specific edge.

  • public double getMaxFlow() {
        return maxflow;
    }
    
    public double getResidual(Edge edge) {
        return edge.getWeight() - flow_map.get(edge);
    }
    public void updateFlow(List<Edge> path, double flow) {
        path.forEach(e -> updateFlow(e, flow));
        maxflow += flow;
    }
    
    public void updateFlow(Edge edge, double flow) {
        Double prev = flow_map.getOrDefault(edge, 0d);
        flow_map.put(edge, prev + flow);
    }

    9.2. Ford-Fulkerson Algorithm

    This section describes the implementation of Ford-Fulkerson Algorithm

    hashtag
    Subgraph

    Let us define the Subgrapharrow-up-right class that consists of a subset of vertices and edges from the original graph:

    Let us define helper methods:

    hashtag
    Ford-Fulkerson

    Ford-Fulkerson algorithm finds the maximum flow from a flow network as follows:

    Let us create the class:

    • L2: indicates one source and one target vertices.

    • L6: iterates as long as it can find an augmenting path

    Let us define the getMin() method:

    Finally, let us define the getAugmentingPath() method:

    • L2: once the source reaches the target, it found an augmenting path.

    • L6: adding the source vertex would cause a cycle.

    • L7

    hashtag
    Backward Pushing

    Let us consider the following graph:

    As shown, our implementation of Ford-Fulkerson Algorithm does not always guarantee to find the maximum flow correctly. To fix this issue, we need to implement backward pushing:

    The backward pushing can be performed after the applying the flow to all edges as in the implementation above (see the code in the "With Backward Pushing" tab).

    Finally, the updateBackward() method can be implemented as follows:

    public class Subgraph {
        private final List<Edge> edges;
        private final Set<Integer> vertices;
    
        public Subgraph() {
            edges = new ArrayList<>();
            vertices = new HashSet<>();
        }
    
        public Subgraph(Subgraph graph) {
            edges = new ArrayList<>(graph.getEdges());
            vertices = new HashSet<>(graph.getVertices());
        }
    }
    public List<Edge> getEdges() { return edges; }
    
    public Set<Integer> getVertices() { return vertices; }
    
    public void addEdge(Edge edge) {
        edges.add(edge);
        vertices.add(edge.getSource());
        vertices.add(edge.getTarget());
    }
    
    public boolean contains(int vertex) {
        return vertices.contains(vertex);
    }
    L7
    : finds the edge with the minimum capacity in the augmenting path.
  • L8: updates the edges in the path with the flow.

  • : cannot push the flow when there is no residual left.
  • L10: recursively finds the augmenting path by switching the target.

  • FordFulkersonarrow-up-right
    public class FordFulkerson implements NetworkFlow {
        public MaxFlow getMaximumFlow(Graph graph, int source, int target) {
            MaxFlow mf = new MaxFlow(graph);
            Subgraph sub;
    
            while ((sub = getAugmentingPath(graph, mf, new Subgraph(), source, target)) != null) {
                double min = getMin(mf, sub.getEdges());
                mf.updateFlow(sub.getEdges(), min);
            }
    
            return mf;
        }
    }
    public class FordFulkerson implements NetworkFlow {
        public MaxFlow getMaximumFlow(Graph graph, int source, int target) {
            MaxFlow mf = new MaxFlow(graph);
            Subgraph sub;
    
            while ((sub = getAugmentingPath(graph, mf, new Subgraph(), source, target)) != null) {
                double min = getMin(mf, sub.getEdges());
                mf.updateFlow(sub.getEdges(), min);
                updateBackward(graph, sub, mf, min);
            }
    
            return mf;
        }
    }
    private double getMin(MaxFlow mf, List<Edge> path) {
        double min = mf.getResidual(path.get(0));
    
        for (int i = 1; i < path.size(); i++)
            min = Math.min(min, mf.getResidual(path.get(i)));
    
        return min;
    }
    private Subgraph getAugmentingPath(Graph graph, MaxFlow mf, Subgraph sub, int source, int target) {
        if (source == target) return sub;
        Subgraph tmp;
    
        for (Edge edge : graph.getIncomingEdges(target)) {
            if (sub.contains(edge.getSource())) continue;
            if (mf.getResidual(edge) <= 0) continue;
            tmp = new Subgraph(sub);
            tmp.addEdge(edge);
            tmp = getAugmentingPath(graph, mf, tmp, source, edge.getSource());
            if (tmp != null) return tmp;
        }
    
        return null;
    }
    protected void updateBackward(Graph graph, Subgraph sub, MaxFlow mf, double min) {
        boolean found;
    
        for (Edge edge : sub.getEdges()) {
            found = false;
    
            for (Edge rEdge : graph.getIncomingEdges(edge.getSource())) {
                if (rEdge.getSource() == edge.getTarget()) {
                    mf.updateFlow(rEdge, -min);
                    found = true;
                    break;
                }
            }
    
            if (!found) {
                Edge rEdge = graph.setDirectedEdge(edge.getTarget(), edge.getSource(), 0);
                mf.updateFlow(rEdge, -min);
            }
        }
    }

    9.3. Quiz

    This section provides exercises for better understanding in network flow

    hashtag
    Augmenting Paths

    An augmenting path is a directed path between the source and target vertices; no need to worry about residuals for this quiz.

    • Create the NetworkFlowQuizarrow-up-right class under the package.

    • Update the getAugmentingPaths() method that returns all augmenting paths between the specific source and target vertices using depth-first traverse.

    hashtag
    Extra Credit

    • Create the NetworkFlowQuizExtra class and update the getAugmentingPaths() method such that it uses breadth-first traverse instead of depth-first traverse.

    hashtag
    Simplex Algorithm

    Given the following graph where there are two source vertices, and , and two target vertices, and , define the objective functions and their constraints to find the (1) max-flow and (2) min-cut using the simplex algorithm:

    hashtag
    Report

    Write quiz8 that includes:

    • The worst-case complexity of your getAugmentingPaths() method.

    • An explanation of when the depth-first traverse is preferred over the breadth-first traverse and vice versa to find augmenting paths.

    • An objective function and is constraints to find max-flow.

    An objective function and is constraints to find min-cut.

    S1S_1S1​
    S2S_2S2​
    T1T_1T1​
    T2T_2T2​
    graph.flowarrow-up-right

    9. Network Flow

    This chapter discusses the optimization problem called Network Flows that finds the maximum flow given a flow network.

    hashtag
    Contents

    1. Flow Networks

    hashtag
    References

  • Ford-Fulkerson Algorithm
    Simplex Algorithm
    Quiz
    Network Flowarrow-up-right
    Flow Networkarrow-up-right
    Maximum Flowarrow-up-right
    Ford-Fulkerson Algorithmarrow-up-right
    Edmonds–Karp Algorithmarrow-up-right
    Simplex Online Toolarrow-up-right
    https://www.slideshare.net/jchoi7s/flow-networkwww.slideshare.netchevron-right
    https://www.slideshare.net/jchoi7s/ford-fulkerson-robustnesswww.slideshare.netchevron-right