Network Flows

As quick as possible then:

  1. Flow Networks
  2. Min Cut Max Flow
  3. Bipartite Matching

Flow Networks

Definition. A flow network is a directed graph modelled as a tuple \(G = (V,E,s,t,c)\), where \(s, t\) are the source and sink nodes respectively, and capacity is an array such that \(c(e) \geq 0\) is the capacity of edge \(e\).

Definition. An st-flow \(f\) is a function (i.e. it assigns a number to an edge) that satisfies \begin{align} &\forall e \in E &0 \leq f(e) \leq c(e) \\ &\forall v \in V \setminus \{s,t\} &\sum_{\textrm{into }v} f(e) = \sum_{\textrm{out of } v}f(e) \end{align} Which in english are (1) flow along edge not greater than cap and (2) flow in = flow out

Definition. The value of a flow \(val(f) = \sum_{\textrm{into }s} f(e) - \sum_{\textrm{out of } s}f(e)\): the net flow of the source.

Main Problem. Find the flow of maximum value.

The main method to solve this is the Ford-Fulkerson Algorithm, which is taught in the Discrete section of A Level Further Maths. It relies on the idea of augmenting flows.

The idea is to have a residual graph \(G_f\), which is the backwards graph and has values equal to \(c(e) - f(e)\) for the current flow of an edge. Then, go through the graph repeatedly, finding a passable flow along the arrows (using the backwards arrows if needed) until \(s\) and \(t\) are partitioned into two separate cutsets, with the cut going through all saturated (\(f(e) = c(e)\)) edges.

This seems like a decent enough video.

See the pseuduocde for FORD-FULKERSON, and the helper function AUGMENT

Note the bottleneck, as name implies, is the least roomy edge on the path.

def AUGMENT(\(f,c,P\)): \(\delta \longleftarrow\) bottleneck of augmenting path \(P\) for each edge \(e \in P\): if \(e \in E\): # right way edge \(f(e) \longleftarrow f(e) + \delta\) else: # residual edge \(f(e^{\textrm{reverse}) \longleftarrow f(e^{\textrm{reverse}) - \delta\) return \(f\)

def FORD_FULKERSON(\(G\)): for each edge \(e \in E\): \(f(e) \longleftarrow 0\) \(G_f \longleftarrow\) residual network of \(G\) with respect to \(f\) while exists \(s \leadsto t\) path \(P\) in \(G_f\): \(f \longleftarrow\) AUGMENT(\(f,c,P\)) update \(G_f\) return \(f\)

The idea of cuts is very important:

Min Cut, Max Flow

Definition. an st-cut is a partition \((A,B)\) where \(s \in A,\; t \in B\). The capacity of this cut is the sum of the capacities of the edges \(cap(A,B) = \sum_{e\textrm{ leaving }A}c(e)\).

Lemma 1. (Flow Value) let \(f\) be a flow and \((A,B)\) be an st-cut. The value of flow \(f\) is the net flow across the cut: \[val(f) = \sum_{e \textrm{ out of }A} f(e) - \sum_{e\textrm{ into }A}f(e).\]

Proofs are omitted at this current stage for speed.

As a corollary, max flow = min cut. So, find the min cut to find the max flow.

Theorem 1. (Augmenting Path Thm.) Flow \(f\) is a max flow if and only if there are no available augmenting paths. This proves correctness of the FF algorithm.

Theorem 2. Given a max flow \(f\), we can find the min cut in \(O(m)\) time (\(m\) edges).

Running Time of Ford Fulkerson

Assume that all capacities are positive integers between 1 and some \(C\).

Define the integrality invariant: that throughout FF, every edge's flow and residual capacity will remain integers. Then,

Theorem 3. Ford Fulkerson terminates in at most \(val(f*)\) iterations (\(f*\) means max flow). And also, \[val(f*) \leq nC.\]

This leads to the corollary that the running time of FF is \(O(mnC)\), because FF finds the max flow value, from which we can use DFS/BFS to find the min cut.

Theorem 4. If we assume the integrality constraint, we can guarantee that our max flow is also integral.

Note that the generic FF is not necessarily polynomial, for FF to be poly time, it must be poly on \(m, n, \log_2 C\) (C is a binary value to the computer).

You can engineer graphs that absolutely break a generic, non-deterministic FF algorithm. Suppose

Vertices s v w t
Edges (s,v) (s,w) (v,w) (v,t) (w,t)
Capacities C C 1 C C
This will royally ████ with a PC randomly picking paths, because it could forever pick the path \((s,v,w,t)\) and increment by 1 each time to some stupidly large number \(C\). Now as humans we can easily see past this, but PCs aren't humans ... yet at least.

Thus, in reality we need some way of choosing path good.

Capacity Scaling

The idea of capacity-scaling is to choose a path with a "large enough" capacity, i.e. have a scaling value \(\Delta\) and only pick paths with a bottleneck larger than it.

Alter the algorithm so we have a \(G_f(\Delta)\) be the subgraph of \(G_f\) with all edges lower than Delta removed. Find augmenting paths. Halve Delta. Rinse and repeat.

def CAPCITY_SCALING(\(G\)): for each edge \(e \in E\): \(f(e) \longleftarrow 0\) \(\Delta \longleftarrow\) largest power of 2 that is \(\leq C\) while \(\Delta \geq 1\): \(G_f(\Delta) \longleftarrow\) as described above while exists \(s \leadsto t\) path \(P\) in \(G_f(\Delta)\): \(f \longleftarrow\) AUGMENT(\(f,c,P)\)) update \(G_f(\Delta)\) \(\Delta \longleftarrow \frac{\Delta}{2}\) return \(f\)

Lemma 2. There are \(1 + \left\lfloor{\log_2 C}\right\rfloor \) scaling phases.

Lemma 3. There are \(\leq 2m\) augmentations every scaling phase.

Theorem 5. Thus from the above, capacity scaling has a time complexity of \(O(m^2 \log C\).

Lemma 4. Let \(f\) be a flow at the end of a delta-scaling phase, \[\textrm{max flow } \leq val(f) + m\Delta\] \[\textrm{or }val(f) \geq val(f*) - m\Delta.\]

Bipartite Matching

This section looks at bipartite graphs. Bipartite graphs can be defined \(G(L \cup R, E)\) with a distinct left and right side.

Simple Matching

Definition. A matching in a graph \(G(V,E)\) is a set of edges \(M \subseteq E\) where each node appears in at most 1 edge.

Definition. A bipartite matching is a matching in a bipartite graph, and we want to find the max cardinality (largest) matching.

The matching problem can actually be solved with (reduced to) flows. Given a bipartite graph \(G(L \cup R, E)\):

Theorem 6. There is now a 1-1 correspondence between the max matching size \(k\) in \(G\) and the max flow value in \(G'\).

A corollary is that we can solve bipartite matching in poly-time with max flow. Granted, non-bipartite matchings are also poly-time, but irrelevant.

Perfect Matching

Definition. Given a graph \(G=(V,E)\), a subset \(M \subseteq E\) is a perfect matching if every node appears in \(M\) (M is a vertex cover and a matching).

Since we match one left node to one right node in a matching, it reasons that a bipartite graph with a perfect matching must have \(|L| = |R|\).

Let us denote, for a set \(S\) of nodes, \(N(S)\) as the neighbours of all nodes in \(S\).

Theorem 7. (Hall's Marriage) Given a bipartite graph \(G = (L \cup R, E) : |L| = |R|\), G has a perfect matching if and only if \(|N(S)| \geq |S|\; \forall S \subseteq L\).

Proofs are left as an excersise to the reader.