Overview
When you have a new problem to solve and you already have an algorithm that solves a related problem, there are two general strategies for building an algorithm out of it:
- Modification — change the existing algorithm’s internal logic so it directly tracks/solves the new problem.
- Reduction — leave the existing algorithm untouched, and instead transform the input of the new problem into an instance of the old one, calling the existing algorithm as a subroutine.
This note works through both strategies using the Max Bandwidth Problem as a running example.
Driving Example: Max Bandwidth Problem Graph represents a network, with edges representing communication links. Edge weights are the bandwidth of the link — what is the largest bandwidth of a path from to ?
Defining the Problem Formally
Before picking a strategy, it helps to pin down the problem precisely. Any optimization problem can be broken into 4 parts:
- Instance (Input): what you’re given.
- Solution Type (Output): the shape of the answer.
- Constraints: what must be true of a valid answer.
- Objective: what you’re optimizing over all valid answers.
Driving Example — Max Bandwidth, formalized:
- Instance: Directed graph with positive edge weights , two vertices .
- Solution Type: A sequence of edges.
- Constraints: The sequence of edges is a path from to in .
- Objective: Over all possible paths between and , find one that maximizes the bandwidth of a path:
Approach 1: Algorithm Modification
Take an existing algorithm that solves a structurally similar problem, and change what it tracks internally so it solves the new problem instead — e.g. starting from Graph Search and having it track a new quantity per vertex instead of just visited/unvisited.
Limitations
- Runtime is no longer guaranteed to match the original — it must be reanalyzed from scratch.
- The modified algorithm is not automatically correct just because the original was — it must be reproven, in full, from the ground up.
Driving Example: Max Bandwidth via Modification
Use the basic structure of Graph Search, and for each vertex , keep track of the max bandwidth to found so far. Then move a vertex into only if its max bandwidth has improved.
Algorithm 36 Max Bandwidth Modify Algorithm Approach
procedure MaxBand1()
Initialize = emtpy,
B() = 0 for
B() =
while is not empty do
Pick in
for each neighbor of do
= min(B(), w())
if B() then
move to
B() =
move from to
return B()
Variables: — the bandwidth of the best path found so far from to .
Proof of Correctness
Note this whole proof is only necessary because this is a modification — nothing about Graph Search’s original correctness proof transfers over automatically.
Claim: At the end of the algorithm, is the maximum bandwidth from to , for all vertices .
Part 1 — is always achievable: for all , there is a path from to such that .
- Loop Invariant: after every iteration, for all , there is a path from to with .
- Base Case: before the first iteration, and for every other vertex.
- Inductive Hypothesis: assume the claim holds after iterations.
- Inductive Step: pick in , let be a neighbor of , and .
- Case 1: — doesn’t change.
- Case 2: — updates to .
- Either way, there still exists a path from to with bandwidth exactly .
- So the loop invariant holds after every iteration, including the last — meaning by the end, every vertex has a real path from to achieving bandwidth .
Part 2 — is never an underestimate: for all , is the maximum bandwidth among all paths from to (not just some achievable value).
- Suppose by contradiction there’s a vertex with some path from to where . Let .
- Let be the first vertex along where , and the vertex right before on (so ).
- Since has bandwidth , every edge on it — including — has weight , so .
- When is processed, the algorithm computes . Since , the algorithm updates to .
- This contradicts the assumption that at the end of the algorithm.
Approach 2: Reduction
What is a Reduction?
Instead of modifying an existing algorithm, we modify the input so we can use the existing algorithm as a subroutine. We map instances of one problem to instances of another, then use any known algorithm for that second problem as a subroutine to build an algorithm for the first — the existing algorithm’s correctness and runtime proofs carry over unchanged.
Reduction From a Decision Version
A useful general pattern: to relate a decision problem to an optimization problem, look at the decision version of the optimization problem instead of the optimization problem itself. A decision version asks a yes/no question (“is there a solution at least this good?”) rather than “find the best solution” — and it’s often much easier to reduce to something else.
Driving Example: Max Bandwidth via Reduction
Decision Version of Max Bandwidth: Given , is there a path of bandwidth or better from to ?
Algorithm 37 Max Bandwidth Reduction Approach
procedure MaxBandDecision()
Construct by removing all edges less than from
Run graphSearch()
if is visited then
return true
else
return false
The transformation itself — building — is the entire reduction. Graph Search runs completely unmodified on .
Proof of Correctness
Note how much smaller this proof is compared to the Modification approach — we only need to prove the reduction step correct, since graphSearch itself is already proven correct elsewhere.
Direction 1 — if there’s a path in with bandwidth , the algorithm returns TRUE: Suppose path in from to has bandwidth at least . Then every edge in has weight , so survives entirely in (no edge of gets removed). So graphSearch visits , and the algorithm outputs TRUE.
Direction 2 — if there’s no such path, the algorithm returns FALSE: Restated as the contrapositive: if the algorithm returns TRUE, then there is a path from to in with bandwidth at least . Suppose the algorithm returns TRUE. Then there’s a path in from to . Every edge in has weight by construction, so is also a path in where every edge weight is — meaning in as well.
Time Analysis
Let .
- Time to construct :
- Time to run
graphSearch(already analyzed, unchanged):
Total Time: — note this reuses graphSearch’s existing runtime bound rather than re-deriving it.
To solve the full optimization problem (not just the decision version), binary search over candidate values of (e.g. the distinct edge weights) and call MaxBandDecision at each — this reuses the decision procedure as a subroutine without needing a new correctness proof for the search itself.
Comparing the Two Approaches
| Modification | Reduction | |
|---|---|---|
| What changes | The existing algorithm’s internal logic | The input, via a transformation step; the existing algorithm runs unchanged |
| Correctness burden | Reprove the entire modified algorithm from scratch | Only prove the transformation step correct — the existing algorithm’s proof carries over |
| Runtime burden | Reanalyze the runtime of the modified algorithm | Runtime = cost of the transformation + the existing algorithm’s already-known runtime |
| Reusability | A one-off algorithm specific to this problem | Any correct, analyzed algorithm for the target problem can be swapped in |
| Max Bandwidth outcome | New proof (2 parts, induction) + new complexity argument | Reduction proof (2 directions) + graphSearch’s complexity reused as-is |
When to Use Which
- Prefer Reduction when a well-analyzed algorithm already exists for a problem your new problem’s decision version (or some other variant) can be mapped onto — you inherit its correctness and runtime for free, paying only for the transformation.
- Reach for Modification when no existing algorithm is close enough to reduce to, or when the transformation needed for a reduction would itself be as expensive or as hard to prove correct as just modifying the algorithm directly.
- Either way, the goal is the same: get to a fully specified, analyzed algorithm while doing as little new correctness/runtime work as possible.
