Why Lower Bounds Change the Starting Point
Ordinary maximum flow starts from the all-zero solution. That works because every edge permits zero flow. A lower bound removes that convenience: if a contract requires at least two units on an edge, zero is illegal before the algorithm even begins.
From flow to circulation
Lower Bounds and the Balance Ledger
Each directed edge $(u,v)$ has lower bound $\ell(u,v)$ and upper bound $c(u,v)$:
A circulation must also conserve flow at every vertex:
The reduction first commits every lower bound by writing $f(u,v)=\ell(u,v)+x(u,v)$. The new variable $x$ is the extra flow we may still choose, with capacity $0\le x(u,v)\le c(u,v)-\ell(u,v)$.
Define the committed imbalance using one fixed sign convention:
| Balance | What lower bounds did | What residual flow must do | Auxiliary edge |
|---|---|---|---|
| $b(v)>0$ | Left excess committed inflow | Send $b(v)$ more out | $S^*\to v$ with capacity $b(v)$ |
| $b(v)<0$ | Left a committed inflow deficit | Receive $-b(v)$ more | $v\to T^*$ with capacity $-b(v)$ |
| $b(v)=0$ | Already balanced | No repair required | None |
A free sanity check
Every committed edge subtracts its lower bound at one endpoint and adds the same amount at the other, so $\sum_v b(v)=0$. If your balance array does not sum to zero, the bookkeeping—not the network—is wrong.
The Super-Source Reduction
Create a new source $S^*$ and sink $T^*$. Keep each original edge with residual capacity $c-\ell$, then connect the balance ledger to the two auxiliary vertices.
flowchart TD
L[Commit every lower bound] --> B[Compute each balance b]
B --> A[Add residual capacities and auxiliary edges]
A --> F[Run max flow from S* to T*]
F --> Q{Every S* edge saturated?}
Q -->|Yes| Y[Feasible circulation]
Q -->|No| N[No feasible circulation]- For each bounded edge $(u,v,\ell,c)$, add an ordinary edge $u\to v$ of capacity $c-\ell$.
- Update $b(u)\mathrel{-}=\ell$ and $b(v)\mathrel{+}=\ell$.
- If $b(v)>0$, add $S^*\to v$ with capacity $b(v)$ and add that amount to the required auxiliary flow.
- If $b(v)<0$, add $v\to T^*$ with capacity $-b(v)$.
- Run max flow from $S^*$ to $T^*$. Feasibility is equivalent to sending the full required amount.
The test in one sentence
The auxiliary max flow tries to route every unit of excess committed inflow through unused original capacity until it reaches a vertex with a committed inflow deficit.
Worked Example: Repairing the Triangle
For the three-edge network above, the lower-bound ledger is:
| Vertex | Committed inflow | Committed outflow | $b(v)$ | Auxiliary edge |
|---|---|---|---|---|
| A | $0$ | $2$ | $-2$ | $A\to T^*$, capacity $2$ |
| B | $2$ | $1$ | $+1$ | $S^*\to B$, capacity $1$ |
| C | $1$ | $0$ | $+1$ | $S^*\to C$, capacity $1$ |
Add the repair flow back to the committed lower bounds:
| Original edge | Lower-bound commitment | Residual repair | Final flow | Within bounds? |
|---|---|---|---|---|
| $A\to B$ | $2$ | $0$ | $2$ | Yes: $2\le2\le5$ |
| $B\to C$ | $1$ | $1$ | $2$ | Yes: $1\le2\le4$ |
| $C\to A$ | $0$ | $2$ | $2$ | Yes: $0\le2\le3$ |
The final circulation sends two units around the entire triangle. Every vertex now receives two and sends two, so conservation and all edge bounds hold simultaneously.
Turning a Bounded $s$–$t$ Flow into a Circulation
A normal $s$–$t$ flow intentionally violates conservation at two vertices: $s$ has net outflow and $t$ has net inflow. Close that accounting loop by adding an artificial edge $t\to s$ with lower bound $0$ and a safely large upper bound, then run the same circulation-feasibility reduction.
1. Close the loop
Add $t\to s$. Its flow represents the value transported from $s$ to $t$.
2. Find feasibility
Attach $S^*$ and $T^*$ from balances and saturate all required auxiliary flow.
3. Optimize if needed
Remove auxiliary vertices and the artificial edge, then augment in the appropriate residual direction.
For a maximum feasible bounded $s$–$t$ flow, record the current flow $F_0$ on the artificial $t\to s$ edge. Disable that edge and its paired reverse residual edge, remove $S^*$ and $T^*$, then run ordinary max flow from $s$ to $t$ on the remaining residual network. If that run adds $\Delta$, the answer is $F_0+\Delta$.
“Infinite” should still be finite
In code, use a proven upper bound such as the sum of relevant capacities, not the numeric maximum of the data type. A defensible finite bound avoids overflow in later arithmetic.
Why Saturation Proves Feasibility
The reduction preserves each requirement for a different reason:
Lower bounds
They were committed before max flow began and are added back during reconstruction.
Upper bounds
Extra flow uses capacity $c-\ell$, so commitment plus repair never exceeds $c$.
Conservation
Saturating every auxiliary requirement routes exactly enough repair flow to cancel every balance.
If the maximum auxiliary flow is smaller than $\sum_{b(v)>0}b(v)$, some committed excess cannot reach the deficits through residual capacity. No different arrangement can satisfy all lower bounds, upper bounds, and conservation: the max-flow/min-cut theorem supplies the obstruction.
Implementation: Build the Reduction Carefully
The reusable code is not a new max-flow algorithm. It is a wrapper that converts bounded edges into ordinary residual edges and a balance array, then calls an existing max-flow implementation.
The snippets assume addEdge creates the usual paired forward and reverse residual edges. Keep the original lower bound alongside the residual edge so final flow can be reconstructed as $\ell+x$.
Implementation checklist
- Reject every edge with $\ell>c$ before building the graph.
- Choose and document one balance sign convention; never mix formulas from the opposite convention.
- Use wide integers for capacities, balances, and their sums.
- Compare achieved auxiliary flow with the sum of all $S^*$-edge capacities.
- Recover each original flow by adding its lower bound to the used residual flow.
- Exclude auxiliary and artificial edges from the final domain solution.
Minimum Commitments in Real Networks
Lower bounds represent promises, minimum service levels, or obligations; upper bounds represent physical or policy limits.
Contracted Shipments
Customer lanes require minimum weekly volume while plants, warehouses, and roads impose upper limits.
Reserved Bandwidth
Service guarantees reserve minimum throughput while link capacity restricts the total routed traffic.
Minimum Staffing
Shift and role edges encode mandatory coverage alongside maximum worker availability.
Cash-Flow Obligations
Required transfers and account limits can be tested for simultaneous feasibility before costs are optimized.
Feasibility answers only “can every commitment be honored?” If multiple feasible circulations have different prices, add costs and solve a minimum-cost circulation or flow after applying the same lower-bound transformation.
Diagnosing an Infeasible Instance
A failed max-flow run is useful evidence, not merely a boolean result. Vertices reachable from $S^*$ in the final residual graph define a cut: the original residual edges crossing that cut do not have enough capacity to transport all committed excess toward the required deficits.
Common sources of failure
- An individual lower bound already exceeds its upper bound.
- A group of vertices promises more outgoing flow than the rest of the network can return.
- A required repair exists in the wrong direction because edges are directed.
- The model omitted a legitimate route, duplicated a commitment, or used the wrong balance sign.
Test the worked example
Change the upper bound of $C\to A$ from $3$ to $1$. Does a feasible circulation remain?
Answer: no. After committing lower bounds, A still needs two units of residual inflow, but $C\to A$ can now carry only one extra unit and no other residual edge enters A.
Complexity, Limits, and When to Use It
The transformation adds exactly two vertices and at most one auxiliary edge per original vertex. With $V'=V+2$ and $E'=E+O(V)$, runtime is dominated by the chosen max-flow engine on the transformed graph. Reconstruction is linear in the number of original edges.
| Problem | Recommended starting point | Why |
|---|---|---|
| All lower bounds are zero | Ordinary max flow | The zero flow is already a feasible starting point. |
| Only feasibility with lower/upper bounds | This circulation reduction + Dinic | Directly converts the problem to one max-flow run. |
| Feasibility plus linear per-unit costs | Minimum-cost circulation | Chooses the cheapest solution after satisfying bounds. |
| Logical, nonlinear, or cross-edge constraints | LP/MIP or constraint solver | Ordinary flow conservation cannot express every business rule. |
Mental model to keep
Commit every promise, record who became over-supplied and under-supplied, then ask unused network capacity to rebalance the ledger. Saturating all super-source edges means every promise can coexist.